mirror of
				https://github.com/Telecominfraproject/wlan-lanforge-scripts.git
				synced 2025-10-30 18:27:53 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master'
This commit is contained in:
		| @@ -18,11 +18,13 @@ import time | ||||
| import datetime | ||||
| import subprocess | ||||
| import re | ||||
|  | ||||
| import csv | ||||
| #import operator | ||||
| #import pandas as pd | ||||
|  | ||||
| class L3VariableTimeLongevity(LFCliBase): | ||||
|     def __init__(self, host, port, endp_types, args, tos, side_b, radios, radio_name_list, number_of_stations_per_radio_list, | ||||
|                  ssid_list, ssid_password_list, ssid_security_list, station_lists, name_prefix, debug_on, | ||||
|                  ssid_list, ssid_password_list, ssid_security_list, station_lists, name_prefix, debug_on, outfile, | ||||
|                  side_a_min_rate=56000, side_a_max_rate=0, | ||||
|                  side_b_min_rate=56000, side_b_max_rate=0, | ||||
|                  number_template="00", test_duration="256s", | ||||
| @@ -50,6 +52,14 @@ class L3VariableTimeLongevity(LFCliBase): | ||||
|         self.multicast_profile.name_prefix = "MLT-"; | ||||
|         self.station_profiles = [] | ||||
|         self.args = args | ||||
|         self.outfile = outfile | ||||
|         self.csv_started = False | ||||
|         self.ts = int(time.time()) | ||||
|  | ||||
|         # Full spread-sheet data | ||||
|         if self.outfile is not None: | ||||
|             self.csv_file = open(self.outfile, "w")  | ||||
|             self.csv_writer = csv.writer(self.csv_file, delimiter=",") | ||||
|          | ||||
|         index = 0 | ||||
|         for radio in radios: | ||||
| @@ -73,7 +83,8 @@ class L3VariableTimeLongevity(LFCliBase): | ||||
|         self.cx_profile.side_b_max_bps = side_b_max_rate | ||||
|  | ||||
|     def __get_rx_values(self): | ||||
|         endp_list = self.json_get("endp?fields=name,rx+bytes", debug_=True) | ||||
|         endp_list = self.json_get("endp?fields=name,rx+bytes,rx+drop+%25", debug_=True) | ||||
|         endp_rx_drop_map = {} | ||||
|         endp_rx_map = {} | ||||
|         our_endps = {} | ||||
|         for e in self.multicast_profile.get_mc_names(): | ||||
| @@ -87,24 +98,115 @@ class L3VariableTimeLongevity(LFCliBase): | ||||
|                         for value_name, value_rx in value.items(): | ||||
|                             if value_name == 'rx bytes': | ||||
|                                 endp_rx_map[item] = value_rx | ||||
|         return endp_rx_map | ||||
|                         for value_name, value_rx_drop in value.items(): | ||||
|                             if value_name == 'rx drop %': | ||||
|                                 endp_rx_drop_map[item] = value_rx_drop | ||||
|  | ||||
|         return endp_rx_map, endp_rx_drop_map | ||||
|  | ||||
|     def __record_rx_dropped_percent(self,rx_drop_percent): | ||||
|  | ||||
|         csv_rx_drop_percent_data = [self.ts,'rx_drop_percent'] | ||||
|         csv_performance_values = [] | ||||
|  | ||||
|         # clean up dictionary for only rx values | ||||
|         for key in [key for key in rx_drop_percent if "mtx" in key]: del rx_drop_percent[key] | ||||
|  | ||||
|         filtered_values = [v for _, v in rx_drop_percent.items() if v !=0] | ||||
|         average_rx_drop_percent = sum(filtered_values) / len(filtered_values) if len(filtered_values) != 0 else 0 | ||||
|  | ||||
|         csv_performance_rx_drop_percent_values=sorted(rx_drop_percent.items(), key=lambda x: (x[1],x[0]), reverse=False) | ||||
|         csv_performance_rx_drop_percent_values=self.csv_validate_list(csv_performance_rx_drop_percent_values,5) | ||||
|         for i in range(5): | ||||
|             csv_rx_drop_percent_data.append(str(csv_performance_rx_drop_percent_values[i]).replace(',',';')) | ||||
|         for i in range(-1,-6,-1): | ||||
|             csv_rx_drop_percent_data.append(str(csv_performance_rx_drop_percent_values[i]).replace(',',';')) | ||||
|  | ||||
|         csv_rx_drop_percent_data.append(average_rx_drop_percent) | ||||
|  | ||||
|         for item, value in rx_drop_percent.items(): | ||||
|             print(item, "rx drop percent: ", rx_drop_percent[item]) | ||||
|             csv_rx_drop_percent_data.append(rx_drop_percent[item]) | ||||
|  | ||||
|         self.csv_add_row(csv_rx_drop_percent_data,self.csv_writer,self.csv_file) | ||||
|  | ||||
|     def __compare_vals(self, old_list, new_list): | ||||
|         passes = 0 | ||||
|         expected_passes = 0 | ||||
|         csv_performance_values = [] | ||||
|         csv_rx_headers = [] | ||||
|         csv_rx_delta_dict = {} | ||||
|  | ||||
|         # this may need to be a list as more monitoring takes place. | ||||
|         csv_rx_row_data = [self.ts,'rx'] | ||||
|         csv_rx_delta_row_data = [self.ts,'rx_delta'] | ||||
|  | ||||
|         for key in [key for key in old_list if "mtx" in key]: del old_list[key] | ||||
|         for key in [key for key in new_list if "mtx" in key]: del new_list[key] | ||||
|  | ||||
|         print("rx (ts:{}): calculating worst, best, average".format(self.ts)) | ||||
|         filtered_values = [v for _, v in new_list.items() if v !=0] | ||||
|         average_rx= sum(filtered_values) / len(filtered_values) if len(filtered_values) != 0 else 0 | ||||
|  | ||||
|         csv_performance_values=sorted(new_list.items(), key=lambda x: (x[1],x[0]), reverse=False) | ||||
|         csv_performance_values=self.csv_validate_list(csv_performance_values,5) | ||||
|         for i in range(5): | ||||
|             csv_rx_row_data.append(str(csv_performance_values[i]).replace(',',';')) | ||||
|         for i in range(-1,-6,-1): | ||||
|             csv_rx_row_data.append(str(csv_performance_values[i]).replace(',',';')) | ||||
|  | ||||
|         csv_rx_row_data.append(average_rx) | ||||
|         #print("rx (ts:{}): worst, best, average {}".format(self.ts,csv_rx_row_data)) | ||||
|  | ||||
|         if len(old_list) == len(new_list): | ||||
|             print("rx_delta (ts:{}): calculating worst, best, average".format(self.ts)) | ||||
|             for item, value in old_list.items(): | ||||
|                 expected_passes +=1 | ||||
|                 if item.startswith("mtx"): | ||||
|                     # We ignore the mcast transmitter. | ||||
|                     # This is a hack based on naming and could be improved. | ||||
|                 if new_list[item] > old_list[item]: | ||||
|                     passes += 1 | ||||
|                     print(item, new_list[item], old_list[item], " Difference: ", new_list[item] - old_list[item]) | ||||
|                 else: | ||||
|                     if new_list[item] > old_list[item]: | ||||
|                         passes += 1 | ||||
|                         print(item, new_list[item], old_list[item], " Difference: ", new_list[item] - old_list[item]) | ||||
|                     else: | ||||
|                         print("Failed to increase rx data: ", item, new_list[item], old_list[item]) | ||||
|                     print("Failed to increase rx data: ", item, new_list[item], old_list[item]) | ||||
|                 if not self.csv_started: | ||||
|                     csv_rx_headers.append(item) | ||||
|                 csv_rx_delta_dict.update({item:(new_list[item] - old_list[item])}) | ||||
|                  | ||||
|  | ||||
|             if not self.csv_started: | ||||
|                 csv_header = self.csv_generate_column_headers() | ||||
|                 csv_header += csv_rx_headers | ||||
|                 print(csv_header) | ||||
|                 self.csv_add_column_headers(csv_header) | ||||
|                 self.csv_started = True | ||||
|  | ||||
|             # need to generate list first to determine worst and best | ||||
|             filtered_values = [v for _, v in csv_rx_delta_dict.items() if v !=0] | ||||
|             average_rx_delta= sum(filtered_values) / len(filtered_values) if len(filtered_values) != 0 else 0 | ||||
|  | ||||
|             csv_performance_delta_values=sorted(csv_rx_delta_dict.items(), key=lambda x: (x[1],x[0]), reverse=False) | ||||
|             csv_performance_delta_values=self.csv_validate_list(csv_performance_delta_values,5) | ||||
|             for i in range(5): | ||||
|                 csv_rx_delta_row_data.append(str(csv_performance_delta_values[i]).replace(',',';')) | ||||
|             for i in range(-1,-6,-1): | ||||
|                 csv_rx_delta_row_data.append(str(csv_performance_delta_values[i]).replace(',',';')) | ||||
|  | ||||
|             csv_rx_delta_row_data.append(average_rx_delta) | ||||
|             #print("rx_delta (ts:{}): worst, best, average {}".format(self.ts,csv_rx_delta_row_data)) | ||||
|              | ||||
|             for item, value in old_list.items(): | ||||
|                 expected_passes +=1 | ||||
|                 if new_list[item] > old_list[item]: | ||||
|                     passes += 1 | ||||
|                     print(item, new_list[item], old_list[item], " Difference: ", new_list[item] - old_list[item]) | ||||
|                 else: | ||||
|                     print("Failed to increase rx data: ", item, new_list[item], old_list[item]) | ||||
|                 if not self.csv_started: | ||||
|                     csv_rx_headers.append(item) | ||||
|                 csv_rx_row_data.append(new_list[item]) | ||||
|                 csv_rx_delta_row_data.append(new_list[item] - old_list[item]) | ||||
|  | ||||
|             self.csv_add_row(csv_rx_row_data,self.csv_writer,self.csv_file) | ||||
|             self.csv_add_row(csv_rx_delta_row_data,self.csv_writer,self.csv_file) | ||||
|  | ||||
|             if passes == expected_passes: | ||||
|                 return True | ||||
| @@ -113,7 +215,7 @@ class L3VariableTimeLongevity(LFCliBase): | ||||
|         else: | ||||
|             print("Old-list length: %i  new: %i does not match in compare-vals."%(len(old_list), len(new_list))) | ||||
|             print("old-list:",old_list) | ||||
|             print("new-list:",old_list) | ||||
|             print("new-list:",new_list) | ||||
|             return False | ||||
|  | ||||
|     def verify_controller(self): | ||||
| @@ -177,7 +279,7 @@ class L3VariableTimeLongevity(LFCliBase): | ||||
|  | ||||
|         cur_time = datetime.datetime.now() | ||||
|         print("Getting initial values.") | ||||
|         old_rx_values = self.__get_rx_values() | ||||
|         old_rx_values, rx_drop_percent = self.__get_rx_values() | ||||
|  | ||||
|         end_time = self.local_realm.parse_time(self.test_duration) + cur_time | ||||
|  | ||||
| @@ -186,20 +288,23 @@ class L3VariableTimeLongevity(LFCliBase): | ||||
|         passes = 0 | ||||
|         expected_passes = 0 | ||||
|         while cur_time < end_time: | ||||
|             interval_time = cur_time + datetime.timedelta(minutes=1) | ||||
|             interval_time = cur_time + datetime.timedelta(seconds=60) | ||||
|             while cur_time < interval_time: | ||||
|                 cur_time = datetime.datetime.now() | ||||
|                 time.sleep(1) | ||||
|              | ||||
|             new_rx_values = self.__get_rx_values() | ||||
|             self.ts = int(time.time()) | ||||
|             new_rx_values, rx_drop_percent = self.__get_rx_values() | ||||
|  | ||||
|             expected_passes += 1 | ||||
|             if self.__compare_vals(old_rx_values, new_rx_values): | ||||
|                 passes += 1 | ||||
|             else: | ||||
|                 self._fail("FAIL: Not all stations increased traffic", print_fail) | ||||
|                 break | ||||
|             old_rx_values = new_rx_values | ||||
|  | ||||
|             self.__record_rx_dropped_percent(rx_drop_percent) | ||||
|  | ||||
|             cur_time = datetime.datetime.now() | ||||
|  | ||||
|         if passes == expected_passes: | ||||
| @@ -212,6 +317,7 @@ class L3VariableTimeLongevity(LFCliBase): | ||||
|             for station_name in station_list: | ||||
|                 self.local_realm.admin_down(station_name) | ||||
|  | ||||
|  | ||||
|     def pre_cleanup(self): | ||||
|         self.cx_profile.cleanup_prefix() | ||||
|         self.multicast_profile.cleanup_prefix() | ||||
| @@ -242,16 +348,8 @@ class L3VariableTimeLongevity(LFCliBase): | ||||
|             station_profile.cleanup() | ||||
|                                          | ||||
|     def build(self): | ||||
|         # This is too fragile and limitted, let outside logic configure the upstream port as needed. | ||||
|         #try: | ||||
|         #    eid = self.local_realm.name_to_eid(self.side_b) | ||||
|         #    data = LFUtils.port_dhcp_up_request(eid[1], eid[2]) | ||||
|         #    self.json_post("/cli-json/set_port", data) | ||||
|         #except: | ||||
|         #    print("LFUtils.port_dhcp_up_request didn't complete ") | ||||
|         #    print("or the json_post failed either way {} did not set up dhcp so test may not pass data ".format(self.side_b)) | ||||
|          | ||||
|         index = 0 | ||||
|         total_endp = []  | ||||
|         for station_profile in self.station_profiles: | ||||
|             station_profile.use_security(station_profile.security, station_profile.ssid, station_profile.ssid_pass) | ||||
|             station_profile.set_number_template(station_profile.number_template) | ||||
| @@ -270,8 +368,34 @@ class L3VariableTimeLongevity(LFCliBase): | ||||
|                         print("Creating connections for endpoint type: %s TOS: %s"%(etype, _tos)) | ||||
|                         self.cx_profile.create(endp_type=etype, side_a=station_profile.station_names, side_b=self.side_b, sleep_time=0, tos=_tos) | ||||
|          | ||||
|          | ||||
|         self._pass("PASS: Stations build finished") | ||||
|  | ||||
|     def csv_generate_column_headers(self): | ||||
|         csv_rx_headers = ['Time epoch','Monitor'] | ||||
|         for i in range(1,6): | ||||
|             csv_rx_headers.append("least_rx_data {}".format(i)) | ||||
|         for i in range(1,6): | ||||
|             csv_rx_headers.append("most_rx_data_{}".format(i)) | ||||
|         csv_rx_headers.append("average_rx_data") | ||||
|         return csv_rx_headers | ||||
|  | ||||
|  | ||||
|     def csv_add_column_headers(self,headers): | ||||
|         if self.csv_file is not None: | ||||
|             self.csv_writer.writerow(headers) | ||||
|             self.csv_file.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)) | ||||
|         return csv_list | ||||
|  | ||||
|     def csv_add_row(self,row,writer,csv_file): | ||||
|         if self.csv_file is not None: | ||||
|             writer.writerow(row) | ||||
|             csv_file.flush() | ||||
|  | ||||
| def valid_endp_types(_endp_type): | ||||
|     etypes = _endp_type.split() | ||||
|     for endp_type in etypes: | ||||
| @@ -294,7 +418,7 @@ def main(): | ||||
|         epilog='''\ | ||||
|         Useful Information: | ||||
|             1. Polling interval for checking traffic is fixed at 1 minute | ||||
|             2. The test will exit when traffic has not changed on a station for 1 minute | ||||
|             2. The test will generate csv file  | ||||
|             3. The tx/rx rates are fixed at 256000 bits per second | ||||
|             4. Maximum stations per radio is 64 | ||||
|             ''', | ||||
| @@ -364,6 +488,7 @@ Note:   multiple --radio switches may be entered up to the number of radios avai | ||||
|     parser.add_argument('-t', '--endp_type', help='--endp_type <types of traffic> 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 <cross connect upstream_port> example: --upstream_port eth1',default='eth1') | ||||
|     parser.add_argument('-o','--outfile', help="Output file for csv data", default='longevity_results') | ||||
|  | ||||
|     requiredNamed = parser.add_argument_group('required arguments') | ||||
|     requiredNamed.add_argument('-r', '--radio', action='append', nargs=5, metavar=('<wiphyX>', '<number last station>', '<ssid>', '<ssid password>', 'security'), | ||||
| @@ -387,6 +512,12 @@ Note:   multiple --radio switches may be entered up to the number of radios avai | ||||
|     if args.radio: | ||||
|         radios = args.radio | ||||
|  | ||||
|     if args.outfile != None: | ||||
|         current_time = time.strftime("%m_%d_%Y_%H_%M", time.localtime()) | ||||
|         outfile = "{}_{}.csv".format(args.outfile,current_time) | ||||
|         print("csv output file : {}".format(outfile)) | ||||
|          | ||||
|  | ||||
|     radio_offset = 0 | ||||
|     number_of_stations_offset = 1 | ||||
|     ssid_offset = 2 | ||||
| @@ -444,7 +575,7 @@ Note:   multiple --radio switches may be entered up to the number of radios avai | ||||
|                                    ssid_list=ssid_list, | ||||
|                                    ssid_password_list=ssid_password_list, | ||||
|                                    ssid_security_list=ssid_security_list, test_duration=test_duration, | ||||
|                                    side_a_min_rate=256000, side_b_min_rate=256000, debug_on=debug_on) | ||||
|                                    side_a_min_rate=256000, side_b_min_rate=256000, debug_on=debug_on, outfile=outfile) | ||||
|  | ||||
|     ip_var_test.pre_cleanup() | ||||
|  | ||||
| @@ -458,7 +589,7 @@ Note:   multiple --radio switches may be entered up to the number of radios avai | ||||
|     if not ip_var_test.passes(): | ||||
|         print("stop test failed") | ||||
|         print(ip_var_test.get_fail_message()) | ||||
|         exit(1)  | ||||
|           | ||||
|  | ||||
|     print("Pausing 30 seconds after run for manual inspection before we clean up.") | ||||
|     time.sleep(30) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Logan Lipke
					Logan Lipke