diff --git a/py-scripts/test_l3_longevity.py b/py-scripts/test_l3_longevity.py index fcfce6f4..02c595fd 100755 --- a/py-scripts/test_l3_longevity.py +++ b/py-scripts/test_l3_longevity.py @@ -2,7 +2,7 @@ ''' NAME: test_l3_longevity.py -PURPOSE: +PURPOSE: Supports creating user-specified amount stations on multiple radios Supports configuring upload and download requested rates and PDU sizes. @@ -36,8 +36,8 @@ Example command using attenuator --attenuators 1.1..1 \ --atten_vals 20,21,40,41 -Example using upsteam eth1 downstream eth2 - ./test_l3_longevity.py --test_duration 20s --polling_interval 1s --upstream_port eth1 --downstream_port eth2 +Example using upsteam eth1 downstream eth2 + ./test_l3_longevity.py --test_duration 20s --polling_interval 1s --upstream_port eth1 --downstream_port eth2 --endp_type lf --rates_are_totals --side_a_min_bps=10000000,0 --side_a_min_pdu=1000 --side_b_min_bps=0,300000000 --side_b_min_pdu=1000 COPYRIGHT: @@ -61,7 +61,7 @@ if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) - + sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) lf_report = importlib.import_module("py-scripts.lf_report") @@ -75,24 +75,24 @@ influx_add_parser_args = InfluxRequest.influx_add_parser_args # This class handles running the test and generating reports. class L3VariableTime(Realm): - def __init__(self, - endp_types, - args, - tos, + def __init__(self, + endp_types, + args, + tos, side_b, - side_a, - radio_name_list, + side_a, + radio_name_list, number_of_stations_per_radio_list, - ssid_list, - ssid_password_list, - ssid_security_list, - station_lists, - name_prefix, + ssid_list, + ssid_password_list, + ssid_security_list, + station_lists, + name_prefix, outfile, reset_port_enable_list, reset_port_time_min_list, reset_port_time_max_list, - side_a_min_rate=[56000], + side_a_min_rate=[56000], side_a_max_rate=[0], side_b_min_rate=[56000], side_b_max_rate=[0], @@ -105,11 +105,11 @@ class L3VariableTime(Realm): mconn=1, attenuators=[], atten_vals=[], - number_template="00", + number_template="00", test_duration="256s", polling_interval="60s", - lfclient_host="localhost", - lfclient_port=8080, + lfclient_host="localhost", + lfclient_port=8080, debug=False, influxdb=None, ap_scheduler_stats=False, @@ -141,13 +141,13 @@ class L3VariableTime(Realm): self.side_b = side_b self.side_a = side_a # if it is a dataplane test the side_a is not none and an ethernet port - if self.side_a != None: + if self.side_a is not None: self.dataplane = True else: self.dataplane = False self.ssid_list = ssid_list self.ssid_password_list = ssid_password_list - self.station_lists = station_lists + self.station_lists = station_lists self.ssid_security_list = ssid_security_list self.reset_port_enable_list = reset_port_enable_list self.reset_port_time_min_list = reset_port_time_min_list @@ -156,12 +156,12 @@ class L3VariableTime(Realm): self.name_prefix = name_prefix self.test_duration = test_duration self.radio_name_list = radio_name_list - self.number_of_stations_per_radio_list = number_of_stations_per_radio_list + self.number_of_stations_per_radio_list = number_of_stations_per_radio_list #self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port, debug_=debug_on) self.polling_interval_seconds = self.duration_time_to_seconds(polling_interval) self.cx_profile = self.new_l3_cx_profile() self.multicast_profile = self.new_multicast_profile() - self.multicast_profile.name_prefix = "MLT-"; + self.multicast_profile.name_prefix = "MLT-" self.station_profiles = [] self.args = args self.outfile = outfile @@ -170,8 +170,6 @@ class L3VariableTime(Realm): self.debug = debug self.mconn = mconn self.user_tags = user_tags - - self.side_a_min_rate = side_a_min_rate self.side_a_max_rate = side_a_max_rate @@ -230,7 +228,7 @@ class L3VariableTime(Realm): "Retries", "bw", "mcs", "Nss", "ofdma", "mu-mimo", "channel utilization"] dur = self.duration_time_to_seconds(self.test_duration) - + if (self.polling_interval_seconds > dur + 1): self.polling_interval_seconds = dur - 1 @@ -240,13 +238,13 @@ class L3VariableTime(Realm): kpi = kpi + "-kpi.csv" self.csv_kpi_file = open(kpi, "w") self.csv_kpi_writer = csv.writer(self.csv_kpi_file, delimiter=",") - + # if side_a is None then side_a is radios if self.dataplane == False: - for (radio_, ssid_, ssid_password_, ssid_security_,\ - reset_port_enable_, reset_port_time_min_, reset_port_time_max_) \ - in zip(radio_name_list, ssid_list, ssid_password_list, ssid_security_list,\ - reset_port_enable_list, reset_port_time_min_list, reset_port_time_max_list): + for (radio_, ssid_, ssid_password_, ssid_security_, + reset_port_enable_, reset_port_time_min_, reset_port_time_max_) \ + in zip(radio_name_list, ssid_list, ssid_password_list, ssid_security_list, + reset_port_enable_list, reset_port_time_min_list, reset_port_time_max_list): self.station_profile = self.new_station_profile() self.station_profile.lfclient_url = self.lfclient_url self.station_profile.ssid = ssid_ @@ -254,15 +252,14 @@ class L3VariableTime(Realm): self.station_profile.security = ssid_security_ self.station_profile.number_template = self.number_template self.station_profile.mode = 0 - self.station_profile.set_reset_extra(reset_port_enable=reset_port_enable_,\ - test_duration=self.duration_time_to_seconds(self.test_duration),\ - reset_port_min_time=self.duration_time_to_seconds(reset_port_time_min_),\ - reset_port_max_time=self.duration_time_to_seconds(reset_port_time_max_)) + self.station_profile.set_reset_extra(reset_port_enable=reset_port_enable_, + test_duration=self.duration_time_to_seconds(self.test_duration), + reset_port_min_time=self.duration_time_to_seconds(reset_port_time_min_), + reset_port_max_time=self.duration_time_to_seconds(reset_port_time_max_)) self.station_profiles.append(self.station_profile) else: pass - self.multicast_profile.host = self.lfclient_host self.cx_profile.host = self.lfclient_host self.cx_profile.port = self.lfclient_port @@ -295,7 +292,6 @@ class L3VariableTime(Realm): def get_ap_ofdma_24g(self): return self.ap_ofdma_24g - def get_kpi_csv(self): #print("self.csv_kpi_file {}".format(self.csv_kpi_file.name)) return self.csv_kpi_file.name @@ -315,7 +311,7 @@ class L3VariableTime(Realm): #print("endp-stats-for-port, port-eid: {}".format(eid_name)) eid = self.name_to_eid(eid_name) - print("eid_name: {eid_name} eid: {eid}".format(eid_name=eid_name,eid=eid)) + print("eid_name: {eid_name} eid: {eid}".format(eid_name=eid_name, eid=eid)) # Convert all eid elements to strings eid[0] = str(eid[0]) @@ -325,26 +321,25 @@ class L3VariableTime(Realm): for endp in endps: pprint(endp) eid_endp = endp["eid"].split(".") - print("Comparing eid:{eid} to endp-id {eid_endp}".format(eid=eid,eid_endp=eid_endp)) + print("Comparing eid:{eid} to endp-id {eid_endp}".format(eid=eid, eid_endp=eid_endp)) # Look through all the endpoints (endps), to find the port the eid_name is using. # The eid_name that has the same Shelf, Resource, and Port as the eid_endp (looking at all the endps) # Then read the eid_endp to get the delay, jitter and rx rate - # Note: the endp eid is shelf.resource.port.endp-id, the eid can be treated somewhat as + # Note: the endp eid is shelf.resource.port.endp-id, the eid can be treated somewhat as # child class of port-eid , and look up the port the eid is using. if eid[0] == eid_endp[0] and eid[1] == eid_endp[1] and eid[2] == eid_endp[2]: lat += int(endp["delay"]) jit += int(endp["jitter"]) name = endp["name"] print("endp name {name}".format(name=name)) - sta_name = name.replace('-A','') - #only the -A endpoint will be found so need to look - + sta_name = name.replace('-A', '') + # only the -A endpoint will be found so need to look count += 1 - print("Matched: name: {name} eid:{eid} to endp-id {eid_endp}".format(name=name,eid=eid,eid_endp=eid_endp)) + print("Matched: name: {name} eid:{eid} to endp-id {eid_endp}".format(name=name, eid=eid, eid_endp=eid_endp)) else: name = endp["name"] - print("No Match: name: {name} eid:{eid} to endp-id {eid_endp}".format(name=name,eid=eid,eid_endp=eid_endp)) + print("No Match: name: {name} eid:{eid} to endp-id {eid_endp}".format(name=name, eid=eid, eid_endp=eid_endp)) if count > 1: lat = int(lat / count) @@ -359,13 +354,12 @@ class L3VariableTime(Realm): total_dl_rate += int(endp["rx rate"]) total_dl_rate_ll += int(endp["rx rate ll"]) total_dl_pkts_ll += int(endp["rx pkts ll"]) - # -B upload side - else: + # -B upload side + else: total_ul_rate += int(endp["rx rate"]) total_ul_rate_ll += int(endp["rx rate ll"]) total_ul_pkts_ll += int(endp["rx pkts ll"]) - return lat, jit, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll # Query all endpoints to generate rx and other stats, returned @@ -383,9 +377,9 @@ class L3VariableTime(Realm): total_dl_ll = 0 for e in self.multicast_profile.get_mc_names(): - our_endps[e] = e; + our_endps[e] = e for e in self.cx_profile.created_endp.keys(): - our_endps[e] = e; + our_endps[e] = e for endp_name in endp_list['endpoint']: if endp_name != 'uri' and endp_name != 'handler': for item, value in endp_name.items(): @@ -393,7 +387,7 @@ class L3VariableTime(Realm): endps.append(value) print("endpoint: ", item, " value:\n") pprint(value) - + for value_name, value in value.items(): if value_name == 'rx bytes': endp_rx_map[item] = value @@ -419,7 +413,6 @@ class L3VariableTime(Realm): else: total_ul_ll += int(value) - #print("total-dl: ", total_dl, " total-ul: ", total_ul, "\n") return endp_rx_map, endp_rx_drop_map, endps, total_dl, total_ul, total_dl_ll, total_ul_ll @@ -453,11 +446,11 @@ class L3VariableTime(Realm): def gather_port_eids(self): rv = [self.side_b] - + for station_profile in self.station_profiles: rv = rv + station_profile.station_names - return rv; + return rv # Create stations and connections/endpoints. If rebuild is true, then # only update connections/endpoints. @@ -480,13 +473,13 @@ class L3VariableTime(Realm): if self.dataplane: for etype in self.endp_types: for _tos in self.tos: - print("Creating connections for endpoint type: %s TOS: %s cx-count: %s"%(etype, _tos, self.cx_profile.get_cx_count())) + print("Creating connections for endpoint type: %s TOS: %s cx-count: %s" % (etype, _tos, self.cx_profile.get_cx_count())) # use brackes on [self.side_a] to make it a list these_cx, these_endp = self.cx_profile.create(endp_type=etype, side_a=[self.side_a], - side_b=self.side_b, sleep_time=0, tos=_tos) + side_b=self.side_b, sleep_time=0, tos=_tos) if (etype == "lf_udp" or etype == "lf_udp6"): self.udp_endps = self.udp_endps + these_endp - elif(etype=="lf"): + elif(etype == "lf"): self.lf_endps = self.eth_endps + these_endp else: self.tcp_endps = self.tcp_endps + these_endp @@ -496,7 +489,7 @@ class L3VariableTime(Realm): if not rebuild: station_profile.use_security(station_profile.security, station_profile.ssid, station_profile.ssid_pass) station_profile.set_number_template(station_profile.number_template) - print("Creating stations on radio %s"%(self.radio_name_list[index])) + print("Creating stations on radio %s" % (self.radio_name_list[index])) station_profile.create(radio=self.radio_name_list[index], sta_names_=self.station_lists[index], debug=self.debug, sleep_time=0) index += 1 @@ -506,73 +499,73 @@ class L3VariableTime(Realm): # Build/update connection types for etype in self.endp_types: if etype == "mc_udp" or etype == "mc_udp6": - print("Creating Multicast connections for endpoint type: %s"%(etype)) + print("Creating Multicast connections for endpoint type: %s" % (etype)) self.multicast_profile.create_mc_tx(etype, self.side_b, etype) self.multicast_profile.create_mc_rx(etype, side_rx=station_profile.station_names) else: for _tos in self.tos: - print("Creating connections for endpoint type: %s TOS: %s cx-count: %s"%(etype, _tos, self.cx_profile.get_cx_count())) + print("Creating connections for endpoint type: %s TOS: %s cx-count: %s" % (etype, _tos, self.cx_profile.get_cx_count())) these_cx, these_endp = self.cx_profile.create(endp_type=etype, side_a=station_profile.station_names, - side_b=self.side_b, sleep_time=0, tos=_tos) + side_b=self.side_b, sleep_time=0, tos=_tos) if (etype == "lf_udp" or etype == "lf_udp6"): - self.udp_endps = self.udp_endps + these_endp; + self.udp_endps = self.udp_endps + these_endp else: - self.tcp_endps = self.tcp_endps + these_endp; + self.tcp_endps = self.tcp_endps + these_endp self.cx_count = self.cx_profile.get_cx_count() if self.dataplane == True: - self._pass("PASS: CX build finished: created/updated: %s connections."%(self.cx_count)) + self._pass("PASS: CX build finished: created/updated: %s connections." % (self.cx_count)) else: - self._pass("PASS: Stations & CX build finished: created/updated: %s stations and %s connections."%(self.station_count, self.cx_count)) + self._pass("PASS: Stations & CX build finished: created/updated: %s stations and %s connections." % (self.station_count, self.cx_count)) - def ap_custom_cmd(self,ap_custom_cmd): + def ap_custom_cmd(self, ap_custom_cmd): ap_results = "" try: # configure the serial interface ser = serial.Serial(self.ap_port, int(self.ap_baud), timeout=5) ss = SerialSpawn(ser) ss.sendline(str(ap_custom_cmd)) - ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output - ap_results = ss.before.decode('utf-8','ignore') + ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output + ap_results = ss.before.decode('utf-8', 'ignore') print("ap_custom_cmd: {} ap_results {}".format(ap_custom_cmd, ap_results)) - except: + except BaseException: print("ap_custom_cmd: {} WARNING unable to read AP ".format(ap_custom_cmd)) return ap_results def read_ap_stats_6g(self): - # 6ghz: wl -i wl2 bs_data + # 6ghz: wl -i wl2 bs_data ap_stats_6g = "" try: # configure the serial interface ser = serial.Serial(self.ap_port, int(self.ap_baud), timeout=5) ss = SerialSpawn(ser) ss.sendline(str(self.ap_cmd_6g)) - ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output - ap_stats_6g = ss.before.decode('utf-8','ignore') + ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output + ap_stats_6g = ss.before.decode('utf-8', 'ignore') print("ap_stats_6g from AP: {}".format(ap_stats_6g)) - except: + except BaseException: print("WARNING: ap_stats_6g unable to read AP") - + return ap_stats_6g def read_ap_stats_5g(self): - # 5ghz: wl -i wl1 bs_data + # 5ghz: wl -i wl1 bs_data ap_stats_5g = "" try: # configure the serial interface ser = serial.Serial(self.ap_port, int(self.ap_baud), timeout=5) ss = SerialSpawn(ser) ss.sendline(str(self.ap_cmd_5g)) - ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output - ap_stats_5g = ss.before.decode('utf-8','ignore') + ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output + ap_stats_5g = ss.before.decode('utf-8', 'ignore') print("ap_stats_5g from AP: {}".format(ap_stats_5g)) - except: + except BaseException: print("WARNING: ap_stats_5g unable to read AP") - + return ap_stats_5g def read_ap_stats_2g(self): @@ -583,48 +576,47 @@ class L3VariableTime(Realm): ser = serial.Serial(self.ap_port, int(self.ap_baud), timeout=5) ss = SerialSpawn(ser) ss.sendline(str(self.ap_cmd_2g)) - ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output - ap_stats_2g = ss.before.decode('utf-8','ignore') + ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output + ap_stats_2g = ss.before.decode('utf-8', 'ignore') print("ap_stats_2g from AP: {}".format(ap_stats_2g)) - except: + except BaseException: print("WARNING: ap_stats_2g unable to read AP") - + return ap_stats_2g def read_ap_chanim_stats_6g(self): - # 5ghz: wl -i wl1 chanim_stats + # 5ghz: wl -i wl1 chanim_stats ap_chanim_stats_6g = "" try: # configure the serial interface ser = serial.Serial(self.ap_port, int(self.ap_baud), timeout=5) ss = SerialSpawn(ser) ss.sendline(str(self.ap_chanim_cmd_6g)) - ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output - ap_chanim_stats_6g = ss.before.decode('utf-8','ignore') + ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output + ap_chanim_stats_6g = ss.before.decode('utf-8', 'ignore') print("read_ap_chanim_stats_6g {}".format(ap_chanim_stats_6g)) - except: + except BaseException: print("WARNING: read_ap_chanim_stats_6g unable to read AP") return ap_chanim_stats_6g - def read_ap_chanim_stats_5g(self): - # 5ghz: wl -i wl1 chanim_stats + # 5ghz: wl -i wl1 chanim_stats ap_chanim_stats_5g = "" try: # configure the serial interface ser = serial.Serial(self.ap_port, int(self.ap_baud), timeout=5) ss = SerialSpawn(ser) ss.sendline(str(self.ap_chanim_cmd_5g)) - ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output - ap_chanim_stats_5g = ss.before.decode('utf-8','ignore') + ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output + ap_chanim_stats_5g = ss.before.decode('utf-8', 'ignore') print("read_ap_chanim_stats_5g {}".format(ap_chanim_stats_5g)) - except: + except BaseException: print("WARNING: read_ap_chanim_stats_5g unable to read AP") - + return ap_chanim_stats_5g def read_ap_chanim_stats_2g(self): @@ -635,22 +627,22 @@ class L3VariableTime(Realm): ser = serial.Serial(self.ap_port, int(self.ap_baud), timeout=5) ss = SerialSpawn(ser) ss.sendline(str(self.ap_chanim_cmd_2g)) - ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output - ap_chanim_stats_2g = ss.before.decode('utf-8','ignore') + ss.expect([pexpect.TIMEOUT], timeout=1) # do not detete line, waits for output + ap_chanim_stats_2g = ss.before.decode('utf-8', 'ignore') print("read_ap_chanim_stats_2g {}".format(ap_chanim_stats_2g)) - except: + except BaseException: print("WARNING: read_ap_chanim_stats_2g unable to read AP") - + return ap_chanim_stats_2g # Run the main body of the test logic. def start(self, print_pass=False, print_fail=False): print("Bringing up stations") - self.admin_up(self.side_b) + self.admin_up(self.side_b) for station_profile in self.station_profiles: for sta in station_profile.station_names: - print("Bringing up station %s"%(sta)) + print("Bringing up station %s" % (sta)) self.admin_up(sta) temp_stations_list = [] @@ -665,7 +657,7 @@ class L3VariableTime(Realm): print("print failed to get IP's") csv_header = self.csv_generate_column_headers() - #print(csv_header) + # print(csv_header) self.csv_add_column_headers(csv_header) port_eids = self.gather_port_eids() for eid_name in port_eids: @@ -699,8 +691,8 @@ class L3VariableTime(Realm): if (dl_pdu == "AUTO" or dl_pdu == "MTU"): dl_pdu = "-1" - print("ul: %s dl: %s cx-count: %s rates-are-totals: %s\n"%(ul, dl, self.cx_count, self.rates_are_totals)) - + print("ul: %s dl: %s cx-count: %s rates-are-totals: %s\n" % (ul, dl, self.cx_count, self.rates_are_totals)) + # Set rate and pdu size config self.cx_profile.side_a_min_bps = ul self.cx_profile.side_a_max_bps = ul @@ -738,7 +730,7 @@ class L3VariableTime(Realm): end_time = self.parse_time(self.test_duration) + cur_time - print("Monitoring throughput for duration: %s"%(self.test_duration)) + print("Monitoring throughput for duration: %s" % (self.test_duration)) # Monitor test for the interval duration. passes = 0 @@ -765,29 +757,37 @@ class L3VariableTime(Realm): self.epoch_time = int(time.time()) new_rx_values, rx_drop_percent, endps, total_dl_bps, total_ul_bps, total_dl_ll_bps, total_ul_ll_bps = self.__get_rx_values() - print("main loop, total-dl: ", total_dl_bps, " total-ul: ", total_ul_bps, " total-dl-ll: ", total_dl_ll_bps," total-ul-ll: ", total_ul_ll_bps) + print( + "main loop, total-dl: ", + total_dl_bps, + " total-ul: ", + total_ul_bps, + " total-dl-ll: ", + total_dl_ll_bps, + " total-ul-ll: ", + total_ul_ll_bps) # AP OUTPUT if self.ap_read: # 6G test mode if self.ap_test_mode: # Create the test data as a continuous string - ap_stats_6g="{}{}{}{}{}{}{}".format("root@Docsis-Gateway:~# wl -i wl2 bs_data\n", - "Station Address PHY Mbps Data Mbps Air Use Data Use Retries bw mcs Nss ofdma mu-mimo\n", - "04:f0:21:82:2f:d6 1016.6 48.9 6.5% 24.4% 16.6% 80 9.7 2 0.0% 0.0%\n", - "50:E0:85:84:7A:E7 880.9 52.2 7.7% 26.1% 20.0% 80 8.5 2 0.0% 0.0%\n", - "50:E0:85:89:5D:00 840.0 47.6 6.4% 23.8% 2.3% 80 8.0 2 0.0% 0.0%\n", - "50:E0:85:87:5B:F4 960.7 51.5 5.9% 25.7% 0.0% 80 9 2 0.0% 0.0%\n", - "- note the MAC will match ap_stats.append((overall) - 200.2 26.5% - - \n") + ap_stats_6g = "{}{}{}{}{}{}{}".format("root@Docsis-Gateway:~# wl -i wl2 bs_data\n", + "Station Address PHY Mbps Data Mbps Air Use Data Use Retries bw mcs Nss ofdma mu-mimo\n", + "04:f0:21:82:2f:d6 1016.6 48.9 6.5% 24.4% 16.6% 80 9.7 2 0.0% 0.0%\n", + "50:E0:85:84:7A:E7 880.9 52.2 7.7% 26.1% 20.0% 80 8.5 2 0.0% 0.0%\n", + "50:E0:85:89:5D:00 840.0 47.6 6.4% 23.8% 2.3% 80 8.0 2 0.0% 0.0%\n", + "50:E0:85:87:5B:F4 960.7 51.5 5.9% 25.7% 0.0% 80 9 2 0.0% 0.0%\n", + "- note the MAC will match ap_stats.append((overall) - 200.2 26.5% - - \n") print("ap_stats 6g{}".format(ap_stats_6g)) # Create the test data as a continuous string ap_chanim_stats_6g = "{}{}{}{}".format("root@Docsis-Gateway:~# wl -i wl2 chanim_stats\n", - "version: 3\n", - "chanspec tx inbss obss nocat nopkt doze txop goodtx badtx glitch badplcp knoise idle timestamp\n", - #`"0xe06a 61 15 0 17 0 0 6 53 2 0 0 -91 65 343370578\n") - '0xe06a\t41.82\t20.22\t0.00\t13.56\t0.02\t0.00\t17.58\t29.54\t1.94\t3\t0\t-90\t58\t146903490\n') - #"0xe06a 1.67 15.00 0.00 17.00 0.00 0.00 97.33 53.00 2.00 0 0 -91 65 343370578\n") + "version: 3\n", + "chanspec tx inbss obss nocat nopkt doze txop goodtx badtx glitch badplcp knoise idle timestamp\n", + # `"0xe06a 61 15 0 17 0 0 6 53 2 0 0 -91 65 343370578\n") + '0xe06a\t41.82\t20.22\t0.00\t13.56\t0.02\t0.00\t17.58\t29.54\t1.94\t3\t0\t-90\t58\t146903490\n') + # "0xe06a 1.67 15.00 0.00 17.00 0.00 0.00 97.33 53.00 2.00 0 0 -91 65 343370578\n") else: # read from the AP 6g @@ -806,11 +806,11 @@ class L3VariableTime(Realm): port_eids = self.gather_port_eids() for eid_name in port_eids: eid = self.name_to_eid(eid_name) - url = "/port/%s/%s/%s"%(eid[0], eid[1], eid[2]) + url = "/port/%s/%s/%s" % (eid[0], eid[1], eid[2]) # read LANforge to get the mac response = self.json_get(url) if (response is None) or ("interface" not in response): - print("6g query-port: %s: incomplete response:"%(url)) + print("6g query-port: %s: incomplete response:" % (url)) pprint(response) else: # print("response".format(response)) @@ -818,7 +818,7 @@ class L3VariableTime(Realm): p = response['interface'] print("#### 6g From LANforge: p, response['insterface']:{}".format(p)) mac = p['mac'] - #print("#### From LANforge: p['mac']: {mac}".format(mac=mac)) + # print("#### From LANforge: p['mac']: {mac}".format(mac=mac)) # Parse the ap stats to find the matching mac then use that row for reporting for row in ap_stats_6g_rows: @@ -831,12 +831,12 @@ class L3VariableTime(Realm): mac_found_6g = True else: try: - # split_row[0].lower() , mac from AP + # split_row[0].lower() , mac from AP # mac.lower() , mac from LANforge if split_row[0].lower() == mac.lower(): ap_row = split_row mac_found_6g = True - except: + except BaseException: print("6g 'No stations are currently associated.'? from AP") print(" since possibly no stations: excption on compare split_row[0].lower() ") if mac_found_6g == True: @@ -844,7 +844,8 @@ class L3VariableTime(Realm): print("6g selected ap_row (from split_row): {}".format(ap_row)) # Find latency, jitter for connections using this port. - latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll = self.get_endp_stats_for_port(p["port"], endps) + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll = self.get_endp_stats_for_port( + p["port"], endps) # now report the ap_chanim_stats along side of the ap_stats_6g xtop_reported = False @@ -856,13 +857,13 @@ class L3VariableTime(Realm): try: xtop = split_row[7] print("6g xtop {xtop}".format(xtop=xtop)) - except: + except BaseException: print("6g detected chanspec with reading chanim_stats, exception reading xtop") try: channel_utilization = float(100) - float(xtop) print("6g channel_utilization {utilization}".format(utilization=channel_utilization)) - except: + except BaseException: print("6g detected chanspec with reading chanim_stats, failed calcluating channel_utilization from xtop") # should be only one channel utilization break @@ -871,60 +872,61 @@ class L3VariableTime(Realm): if split_row[0].lower() == 'chanspec': print("6g chanspec found xtop_reported = True") xtop_reported = True - except: + except BaseException: print("6g Error reading xtop") # ap information is passed with ap_row so all information needs to be contained in ap_row ap_row.append(str(channel_utilization)) print("6g channel_utilization {channel_utilization}".format(channel_utilization=channel_utilization)) print("6g ap_row {ap_row}".format(ap_row=ap_row)) - ap_stats_6g_col_titles = ['Station Address','PHY Mbps','Data Mbps','Air Use','Data Use','Retries','bw','mcs','Nss','ofdma','mu-mimo','channel_utilization'] + ap_stats_6g_col_titles = ['Station Address', 'PHY Mbps', 'Data Mbps', 'Air Use', + 'Data Use', 'Retries', 'bw', 'mcs', 'Nss', 'ofdma', 'mu-mimo', 'channel_utilization'] self.write_port_csv(len(temp_stations_list), ul, dl, ul_pdu_str, dl_pdu_str, atten_val, eid_name, p, - latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, - total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll , ap_row, ap_stats_6g_col_titles) #ap_stats_5g_col_titles used as a length + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, + total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll, ap_row, ap_stats_6g_col_titles) # ap_stats_5g_col_titles used as a length # 5G test mode if self.ap_test_mode: # Create the test data as a continuous string - ap_stats_5g="{}{}{}{}{}{}{}".format("root@Docsis-Gateway:~# wl -i wl1 bs_data\n", - "Station Address PHY Mbps Data Mbps Air Use Data Use Retries bw mcs Nss ofdma mu-mimo\n", - "04:f0:21:82:2f:d6 1016.6 48.9 6.5% 24.4% 16.6% 80 9.7 2 0.0% 0.0%\n", - "50:E0:85:84:7A:E7 880.9 52.2 7.7% 26.1% 20.0% 80 8.5 2 0.0% 0.0%\n", - "50:E0:85:89:5D:00 840.0 47.6 6.4% 23.8% 2.3% 80 8.0 2 0.0% 0.0%\n", - "50:E0:85:87:5B:F4 960.7 51.5 5.9% 25.7% 0.0% 80 9 2 0.0% 0.0%\n", - "- note the MAC will match ap_stats.append((overall) - 200.2 26.5% - - \n") + ap_stats_5g = "{}{}{}{}{}{}{}".format("root@Docsis-Gateway:~# wl -i wl1 bs_data\n", + "Station Address PHY Mbps Data Mbps Air Use Data Use Retries bw mcs Nss ofdma mu-mimo\n", + "04:f0:21:82:2f:d6 1016.6 48.9 6.5% 24.4% 16.6% 80 9.7 2 0.0% 0.0%\n", + "50:E0:85:84:7A:E7 880.9 52.2 7.7% 26.1% 20.0% 80 8.5 2 0.0% 0.0%\n", + "50:E0:85:89:5D:00 840.0 47.6 6.4% 23.8% 2.3% 80 8.0 2 0.0% 0.0%\n", + "50:E0:85:87:5B:F4 960.7 51.5 5.9% 25.7% 0.0% 80 9 2 0.0% 0.0%\n", + "- note the MAC will match ap_stats.append((overall) - 200.2 26.5% - - \n") print("ap_stats 5g {}".format(ap_stats_5g)) # Create the test data as a continuous string ap_chanim_stats_5g = "{}{}{}{}".format("root@Docsis-Gateway:~# wl -i wl1 chanim_stats\n", - "version: 3\n", - "chanspec tx inbss obss nocat nopkt doze txop goodtx badtx glitch badplcp knoise idle timestamp\n", - #`"0xe06a 61 15 0 17 0 0 6 53 2 0 0 -91 65 343370578\n") - '0xe06a\t41.82\t20.22\t0.00\t13.56\t0.02\t0.00\t17.58\t29.54\t1.94\t3\t0\t-90\t58\t146903490\n') - #"0xe06a 1.67 15.00 0.00 17.00 0.00 0.00 97.33 53.00 2.00 0 0 -91 65 343370578\n") + "version: 3\n", + "chanspec tx inbss obss nocat nopkt doze txop goodtx badtx glitch badplcp knoise idle timestamp\n", + # `"0xe06a 61 15 0 17 0 0 6 53 2 0 0 -91 65 343370578\n") + '0xe06a\t41.82\t20.22\t0.00\t13.56\t0.02\t0.00\t17.58\t29.54\t1.94\t3\t0\t-90\t58\t146903490\n') + # "0xe06a 1.67 15.00 0.00 17.00 0.00 0.00 97.33 53.00 2.00 0 0 -91 65 343370578\n") else: # read from the AP ap_stats_5g = self.read_ap_stats_5g() ap_chanim_stats_5g = self.read_ap_chanim_stats_5g() - + ap_stats_5g_rows = ap_stats_5g.splitlines() print("From AP stats: ap_stats_5g_rows {}".format(ap_stats_5g_rows)) ap_chanim_stats_rows_5g = ap_chanim_stats_5g.splitlines() print("From AP chanim: ap_chanim_stats_rows_5g {}".format(ap_chanim_stats_rows_5g)) channel_utilization = 0 - + # Query all of our ports # Note: the endp eid is the shelf.resource.port.endp-id port_eids = self.gather_port_eids() for eid_name in port_eids: eid = self.name_to_eid(eid_name) - url = "/port/%s/%s/%s"%(eid[0], eid[1], eid[2]) + url = "/port/%s/%s/%s" % (eid[0], eid[1], eid[2]) # read LANforge to get the mac response = self.json_get(url) if (response is None) or ("interface" not in response): - print("query-port 5g: %s: incomplete response:"%(url)) + print("query-port 5g: %s: incomplete response:" % (url)) pprint(response) else: # print("response".format(response)) @@ -932,8 +934,8 @@ class L3VariableTime(Realm): p = response['interface'] print("#### From LANforge: p, response['insterface']:{}".format(p)) mac = p['mac'] - #print("#### From LANforge: p['mac']: {mac}".format(mac=mac)) - + # print("#### From LANforge: p['mac']: {mac}".format(mac=mac)) + # Parse the ap stats to find the matching mac then use that row for reporting for row in ap_stats_5g_rows: split_row = row.split() @@ -945,20 +947,21 @@ class L3VariableTime(Realm): mac_found_5g = True else: try: - # split_row[0].lower() , mac from AP + # split_row[0].lower() , mac from AP # mac.lower() , mac from LANforge if split_row[0].lower() == mac.lower(): ap_row = split_row mac_found_5g = True - except: + except BaseException: print("5g 'No stations are currently associated.'? from AP") print("5g since possibly no stations: excption on compare split_row[0].lower() ") if mac_found_5g == True: - mac_found_5g = False + mac_found_5g = False print("5g selected ap_row (from split_row): {}".format(ap_row)) # Find latency, jitter for connections using this port. - latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll = self.get_endp_stats_for_port(p["port"], endps) + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll = self.get_endp_stats_for_port( + p["port"], endps) # now report the ap_chanim_stats along side of the ap_stats_5g xtop_reported = False @@ -970,83 +973,84 @@ class L3VariableTime(Realm): try: xtop = split_row[7] print("5g xtop {xtop}".format(xtop=xtop)) - except: + except BaseException: print("5g detected chanspec with reading chanim_stats, exception reading xtop") - try: + try: channel_utilization = float(100) - float(xtop) print("5g channel_utilization {utilization}".format(utilization=channel_utilization)) - except: + except BaseException: print("5g detected chanspec with reading chanim_stats, failed calcluating channel_utilization from xtop") - # should be only one channel utilization - break + # should be only one channel utilization + break else: try: if split_row[0].lower() == 'chanspec': print("5g chanspec found xtop_reported = True") xtop_reported = True - except: + except BaseException: print("5g Error reading xtop") # ap information is passed with ap_row so all information needs to be contained in ap_row ap_row.append(str(channel_utilization)) print("5g channel_utilization {channel_utilization}".format(channel_utilization=channel_utilization)) print("5g ap_row {ap_row}".format(ap_row=ap_row)) - ap_stats_5g_col_titles = ['Station Address','PHY Mbps','Data Mbps','Air Use','Data Use','Retries','bw','mcs','Nss','ofdma','mu-mimo','channel_utilization'] + ap_stats_5g_col_titles = ['Station Address', 'PHY Mbps', 'Data Mbps', 'Air Use', + 'Data Use', 'Retries', 'bw', 'mcs', 'Nss', 'ofdma', 'mu-mimo', 'channel_utilization'] self.write_port_csv(len(temp_stations_list), ul, dl, ul_pdu_str, dl_pdu_str, atten_val, eid_name, p, - latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, - total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll , ap_row, ap_stats_5g_col_titles) #ap_stats_5g_col_titles used as a length + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, + total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll, ap_row, ap_stats_5g_col_titles) # ap_stats_5g_col_titles used as a length # 2g test mode if self.ap_test_mode: # Create the test data as a continuous string - ap_stats_2g="{}{}{}{}{}{}{}".format("root@Docsis-Gateway:~# wl -i wl0 bs_data\n", - "Station Address PHY Mbps Data Mbps Air Use Data Use Retries bw mcs Nss ofdma mu-mimo\n", - "04:f0:21:82:2f:d6 1016.6 48.9 6.5% 24.4% 16.6% 80 9.7 2 0.0% 0.0%\n", - "50:E0:85:84:7A:E7 880.9 52.2 7.7% 26.1% 20.0% 80 8.5 2 0.0% 0.0%\n", - "50:E0:85:89:5D:00 840.0 47.6 6.4% 23.8% 2.3% 80 8.0 2 0.0% 0.0%\n", - "50:E0:85:87:5B:F4 960.7 51.5 5.9% 25.7% 0.0% 80 9 2 0.0% 0.0%\n", - "- note the MAC will match ap_stats_2g.append((overall) - 200.2 26.5% - - \n") + ap_stats_2g = "{}{}{}{}{}{}{}".format("root@Docsis-Gateway:~# wl -i wl0 bs_data\n", + "Station Address PHY Mbps Data Mbps Air Use Data Use Retries bw mcs Nss ofdma mu-mimo\n", + "04:f0:21:82:2f:d6 1016.6 48.9 6.5% 24.4% 16.6% 80 9.7 2 0.0% 0.0%\n", + "50:E0:85:84:7A:E7 880.9 52.2 7.7% 26.1% 20.0% 80 8.5 2 0.0% 0.0%\n", + "50:E0:85:89:5D:00 840.0 47.6 6.4% 23.8% 2.3% 80 8.0 2 0.0% 0.0%\n", + "50:E0:85:87:5B:F4 960.7 51.5 5.9% 25.7% 0.0% 80 9 2 0.0% 0.0%\n", + "- note the MAC will match ap_stats_2g.append((overall) - 200.2 26.5% - - \n") print("ap_stats_2g {}".format(ap_stats_2g)) # Create the test data as a continuous string ap_chanim_stats_2g = "{}{}{}{}".format("root@Docsis-Gateway:~# wl -i wl1 chanim_stats\n", - "version: 3\n", - "chanspec tx inbss obss nocat nopkt doze txop goodtx badtx glitch badplcp knoise idle timestamp\n", - #"0xe06a 62 15 0 17 0 0 6 53 2 0 0 -91 65 343370578\n") - '0xe06a\t41.82\t20.22\t0.00\t13.56\t0.02\t0.00\t17.58\t29.54\t1.94\t3\t0\t-90\t58\t146903490\n') - #"0xe06a 1.67 15.00 0.00 17.00 0.00 0.00 97.33 53.00 2.00 0 0 -91 65 343370578\n") + "version: 3\n", + "chanspec tx inbss obss nocat nopkt doze txop goodtx badtx glitch badplcp knoise idle timestamp\n", + # "0xe06a 62 15 0 17 0 0 6 53 2 0 0 -91 65 343370578\n") + '0xe06a\t41.82\t20.22\t0.00\t13.56\t0.02\t0.00\t17.58\t29.54\t1.94\t3\t0\t-90\t58\t146903490\n') + # "0xe06a 1.67 15.00 0.00 17.00 0.00 0.00 97.33 53.00 2.00 0 0 -91 65 343370578\n") else: # read from the AP ap_stats_2g = self.read_ap_stats_2g() ap_chanim_stats_2g = self.read_ap_chanim_stats_2g() - + ap_stats_2g_rows = ap_stats_2g.splitlines() print("From AP stats: ap_stats_2g_rows {}".format(ap_stats_2g_rows)) ap_chanim_stats_rows_2g = ap_chanim_stats_2g.splitlines() print("From AP chanim: ap_chanim_stats_rows_2g {}".format(ap_chanim_stats_rows_2g)) channel_utilization = 0 - + # Query all of our ports # Note: the endp eid is the shelf.resource.port.endp-id port_eids = self.gather_port_eids() for eid_name in port_eids: eid = self.name_to_eid(eid_name) - url = "/port/%s/%s/%s"%(eid[0], eid[1], eid[2]) + url = "/port/%s/%s/%s" % (eid[0], eid[1], eid[2]) # read LANforge to get the mac response = self.json_get(url) if (response is None) or ("interface" not in response): - print("2g query-port: %s: incomplete response:"%(url)) + print("2g query-port: %s: incomplete response:" % (url)) pprint(response) else: # print("response".format(response)) pprint(response) p = response['interface'] - #print("#### From LANforge: p, response['insterface']:{}".format(p)) + # print("#### From LANforge: p, response['insterface']:{}".format(p)) mac = p['mac'] - #print("#### From LANforge: p['mac']: {mac}".format(mac=mac)) - + # print("#### From LANforge: p['mac']: {mac}".format(mac=mac)) + # Parse the ap stats to find the matching mac then use that row for reporting for row in ap_stats_2g_rows: split_row = row.split() @@ -1058,20 +1062,21 @@ class L3VariableTime(Realm): mac_found_2g = True else: try: - # split_row[0].lower() , mac from AP + # split_row[0].lower() , mac from AP # mac.lower() , mac from LANforge if split_row[0].lower() == mac.lower(): ap_row = split_row mac_found_2g = True - except: + except BaseException: print("2g 'No stations are currently associated.'? from AP") print("2g since possibly no stations: excption on compare split_row[0].lower() ") if mac_found_2g == True: - mac_found_2g = False + mac_found_2g = False print("2g selected ap_row (from split_row): {}".format(ap_row)) # Find latency, jitter for connections using this port. - latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll = self.get_endp_stats_for_port(p["port"], endps) + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll = self.get_endp_stats_for_port( + p["port"], endps) # now report the ap_chanim_stats along side of the ap_stats_2g xtop_reported = False @@ -1083,33 +1088,34 @@ class L3VariableTime(Realm): try: xtop = split_row[7] print("2g xtop {xtop}".format(xtop=xtop)) - except: + except BaseException: print("2g detected chanspec with reading chanim_stats, exception reading xtop") try: channel_utilization = float(100) - float(xtop) print("2g channel_utilization {utilization}".format(utilization=channel_utilization)) - except: + except BaseException: print("2g detected chanspec with reading chanim_stats, failed calcluating channel_utilization from xtop") - # should be only one channel utilization - break + # should be only one channel utilization + break else: try: if split_row[0].lower() == 'chanspec': print("2g chanspec found xtop_reported = True") xtop_reported = True - except: + except BaseException: print("2g Error reading xtop") # ap information is passed with ap_row so all information needs to be contained in ap_row ap_row.append(str(channel_utilization)) print("2g channel_utilization {channel_utilization}".format(channel_utilization=channel_utilization)) print("2g ap_row {ap_row}".format(ap_row=ap_row)) - ap_stats_2g_col_titles = ['Station Address','PHY Mbps','Data Mbps','Air Use','Data Use','Retries','bw','mcs','Nss','ofdma','mu-mimo','channel_utilization'] + ap_stats_2g_col_titles = ['Station Address', 'PHY Mbps', 'Data Mbps', 'Air Use', + 'Data Use', 'Retries', 'bw', 'mcs', 'Nss', 'ofdma', 'mu-mimo', 'channel_utilization'] self.write_port_csv(len(temp_stations_list), ul, dl, ul_pdu_str, dl_pdu_str, atten_val, eid_name, p, - latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, - total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll, ap_row, ap_stats_2g_col_titles) #ap_stats_2g_col_titles used as a length + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, + total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll, ap_row, ap_stats_2g_col_titles) # ap_stats_2g_col_titles used as a length else: @@ -1118,22 +1124,32 @@ class L3VariableTime(Realm): port_eids = self.gather_port_eids() for eid_name in port_eids: eid = self.name_to_eid(eid_name) - url = "/port/%s/%s/%s"%(eid[0], eid[1], eid[2]) + url = "/port/%s/%s/%s" % (eid[0], eid[1], eid[2]) response = self.json_get(url) if (response is None) or ("interface" not in response): - print("query-port: %s: incomplete response:"%(url)) + print("query-port: %s: incomplete response:" % (url)) pprint(response) else: p = response['interface'] - latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll= self.get_endp_stats_for_port(p["port"], endps) - - self.write_port_csv(len(temp_stations_list), ul, dl, ul_pdu_str, dl_pdu_str, atten_val, eid_name, p, - latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, - total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll, ap_row, ap_stats_col_titles) #ap_stats_col_titles used as a length + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll = self.get_endp_stats_for_port( + p["port"], endps) + self.write_port_csv(len(temp_stations_list), ul, dl, ul_pdu_str, dl_pdu_str, atten_val, eid_name, p, + latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, + total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll, ap_row, ap_stats_col_titles) # ap_stats_col_titles used as a length # At end of test step, record KPI information. This is different the kpi.csv - self.record_kpi(len(temp_stations_list), ul, dl, ul_pdu_str, dl_pdu_str, atten_val, total_dl_bps, total_ul_bps, total_dl_ll_bps, total_ul_ll_bps) + self.record_kpi( + len(temp_stations_list), + ul, + dl, + ul_pdu_str, + dl_pdu_str, + atten_val, + total_dl_bps, + total_ul_bps, + total_dl_ll_bps, + total_ul_ll_bps) # At end of test if requested store upload and download stats if self.ap_scheduler_stats: @@ -1152,7 +1168,6 @@ class L3VariableTime(Realm): # get the (DL) Download 24g schduler staticstics self.ap_24g_msched += self.ap_custom_cmd('wl -i wl0 dump msched') - if self.ap_ofdma_stats: # provide OFDMA stats 6GHz self.ap_ofdma_6g += self.ap_custom_cmd('wl -i wl2 muinfo -v') @@ -1170,19 +1185,19 @@ class L3VariableTime(Realm): cur_time = datetime.datetime.now() if passes == expected_passes: - self._pass("PASS: Requested-Rate: %s <-> %s PDU: %s <-> %s All tests passed" % (ul, dl, ul_pdu, dl_pdu), print_pass) + self._pass("PASS: Requested-Rate: %s <-> %s PDU: %s <-> %s All tests passed" % (ul, dl, ul_pdu, dl_pdu), print_pass) - def write_port_csv(self, sta_count, ul, dl, ul_pdu, dl_pdu, atten, eid_name, port_data, latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, - total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll, ap_row, ap_stats_col_titles): + def write_port_csv(self, sta_count, ul, dl, ul_pdu, dl_pdu, atten, eid_name, port_data, latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, + total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll, ap_row, ap_stats_col_titles): row = [self.epoch_time, self.time_stamp(), sta_count, ul, ul, dl, dl, dl_pdu, dl_pdu, ul_pdu, ul_pdu, atten, eid_name ] row = row + [port_data['bps rx'], port_data['bps tx'], port_data['rx-rate'], port_data['tx-rate'], - port_data['signal'], port_data['ap'], port_data['mode'], latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll] + port_data['signal'], port_data['ap'], port_data['mode'], latency, jitter, total_ul_rate, total_ul_rate_ll, total_ul_pkts_ll, total_dl_rate, total_dl_rate_ll, total_dl_pkts_ll] - #Add in info queried from AP. NOTE: do not need to pass in the ap_stats_col_titles + # Add in info queried from AP. NOTE: do not need to pass in the ap_stats_col_titles #print("ap_row length {} col_titles length {}".format(len(ap_row),len(self.ap_stats_col_titles))) #print("self.ap_stats_col_titles {} ap_stats_col_titles {}".format(self.ap_stats_col_titles,ap_stats_col_titles)) if len(ap_row) == len(self.ap_stats_col_titles): @@ -1195,8 +1210,8 @@ class L3VariableTime(Realm): writer.writerow(row) self.port_csv_files[eid_name].flush() - # Submit data to the influx db if configured to do so. + def record_kpi(self, sta_count, ul, dl, ul_pdu, dl_pdu, atten, total_dl_bps, total_ul_bps, total_dl_ll_bps, total_ul_ll_bps): tags = dict() @@ -1214,7 +1229,8 @@ class L3VariableTime(Realm): now = str(datetime.datetime.utcnow().isoformat()) - print("NOTE: Adding kpi to influx, total-download-bps: %s upload: %s bi-directional: %s\n"%(total_dl_bps, total_ul_bps, (total_ul_bps + total_dl_bps))) + print("NOTE: Adding kpi to influx, total-download-bps: %s upload: %s bi-directional: %s\n" % + (total_dl_bps, total_ul_bps, (total_ul_bps + total_dl_bps))) if self.influxdb is not None: self.influxdb.post_to_influx("total-download-bps", total_dl_bps, tags, now) @@ -1251,17 +1267,17 @@ class L3VariableTime(Realm): station_profile.cleanup() def csv_generate_column_headers(self): - csv_rx_headers = ['Time epoch','Time','Monitor', - 'UL-Min-Requested','UL-Max-Requested','DL-Min-Requested','DL-Max-Requested', - 'UL-Min-PDU','UL-Max-PDU','DL-Min-PDU','DL-Max-PDU', + csv_rx_headers = ['Time epoch', 'Time', 'Monitor', + 'UL-Min-Requested', 'UL-Max-Requested', 'DL-Min-Requested', 'DL-Max-Requested', + 'UL-Min-PDU', 'UL-Max-PDU', 'DL-Min-PDU', 'DL-Max-PDU', ] csv_rx_headers.append("average_rx_data_bytes") return csv_rx_headers def csv_generate_port_column_headers(self): csv_rx_headers = ['Time epoch', 'Time', 'Station-Count', - 'UL-Min-Requested','UL-Max-Requested','DL-Min-Requested','DL-Max-Requested', - 'UL-Min-PDU','UL-Max-PDU','DL-Min-PDU','DL-Max-PDU','Attenuation', + 'UL-Min-Requested', 'UL-Max-Requested', 'DL-Min-Requested', 'DL-Max-Requested', + 'UL-Min-PDU', 'UL-Max-PDU', 'DL-Min-PDU', 'DL-Max-PDU', 'Attenuation', 'Name', 'Rx-Bps', 'Tx-Bps', 'Rx-Link-Rate', 'Tx-Link-Rate', 'RSSI', 'AP', 'Mode', 'Rx-Latency', 'Rx-Jitter', 'Ul-Rx-Goodput-bps', 'Ul-Rx-Rate-ll', 'Ul-Rx-Pkts-ll', 'Dl-Rx-Goodput-bps', 'Dl-Rx-Rate-ll', 'Dl-Rx-Pkts-ll' ] @@ -1273,10 +1289,10 @@ class L3VariableTime(Realm): def csv_generate_kpi_column_headers(self): csv_rx_headers = ['Time epoch', 'Time', 'Station-Count', - 'UL-Min-Requested','UL-Max-Requested','DL-Min-Requested','DL-Max-Requested', - 'UL-Min-PDU','UL-Max-PDU','DL-Min-PDU','DL-Max-PDU','Attenuation', + 'UL-Min-Requested', 'UL-Max-Requested', 'DL-Min-Requested', 'DL-Max-Requested', + 'UL-Min-PDU', 'UL-Max-PDU', 'DL-Min-PDU', 'DL-Max-PDU', 'Attenuation', 'Total-Download-Bps', 'Total-Upload-Bps', 'Total-UL/DL-Bps', - 'Total-Download-LL-Bps', 'Total-Upload-LL-Bps','Total-UL/DL-LL-Bps' + 'Total-Download-LL-Bps', 'Total-Upload-LL-Bps', 'Total-UL/DL-LL-Bps' ] for k in self.user_tags: csv_rx_headers.append(k[0]) @@ -1284,30 +1300,30 @@ class L3VariableTime(Realm): return csv_rx_headers # Write initial headers to csv file. - def csv_add_column_headers(self,headers): + def csv_add_column_headers(self, headers): if self.csv_kpi_file is not None: self.csv_kpi_writer.writerow(self.csv_generate_kpi_column_headers()) self.csv_kpi_file.flush() # Write initial headers to port csv file. def csv_add_port_column_headers(self, eid_name, headers): - #if self.csv_file is not None: + # if self.csv_file is not None: fname = self.outfile[:-4] # Strip '.csv' from file name fname = fname + "-" + eid_name + ".csv" pfile = open(fname, "w") port_csv_writer = csv.writer(pfile, delimiter=",") self.port_csv_files[eid_name] = pfile self.port_csv_writers[eid_name] = port_csv_writer - + port_csv_writer.writerow(headers) pfile.flush() def csv_validate_list(self, csv_list, length): if len(csv_list) < length: - csv_list = csv_list + [('no data','no data')] * (length - len(csv_list)) + csv_list = csv_list + [('no data', 'no data')] * (length - len(csv_list)) return csv_list - def csv_add_row(self,row,writer,csv_file): + def csv_add_row(self, row, writer, csv_file): if csv_file is not None: writer.writerow(row) csv_file.flush() @@ -1315,10 +1331,12 @@ class L3VariableTime(Realm): # End of the main class. # Check some input values. + + def valid_endp_types(_endp_type): etypes = _endp_type.split(',') for endp_type in etypes: - valid_endp_type=['lf','lf_udp','lf_udp6','lf_tcp','lf_tcp6','mc_udp','mc_udp6'] + valid_endp_type = ['lf', 'lf_udp', 'lf_udp6', 'lf_tcp', 'lf_tcp6', 'mc_udp', 'mc_udp6'] if not (str(endp_type) in valid_endp_type): print('invalid endp_type: %s. Valid types lf, lf_udp, lf_udp6, lf_tcp, lf_tcp6, mc_udp, mc_udp6' % endp_type) exit(1) @@ -1334,29 +1352,29 @@ def main(): parser = argparse.ArgumentParser( prog='test_l3_longevity.py', - #formatter_class=argparse.RawDescriptionHelpFormatter, + # formatter_class=argparse.RawDescriptionHelpFormatter, formatter_class=argparse.RawTextHelpFormatter, epilog='''\ Useful Information: 1. Polling interval for checking traffic is fixed at 1 minute - 2. The test will generate csv file + 2. The test will generate csv file 3. The tx/rx rates are fixed at 256000 bits per second 4. Maximum stations per radio based on radio ''', - + description='''\ test_l3_longevity.py: -------------------- -Summary : +Summary : ---------- -create stations, create traffic between upstream port and stations, run traffic. +create stations, create traffic between upstream port and stations, run traffic. The traffic on the stations will be checked once per minute to verify that traffic is transmitted and received. Generic command layout: ----------------------- -python .\\test_l3_longevity.py --test_duration --endp_type --upstream_port +python .\\test_l3_longevity.py --test_duration --endp_type --upstream_port --radio "radio== stations== ssid== ssid_pw== security==" --debug Multiple radios may be entered with individual --radio switches @@ -1366,13 +1384,13 @@ Multiple radios may be entered with individual --radio switches --radio "radio==1.1.wiphy2 stations==1 ssid==ASUS_70 ssid_pw==[BLANK] security==open" \ --test_duration 30s -: number followed by one of the following +: number followed by one of the following d - days h - hours m - minutes s - seconds -: +: lf_udp : IPv4 UDP traffic lf_tcp : IPv4 TCP traffic lf_udp6 : IPv6 UDP traffic @@ -1380,7 +1398,7 @@ lf_tcp6 : IPv6 TCP traffic mc_udp : IPv4 multi cast UDP traffic mc_udp6 : IPv6 multi cast UDP traffic -: +: BK, BE, VI, VO: Optional wifi related Tos Settings. Or, use your preferred numeric values. ################################# @@ -1398,7 +1416,7 @@ BK, BE, VI, VO: Optional wifi related Tos Settings. Or, use your preferred num ######################################### # Examples -# ####################################### +# ####################################### Example #1 running traffic with two radios 1. Test duration 4 minutes 2. Traffic IPv4 TCP @@ -1408,37 +1426,43 @@ Example #1 running traffic with two radios 6. Create connections with TOS of BK and VI Command: (remove carriage returns) -python3 .\\test_l3_longevity.py --test_duration 4m --endp_type \"lf_tcp lf_udp mc_udp\" --tos \"BK VI\" --upstream_port eth1 +python3 .\\test_l3_longevity.py --test_duration 4m --endp_type \"lf_tcp lf_udp mc_udp\" --tos \"BK VI\" --upstream_port eth1 --radio "radio==wiphy0 stations==32 ssid==candelaTech-wpa2-x2048-4-1 ssid_pw==candelaTech-wpa2-x2048-4-1 security==wpa2" --radio "radio==wiphy1 stations==64 ssid==candelaTech-wpa2-x2048-5-3 ssid_pw==candelaTech-wpa2-x2048-5-3 security==wpa2" ''') - parser.add_argument('--local_lf_report_dir', help='--local_lf_report_dir override the report path, primary use when running test in test suite',default="") - parser.add_argument('-o','--csv_outfile', help="--csv_outfile ", default="") + parser.add_argument( + '--local_lf_report_dir', + help='--local_lf_report_dir override the report path, primary use when running test in test suite', + default="") + parser.add_argument('-o', '--csv_outfile', help="--csv_outfile ", default="") - parser.add_argument('--tty', help='--tty \"/dev/ttyUSB2\" the serial interface to the AP',default="") - parser.add_argument('--baud', help='--baud \"9600\" AP baud rate for the serial interface',default="9600") + parser.add_argument('--tty', help='--tty \"/dev/ttyUSB2\" the serial interface to the AP', default="") + parser.add_argument('--baud', help='--baud \"9600\" AP baud rate for the serial interface', default="9600") parser.add_argument('--amount_ports_to_reset', help='--amount_ports_to_reset \" \" ', default=None) parser.add_argument('--port_reset_seconds', help='--ports_reset_seconds \" \" ', default="10 30") - parser.add_argument('--lfmgr', help='--lfmgr ',default='localhost') - parser.add_argument('--test_duration', help='--test_duration example --time 5d (5 days) default: 3m options: number followed by d, h, m or s',default='3m') - parser.add_argument('--tos', help='--tos: Support different ToS settings: BK | BE | VI | VO | numeric',default="BE") - parser.add_argument('--debug', help='--debug flag present debug on enable debugging',action='store_true') + parser.add_argument('--lfmgr', help='--lfmgr ', default='localhost') + parser.add_argument( + '--test_duration', + help='--test_duration example --time 5d (5 days) default: 3m options: number followed by d, h, m or s', + default='3m') + parser.add_argument('--tos', help='--tos: Support different ToS settings: BK | BE | VI | VO | numeric', default="BE") + parser.add_argument('--debug', help='--debug flag present debug on enable debugging', action='store_true') parser.add_argument('-t', '--endp_type', help='--endp_type example --endp_type \"lf_udp lf_tcp mc_udp\" Default: lf_udp , options: lf_udp, lf_udp6, lf_tcp, lf_tcp6, mc_udp, mc_udp6', default='lf_udp', type=valid_endp_types) - parser.add_argument('-u', '--upstream_port', help='--upstream_port example: --upstream_port eth1',default='eth1') + parser.add_argument('-u', '--upstream_port', help='--upstream_port example: --upstream_port eth1', default='eth1') parser.add_argument('--downstream_port', help='--downstream_port example: --downstream_port eth2') parser.add_argument('--polling_interval', help="--polling_interval ", default='60s') - parser.add_argument('-r','--radio', action='append', nargs=1, help='--radio \ + parser.add_argument('-r', '--radio', action='append', nargs=1, help='--radio \ \"radio== ssid== ssid_pw== security==\" ') parser.add_argument('--ap_read', help='--ap_read flag present enable reading ap', action='store_true') - parser.add_argument('--ap_port', help='--ap_port \'/dev/ttyUSB0\'',default='/dev/ttyUSB0') - parser.add_argument('--ap_baud', help='--ap_baud \'115200\'',default='115200') + parser.add_argument('--ap_port', help='--ap_port \'/dev/ttyUSB0\'', default='/dev/ttyUSB0') + parser.add_argument('--ap_baud', help='--ap_baud \'115200\'', default='115200') # note wl2 is the 6G interface , check the MAC ifconfig -a of the interface to the AP BSSID connection (default may be eth8) parser.add_argument('--ap_cmd_6g', help='ap_cmd_5g \'wl -i wl2 bs_data\'', default="wl -i wl2 bs_data") # note wl1 is the 5G interface , check the MAC ifconfig -a of the interface to the AP BSSID connection (default may be eth7) @@ -1448,32 +1472,40 @@ python3 .\\test_l3_longevity.py --test_duration 4m --endp_type \"lf_tcp lf_udp m parser.add_argument('--ap_chanim_cmd_6g', help='ap_chanim_cmd_6g \'wl -i wl2 chanim_stats\'', default="wl -i wl2 chanim_stats") parser.add_argument('--ap_chanim_cmd_5g', help='ap_chanim_cmd_5g \'wl -i wl1 chanim_stats\'', default="wl -i wl1 chanim_stats") parser.add_argument('--ap_chanim_cmd_2g', help='ap_chanim_cmd_2g \'w1 -i wl0 chanim_stats\'', default="wl -i wl0 chanim_stats") - parser.add_argument('--ap_scheduler_stats', help='--ap_scheduler_stats flag to clear stats run test then dump ul and dl stats to file', action='store_true') - parser.add_argument('--ap_ofdma_stats', help='--ap_ofdma_stats flag to clear stats run test then dumps wl -i wl1 muinfo -v and wl 0i wl0 muinof -v to file', action='store_true') + parser.add_argument( + '--ap_scheduler_stats', + help='--ap_scheduler_stats flag to clear stats run test then dump ul and dl stats to file', + action='store_true') + parser.add_argument( + '--ap_ofdma_stats', + help='--ap_ofdma_stats flag to clear stats run test then dumps wl -i wl1 muinfo -v and wl 0i wl0 muinof -v to file', + action='store_true') parser.add_argument('--ap_test_mode', help='ap_test_mode flag present use ap canned data', action='store_true') - parser.add_argument('-amr','--side_a_min_bps', + parser.add_argument('-amr', '--side_a_min_bps', help='--side_a_min_bps, requested downstream min tx rate, comma separated list for multiple iterations. Default 256k', default="256000") - parser.add_argument('-amp','--side_a_min_pdu', + parser.add_argument('-amp', '--side_a_min_pdu', help='--side_a_min_pdu, downstream pdu size, comma separated list for multiple iterations. Default MTU', default="MTU") - parser.add_argument('-bmr','--side_b_min_bps', + parser.add_argument('-bmr', '--side_b_min_bps', help='--side_b_min_bps, requested upstream min tx rate, comma separated list for multiple iterations. Default 256000', default="256000") - parser.add_argument('-bmp','--side_b_min_pdu', + parser.add_argument('-bmp', '--side_b_min_pdu', help='--side_b_min_pdu, upstream pdu size, comma separated list for multiple iterations. Default MTU', default="MTU") parser.add_argument("--rates_are_totals", default=False, help="Treat configured rates as totals instead of using the un-modified rate for every connection.", action='store_true') parser.add_argument("--multiconn", default=1, help="Configure multi-conn setting for endpoints. Default is 1 (auto-helper is enabled by default as well).") - parser.add_argument('--attenuators', help='--attenuators, comma separated list of attenuator module eids: shelf.resource.atten-serno.atten-idx', default="") + parser.add_argument( + '--attenuators', + help='--attenuators, comma separated list of attenuator module eids: shelf.resource.atten-serno.atten-idx', + default="") parser.add_argument('--atten_vals', help='--atten_vals, comma separated list of attenuator settings in ddb units (1/10 of db)', default="") influx_add_parser_args(parser) - parser.add_argument("--cap_ctl_out", help="--cap_ctl_out, switch the controller output will be captured", action='store_true') - parser.add_argument("--wait", help="--wait