diff --git a/cisco_wifi_ctl.py b/cisco_wifi_ctl.py old mode 100644 new mode 100755 index 6caa9687..725af2fb --- a/cisco_wifi_ctl.py +++ b/cisco_wifi_ctl.py @@ -11,7 +11,11 @@ $ sudo yum install python3-pexpect You might need to install pexpect-serial using pip: $ pip3 install pexpect-serial -./cisco_wifi_ctl.py -d 172.19.27.95 -o 2013 -l stdout -a AxelMain -u cisco -p Cisco123 -s telnet +./cisco_wifi_ctl.py -d 172.19.27.95 -o 2013 -l stdout -a AxelMain -u cisco -p Cisco123 -s telnet + +# For LANforge lab system. +./cisco_wifi_ctl.py --scheme ssh -d 192.168.100.112 -u admin -p Cisco123 --action summary --prompt "\(Cisco Controller\) >" +./cisco_wifi_ctl.py --scheme ssh -d 192.168.100.112 -u admin -p Cisco123 --action cmd --value "show ap config general APA453.0E7B.CF9C" ''' @@ -46,6 +50,7 @@ def usage(): print("$0 used connect to controller:") print("-d|--dest: destination host") print("-o|--port: destination port") + print("--prompt: prompt to expect, ie \"\\(Cisco Controller\\) >\"") print("-u|--user: login name") print("-p|--pass: password") print("-s|--scheme (serial|telnet|ssh): connect via serial, ssh or telnet") @@ -71,6 +76,7 @@ def main(): parser = argparse.ArgumentParser(description="Cisco AP Control Script") parser.add_argument("-d", "--dest", type=str, help="address of the cisco controller") parser.add_argument("-o", "--port", type=int, help="control port on the controller") + parser.add_argument("--prompt", type=str, help="Prompt to expect", default="\(Cisco Controller\) >") parser.add_argument("-u", "--user", type=str, help="credential login/username") parser.add_argument("-p", "--passwd", type=str, help="credential password") parser.add_argument("-s", "--scheme", type=str, choices=["serial", "ssh", "telnet"], help="Connect via serial, ssh or telnet") @@ -187,12 +193,14 @@ def main(): command = None time.sleep(0.1) - CCPROMPT = '\(Voice-Talwar\) >' + CCPROMPT = args.prompt #'\(Voice-Talwar\) >' LOGOUTPROMPT = 'User:' EXITPROMPT = "Would you like to save them now\? \(y/N\)" AREYOUSURE = "Are you sure you want to continue\? \(y/n\)" CLOSEDBYREMOTE = "closed by remote host." CLOSEDCX = "Connection to .* closed." + + logg.info("waiting for prompt: %s"%(CCPROMPT)) egg.expect(CCPROMPT) logg.info("Ap[%s] Action[%s] Value[%s] "%(args.ap, args.action, args.value)) diff --git a/py-json/LANforge/LFRequest.py b/py-json/LANforge/LFRequest.py index de647726..36b59eac 100644 --- a/py-json/LANforge/LFRequest.py +++ b/py-json/LANforge/LFRequest.py @@ -20,8 +20,7 @@ class LFRequest: No_Data = {'No Data':0} requested_url = "" post_data = No_Data - default_headers = { - 'Accept': 'application/json'} + default_headers = { 'Accept': 'application/json'} def __init__(self, url, uri=None, debug_=False, die_on_error_=False): self.debug = debug_ @@ -47,6 +46,8 @@ class LFRequest: # request first url on stack def formPost(self, show_error=True, debug=False, die_on_error_=False): + if self.die_on_error: + die_on_error_ = True if (debug == False) and (self.debug == True): debug = True; responses = [] @@ -87,21 +88,22 @@ class LFRequest: LFUtils.debug_printer.pprint(responses[0].reason) print("------------------------------------------------------------------------") - if (die_on_error_ == True) or (self.die_on_error == True): + if die_on_error_: exit(1) except urllib.error.URLError as uerror: - if (show_error): + if show_error: print("----- LFRequest::formPost:94 URLError: ---------------------------------------------") print("Reason: %s; URL: %s"%(uerror.reason, request.get_full_url())) print("------------------------------------------------------------------------") if (die_on_error_ == True) or (self.die_on_error == True): exit(1) - return None def jsonPost(self, show_error=True, debug=False, die_on_error_=False, response_json_list_=None): if (debug == False) and (self.debug == True): debug = True + if self.die_on_error: + die_on_error_ = True responses = [] if ((self.post_data != None) and (self.post_data is not self.No_Data)): request = urllib.request.Request(url=self.requested_url, @@ -134,7 +136,7 @@ class LFRequest: response_json_list_.append(j) return responses[0] except urllib.error.HTTPError as error: - if show_error: + if show_error or die_on_error_ or (error.code != 404): print("----- LFRequest::jsonPost:138 HTTPError: --------------------------------------------") print("<%s> HTTP %s: %s"%(request.get_full_url(), error.code, error.reason, )) @@ -155,8 +157,8 @@ class LFRequest: print("----- Response: --------------------------------------------------------") LFUtils.debug_printer.pprint(responses[0].reason) print("------------------------------------------------------------------------") - if (die_on_error_ == True) or (self.die_on_error == True): - exit(1) + if die_on_error_ or (error.code != 404): + exit(1) except urllib.error.URLError as uerror: if show_error: print("----- LFRequest::jsonPost:162 URLError: ---------------------------------------------") @@ -167,10 +169,12 @@ class LFRequest: return None def get(self, debug=False, die_on_error_=False): - if (debug == False) and (self.debug == True): + if self.debug == True: debug = True - if (debug): - print("get: url: "+self.requested_url) + if self.die_on_error == True: + die_on_error_ = True + if debug: + print("LFUtils.get: url: "+self.requested_url) myrequest = urllib.request.Request(url=self.requested_url, headers=self.default_headers) myresponses = [] try: @@ -198,14 +202,15 @@ class LFRequest: print("----- Response: --------------------------------------------------------") LFUtils.debug_printer.pprint(myresponses[0].reason) print("------------------------------------------------------------------------") - if (die_on_error_ == True) or (self.die_on_error == True): + if die_on_error_ == True: + # print("--------------------------------------------- s.doe %s v doe %s ---------------------------" % (self.die_on_error, die_on_error_)) exit(1) except urllib.error.URLError as uerror: if debug: print("----- LFRequest::get:205 URLError: ---------------------------------------------") print("Reason: %s; URL: %s"%(uerror.reason, myrequest.get_full_url())) print("------------------------------------------------------------------------") - if (die_on_error_ == True) or (self.die_on_error == True): + if die_on_error_ == True: exit(1) return None @@ -225,4 +230,46 @@ class LFRequest: def addPostData(self, data): self.post_data = data + +def plain_get(url_=None, debug_=False, die_on_error_=False): + myrequest = urllib.request.Request(url=url_) + myresponses = [] + try: + myresponses.append(urllib.request.urlopen(myrequest)) + return myresponses[0] + except urllib.error.HTTPError as error: + if debug_: + print("----- LFRequest::get:181 HTTPError: --------------------------------------------") + print("<%s> HTTP %s: %s"%(myrequest.get_full_url(), error.code, error.reason)) + if error.code != 404: + print("Error: ", sys.exc_info()[0]) + print("Request URL:", myrequest.get_full_url()) + print("Request Content-type:", myrequest.get_header('Content-type')) + print("Request Accept:", myrequest.get_header('Accept')) + print("Request Data:") + LFUtils.debug_printer.pprint(myrequest.data) + + if error.headers: + # the HTTPError is of type HTTPMessage a subclass of email.message + # print(type(error.keys())) + for headername in sorted(error.headers.keys()): + print ("Response %s: %s "%(headername, error.headers.get(headername))) + + if len(myresponses) > 0: + print("----- Response: --------------------------------------------------------") + LFUtils.debug_printer.pprint(myresponses[0].reason) + print("------------------------------------------------------------------------") + if die_on_error_ == True: + # print("--------------------------------------------- s.doe %s v doe %s ---------------------------" % (self.die_on_error, die_on_error_)) + exit(1) + except urllib.error.URLError as uerror: + if debug_: + print("----- LFRequest::get:205 URLError: ---------------------------------------------") + print("Reason: %s; URL: %s"%(uerror.reason, myrequest.get_full_url())) + print("------------------------------------------------------------------------") + if die_on_error_ == True: + exit(1) + return None + + # ~LFRequest diff --git a/py-json/LANforge/LFUtils.py b/py-json/LANforge/LFUtils.py index f6d57a31..1dbd902c 100644 --- a/py-json/LANforge/LFUtils.py +++ b/py-json/LANforge/LFUtils.py @@ -150,8 +150,10 @@ def port_up_request(resource_id, port_name, debug_on=False): debug_printer.pprint(data) return data - def portDownRequest(resource_id, port_name, debug_on=False): + return port_down_request(resource_id, port_name, debug_on) + +def port_down_request(resource_id, port_name, debug_on=False): """ Does not change the use_dhcp flag See http://localhost:8080/help/set_port @@ -185,7 +187,7 @@ def generateMac(parent_mac, random_octet, debug=False): return ":".join(octets) -def portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000): +def portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000, radio=None): """ This produces a named series similar to "sta000, sta001, sta002...sta0(end_id)" the padding_number is added to the start and end numbers and the resulting sum @@ -197,10 +199,10 @@ def portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000) :param padding_number_: :return: """ - return port_name_series(prefix=prefix_, start_id=start_id_, end_id=end_id_, padding_number=padding_number_) + return port_name_series(prefix=prefix_, start_id=start_id_, end_id=end_id_, padding_number=padding_number_, radio=radio) -def port_name_series(prefix="sta", start_id=0, end_id=1, padding_number=10000): +def port_name_series(prefix="sta", start_id=0, end_id=1, padding_number=10000, radio=None): """ This produces a named series similar to "sta000, sta001, sta002...sta0(end_id)" the padding_number is added to the start and end numbers and the resulting sum @@ -212,10 +214,18 @@ def port_name_series(prefix="sta", start_id=0, end_id=1, padding_number=10000): :param padding_number_: used for width of resulting station number :return: list of stations """ + + eid = None + if radio != None: + eid = name_to_eid(radio) + name_list = [] for i in range((padding_number + start_id), (padding_number + end_id + 1)): sta_name = prefix + str(i)[1:] - name_list.append(sta_name) + if eid != None: + name_list.append("%i.%i.%s"%(eid[0], eid[1], sta_name)) + else: + name_list.append(sta_name) return name_list @@ -312,6 +322,9 @@ def waitUntilPortsAdminDown(resource_id=1, base_url="http://localhost:8080", por def waitUntilPortsAdminUp(resource_id=1, base_url="http://localhost:8080", port_list=()): + return wait_until_ports_admin_up(resource_id=resource_id, base_url=base_url, port_list=port_list) + +def wait_until_ports_admin_up(resource_id=1, base_url="http://localhost:8080", port_list=()): print("Waiting until ports appear admin-up...") down_stations = port_list.copy() sleep(1) @@ -324,7 +337,7 @@ def waitUntilPortsAdminUp(resource_id=1, base_url="http://localhost:8080", port_ lf_r = LFRequest.LFRequest(base_url, uri) json_response = lf_r.getAsJson(debug_=False) if json_response == None: - print("port %s disappeared" % port_name) + print("port %s appeared" % port_name) continue if "interface" in json_response: json_response = json_response['interface'] @@ -333,18 +346,24 @@ def waitUntilPortsAdminUp(resource_id=1, base_url="http://localhost:8080", port_ sleep(1) return None -def waitUntilPortsDisappear(resource_id=1, base_url="http://localhost:8080", port_list=[], debug=False): - wait_until_ports_disappear(resource_id, base_url, port_list, debug) +def waitUntilPortsDisappear(base_url="http://localhost:8080", port_list=[], debug=False): + wait_until_ports_disappear(base_url, port_list, debug) -def wait_until_ports_disappear(resource_id=1, base_url="http://localhost:8080", port_list=[], debug=False): +def wait_until_ports_disappear(base_url="http://localhost:8080", port_list=[], debug=False): print("Waiting until ports disappear...") url = "/port/1" found_stations = port_list.copy() - sleep(1) + while len(found_stations) > 0: found_stations = [] sleep(1) - for port_name in port_list: + + for port_eid in port_list: + eid = name_to_eid(port_eid) + shelf = eid[0] + resource_id = eid[1] + port_name = eid[2] + check_url = "%s/%s/%s" % (url, resource_id, port_name) if debug: print("checking:" + check_url) @@ -355,40 +374,59 @@ def wait_until_ports_disappear(resource_id=1, base_url="http://localhost:8080", return -def waitUntilPortsAppear(resource_id=1, base_url="http://localhost:8080", port_list=(), debug=False): +def waitUntilPortsAppear(base_url="http://localhost:8080", port_list=(), debug=False): """ Deprecated - :param resource_id: :param base_url: :param port_list: :param debug: :return: """ - return wait_until_ports_appear(resource_id, base_url, port_list, debug=debug) + return wait_until_ports_appear(base_url, port_list, debug=debug) -def wait_until_ports_appear(resource_id=1, base_url="http://localhost:8080", port_list=(), debug=False): +def name_to_eid(eid): + rv = [1, 1, ""]; + info = [] + if (eid is None) or (eid == ""): + raise ValueError("name_to_eid wants eid like 1.1.sta0 but given[%s]" % eid) + + info = eid.split('.') + if (len(info) == 1): + rv[2] = info[0]; # just port name + if len(info) == 2: # resource.port-name + rv[1] = int(info[0]) + rv[2] = info[1] + if len(info) == 3: # shelf.resource.port-name + rv[0] = int(info[0]) + rv[1] = int(info[1]) + rv[2] = info[2] + + return rv; + +def wait_until_ports_appear(base_url="http://localhost:8080", port_list=(), debug=False): """ - :param resource_id: :param base_url: :param port_list: :param debug: :return: """ - print("Waiting until ports appear...") found_stations = [] - sleep(2) port_url = "/port/1" - ncshow_url = "/cli-form/nc_show_ports" + ncshow_url = "/cli-json/nc_show_ports" if base_url.endswith('/'): port_url = port_url[1:] ncshow_url = ncshow_url[1:] while len(found_stations) < len(port_list): found_stations = [] - for port_name in port_list: - sleep(1) + for port_eid in port_list: + eid = name_to_eid(port_eid) + shelf = eid[0] + resource_id = eid[1] + port_name = eid[2] + uri = "%s/%s/%s" % (port_url, resource_id, port_name) lf_r = LFRequest.LFRequest(base_url, uri) json_response = lf_r.getAsJson(debug_=False) @@ -396,9 +434,52 @@ def wait_until_ports_appear(resource_id=1, base_url="http://localhost:8080", por found_stations.append(port_name) else: lf_r = LFRequest.LFRequest(base_url, ncshow_url) - lf_r.addPostData({"shelf": 1, "resource": resource_id, "port": port_name, "flags": 1}) + lf_r.addPostData({"shelf": shelf, "resource": resource_id, "port": port_name, "probe_flags": "1"}) + lf_r.jsonPost() + if (len(found_stations) < len(port_list)): + sleep(2) + + if debug: + print("These stations appeared: " + ", ".join(found_stations)) + return + +def wait_until_endps(base_url="http://localhost:8080", endp_list=(), debug=False): + """ + + :param base_url: + :param port_list: + :param debug: + :return: + """ + print("Waiting until endpoints appear...") + found_endps = [] + port_url = "/port/1" + ncshow_url = "/cli-form/show_endp" + if base_url.endswith('/'): + port_url = port_url[1:] + ncshow_url = ncshow_url[1:] + + while len(found_stations) < len(port_list): + found_stations = [] + for port_eid in port_list: + + eid = name_to_eid(port_eid) + shelf = eid[0] + resource_id = eid[1] + port_name = eid[2] + + uri = "%s/%s/%s" % (port_url, resource_id, port_name) + lf_r = LFRequest.LFRequest(base_url, uri) + json_response = lf_r.getAsJson(debug_=False) + if (json_response != None): + found_stations.append(port_name) + else: + lf_r = LFRequest.LFRequest(base_url, ncshow_url) + lf_r.addPostData({"shelf": shelf, "resource": resource_id, "port": port_name, "flags": 1}) lf_r.formPost() - sleep(2) + if (len(found_stations) < len(port_list)): + sleep(2) + if debug: print("These stations appeared: " + ", ".join(found_stations)) return diff --git a/py-json/LANforge/add_vap.py b/py-json/LANforge/add_vap.py new file mode 100644 index 00000000..8797b1ac --- /dev/null +++ b/py-json/LANforge/add_vap.py @@ -0,0 +1,30 @@ +add_vap_flags = { +"enable_wpa" : 0x10, # Enable WPA +"hostapd_config" : 0x20, # Use Custom hostapd config file. +"enable_80211d" : 0x40, # Enable 802.11D to broadcast country-code & channels in VAPs +"short_preamble" : 0x80, # Allow short-preamble +"pri_sec_ch_enable" : 0x100, # Enable Primary/Secondary channel switch. +"wep_enable" : 0x200, # Enable WEP Encryption +"wpa2_enable" : 0x400, # Enable WPA2 Encryption +"disable_ht40" : 0x800, # Disable HT-40 (will use HT-20 if available). +"verbose" : 0x10000, # Verbose-Debug: Increase debug info in wpa-supplicant and hostapd logs. +"80211u_enable" : 0x20000, # Enable 802.11u (Interworking) feature. +"80211u_auto" : 0x40000, # Enable 802.11u (Interworking) Auto-internetworking feature. Always enabled currently. +"80211u_gw" : 0x80000, # AP Provides access to internet (802.11u Interworking) +"80211u_additional" : 0x100000, # AP requires additional step for access (802.11u Interworking) +"80211u_e911" : 0x200000, # AP claims emergency services reachable (802.11u Interworking) +"80211u_e911_unauth" : 0x400000, # AP provides Unauthenticated emergency services (802.11u Interworking) +"hs20_enable" : 0x800000, # Enable Hotspot 2.0 (HS20) feature. Requires WPA-2. +"disable_dgaf" : 0x1000000, # AP Disable DGAF (used by HotSpot 2.0). +"8021x_radius" : 0x2000000, # Use 802.1x (RADIUS for AP). +"80211r_pmska_cache" : 0x4000000, # Enable oportunistic PMSKA caching for WPA2 (Related to 802.11r). +"disable_ht80" : 0x8000000, # Disable HT80 (for AC chipset NICs only) +"80211h_enable" : 0x10000000, # Enable 802.11h (needed for running on DFS channels) Requires 802.11d. +"osen_enable" : 0x40000000, # Enable OSEN protocol (OSU Server-only Authentication) +"ht160_enable" : 0x100000000, # Enable HT160 mode. +"create_admin_down" : 0x1000000000, # Station should be created admin-down. +"use-wpa3" : 0x10000000000, # Enable WPA-3 (SAE Personal) mode. +"use-bss-load" : 0x20000000000, # Enable BSS Load IE in Beacons and Probe Responses (.11e). +"use-rrm-report" : 0x40000000000, # Enable Radio measurements IE in beacon and probe responses. +"use-bss-transition" : 0x80000000000, # Enable BSS transition. +} diff --git a/py-json/LANforge/lfcli_base.py b/py-json/LANforge/lfcli_base.py index 9e382f7a..da027ce8 100644 --- a/py-json/LANforge/lfcli_base.py +++ b/py-json/LANforge/lfcli_base.py @@ -6,14 +6,14 @@ from pprint import pprint import LANforge.LFUtils from LANforge.LFUtils import * +import argparse class LFCliBase: # do not use `super(LFCLiBase,self).__init__(self, host, port, _debug) # that is py2 era syntax and will force self into the host variable, making you # very confused. - def __init__(self, _lfjson_host, _lfjson_port, _debug=False, _halt_on_error=False, _exit_on_error=False, - _exit_on_fail=False): + def __init__(self, _lfjson_host, _lfjson_port, _debug=False, _halt_on_error=False, _exit_on_error=False, _exit_on_fail=False): self.fail_pref = "FAILED: " self.pass_pref = "PASSED: " self.lfclient_host = _lfjson_host @@ -71,9 +71,9 @@ class LFCliBase: lf_r.addPostData(_data) if debug_ or self.debug: LANforge.LFUtils.debug_printer.pprint(_data) - json_response = lf_r.jsonPost(show_error=self.debug, \ - debug=(self.debug or debug_), \ - response_json_list_=response_json_list_, \ + json_response = lf_r.jsonPost(show_error=self.debug, + debug=(self.debug or debug_), + response_json_list_=response_json_list_, die_on_error_=self.exit_on_error) if debug_ and (response_json_list_ is not None): pprint.pprint(response_json_list_) @@ -94,10 +94,11 @@ class LFCliBase: json_response = None try: lf_r = LFRequest.LFRequest(self.lfclient_url, _req_url, debug_=(self.debug or debug_), die_on_error_=self.exit_on_error) - json_response = lf_r.getAsJson(self.debug) + json_response = lf_r.getAsJson(debug_=self.debug, die_on_error_=self.halt_on_error) #debug_printer.pprint(json_response) if (json_response is None) and (self.debug or debug_): - raise ValueError(json_response) + print("LFCliBase.json_get: no entity/response, probabily status 404") + return None except ValueError as ve: if self.debug or self.halt_on_error or self.exit_on_error: print("jsonGet asked for " + _req_url) @@ -139,7 +140,6 @@ class LFCliBase: return reverse_map - def error(self, exception): # print("lfcli_base error: %s" % exception) pprint.pprint(exception) @@ -197,7 +197,7 @@ class LFCliBase: # use this inside the class to log a failure result def _fail(self, message, print_=False): self.test_results.append(self.fail_pref + message) - if print_: + if print_ or self.exit_on_fail: print(self.fail_pref + message) if self.exit_on_fail: sys.exit(1) @@ -208,4 +208,22 @@ class LFCliBase: if print_: print(self.pass_pref + message) + @staticmethod + def create_basic_argparse(prog=None, formatter_class=None, epilog=None, description=None): + if prog is not None or formatter_class is not None or epilog is not None or description is not None: + parser = argparse.ArgumentParser(prog=prog, formatter_class=formatter_class, epilog=epilog, + description=description) + else: + parser = argparse.ArgumentParser() + + parser.add_argument('--mgr', help='--mgr ', default='localhost') + parser.add_argument('-u', '--upstream_port', help='--upstream_port <1.eth1, etc>', default='1.eth1') + parser.add_argument('--radio', help='--radio ', default='wiphy2') + parser.add_argument('--ssid', help='--ssid ', default='jedway-wpa2-160') + parser.add_argument('--passwd', help='--passwd ', default='jedway-wpa2-160') + parser.add_argument('--security', help='--security ', default='wpa2') + parser.add_argument('--debug', help='--debug: Enable debugging', default=False, action="store_true") + + return parser + # ~class diff --git a/py-json/realm.py b/py-json/realm.py index 17088919..6c09b58c 100755 --- a/py-json/realm.py +++ b/py-json/realm.py @@ -8,6 +8,7 @@ from LANforge import LFUtils from LANforge import set_port from LANforge import add_sta from LANforge import lfcli_base +from LANforge import add_vap from LANforge.lfcli_base import LFCliBase from generic_cx import GenericCx from LANforge import add_monitor @@ -21,6 +22,217 @@ class Realm(LFCliBase): # self.lfclient_url = "http://%s:%s" % (lfclient_host, lfclient_port) self.debug = debug_ self.check_connect() + self.chan_to_freq = {} + self.freq_to_chan = {} + freq = 0 + chan = 1 + for freq in range( 2412, 2472, 5): + self.freq_to_chan[freq] = chan + self.chan_to_freq[chan] = freq + chan += 1 + + self.chan_to_freq[14] = 2484 + self.chan_to_freq[34] = 5170 + self.chan_to_freq[36] = 5180 + self.chan_to_freq[38] = 5190 + self.chan_to_freq[40] = 5200 + self.chan_to_freq[42] = 5210 + self.chan_to_freq[44] = 5220 + self.chan_to_freq[46] = 5230 + self.chan_to_freq[48] = 5240 + self.chan_to_freq[52] = 5260 + self.chan_to_freq[56] = 5280 + self.chan_to_freq[60] = 5300 + self.chan_to_freq[64] = 5320 + self.chan_to_freq[100] = 5500 + self.chan_to_freq[104] = 5520 + self.chan_to_freq[108] = 5540 + self.chan_to_freq[112] = 5560 + self.chan_to_freq[116] = 5580 + self.chan_to_freq[120] = 5600 + self.chan_to_freq[124] = 5620 + self.chan_to_freq[128] = 5640 + self.chan_to_freq[132] = 5660 + self.chan_to_freq[136] = 5680 + self.chan_to_freq[140] = 5700 + self.chan_to_freq[144] = 5720 + self.chan_to_freq[149] = 5745 + self.chan_to_freq[153] = 5765 + self.chan_to_freq[157] = 5785 + self.chan_to_freq[161] = 5805 + self.chan_to_freq[165] = 5825 + self.chan_to_freq[169] = 5845 + self.chan_to_freq[173] = 5865 + + self.freq_to_chan[2484] = 14 + self.freq_to_chan[5170] = 34 + self.freq_to_chan[5180] = 36 + self.freq_to_chan[5190] = 38 + self.freq_to_chan[5200] = 40 + self.freq_to_chan[5210] = 42 + self.freq_to_chan[5220] = 44 + self.freq_to_chan[5230] = 46 + self.freq_to_chan[5240] = 48 + self.freq_to_chan[5260] = 52 + self.freq_to_chan[5280] = 56 + self.freq_to_chan[5300] = 60 + self.freq_to_chan[5320] = 64 + self.freq_to_chan[5500] = 100 + self.freq_to_chan[5520] = 104 + self.freq_to_chan[5540] = 108 + self.freq_to_chan[5560] = 112 + self.freq_to_chan[5580] = 116 + self.freq_to_chan[5600] = 120 + self.freq_to_chan[5620] = 124 + self.freq_to_chan[5640] = 128 + self.freq_to_chan[5660] = 132 + self.freq_to_chan[5680] = 136 + self.freq_to_chan[5700] = 140 + self.freq_to_chan[5720] = 144 + self.freq_to_chan[5745] = 149 + self.freq_to_chan[5765] = 153 + self.freq_to_chan[5785] = 157 + self.freq_to_chan[5805] = 161 + self.freq_to_chan[5825] = 165 + self.freq_to_chan[5845] = 169 + self.freq_to_chan[5865] = 173 + + # 4.9Ghz police band + self.chan_to_freq[183] = 4915 + self.chan_to_freq[184] = 4920 + self.chan_to_freq[185] = 4925 + self.chan_to_freq[187] = 4935 + self.chan_to_freq[188] = 4940 + self.chan_to_freq[189] = 4945 + self.chan_to_freq[192] = 4960 + self.chan_to_freq[194] = 4970 + self.chan_to_freq[196] = 4980 + + self.freq_to_chan[4915] = 183 + self.freq_to_chan[4920] = 184 + self.freq_to_chan[4925] = 185 + self.freq_to_chan[4935] = 187 + self.freq_to_chan[4940] = 188 + self.freq_to_chan[4945] = 189 + self.freq_to_chan[4960] = 192 + self.freq_to_chan[4970] = 194 + self.freq_to_chan[4980] = 196 + + def wait_until_ports_appear(self, sta_list=None, debug_=False): + if (sta_list is None) or (len(sta_list) < 1): + print("realm.wait_until_ports_appear: no stations provided") + return + LFUtils.wait_until_ports_appear(base_url=self.lfclient_url, + port_list=sta_list, + debug=debug_) + + def rm_port(self, port_eid, check_exists=True): + req_url = "/cli-json/rm_vlan" + eid = self.name_to_eid(port_eid) + do_rm = True; + if check_exists: + if not self.port_exists(port_eid): + do_rm = False + if do_rm: + data = { + "shelf": eid[0], + "resource": eid[1], + "port": eid[2] + } + rsp = self.json_post(req_url, data, debug_=self.debug) + return True + return False + + def port_exists(self, port_eid): + data = {} + eid = self.name_to_eid(port_eid) + data["shelf"] = eid[0] + data["resource"] = eid[1] + data["port"] = eid[2] + current_stations = self.json_get("/port/%s/%s/%s?fields=alias" % (eid[0], eid[1], eid[2])) + if not current_stations is None: + return True + return False + + def admin_up(self, port_eid): + eid = self.name_to_eid(port_eid) + shelf = eid[0] + resource = eid[1] + port = eid[2] + request = LFUtils.port_up_request(resource_id=resource, port_name=port) + self.json_post("/cli-json/set_port", request) + + def admin_down(self, port_eid): + eid = self.name_to_eid(port_eid) + shelf = eid[0] + resource = eid[1] + port = eid[2] + request = LFUtils.port_down_request(resource_id=resource, port_name=port) + self.json_post("/cli-json/set_port", request) + + def rm_cx(self, cx_name): + req_url = "cli-json/rm_cx" + data = { + "test_mgr": "ALL", + "cx_name": cx_name + } + self.json_post(req_url, data) + + def rm_endp(self, ename, debug_=False, suppress_related_commands_=True): + req_url = "cli-json/rm_endp" + data = { + "endp_name": ename + } + self.json_post(req_url, data, debug_=debug_, suppress_related_commands_=suppress_related_commands_) + + def set_endp_tos(self, ename, _tos, debug_=False, suppress_related_commands_=True): + req_url = "cli-json/set_endp_tos" + tos = _tos; + # Convert some human readable values to numeric needed by LANforge. + if _tos == "BK": + tos = "64" + if _tos == "BE": + tos = "96" + if _tos == "VI": + tos = "128" + if _tos == "VO": + tos = "192" + data = { + "name": ename, + "tos": tos + } + self.json_post(req_url, data, debug_=debug_, suppress_related_commands_=suppress_related_commands_) + + def stop_cx(self, cx_name): + self.json_post("/cli-json/set_cx_state", { + "test_mgr": "ALL", + "cx_name": cx_name, + "cx_state": "STOPPED" + }, debug_=self.debug) + + def cleanup_cxe_prefix(self, prefix): + cx_list = self.cx_list() + if cx_list is not None: + for cx_name in cx_list: + if cx_name.startswith(prefix): + self.rm_cx(cx_name) + + endp_list = self.json_get("/endp/list") + if endp_list is not None: + if 'endpoint' in endp_list: + endp_list = list(endp_list['endpoint']) + for idx in range(len(endp_list)): + endp_name = list(endp_list[idx])[0] + if endp_name.startswith(prefix): + self.rm_endp(endp_name) + else: + print("cleanup_cxe_prefix no endpoints: endp_list{}".format(endp_list) ) + + def channel_freq(self, channel_=0): + return self.chan_to_freq[channel_] + + def freq_channel(self, freq_=0): + return self.freq_to_chan[freq_] # checks for OK or BUSY when querying cli-json/cv+is_built def wait_while_building(self, debug_=False): @@ -61,9 +273,66 @@ class Realm(LFCliBase): # Returns json response from webpage of all layer 3 cross connects def cx_list(self): - response = super().json_get("/cx") + response = self.json_get("/cx/list") return response + def waitUntilEndpsAppear(self, these_endp, debug=False): + return self.wait_until_endps_appear(these_endp, debug=debug) + + def wait_until_endps_appear(self, these_endp, debug=False): + wait_more = True; + count = 0 + while wait_more: + time.sleep(1) + wait_more = False + endp_list = self.json_get("/endp/list") + found_endps = {} + if (endp_list is not None) and ("items" not in endp_list): + endp_list = list(endp_list['endpoint']) + for idx in range(len(endp_list)): + name = list(endp_list[idx])[0] + found_endps[name] = name + + for req in these_endp: + if not req in found_endps: + if debug: + print("Waiting on endpoint: %s"%(req)) + wait_more = True + count += 1 + if (count > 100): + break + + return not wait_more + + def waitUntilCxsAppear(self, these_cx, debug=False): + return self.wait_until_cxs_appear(these_cx, debug=debug) + + def wait_until_cxs_appear(self, these_cx, debug=False): + wait_more = True; + count = 0 + while wait_more: + time.sleep(1) + wait_more = False + found_cxs = {} + cx_list = self.cx_list() + not_cx = ['warnings', 'errors', 'handler', 'uri', 'items'] + if cx_list is not None: + for cx_name in cx_list: + if cx_name in not_cx: + continue + found_cxs[cx_name] = cx_name + + for req in these_cx: + if not req in found_cxs: + if debug: + print("Waiting on CX: %s"%(req)) + wait_more = True + count += 1 + if (count > 100): + break + + return not wait_more + # Returns map of all stations with port+type == WIFI-STATION def station_map(self): response = super().json_get("/port/list?fields=_links,alias,device,port+type") @@ -192,60 +461,61 @@ class Realm(LFCliBase): return matched_map def name_to_eid(self, eid): - info = [] - if (eid is None) or (eid == "") or ('.' not in eid): - raise ValueError("name_to_eid wants eid like 1.1.sta0 but given[%s]" % eid) + return LFUtils.name_to_eid(eid) - info = eid.split('.') - info[0] = int(info[0]) - if len(info) == 3: - info[1] = int(info[1]) - return info - return [1, int(info[0]), info[1]] + def wait_for_ip(self, station_list=None, ipv4=True, ipv6=False, timeout_sec=60, debug=False): + print("Waiting for ips, timeout: %i..."%(timeout_sec)) + #print(station_list) - def wait_for_ip(self, resource, station_list, ipv6=False): - num_ports = 0 - num_ips = 0 - print("Waiting for ips...") - response = super().json_get("/port/1/%s/%s?fields=alias,ip,port+type" % (resource, ",".join(station_list))) - if (response is None) or ("interfaces" not in response): - print("station_list: incomplete response:") - pprint(response) - exit(1) + if (station_list is None) or (len(station_list) < 1): + raise ValueError("wait_for_ip: expects non-empty list of ports") - for x in range(len(response['interfaces'])): - for k, v in response['interfaces'][x].items(): - if "wlan" not in v['alias'] and v['port type'] == "WIFI-STA" \ - or v['port type'] == "Ethernet": - num_ports += 1 - if ipv6: - num_ports -= 1 # Prevents eth0 from being counted, preventing infinite loop + wait_more = True + while wait_more and timeout_sec != 0: + wait_more = False - while num_ips != num_ports: - num_ips = 0 - response = super().json_get("/port/1/%s/%s?fields=alias,ip,port+type,ipv6+address" % - (resource, ",".join(station_list))) - if (response is None) or ("interfaces" not in response): - print("station_list: incomplete response:") - pprint(response) - exit(1) + for sta_eid in station_list: + if debug: + print("checking sta-eid: %s"%(sta_eid)) + eid = self.name_to_eid(sta_eid) - if not ipv6: - for x in range(len(response['interfaces'])): - for k, v in response['interfaces'][x].items(): - if "wlan" not in v['alias'] and v['port type'] == "WIFI-STA" or v['port type'] == "Ethernet": - if v['ip'] != '0.0.0.0': - num_ips += 1 - time.sleep(1) - if ipv6: - for x in range(len(response['interfaces'])): - for k, v in response['interfaces'][x].items(): - if v['alias'] != "eth0" and "wlan" not in v['alias'] and v['port type'] == "WIFI-STA" \ - or v['port type'] == "Ethernet": - if v['ipv6 address'] != 'DELETED' and not v['ipv6 address'].startswith('fe80') \ - and v['ipv6 address'] != 'AUTO': - num_ips += 1 + response = super().json_get("/port/%s/%s/%s?fields=alias,ip,port+type,ipv6+address" % + (eid[0], eid[1], eid[2])) + #pprint(response) + + if (response is None) or ("interface" not in response): + print("station_list: incomplete response:") + pprint(response) + wait_more = True + break + + if ipv4: + v = response['interface'] + if v['ip'] == '0.0.0.0': + wait_more = True + if debug: + print("Waiting for port %s to get IPv4 Address."%(sta_eid)) + else: + if debug: + print("Found IP: %s on port: %s"%(v['ip'], sta_eid)) + + if ipv6: + v = response['interface'] + print(v) + if v['ipv6 address'] != 'DELETED' and not v['ipv6 address'].startswith('fe80') \ + and v['ipv6 address'] != 'AUTO': + if debug: + print("Found IPv6: %s on port: %s" % (v['ipv6 address'], sta_eid)) + else: + wait_more = True + if debug: + print("Waiting for port %s to get IPv6 Address."%(sta_eid)) + + if wait_more: time.sleep(1) + timeout_sec -= 1 + + return not wait_more def parse_time(self, time_string): if isinstance(time_string, str): @@ -287,8 +557,10 @@ class Realm(LFCliBase): self.json_post(req_url, data) def remove_all_endps(self): - endp_list = self.json_get("/endp") - if endp_list is not None: + endp_list = self.json_get("/endp/list") + if "items" in endp_list or "empty" in endp_list: + return + if endp_list is not None or endp_list : print("Removing all endps") endp_list = list(endp_list['endpoint']) for endp_name in range(len(endp_list)): @@ -304,19 +576,22 @@ class Realm(LFCliBase): # remove endpoints # nc show endpoints # nc show cross connects - cx_list = list(self.cx_list()) - not_cx = ['warnings', 'errors', 'handler', 'uri', 'items'] - if cx_list is not None: - print("Removing all cxs") - for cx_name in cx_list: - if cx_name in not_cx: - continue - req_url = "cli-json/rm_cx" - data = { - "test_mgr": "default_tm", - "cx_name": cx_name - } - self.json_post(req_url, data) + try: + cx_list = list(self.cx_list()) + not_cx = ['warnings', 'errors', 'handler', 'uri', 'items', 'empty'] + if cx_list is not None: + print("Removing all cxs") + for cx_name in cx_list: + if cx_name in not_cx: + continue + req_url = "cli-json/rm_cx" + data = { + "test_mgr": "default_tm", + "cx_name": cx_name + } + self.json_post(req_url, data) + except: + print("no cxs to remove") if remove_all_endpoints: self.remove_all_endps() @@ -336,12 +611,28 @@ class Realm(LFCliBase): info = () def new_station_profile(self): - station_prof = StationProfile(self.lfclient_url, local_realm=self, debug_=self.debug) + station_prof = StationProfile(self.lfclient_url, local_realm=self, debug_=self.debug, up=False) return station_prof + # just here for now for initial coding, move later to correct spot + def new_multicast_profile(self): + multi_prof = MULTICASTProfile(self.lfclient_host, self.lfclient_port, \ + local_realm=self, debug_=self.debug, report_timer_=3000) + return multi_prof + + def new_wifi_monitor_profile(self, resource_=1, debug_=False, up_=False): + wifi_mon_prof = WifiMonitor(self.lfclient_url, + local_realm=self, + resource_=resource_, + up=up_, + debug_=(self.debug or debug_)) + return wifi_mon_prof def new_l3_cx_profile(self): - cx_prof = L3CXProfile(self.lfclient_host, self.lfclient_port, \ - local_realm=self, debug_=self.debug, report_timer_=3000) + cx_prof = L3CXProfile(self.lfclient_host, + self.lfclient_port, + local_realm=self, + debug_=self.debug, + report_timer_=3000) return cx_prof def new_l4_cx_profile(self): @@ -349,10 +640,190 @@ class Realm(LFCliBase): return cx_prof def new_generic_cx_profile(self): - cx_prof = GenCXProfile(self.lfclient_host, self.lfclient_port,local_realm=self, debug_=self.debug) + cx_prof = GenCXProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug) return cx_prof + def new_vap_profile(self): + vap_prof = VAPProfile(lfclient_url=self.lfclient_url, local_realm=self, debug_=self.debug) + return vap_prof +class MULTICASTProfile(LFCliBase): + def __init__(self, lfclient_host, lfclient_port, local_realm, + report_timer_=3000, name_prefix_="Unset", number_template_="00000", debug_=False): + """ + + :param lfclient_host: + :param lfclient_port: + :param local_realm: + :param name_prefix: prefix string for connection + :param number_template_: how many zeros wide we padd, possibly a starting integer with left padding + :param debug_: + """ + super().__init__(lfclient_host, lfclient_port, debug_, _halt_on_error=True) + self.lfclient_url = "http://%s:%s" % (lfclient_host, lfclient_port) + self.debug = debug_ + self.local_realm = local_realm + self.report_timer = report_timer_ + self.created_mc = {} + self.name_prefix = name_prefix_ + self.number_template = number_template_ + + def get_mc_names(self): + return self.created_mc.keys() + + def refresh_mc(self, debug_=False): + for endp_name in self.get_mc_names(): + self.json_post("/cli-json/show_endpoints", { + "endpoint": endp_name + }, debug_=debug_) + + def start_mc(self, suppress_related_commands=None, debug_ = False): + if self.debug: + debug_=True + + for endp_name in self.get_mc_names(): + print("Starting mcast endpoint: %s"%(endp_name)) + json_data = { + "endp_name":endp_name + } + url = "cli-json/start_endp" + self.local_realm.json_post(url, json_data, debug_=debug_, suppress_related_commands_=suppress_related_commands) + + pass + + def stop_mc(self, suppress_related_commands=None, debug_ = False): + if self.debug: + debug_=True + + for endp_name in self.get_mc_names(): + json_data = { + "endp_name":endp_name + } + url = "cli-json/stop_endp" + self.local_realm.json_post(url, json_data, debug_=debug_, suppress_related_commands_=suppress_related_commands) + + pass + + def cleanup_prefix(self): + self.local_realm.cleanup_cxe_prefix(self.name_prefix) + + def cleanup(self, suppress_related_commands=None, debug_ = False): + if self.debug: + debug_=True + + for endp_name in self.get_mc_names(): + self.local_realm.rm_endp(endp_name, debug_=debug_, suppress_related_commands_=suppress_related_commands) + + def create_mc_tx(self, endp_type, side_tx, suppress_related_commands=None, debug_=False): + if self.debug: + debug_=True + + side_tx_info = self.local_realm.name_to_eid(side_tx) + side_tx_shelf = side_tx_info[0] + side_tx_resource = side_tx_info[1] + side_tx_port = side_tx_info[2] + side_tx_name = "%smtx-%s-%i"%(self.name_prefix, side_tx_port, len(self.created_mc)) + + json_data = [] + + #add_endp mcast-xmit-sta 1 1 side_tx mc_udp -1 NO 4000000 0 NO 1472 0 INCREASING NO 32 0 0 + json_data = { + 'alias':side_tx_name, + 'shelf':side_tx_shelf, + 'resource':side_tx_resource, + 'port':side_tx_port, + 'type':endp_type, + 'ip_port':-1, + 'is_rate_bursty': + 'NO','min_rate':256000, + 'max_rate':0, + 'is_pkt_sz_random':'NO', + 'min_pkt':1472, + 'max_pkt':0, + 'payload_pattern':'INCREASING', + 'use_checksum':'NO', + 'ttl':32, + 'send_bad_crc_per_million':0, + 'multi_conn':0 + } + + url = "/cli-json/add_endp" + self.local_realm.json_post(url, json_data, debug_=debug_, suppress_related_commands_=suppress_related_commands) + + #set_mc_endp mcast-xmit-sta 32 224.9.9.9 9999 No # critical + json_data = { + 'name':side_tx_name, + 'ttl':32, + 'mcast_group':'224.9.9.9', + 'mcast_dest_port':9999, + 'rcv_mcast':'No' + } + + url = "cli-json/set_mc_endp" + self.local_realm.json_post(url, json_data, debug_=debug_, suppress_related_commands_=suppress_related_commands) + + self.created_mc[side_tx_name] = side_tx_name + + these_endp = [side_tx_name] + self.local_realm.wait_until_endps_appear(these_endp, debug=debug_) + + + def create_mc_rx(self, endp_type, side_rx, suppress_related_commands=None, debug_ = False): + if self.debug: + debug_=True + + these_endp = [] + + for port_name in side_rx: + side_rx_info = self.local_realm.name_to_eid(port_name) + side_rx_shelf = side_rx_info[0] + side_rx_resource = side_rx_info[1] + side_rx_port = side_rx_info[2] + side_rx_name = "%smrx-%s-%i"%(self.name_prefix, side_rx_port, len(self.created_mc)) + # add_endp mcast-rcv-sta-001 1 1 sta0002 mc_udp 9999 NO 0 0 NO 1472 0 INCREASING NO 32 0 0 + json_data = { + 'alias':side_rx_name, + 'shelf':side_rx_shelf, + 'resource':side_rx_resource, + 'port':side_rx_port, + 'type':endp_type, + 'ip_port':9999, + 'is_rate_bursty':'NO', + 'min_rate':0, + 'max_rate':0, + 'is_pkt_sz_random':'NO', + 'min_pkt':1472, + 'max_pkt':0, + 'payload_pattern':'INCREASING', + 'use_checksum':'NO', + 'ttl':32, + 'send_bad_crc_per_million':0, + 'multi_conn':0 + } + + url = "cli-json/add_endp" + self.local_realm.json_post(url, json_data, debug_=debug_, suppress_related_commands_=suppress_related_commands) + + json_data = { + 'name':side_rx_name, + 'ttl':32, + 'mcast_group':'224.9.9.9', + 'mcast_dest_port':9999, + 'rcv_mcast':'Yes' + } + url = "cli-json/set_mc_endp" + self.local_realm.json_post(url, json_data, debug_=debug_, suppress_related_commands_=suppress_related_commands) + + self.created_mc[side_rx_name] = side_rx_name + these_endp.append(side_rx_name) + + self.local_realm.wait_until_endps_appear(these_endp, debug=debug_) + + def to_string(self): + pprint.pprint(self) + + + class L3CXProfile(LFCliBase): def __init__(self, lfclient_host, lfclient_port, local_realm, side_a_min_bps=None, side_b_min_bps=None, @@ -391,6 +862,7 @@ class L3CXProfile(LFCliBase): self.side_b_max_bps = side_b_max_bps self.report_timer = report_timer_ self.created_cx = {} + self.created_endp = {} self.name_prefix = name_prefix_ self.number_template = number_template_ @@ -408,6 +880,7 @@ class L3CXProfile(LFCliBase): def start_cx(self): print("Starting CXs...") for cx_name in self.created_cx.keys(): + print("cx-name: %s"%(cx_name)) self.json_post("/cli-json/set_cx_state", { "test_mgr": "default_tm", "cx_name": cx_name, @@ -419,38 +892,34 @@ class L3CXProfile(LFCliBase): def stop_cx(self): print("Stopping CXs...") for cx_name in self.created_cx.keys(): - self.json_post("/cli-json/set_cx_state", { - "test_mgr": "default_tm", - "cx_name": cx_name, - "cx_state": "STOPPED" - }, debug_=self.debug) + self.local_realm.stop_cx(cx_name) print(".", end='') print("") + def cleanup_prefix(self): + self.local_realm.cleanup_cxe_prefix(self.name_prefix) + def cleanup(self): print("Cleaning up cxs and endpoints") if len(self.created_cx) != 0: for cx_name in self.created_cx.keys(): - req_url = "cli-json/rm_cx" - data = { - "test_mgr": "default_tm", - "cx_name": cx_name - } - self.json_post(req_url, data) + print("Cleaning cx: %s"%(cx_name)) + self.local_realm.rm_cx(cx_name) for side in range(len(self.created_cx[cx_name])): - req_url = "cli-json/rm_endp" - data = { - "endp_name": self.created_cx[cx_name][side] - } - self.json_post(req_url, data) + ename = self.created_cx[cx_name][side] + print("Cleaning endpoint: %s"%(ename)) + self.local_realm.rm_endp(self.created_cx[cx_name][side]) - def create(self, endp_type, side_a, side_b, sleep_time=0.03, suppress_related_commands=None, debug_=False): + def create(self, endp_type, side_a, side_b, sleep_time=0.03, suppress_related_commands=None, debug_=False, tos=None): if self.debug: debug_=True cx_post_data = [] timer_post_data = [] + these_endp = [] + these_cx = [] + # print(self.side_a_min_rate, self.side_a_max_rate) # print(self.side_b_min_rate, self.side_b_max_rate) if (self.side_a_min_bps is None) \ @@ -463,19 +932,27 @@ class L3CXProfile(LFCliBase): side_b_info = self.local_realm.name_to_eid(side_b) side_b_shelf = side_b_info[0] side_b_resource = side_b_info[1] - side_b_name = "%s%s" % (self.name_prefix, side_b_info[2]) for port_name in side_a: + if port_name.find('.') < 0: + port_name = "%d.%s" % (side_a_info[1], port_name) + side_a_info = self.local_realm.name_to_eid(port_name) side_a_shelf = side_a_info[0] side_a_resource = side_a_info[1] - side_a_name = "%s%s"%(self.name_prefix, side_a_info[2]) + cx_name = "%s%s-%i"%(self.name_prefix, side_a_info[2], len(self.created_cx)) - cx_name = "%s%s" % (self.name_prefix, port_name) - self.created_cx[ cx_name ] = [side_a_name + "-A", side_a_name + "-B"] + endp_a_name = cx_name + "-A"; + endp_b_name = cx_name + "-B"; + self.created_cx[ cx_name ] = [endp_a_name, endp_b_name] + self.created_endp[endp_a_name] = endp_a_name; + self.created_endp[endp_b_name] = endp_b_name; + these_cx.append(cx_name) + these_endp.append(endp_a_name) + these_endp.append(endp_b_name) endp_side_a = { - "alias": side_a_name + "-A", - "shelf": 1, + "alias": endp_a_name, + "shelf": side_a_shelf, "resource": side_a_resource, "port": side_a_info[2], "type": endp_type, @@ -486,8 +963,8 @@ class L3CXProfile(LFCliBase): "ip_port": -1 } endp_side_b = { - "alias": side_a_name + "-B", - "shelf": 1, + "alias": endp_b_name, + "shelf": side_b_shelf, "resource": side_b_resource, "port": side_b_info[2], "type": endp_type, @@ -506,7 +983,7 @@ class L3CXProfile(LFCliBase): url = "cli-json/set_endp_flag" data = { - "name": side_a_name + "-A", + "name": endp_a_name, "flag": "autohelper", "val": 1 } @@ -514,18 +991,23 @@ class L3CXProfile(LFCliBase): url = "cli-json/set_endp_flag" data = { - "name": side_a_name + "-B", + "name": endp_b_name, "flag": "autohelper", "val": 1 } self.local_realm.json_post(url, data, debug_=debug_, suppress_related_commands_=suppress_related_commands) + + if tos != None: + self.local_realm.set_endp_tos(endp_a_name, tos) + self.local_realm.set_endp_tos(endp_b_name, tos) + #print("CXNAME366:") #pprint(cx_name) data = { "alias": cx_name, "test_mgr": "default_tm", - "tx_endp": side_a_name + "-A", - "rx_endp": side_a_name + "-B" + "tx_endp": endp_a_name, + "rx_endp": endp_b_name, } #pprint(data) cx_post_data.append(data) @@ -548,11 +1030,18 @@ class L3CXProfile(LFCliBase): side_b_resource = side_b_info[1] side_b_name = side_b_info[2] - cx_name = "%s%s" % (self.name_prefix, port_name) - self.created_cx[ cx_name ] = [side_a_name + "-A", side_a_name + "-B"] + cx_name = "%s%s-%i" % (self.name_prefix, port_name, len(self.created_cx)) + endp_a_name = cx_name + "-A"; + endp_b_name = cx_name + "-B"; + self.created_cx[ cx_name ] = [endp_a_name, endp_b_name] + self.created_endp[endp_a_name] = endp_a_name; + self.created_endp[endp_b_name] = endp_b_name; + these_cx.append(cx_name) + these_endp.append(endp_a_name) + these_endp.append(endp_b_name) endp_side_a = { - "alias": side_b_name + "-A", - "shelf": 1, + "alias": endp_a_name, + "shelf": side_a_shelf, "resource": side_a_resource, "port": side_a_info[2], "type": endp_type, @@ -563,8 +1052,8 @@ class L3CXProfile(LFCliBase): "ip_port": -1 } endp_side_b = { - "alias": side_b_name + "-B", - "shelf": 1, + "alias": endp_b_name, + "shelf": side_b_shelf, "resource": side_b_resource, "port": side_b_info[2], "type": endp_type, @@ -583,7 +1072,7 @@ class L3CXProfile(LFCliBase): url = "cli-json/set_endp_flag" data = { - "name": side_b_name + "-A", + "name": endp_a_name, "flag": "autohelper", "val": 1 } @@ -591,7 +1080,7 @@ class L3CXProfile(LFCliBase): url = "cli-json/set_endp_flag" data = { - "name": side_b_name + "-B", + "name": endp_b_name, "flag": "autohelper", "val": 1 } @@ -600,8 +1089,8 @@ class L3CXProfile(LFCliBase): data = { "alias": cx_name, "test_mgr": "default_tm", - "tx_endp": side_b_name + "-A", - "rx_endp": side_b_name + "-B" + "tx_endp": endp_a_name, + "rx_endp": endp_b_name, } cx_post_data.append(data) timer_post_data.append({ @@ -612,13 +1101,14 @@ class L3CXProfile(LFCliBase): else: raise ValueError("side_a or side_b must be of type list but not both: side_a is type %s side_b is type %s" % (type(side_a), type(side_b))) - #print("post_data", cx_post_data) + self.local_realm.wait_until_endps_appear(these_endp, debug=debug_) + for data in cx_post_data: url = "/cli-json/add_cx" self.local_realm.json_post(url, data, debug_=debug_, suppress_related_commands_=suppress_related_commands) - #print(" napping %f sec"%sleep_time, end='') - time.sleep(sleep_time) - #print("") + time.sleep(0.01) + + self.local_realm.wait_until_cxs_appear(these_cx, debug=debug_) def to_string(self): pprint.pprint(self) @@ -633,6 +1123,7 @@ class L4CXProfile(LFCliBase): self.requests_per_ten = 600 self.local_realm = local_realm self.created_cx = {} + self.created_endp = [] def check_errors(self, debug=False): fields_list = ["!conn", "acc.+denied", "bad-proto", "bad-url", "other-err", "total-err", "rslv-p", "rslv-h", @@ -745,33 +1236,102 @@ class GenCXProfile(LFCliBase): self.type = "lfping" self.dest = "127.0.0.1" self.interval = 1 - self.count = 2 self.cmd = "" self.local_realm = local_realm + self.created_cx = [] + self.created_endp = [] + + def parse_command(self, sta_name): + if self.type == "lfping": + if (self.dest is not None or self.dest != "") and (self.interval is not None or self.interval > 0): + self.cmd = "%s -i %s -I %s %s" % (self.type, self.interval, sta_name, self.dest) + #print(self.cmd) + else: + raise ValueError("Please ensure dest and interval have been set correctly") + else: + raise ValueError("Unknown command type") + + def start_cx(self): + print("Starting CXs...") + #print(self.created_cx) + #print(self.created_endp) + for cx_name in self.created_cx: + self.json_post("/cli-json/set_cx_state", { + "test_mgr": "default_tm", + "cx_name": cx_name, + "cx_state": "RUNNING" + }, debug_=self.debug) + print(".", end='') + print("") + + def stop_cx(self): + print("Stopping CXs...") + for cx_name in self.created_cx: + self.json_post("/cli-json/set_cx_state", { + "test_mgr": "default_tm", + "cx_name": cx_name, + "cx_state": "STOPPED" + }, debug_=self.debug) + print(".", end='') + print("") + + def cleanup(self): + print("Cleaning up cxs and endpoints") + for cx_name in self.created_cx: + req_url = "cli-json/rm_cx" + data = { + "test_mgr": "default_tm", + "cx_name": cx_name + } + self.json_post(req_url, data) + + for endp_name in self.created_endp: + req_url = "cli-json/rm_endp" + data = { + "endp_name": endp_name + } + self.json_post(req_url, data) + def create(self, ports=[], sleep_time=.5, debug_=False, suppress_related_commands_=None): if self.debug: - debug_ = True; + debug_ = True post_data = [] for port_name in ports: - gen_name = self.local_realm.name_to_eid(port_name)[-1] + "_gen0" - gen_name2 = self.local_realm.name_to_eid(port_name)[-1] + "_gen1" + port_info = self.local_realm.name_to_eid(port_name) + if len(port_info) == 2: + resource = 1 + shelf = port_info[0] + name = port_info[-1] + elif len(port_info) == 3: + resource = port_info[0] + shelf = port_info[1] + name = port_info[-1] + else: + raise ValueError("Unexpected name for port_name %s" % port_name) + + gen_name = name + "_gen0" + gen_name1 = name + "_gen1" genl = GenericCx(lfclient_host=self.lfclient_host, lfclient_port=self.lfclient_port) - genl.createGenEndp(gen_name, 1, 1, port_name, "gen_generic") - genl.createGenEndp(gen_name2, 1, 1, port_name, "gen_generic") + genl.createGenEndp(gen_name, shelf, resource, name, "gen_generic") + genl.createGenEndp(gen_name1, shelf, resource, name, "gen_generic") genl.setFlags(gen_name, "ClearPortOnStart", 1) - genl.setFlags(gen_name2, "ClearPortOnStart", 1) - genl.setFlags(gen_name2, "Unmanaged", 1) + genl.setFlags(gen_name1, "ClearPortOnStart", 1) + genl.setFlags(gen_name1, "Unmanaged", 1) + self.parse_command(name) genl.setCmd(gen_name, self.cmd) time.sleep(sleep_time) data = { - "alias": self.local_realm.name_to_eid(port_name)[-1] + "_gen_CX", + "alias": "CX_" + name + "_gen", "test_mgr": "default_tm", "tx_endp": gen_name, - "rx_endp": gen_name2 + "rx_endp": gen_name1 } post_data.append(data) + self.created_cx.append("CX_" + name + "_gen") + self.created_endp.append(gen_name) + self.created_endp.append(gen_name1) for data in post_data: url = "/cli-json/add_cx" @@ -792,23 +1352,37 @@ class WifiMonitor: self.aid = "NA" # used when sniffing /ax radios self.bsssid = "00:00:00:00:00:00" # used when sniffing on /ax radios - def create(self, resource_=1,channel=None, radio_="wiphy0", name_="moni0" ): + def create(self, resource_=1, channel=None, radio_="wiphy0", name_="moni0" ): print("Creating monitor " + name_) self.monitor_name = name_ computed_flags = 0 for flag_n in self.flag_names: computed_flags += add_monitor.flags[flag_n] - data ={ - "shelf": 1, - "resource": resource_, - "radio": radio_, - "freqency":5785, - "mode": "NA", #0 for AUTO or "NA" - "channel": channel - - } - self.local_realm.json_post("/cli-json/set_wifi_radio", _data= data) + # we want to query the existing country code of the radio + # there's no reason to change it but we get hollering from server + # if we don't provide a value for the parameter + jr = self.local_realm.json_get("/radiostatus/1/%s/%s?fields=channel,frequency,country"%(resource_, radio_), debug_=self.debug) + if jr is None: + raise ValueError("No radio %s.%s found"%(resource_, radio_)) + + eid = "1.%s.%s"%(resource_, radio_) + frequency = 0 + country = 0 + if eid in jr: + country = jr[eid]["country"] + + data = { + "shelf": 1, + "resource": resource_, + "radio": radio_, + "mode": 0, #"NA", #0 for AUTO or "NA" + "channel": channel, + "country": country, + "frequency": self.local_realm.channel_freq(channel_=channel) + } + self.local_realm.json_post("/cli-json/set_wifi_radio", _data=data) + time.sleep(1) self.local_realm.json_post("/cli-json/add_monitor", { "shelf": 1, "resource": resource_, @@ -817,6 +1391,7 @@ class WifiMonitor: "flags": computed_flags, "flags_mask": self.flags_mask }) + def set_flag(self, param_name, value): if (param_name not in add_monitor.flags): raise ValueError("Flag '%s' does not exist for add_monitor, consult add_monitor.py" % param_name) @@ -826,10 +1401,36 @@ class WifiMonitor: del self.flag_names[param_name] self.flags_mask |= add_monitor.flags[param_name] - def cleanup(self): + def cleanup(self, resource_=1, desired_ports=None): print("Cleaning up monitors") - LFUtils.removePort(resource=self.resource, port_name = self.monitor_name, baseurl=self.lfclient_url, debug=self.debug) - + if (desired_ports is None) or (len(desired_ports) < 1): + if (self.monitor_name is None) or (self.monitor_name == ""): + print("No monitor name set to delete") + return + LFUtils.removePort(resource=resource_, + port_name=self.monitor_name, + baseurl=self.lfclient_url, + debug=self.debug) + else: + names = ",".join(desired_ports) + existing_ports = self.local_realm.json_get("/port/1/%d/%s?fields=alias"%(resource_, names), debug_=False) + if (existing_ports is None) or ("interfaces" not in existing_ports) or ("interface" not in existing_ports): + print("No monitor names found to delete") + return + if ("interfaces" in existing_ports): + for eid,info in existing_ports["interfaces"].items(): + LFUtils.removePort(resource=resource_, + port_name=info["alias"], + baseurl=self.lfclient_url, + debug=self.debug) + if ("interface" in existing_ports): + for eid,info in existing_ports["interface"].items(): + LFUtils.removePort(resource=resource_, + port_name=info["alias"], + baseurl=self.lfclient_url, + debug=self.debug) + + def admin_up(self): up_request = LFUtils.port_up_request(resource_id=self.resource, port_name=self.monitor_name) @@ -839,7 +1440,7 @@ class WifiMonitor: down_request = LFUtils.portDownRequest(resource_id=self.resource, port_name=self.monitor_name) self.local_realm.json_post("/cli-json/set_port", down_request) - def start_sniff(self, capname=None): + def start_sniff(self, capname=None, duration_sec=60): if capname is None: raise ValueError("Need a capture file name") data = { @@ -849,14 +1450,335 @@ class WifiMonitor: "display": "NA", "flags": 0x2, "outfile": capname, - "duration": 45 + "duration": duration_sec } self.local_realm.json_post("/cli-json/sniff_port", _data= data) - + # "sniff_port 1 %s %s NA %s %s.pcap %i"%(r, m, sflags, m, int(dur)) +class VAPProfile(LFCliBase): + def __init__(self, lfclient_url, local_realm, vap_name="", ssid="NA", ssid_pass="NA", mode=0, use_ht160=False, debug_=False): + self.debug = debug_ + self.lfclient_url = lfclient_url + self.ssid = ssid + self.ssid_pass = ssid_pass + self.mode = mode + self.local_realm = local_realm + self.vap_name = vap_name + self.use_ht160 = use_ht160 + self.COMMANDS = ["add_vap", "set_port"] + self.desired_add_vap_flags = ["wpa2_enable", "80211u_enable", "create_admin_down"] + self.desired_add_vap_flags_mask = ["wpa2_enable", "80211u_enable", "create_admin_down"] + self.add_vap_data = { + "shelf": 1, + "resource": 1, + "radio": None, + "ap_name": None, + "flags": 0, + "flags_mask": 0, + "mode": 0, + "ssid": None, + "key": None, + "mac": "xx:xx:xx:xx:*:xx" + } + self.desired_set_port_cmd_flags = [] + self.desired_set_port_current_flags = ["if_down"] + self.desired_set_port_interest_flags = ["current_flags", "ifdown"] + self.set_port_data = { + "shelf": 1, + "resource": 1, + "port": None, + "current_flags": 0, + "interest": 0, # (0x2 + 0x4000 + 0x800000) # current, dhcp, down + } + + def admin_up(self, resource): + set_port_r = LFRequest.LFRequest(self.lfclient_url, "/cli-json/set_port", debug_=self.debug) + req_json = LFUtils.portUpRequest(resource, None, debug_on=self.debug) + req_json["port"] = self.vap_name + set_port_r.addPostData(req_json) + json_response = set_port_r.jsonPost(self.debug) + time.sleep(0.03) + + def admin_down(self, resource): + set_port_r = LFRequest.LFRequest(self.lfclient_url, "/cli-json/set_port", debug_=self.debug) + req_json = LFUtils.port_down_request(resource, None, debug_on=self.debug) + req_json["port"] = self.vap_name + set_port_r.addPostData(req_json) + json_response = set_port_r.jsonPost(self.debug) + time.sleep(0.03) + + def use_security(self, security_type, ssid=None, passwd=None): + types = {"wep": "wep_enable", "wpa": "wpa_enable", "wpa2": "wpa2_enable", "wpa3": "use-wpa3", "open": "[BLANK]"} + self.add_vap_data["ssid"] = ssid + if security_type in types.keys(): + if (ssid is None) or (ssid == ""): + raise ValueError("use_security: %s requires ssid" % security_type) + if (passwd is None) or (passwd == ""): + raise ValueError("use_security: %s requires passphrase or [BLANK]" % security_type) + for name in types.values(): + if name in self.desired_add_vap_flags and name in self.desired_add_vap_flags_mask: + self.desired_add_vap_flags.remove(name) + self.desired_add_vap_flags_mask.remove(name) + if security_type != "open": + self.desired_add_vap_flags.append(types[security_type]) + self.desired_add_vap_flags_mask.append(types[security_type]) + else: + passwd = "[BLANK]" + self.set_command_param("add_vap", "ssid", ssid) + self.set_command_param("add_vap", "key", passwd) + # unset any other security flag before setting our present flags + if security_type == "wpa3": + self.set_command_param("add_vap", "ieee80211w", 2) + + def set_command_flag(self, command_name, param_name, value): + # we have to check what the param name is + if (command_name is None) or (command_name == ""): + return + if (param_name is None) or (param_name == ""): + return + if command_name not in self.COMMANDS: + print("Command name name [%s] not defined in %s" % (command_name, self.COMMANDS)) + return + if command_name == "add_vap": + if (param_name not in add_vap.add_vap_flags): + print("Parameter name [%s] not defined in add_vap.py" % param_name) + if self.debug: + pprint(add_vap.add_vap_flags) + return + if (value == 1) and (param_name not in self.desired_add_vap_flags): + self.desired_add_vap_flags.append(param_name) + self.desired_add_vap_flags_mask.append(param_name) + elif value == 0: + self.desired_add_vap_flags.remove(param_name) + self.desired_add_vap_flags_mask.append(param_name) + + elif command_name == "set_port": + if (param_name not in set_port.set_port_current_flags) and (param_name not in set_port.set_port_cmd_flags) and (param_name not in set_port.set_port_interest_flags): + print("Parameter name [%s] not defined in set_port.py" % param_name) + if self.debug: + pprint(set_port.set_port_cmd_flags) + pprint(set_port.set_port_current_flags) + pprint(set_port.set_port_interest_flags) + return + if param_name in set_port.set_port_cmd_flags: + if (value == 1) and (param_name not in self.desired_set_port_cmd_flags): + self.desired_set_port_cmd_flags.append(param_name) + elif value == 0: + self.desired_set_port_cmd_flags.remove(param_name) + elif param_name in set_port.set_port_current_flags: + if (value == 1) and (param_name not in self.desired_set_port_current_flags): + self.desired_set_port_current_flags.append(param_name) + elif value == 0: + self.desired_set_port_current_flags.remove(param_name) + elif param_name in set_port.set_port_interest_flags: + if (value == 1) and (param_name not in self.desired_set_port_interest_flags): + self.desired_set_port_interest_flags.append(param_name) + elif value == 0: + self.desired_set_port_interest_flags.remove(param_name) + else: + raise ValueError("Unknown param name: " + param_name) + + def set_command_param(self, command_name, param_name, param_value): + # we have to check what the param name is + if (command_name is None) or (command_name == ""): + return + if (param_name is None) or (param_name == ""): + return + if command_name not in self.COMMANDS: + self.error("Command name name [%s] not defined in %s" % (command_name, self.COMMANDS)) + return + if command_name == "add_vap": + self.add_vap_data[param_name] = param_value + elif command_name == "set_port": + self.set_port_data[param_name] = param_value + + def add_named_flags(self, desired_list, command_ref): + if desired_list is None: + raise ValueError("addNamedFlags wants a list of desired flag names") + if len(desired_list) < 1: + print("addNamedFlags: empty desired list") + return 0 + if (command_ref is None) or (len(command_ref) < 1): + raise ValueError("addNamedFlags wants a maps of flag values") + + result = 0 + for name in desired_list: + if (name is None) or (name == ""): + continue + if name not in command_ref: + if self.debug: + pprint(command_ref) + raise ValueError("flag %s not in map" % name) + #print("add-named-flags: %s %i"%(name, command_ref[name])) + result |= command_ref[name] + + return result + + def create(self, resource, radio, channel=None, up_=None, debug=False, suppress_related_commands_=True): + + if self.use_ht160: + self.desired_add_vap_flags.append("enable_80211d") + self.desired_add_vap_flags_mask.append("enable_80211d") + self.desired_add_vap_flags.append("80211h_enable") + self.desired_add_vap_flags_mask.append("80211h_enable") + self.desired_add_vap_flags.append("ht160_enable") + self.desired_add_vap_flags_mask.append("ht160_enable") + + print("MODE ========= ", self.mode) + + jr = self.local_realm.json_get("/radiostatus/1/%s/%s?fields=channel,frequency,country" % (resource, radio), debug_=self.debug) + if jr is None: + raise ValueError("No radio %s.%s found" % (resource, radio)) + + eid = "1.%s.%s" % (resource, radio) + frequency = 0 + country = 0 + if eid in jr: + country = jr[eid]["country"] + + data = { + "shelf": 1, + "resource": resource, + "radio": radio, + "mode": self.mode, #"NA", #0 for AUTO or "NA" + "channel": channel, + "country": country, + "frequency": self.local_realm.channel_freq(channel_=channel) + } + self.local_realm.json_post("/cli-json/set_wifi_radio", _data=data) + if up_ is not None: + self.up = up_ + if self.up: + if "create_admin_down" in self.desired_add_vap_flags: + del self.desired_add_vap_flags[self.desired_add_vap_flags.index("create_admin_down")] + elif "create_admin_down" not in self.desired_add_vap_flags: + self.desired_add_vap_flags.append("create_admin_down") + + # create vaps down, do set_port on them, then set vaps up + self.add_vap_data["mode"] = self.mode + self.add_vap_data["flags"] = self.add_named_flags(self.desired_add_vap_flags, add_vap.add_vap_flags) + self.add_vap_data["flags_mask"] = self.add_named_flags(self.desired_add_vap_flags_mask, add_vap.add_vap_flags) + self.add_vap_data["radio"] = radio + + self.add_vap_data["resource"] = resource + self.set_port_data["current_flags"] = self.add_named_flags(self.desired_set_port_current_flags, + set_port.set_port_current_flags) + self.set_port_data["interest"] = self.add_named_flags(self.desired_set_port_interest_flags, + set_port.set_port_interest_flags) + # these are unactivated LFRequest objects that we can modify and + # re-use inside a loop, reducing the number of object creations + add_vap_r = LFRequest.LFRequest(self.lfclient_url + "/cli-json/add_vap") + set_port_r = LFRequest.LFRequest(self.lfclient_url + "/cli-json/set_port") + + if suppress_related_commands_: + self.add_vap_data["suppress_preexec_cli"] = "yes" + self.add_vap_data["suppress_preexec_method"] = 1 + self.set_port_data["suppress_preexec_cli"] = "yes" + self.set_port_data["suppress_preexec_method"] = 1 + + # pprint(self.station_names) + # exit(1) + self.set_port_data["port"] = self.vap_name + self.add_vap_data["ap_name"] = self.vap_name + add_vap_r.addPostData(self.add_vap_data) + if debug: + print("- 1502 - %s- - - - - - - - - - - - - - - - - - " % self.vap_name) + pprint(self.add_vap_data) + pprint(self.set_port_data) + pprint(add_vap_r) + print("- ~1502 - - - - - - - - - - - - - - - - - - - ") + + json_response = add_vap_r.jsonPost(debug) + # time.sleep(0.03) + time.sleep(2) + set_port_r.addPostData(self.set_port_data) + json_response = set_port_r.jsonPost(debug) + time.sleep(0.03) + + # create bridge + data = { + "shelf": 1, + "resource": resource, + "port": "br0", + "network_devs": "eth1,%s" % self.vap_name + } + self.local_realm.json_post("cli-json/add_br", data) + + if (self.up): + self.admin_up(1) + + def cleanup(self, resource, desired_ports=None, delay=0.03): + print("Cleaning up VAPs") + req_url = "/cli-json/rm_vlan" + data = { + "shelf": 1, + "resource": resource, + "port": None + } + if (desired_ports is not None): + if len(desired_ports) < 1: + print("No stations requested for cleanup, returning.") + return + names = ','.join(desired_ports) + current_stations = self.local_realm.json_get("/port/1/%s/%s?fields=alias" % (resource, names)) + if current_stations is None: + return + if "interfaces" in current_stations: + for station in current_stations['interfaces']: + for eid, info in station.items(): + data["port"] = info["alias"] + self.local_realm.json_post(req_url, data, debug_=self.debug) + time.sleep(delay) + + if "interface" in current_stations: + data["port"] = current_stations["interface"]["alias"] + self.local_realm.json_post(req_url, data, debug_=self.debug) + + return + + names = ','.join(self.station_names) + current_stations = self.local_realm.json_get("/port/1/%s/%s?fields=alias" % (resource, names)) + if current_stations is None or current_stations['interfaces'] is None: + print("No stations to clean up") + return + + if "interfaces" in current_stations: + for station in current_stations['interfaces']: + for eid, info in station.items(): + data["port"] = info["alias"] + self.local_realm.json_post(req_url, data, debug_=self.debug) + time.sleep(delay) + + if "interface" in current_stations: + data["port"] = current_stations["interface"]["alias"] + self.local_realm.json_post(req_url, data, debug_=self.debug) + +class PortUtils(LFCliBase): + def __init__(self, local_realm): + self.local_realm = local_realm + + def set_ftp(self, port_name="", resource=1, on=False): + if port_name != "": + data = { + "shelf": 1, + "resource": resource, + "port": port_name, + "current_flags": 0, + "interest": 0 + } + + if on: + data["current_flags"] = 0x400000000000 + data["interest"] = 0x10000000 + else: + data["interest"] = 0x10000000 + + self.local_realm.json_post("cli-json/set_port", data) + else: + raise ValueError("Port name required") # use the station profile to set the combination of features you want on your stations # once this combination is configured, build the stations with the build(resource, radio, number) call @@ -870,7 +1792,7 @@ class WifiMonitor: # class StationProfile: def __init__(self, lfclient_url, local_realm, ssid="NA", ssid_pass="NA", security="open", number_template_="00000", mode=0, up=True, - dhcp=True, debug_=False): + dhcp=True, debug_=False, use_ht160=False): self.debug = debug_ self.lfclient_url = lfclient_url self.ssid = ssid @@ -880,11 +1802,12 @@ class StationProfile: self.dhcp = dhcp self.security = security self.local_realm = local_realm + self.use_ht160 = use_ht160 self.COMMANDS = ["add_sta", "set_port"] self.desired_add_sta_flags = ["wpa2_enable", "80211u_enable", "create_admin_down"] self.desired_add_sta_flags_mask = ["wpa2_enable", "80211u_enable", "create_admin_down"] self.number_template = number_template_ - self.station_names = [] + self.station_names = [] # eids self.add_sta_data = { "shelf": 1, "resource": 1, @@ -895,7 +1818,6 @@ class StationProfile: "mode": 0, "mac": "xx:xx:xx:xx:*:xx", "flags": 0, # (0x400 + 0x20000 + 0x1000000000) # create admin down - } self.desired_set_port_cmd_flags = [] self.desired_set_port_current_flags = ["if_down"] @@ -912,15 +1834,13 @@ class StationProfile: "interest": 0, # (0x2 + 0x4000 + 0x800000) # current, dhcp, down, } - # TODO: create use_wpa3() - def use_security(self, security_type, ssid=None, passwd=None): types = {"wep": "wep_enable", "wpa": "wpa_enable", "wpa2": "wpa2_enable", "wpa3": "use-wpa3", "open": "[BLANK]"} self.add_sta_data["ssid"] = ssid if security_type in types.keys(): - if (ssid is None) or ("" == ssid): + if (ssid is None) or (ssid == ""): raise ValueError("use_security: %s requires ssid" % security_type) - if (passwd is None) or ("" == passwd): + if (passwd is None) or (passwd == ""): raise ValueError("use_security: %s requires passphrase or [BLANK]" % security_type) for name in types.values(): if name in self.desired_add_sta_flags and name in self.desired_add_sta_flags_mask: @@ -1028,39 +1948,46 @@ class StationProfile: return result - def admin_up(self, resource): - set_port_r = LFRequest.LFRequest(self.lfclient_url, "/cli-json/set_port", debug_=self.debug) + def admin_up(self): for sta_name in self.station_names: - req_json = LFUtils.portUpRequest(resource, sta_name, debug_on=False) - set_port_r.addPostData(req_json) - json_response = set_port_r.jsonPost(self.debug) - time.sleep(0.03) + self.local_realm.admin_up(sta_name) + + def admin_down(self): + for sta_name in self.station_names: + self.local_realm.admin_down(sta_name) + + def cleanup(self, desired_stations=None, delay=0.03): + print("Cleaning up stations") + + if (desired_stations is None): + desired_stations = self.station_names + + if len(desired_stations) < 1: + print("ERROR: StationProfile cleanup, list is empty") + return + + del_count = len(desired_stations) + + # First, request remove on the list. + for port_eid in desired_stations: + self.local_realm.rm_port(port_eid, check_exists=True) + + # And now see if they are gone + LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=desired_stations) - def cleanup(self, resource, desired_stations): - current_stations = self.local_realm.json_get("port/1/%s/%s?fields=alias" % (resource, ','.join(self.station_names))) - if current_stations is not None and current_stations['interfaces'] is not None: - print("Cleaning up stations") - for station in current_stations['interfaces']: - for eid,info in station.items(): - if info['alias'] in desired_stations: - req_url = "cli-json/rm_vlan" - data = { - "shelf": 1, - "resource": resource, - "port": info['alias'] - } - self.local_realm.json_post(req_url, data) # Checks for errors in initialization values and creates specified number of stations using init parameters - def create(self, resource, radio, num_stations=0, sta_names_=None, dry_run=False, up_=None, debug=False): - # try: - # resource = resource_radio[0: resource_radio.index(".")] - # name = resource_radio[resource_radio.index(".") + 1:] - # if name.index(".") >= 0: - # radio_name = name[name.index(".")+1 : ] - # print("Building %s on radio %s.%s" % (num_stations, resource, radio_name)) - # except ValueError as e: - # print(e) + def create(self, radio, num_stations=0, sta_names_=None, dry_run=False, up_=None, debug=False, suppress_related_commands_=True, sleep_time=2): + radio_eid = self.local_realm.name_to_eid(radio) + radio_shelf = radio_eid[0] + radio_resource = radio_eid[1] + radio_port = radio_eid[2] + + if self.use_ht160: + self.desired_add_sta_flags.append("ht160_enable") + self.desired_add_sta_flags_mask.append("ht160_enable") + self.add_sta_data["mode"] = self.mode + if up_ is not None: self.up = up_ @@ -1076,23 +2003,25 @@ class StationProfile: # create stations down, do set_port on them, then set stations up self.add_sta_data["flags"] = self.add_named_flags(self.desired_add_sta_flags, add_sta.add_sta_flags) self.add_sta_data["flags_mask"] = self.add_named_flags(self.desired_add_sta_flags_mask, add_sta.add_sta_flags) - self.add_sta_data["radio"] = radio + self.add_sta_data["radio"] = radio_port - self.add_sta_data["resource"] = resource + self.add_sta_data["resource"] = radio_resource self.set_port_data["current_flags"] = self.add_named_flags(self.desired_set_port_current_flags, set_port.set_port_current_flags) self.set_port_data["interest"] = self.add_named_flags(self.desired_set_port_interest_flags, set_port.set_port_interest_flags) - + # these are unactivated LFRequest objects that we can modify and + # re-use inside a loop, reducing the number of object creations add_sta_r = LFRequest.LFRequest(self.lfclient_url + "/cli-json/add_sta") set_port_r = LFRequest.LFRequest(self.lfclient_url + "/cli-json/set_port") - self.station_names = [] - if num_stations > 0: - self.station_names = LFUtils.portNameSeries("sta", 0, num_stations - 1, int("1" + self.number_template)) - else: - self.station_names = sta_names_ - if len(self.station_names) >= 15: + my_sta_names = [] + if num_stations > 0: + my_sta_names = LFUtils.portNameSeries("sta", 0, num_stations - 1, int("1" + self.number_template)) + else: + my_sta_names = sta_names_ + + if (len(my_sta_names) >= 15) or (suppress_related_commands_ == True): self.add_sta_data["suppress_preexec_cli"] = "yes" self.add_sta_data["suppress_preexec_method"] = 1 self.set_port_data["suppress_preexec_cli"] = "yes" @@ -1101,10 +2030,17 @@ class StationProfile: num = 0 #pprint(self.station_names) #exit(1) - for name in self.station_names: - self.set_port_data["port"] = name + for eidn in my_sta_names: + eid = self.local_realm.name_to_eid(eidn) + name = eid[2] num += 1 - self.add_sta_data["sta_name"] = name + self.add_sta_data["shelf"] = radio_shelf + self.add_sta_data["resource"] = radio_resource + self.add_sta_data["radio"] = radio_port + self.add_sta_data["sta_name"] = name # for create station calls + self.set_port_data["port"] = name # for set_port calls. + + self.station_names.append("%s.%s.%s" % (radio_shelf, radio_resource, name)) add_sta_r.addPostData(self.add_sta_data) if debug: print("- 381 - %s- - - - - - - - - - - - - - - - - - " % name) @@ -1118,12 +2054,12 @@ class StationProfile: json_response = add_sta_r.jsonPost(debug) # time.sleep(0.03) - time.sleep(2) + time.sleep(sleep_time) set_port_r.addPostData(self.set_port_data) json_response = set_port_r.jsonPost(debug) - time.sleep(.03) + time.sleep(0.03) - LFUtils.waitUntilPortsAppear(resource, self.lfclient_url, self.station_names) + LFUtils.waitUntilPortsAppear(self.lfclient_url, self.station_names) # and set ports up if dry_run: diff --git a/py-scripts/__init__.py b/py-scripts/__init__.py old mode 100644 new mode 100755 diff --git a/py-scripts/cicd_TipIntegration.py b/py-scripts/cicd_TipIntegration.py old mode 100644 new mode 100755 diff --git a/py-scripts/cicd_testrail.py b/py-scripts/cicd_testrail.py old mode 100644 new mode 100755 diff --git a/py-scripts/cicd_testrailAndInfraSetup.py b/py-scripts/cicd_testrailAndInfraSetup.py old mode 100644 new mode 100755 diff --git a/py-scripts/sta_connect2.py b/py-scripts/sta_connect2.py index 87cce840..19663de2 100755 --- a/py-scripts/sta_connect2.py +++ b/py-scripts/sta_connect2.py @@ -22,6 +22,7 @@ from LANforge.lfcli_base import LFCliBase from LANforge.LFUtils import * import realm from realm import Realm +import pprint OPEN="open" WEP="wep" @@ -30,9 +31,9 @@ WPA2="wpa2" MODE_AUTO=0 class StaConnect2(LFCliBase): - def __init__(self, host, port, _dut_ssid="MyAP", _dut_passwd="NA", _dut_bssid="", + def __init__(self, host, port, _dut_ssid="jedway-open-1", _dut_passwd="NA", _dut_bssid="", _user="", _passwd="", _sta_mode="0", _radio="wiphy0", - _resource=1, _upstream_resource=1, _upstream_port="eth2", + _resource=1, _upstream_resource=1, _upstream_port="eth1", _sta_name=None, debug_=False, _dut_security=OPEN, _exit_on_error=False, _cleanup_on_exit=True, _runtime_sec=60, _exit_on_fail=False): # do not use `super(LFCLiBase,self).__init__(self, host, port, _debugOn) @@ -62,7 +63,7 @@ class StaConnect2(LFCliBase): self.localrealm = Realm(lfclient_host=host, lfclient_port=port) # py > 3.6 self.resulting_stations = {} self.resulting_endpoints = {} - self.sta_profile = None + self.station_profile = None self.l3_udp_profile = None self.l3_tcp_profile = None @@ -141,20 +142,20 @@ class StaConnect2(LFCliBase): if (response is not None) and (response["interface"] is not None): for sta_name in self.station_names: LFUtils.removePort(self.resource, sta_name, self.lfclient_url) - LFUtils.wait_until_ports_disappear(self.resource, self.lfclient_url, self.station_names) + LFUtils.wait_until_ports_disappear(self.lfclient_url, self.station_names) # Create stations and turn dhcp on self.station_profile = self.localrealm.new_station_profile() if self.dut_security == WPA2: - self.station_profile.use_wpa2(on=True, ssid=self.dut_ssid, passwd=self.dut_passwd) + self.station_profile.use_security(security_type="wpa2", ssid=self.dut_ssid, passwd=self.dut_passwd) elif self.dut_security == OPEN: - self.station_profile.use_wpa2(on=False, ssid=self.dut_ssid) + self.station_profile.use_security(security_type="open", ssid=self.dut_ssid, passwd="[BLANK]") self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) print("Adding new stations ", end="") - self.station_profile.create(resource=self.resource, radio=self.radio, sta_names_=self.station_names, up_=False, debug=False) - LFUtils.wait_until_ports_appear(self.resource, self.lfclient_url, self.station_names) + self.station_profile.create(radio=self.radio, sta_names_=self.station_names, up_=False, debug=self.debug, suppress_related_commands_=True) + LFUtils.wait_until_ports_appear(self.lfclient_url, self.station_names, debug=self.debug) # Create UDP endpoints self.l3_udp_profile = self.localrealm.new_l3_cx_profile() @@ -181,14 +182,19 @@ class StaConnect2(LFCliBase): suppress_related_commands=True) def start(self): - if not self.station_profile.up: + if self.station_profile is None: + self._fail("Incorrect setup") + pprint.pprint(self.station_profile) + if self.station_profile.up is None: + self._fail("Incorrect station profile, missing profile.up") + if self.station_profile.up == False: print("\nBringing ports up...") data = {"shelf": 1, "resource": self.resource, "port": "ALL", "probe_flags": 1} self.json_post("/cli-json/nc_show_ports", data) - self.station_profile.admin_up(self.resource) + self.station_profile.admin_up() LFUtils.waitUntilPortsAdminUp(self.resource, self.lfclient_url, self.station_names) # station_info = self.jsonGet(self.mgr_url, "%s?fields=port,ip,ap" % (self.getStaUrl())) @@ -324,14 +330,16 @@ class StaConnect2(LFCliBase): if self.cleanup_on_exit: for sta_name in self.station_names: LFUtils.removePort(self.resource, sta_name, self.lfclient_url) - endp_names = [] - + curr_endp_names = [] removeCX(self.lfclient_url, self.l3_udp_profile.get_cx_names()) removeCX(self.lfclient_url, self.l3_tcp_profile.get_cx_names()) for (cx_name, endp_names) in self.l3_udp_profile.created_cx.items(): - endp_names.append(endp_names[0]) - endp_names.append(endp_names[1]) - removeEndps(self.lfclient_url, endp_names) + curr_endp_names.append(endp_names[0]) + curr_endp_names.append(endp_names[1]) + for (cx_name, endp_names) in self.l3_tcp_profile.created_cx.items(): + curr_endp_names.append(endp_names[0]) + curr_endp_names.append(endp_names[1]) + removeEndps(self.lfclient_url, curr_endp_names, debug= self.debug) # ~class @@ -375,7 +383,10 @@ Example: if args.debug in on_flags: debug_v = True - staConnect = StaConnect2(lfjson_host, lfjson_port, debug_=debug_v) + staConnect = StaConnect2(lfjson_host, lfjson_port, + debug_=True, + _exit_on_fail=True, + _exit_on_error=False) staConnect.station_names = [ "sta0000" ] if args.user is not None: staConnect.user = args.user @@ -400,6 +411,7 @@ Example: if args.dut_security is not None: staConnect.dut_security = args.dut_security + # staConnect.cleanup() staConnect.setup() staConnect.start() print("napping %f sec" % staConnect.runtime_secs) diff --git a/py-scripts/test_generic.py b/py-scripts/test_generic.py new file mode 100755 index 00000000..020038c7 --- /dev/null +++ b/py-scripts/test_generic.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 + +import sys +import os + +if sys.version_info[0] != 3: + print("This script requires Python 3") + exit(1) + +if 'py-json' not in sys.path: + sys.path.append(os.path.join(os.path.abspath('..'), 'py-json')) + +import argparse +from LANforge.lfcli_base import LFCliBase +from LANforge import LFUtils +import realm +import time +import datetime + + +class GenTest(LFCliBase): + def __init__(self, host, port, ssid, security, password, sta_list, name_prefix, upstream, + number_template="00000", test_duration="5m", type="lfping", dest="127.0.0.1", + interval=1, radio="wiphy0", + _debug_on=False, + _exit_on_error=False, + _exit_on_fail=False): + super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) + self.host = host + self.port = port + self.ssid = ssid + self.radio = radio + self.upstream = upstream + self.sta_list = sta_list + self.security = security + self.password = password + self.number_template = number_template + self.name_prefix = name_prefix + self.test_duration = test_duration + self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port) + self.station_profile = self.local_realm.new_station_profile() + self.cx_profile = self.local_realm.new_generic_cx_profile() + + self.station_profile.lfclient_url = self.lfclient_url + self.station_profile.ssid = self.ssid + self.station_profile.ssid_pass = self.password, + self.station_profile.security = self.security + self.station_profile.number_template_ = self.number_template + self.station_profile.mode = 0 + + self.cx_profile.type = type + self.cx_profile.dest = dest + self.cx_profile.interval = interval + + def start(self, print_pass=False, print_fail=False): + self.station_profile.admin_up() + temp_stas = self.sta_list.copy() + temp_stas.append(self.upstream) + if self.local_realm.wait_for_ip(temp_stas): + self._pass("All stations got IPs", print_pass) + else: + self._fail("Stations failed to get IPs", print_fail) + exit(1) + cur_time = datetime.datetime.now() + passes = 0 + expected_passes = 0 + self.cx_profile.start_cx() + time.sleep(15) + end_time = self.local_realm.parse_time("30s") + cur_time + print("Starting Test...") + while cur_time < end_time: + cur_time = datetime.datetime.now() + gen_results = self.json_get("generic/list?fields=name,last+results", debug_=self.debug) + if gen_results['endpoints'] is not None: + for name in gen_results['endpoints']: + for k, v in name.items(): + if v['name'] in self.cx_profile.created_endp and not v['name'].endswith('1'): + expected_passes += 1 + if v['last results'] != "" and "Unreachable" not in v['last results']: + passes += 1 + else: + self._fail("%s Failed to ping %s " % (v['name'], self.cx_profile.dest), print_fail) + break + # print(cur_time) + # print(end_time) + time.sleep(1) + + if passes == expected_passes: + self._pass("PASS: All tests passed", print_pass) + + + def stop(self): + self.cx_profile.stop_cx() + for sta_name in self.sta_list: + data = LFUtils.portDownRequest(1, sta_name) + url = "cli-json/set_port" + self.json_post(url, data) + + def build(self): + self.station_profile.use_security(self.security, self.ssid, self.password) + self.station_profile.set_number_template(self.number_template) + print("Creating stations") + self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) + self.station_profile.set_command_param("set_port", "report_timer", 1500) + self.station_profile.set_command_flag("set_port", "rpt_timer", 1) + self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug) + self.cx_profile.create(ports=self.station_profile.station_names, sleep_time=.5) + self._pass("PASS: Station build finished") + + def cleanup(self, sta_list): + self.cx_profile.cleanup() + self.station_profile.cleanup(sta_list) + LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=sta_list, + debug=self.debug) + + +def main(): + lfjson_port = 8080 + + parser = LFCliBase.create_basic_argparse( + prog='test_generic.py', + # formatter_class=argparse.RawDescriptionHelpFormatter, + formatter_class=argparse.RawTextHelpFormatter, + epilog='''\ + Useful Information: + 1. TBD + ''', + + description='''\ + test_generic.py: + -------------------- + TBD + + Generic command layout: + python ./test_generic.py --upstream_port --radio --debug + + Note: multiple --radio switches may be entered up to the number of radios available: + --radio --radio + + python3 ./test_generic.py --upstream_port eth1 --radio wiphy0 32 candelaTech-wpa2-x2048-4-1 candelaTech-wpa2-x2048-4-1 wpa2 --radio wiphy1 64 candelaTech-wpa2-x2048-5-3 candelaTech-wpa2-x2048-5-3 wpa2 + + ''') + + parser.add_argument('--type', help='--type type of command to run', default="lfping") + parser.add_argument('--dest', help='--dest destination for command', default="10.40.0.1") + parser.add_argument('--test_duration', help='--test_duration sets the duration of the test', default="5m") + parser.add_argument('--interval', help='--interval interval to use when running lfping', default=1) + + args = parser.parse_args() + + station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000, + radio=args.radio) + + generic_test = GenTest(args.mgr, lfjson_port, number_template="00", sta_list=station_list, + name_prefix="GT", type=args.type, dest=args.dest, interval=1, + ssid=args.ssid, upstream=args.upstream_port, + password=args.passwd, security=args.security, test_duration=args.test_duration, + _debug_on=args.debug, radio=args.radio) + + generic_test.cleanup(station_list) + generic_test.build() + if not generic_test.passes(): + print(generic_test.get_fail_message()) + exit(1) + generic_test.start() + if not generic_test.passes(): + print(generic_test.get_fail_message()) + exit(1) + generic_test.stop() + time.sleep(30) + generic_test.cleanup(station_list) + if generic_test.passes(): + print("Full test passed, all connections increased rx bytes") + + + +if __name__ == "__main__": + main() diff --git a/py-scripts/test_ipv4_connection.py b/py-scripts/test_ipv4_connection.py new file mode 100644 index 00000000..0fddcd7c --- /dev/null +++ b/py-scripts/test_ipv4_connection.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 + + +import sys +import os +import argparse + +if sys.version_info[0] != 3: + print("This script requires Python 3") + exit(1) + +if 'py-json' not in sys.path: + sys.path.append(os.path.join(os.path.abspath('..'), 'py-json')) +import LANforge +from LANforge.lfcli_base import LFCliBase +from LANforge import LFUtils +import realm +import time +import pprint + + +class IPv4Test(LFCliBase): + def __init__(self, host, port, ssid, security, password, sta_list=None, number_template="00000", _debug_on=False, + _exit_on_error=False, + _exit_on_fail=False): + super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) + self.host = host + self.port = port + self.ssid = ssid + self.security = security + self.password = password + self.sta_list = sta_list + self.timeout = 120 + self.number_template = number_template + self.debug = _debug_on + self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port) + self.station_profile = self.local_realm.new_station_profile() + + self.station_profile.lfclient_url = self.lfclient_url + self.station_profile.ssid = self.ssid + self.station_profile.ssid_pass = self.password, + self.station_profile.security = self.security + self.station_profile.number_template_ = self.number_template + self.station_profile.mode = 0 + + def build(self): + # Build stations + self.station_profile.use_security(self.security, self.ssid, self.password) + self.station_profile.set_number_template(self.number_template) + print("Creating stations") + self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) + self.station_profile.set_command_param("set_port", "report_timer", 1500) + self.station_profile.set_command_flag("set_port", "rpt_timer", 1) + self.station_profile.create(radio="wiphy0", sta_names_=self.sta_list, debug=self.debug) + self._pass("PASS: Station build finished") + + def start(self, sta_list, print_pass, print_fail): + self.station_profile.admin_up() + associated_map = {} + ip_map = {} + print("Starting test...") + for sec in range(self.timeout): + for sta_name in sta_list: + sta_status = self.json_get("port/1/1/" + sta_name + "?fields=port,alias,ip,ap", debug_=self.debug) + # print(sta_status) + if sta_status is None or sta_status['interface'] is None or sta_status['interface']['ap'] is None: + continue + if len(sta_status['interface']['ap']) == 17 and sta_status['interface']['ap'][-3] == ':': + # print("Associated", sta_name, sta_status['interface']['ap'], sta_status['interface']['ip']) + associated_map[sta_name] = 1 + if sta_status['interface']['ip'] != '0.0.0.0': + # print("IP", sta_name, sta_status['interface']['ap'], sta_status['interface']['ip']) + ip_map[sta_name] = 1 + if (len(sta_list) == len(ip_map)) and (len(sta_list) == len(associated_map)): + break + else: + time.sleep(1) + + if self.debug: + print("sta_list", len(sta_list), sta_list) + print("ip_map", len(ip_map), ip_map) + print("associated_map", len(associated_map), associated_map) + if (len(sta_list) == len(ip_map)) and (len(sta_list) == len(associated_map)): + self._pass("PASS: All stations associated with IP", print_pass) + else: + self._fail("FAIL: Not all stations able to associate/get IP", print_fail) + print("sta_list", sta_list) + print("ip_map", ip_map) + print("associated_map", associated_map) + + return self.passes() + + def stop(self): + # Bring stations down + for sta_name in self.sta_list: + data = LFUtils.portDownRequest(1, sta_name) + url = "cli-json/set_port" + # print(sta_name) + self.json_post(url, data) + + def cleanup(self, sta_list): + self.station_profile.cleanup(sta_list) + LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=sta_list, + debug=self.debug) + +def main(): + #Params for different tests: + # + # + # + # + # + lfjson_host = "localhost" + lfjson_port = 8080 + + parser = LFCliBase.create_basic_argparse( + prog='test_ipv4_connection.py', + #formatter_class=argparse.RawDescriptionHelpFormatter, + formatter_class=argparse.RawTextHelpFormatter, + epilog='''\ + Useful Information: + 1. TBD + ''', + + description='''\ + test_ipv4_variable_tim.py: + -------------------- + TBD + + Generic command layout: + python ./test_ipv4_variable_time.py --upstream_port --radio --debug + + Note: multiple --radio switches may be entered up to the number of radios available: + --radio --radio + + python3 ./test_ipv4_variable_time.py --upstream_port eth1 --radio wiphy0 32 candelaTech-wpa2-x2048-4-1 candelaTech-wpa2-x2048-4-1 wpa2 --radio wiphy1 64 candelaTech-wpa2-x2048-5-3 candelaTech-wpa2-x2048-5-3 wpa2 + + ''') + + + args = parser.parse_args() + station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000) + ip_test = IPv4Test(lfjson_host, lfjson_port, ssid=args.ssid, password=args.passwd, + security=args.security, sta_list=station_list) + ip_test.cleanup(station_list) + #ip_test.timeout = 60 + ip_test.build() + if not ip_test.passes(): + print(ip_test.get_fail_message()) + exit(1) + ip_test.start(station_list, False, False) + ip_test.stop() + if not ip_test.passes(): + print(ip_test.get_fail_message()) + exit(1) + time.sleep(30) + ip_test.cleanup(station_list) + if ip_test.passes(): + print("Full test passed, all stations associated and got IP") + + +if __name__ == "__main__": + main() diff --git a/py-scripts/test_ipv4_l4.py b/py-scripts/test_ipv4_l4.py index 7ea3d86e..0458cf8d 100755 --- a/py-scripts/test_ipv4_l4.py +++ b/py-scripts/test_ipv4_l4.py @@ -13,21 +13,24 @@ import argparse from LANforge.lfcli_base import LFCliBase from LANforge.LFUtils import * from LANforge import LFUtils +import argparse import realm import time import datetime class IPV4L4(LFCliBase): - def __init__(self, host, port, ssid, security, password, url, requests_per_ten, station_list, number_template="00000", - resource=1, - test_duration="5m", + def __init__(self, host, port, ssid, security, password, url, requests_per_ten, station_list, + number_template="00000", radio="wiphy0", + test_duration="5m", upstream_port="eth1", _debug_on=False, _exit_on_error=False, _exit_on_fail=False): super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) self.host = host self.port = port + self.radio = radio + self.upstream_port = upstream_port self.ssid = ssid self.security = security self.password = password @@ -35,7 +38,6 @@ class IPV4L4(LFCliBase): self.requests_per_ten = requests_per_ten self.number_template = number_template self.sta_list = station_list - self.resource = resource self.test_duration = test_duration self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port) @@ -78,7 +80,7 @@ class IPV4L4(LFCliBase): if cx_name != 'uri' and cx_name != 'handler': for item, value in cx_name.items(): for value_name, value_rx in value.items(): - if value_name == 'bytes-rd': + if item in self.cx_profile.created_cx.keys() and value_name == 'bytes-rd': cx_map[item] = value_rx return cx_map @@ -90,22 +92,24 @@ class IPV4L4(LFCliBase): self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) self.station_profile.set_command_param("set_port", "report_timer", 1500) self.station_profile.set_command_flag("set_port", "rpt_timer", 1) - self.station_profile.create(resource=1, radio="wiphy0", sta_names_=self.sta_list, debug=self.debug) + self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug) self._pass("PASS: Station build finished") - temp_sta_list = [] - for station in range(len(self.sta_list)): - temp_sta_list.append(str(self.resource) + "." + self.sta_list[station]) - self.cx_profile.create(ports=temp_sta_list, sleep_time=.5, debug_=self.debug, suppress_related_commands_=None) + self.cx_profile.create(ports=self.station_profile.station_names, sleep_time=.5, debug_=self.debug, + suppress_related_commands_=None) def start(self, print_pass=False, print_fail=False): temp_stas = self.sta_list.copy() - temp_stas.append("eth1") - self.local_realm.wait_for_ip(self.resource, temp_stas) + temp_stas.append(self.local_realm.name_to_eid(self.upstream_port)[2]) + if self.local_realm.wait_for_ip(temp_stas): + self._pass("All stations got IPs", print_pass) + else: + self._fail("Stations failed to get IPs", print_fail) + exit(1) cur_time = datetime.datetime.now() old_rx_values = self.__get_values() end_time = self.local_realm.parse_time(self.test_duration) + cur_time - self.station_profile.admin_up(1) + self.station_profile.admin_up() self.cx_profile.start_cx() passes = 0 expected_passes = 0 @@ -135,24 +139,58 @@ class IPV4L4(LFCliBase): def stop(self): self.cx_profile.stop_cx() for sta_name in self.sta_list: - data = LFUtils.portDownRequest(1, sta_name) - url = "json-cli/set_port" + data = LFUtils.port_down_request(1, self.local_realm.name_to_eid(sta_name)[2]) + url = "cli-json/set_port" self.json_post(url, data) def cleanup(self, sta_list): self.cx_profile.cleanup() - self.station_profile.cleanup(self.resource, sta_list) - LFUtils.wait_until_ports_disappear(resource_id=self.resource, base_url=self.lfclient_url, port_list=sta_list, + self.station_profile.cleanup(sta_list) + LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=sta_list, debug=self.debug) def main(): lfjson_host = "localhost" lfjson_port = 8080 - station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000) - ip_test = IPV4L4(lfjson_host, lfjson_port, ssid="jedway-wpa2-x2048-4-4", password="jedway-wpa2-x2048-4-4", - security="wpa2", station_list=station_list, url="dl http://10.40.0.1 /dev/null", test_duration="5m", - requests_per_ten=600, _debug_on=False) + + parser = LFCliBase.create_basic_argparse( + prog='test_generic.py', + # formatter_class=argparse.RawDescriptionHelpFormatter, + formatter_class=argparse.RawTextHelpFormatter, + epilog='''\ + Useful Information: + 1. TBD + ''', + + description='''\ + test_generic.py: + -------------------- + TBD + + Generic command layout: + python ./test_ipv4_l4.py --upstream_port --radio --debug + + Note: multiple --radio switches may be entered up to the number of radios available: + --radio --radio + + python3 ./test_ipv4_l4.py --upstream_port eth1 --radio wiphy0 32 candelaTech-wpa2-x2048-4-1 candelaTech-wpa2-x2048-4-1 wpa2 --radio wiphy1 64 candelaTech-wpa2-x2048-5-3 candelaTech-wpa2-x2048-5-3 wpa2 + + ''') + + parser.add_argument('--test_duration', help='--test_duration sets the duration of the test', default="5m") + parser.add_argument('--requests_per_ten', help='--requests_per_ten number of request per ten minutes', default=600) + parser.add_argument('--url', help='--url specifies upload/download, address, and dest', default="dl http://10.40.0.1 /dev/null") + + args = parser.parse_args() + + station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000, + radio=args.radio) + + ip_test = IPV4L4(args.mgr, lfjson_port, ssid=args.ssid, password=args.passwd, + security=args.security, station_list=station_list, url=args.url, + test_duration=args.test_duration, upstream_port=args.upstream_port, + requests_per_ten=args.requests_per_ten, _debug_on=args.debug) ip_test.cleanup(station_list) ip_test.build() if not ip_test.passes(): diff --git a/py-scripts/test_ipv4_l4_ftp_upload.py b/py-scripts/test_ipv4_l4_ftp_upload.py new file mode 100755 index 00000000..25fc441f --- /dev/null +++ b/py-scripts/test_ipv4_l4_ftp_upload.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python3 + +import sys + +if sys.version_info[0] != 3: + print("This script requires Python 3") + exit(1) + +if 'py-json' not in sys.path: + sys.path.append('../py-json') + +import argparse +from LANforge.lfcli_base import LFCliBase +from LANforge.LFUtils import * +from LANforge import LFUtils +import realm +import time +import datetime + + +class IPV4L4(LFCliBase): + def __init__(self, host, port, ssid, security, password, url, requests_per_ten, station_list, number_template="00000", + upstream_port="eth1", radio="wiphy0", + test_duration="5m", + _debug_on=False, + _exit_on_error=False, + _exit_on_fail=False): + super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) + self.host = host + self.port = port + self.ssid = ssid + self.radio = radio + self.upstream_port = upstream_port + self.security = security + self.password = password + self.url = url + self.requests_per_ten = requests_per_ten + self.number_template = number_template + self.sta_list = station_list + self.test_duration = test_duration + + self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port) + self.station_profile = self.local_realm.new_station_profile() + self.cx_profile = self.local_realm.new_l4_cx_profile() + + self.station_profile.lfclient_url = self.lfclient_url + self.station_profile.ssid = self.ssid + self.station_profile.ssid_pass = self.password, + self.station_profile.security = self.security + self.station_profile.number_template_ = self.number_template + self.station_profile.mode = 0 + + self.cx_profile.url = self.url + self.cx_profile.requests_per_ten = self.requests_per_ten + + self.port_util = realm.PortUtils(self.local_realm) + + def __compare_vals(self, old_list, new_list): + passes = 0 + expected_passes = 0 + if len(old_list) == len(new_list): + for item, value in old_list.items(): + expected_passes += 1 + if new_list[item] > old_list[item]: + passes += 1 + # print(item, old_list[item], new_list[item], passes, expected_passes) + + if passes == expected_passes: + return True + else: + return False + else: + return False + + def __get_values(self): + time.sleep(1) + cx_list = self.json_get("layer4/list?fields=name,bytes-rd", debug_=self.debug) + # print("==============\n", cx_list, "\n==============") + cx_map = {} + for cx_name in cx_list['endpoint']: + if cx_name != 'uri' and cx_name != 'handler': + for item, value in cx_name.items(): + for value_name, value_rx in value.items(): + if item in self.cx_profile.created_cx.keys() and value_name == 'bytes-wr': + cx_map[item] = value_rx + return cx_map + + def build(self): + # Build stations + self.station_profile.use_security(self.security, self.ssid, self.password) + self.station_profile.set_number_template(self.number_template) + print("Creating stations") + self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) + self.station_profile.set_command_param("set_port", "report_timer", 1500) + self.station_profile.set_command_flag("set_port", "rpt_timer", 1) + self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug) + self._pass("PASS: Station build finished") + + self.cx_profile.create(ports=self.station_profile.station_names, sleep_time=.5, debug_=self.debug, suppress_related_commands_=True) + + def start(self, print_pass=False, print_fail=False): + self.port_util.set_ftp(port_name=self.local_realm.name_to_eid(self.upstream_port)[2], resource=1, on=True) + temp_stas = self.sta_list.copy() + self.station_profile.admin_up() + temp_stas.append(self.local_realm.name_to_eid(self.upstream_port)[2]) + if self.local_realm.wait_for_ip(temp_stas): + self._pass("All stations got IPs", print_pass) + else: + self._fail("Stations failed to get IPs", print_fail) + exit(1) + cur_time = datetime.datetime.now() + old_rx_values = self.__get_values() + end_time = self.local_realm.parse_time(self.test_duration) + cur_time + self.cx_profile.start_cx() + passes = 0 + expected_passes = 0 + print("Starting Test...") + while cur_time < end_time: + interval_time = cur_time + datetime.timedelta(minutes=1) + while cur_time < interval_time: + cur_time = datetime.datetime.now() + time.sleep(1) + + new_rx_values = self.__get_values() + # print(old_rx_values, new_rx_values) + # print("\n-----------------------------------") + # print(cur_time, end_time, cur_time + datetime.timedelta(minutes=1)) + # print("-----------------------------------\n") + 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 + cur_time = datetime.datetime.now() + if passes == expected_passes: + self._pass("PASS: All tests passes", print_pass) + + def stop(self): + self.port_util.set_ftp(port_name=self.local_realm.name_to_eid(self.upstream_port)[2], resource=1, on=False) + self.cx_profile.stop_cx() + self.station_profile.admin_down() + + def cleanup(self, sta_list): + self.cx_profile.cleanup() + self.station_profile.cleanup(sta_list) + LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=sta_list, + debug=self.debug) + + +def main(): + lfjson_port = 8080 + + parser = LFCliBase.create_basic_argparse( + prog='test_ipv4_l4_ftp', + # formatter_class=argparse.RawDescriptionHelpFormatter, + formatter_class=argparse.RawTextHelpFormatter, + epilog='''\ + Useful Information: + 1. TBD + ''', + + description='''\ + test_ipv4_l4_ftp_upload.py: + -------------------- + TBD + + Generic command layout: + python ./test_ipv4_l4_ftp_upload.py --upstream_port --radio --debug + + Note: multiple --radio switches may be entered up to the number of radios available: + --radio --radio + + python3 ./test_ipv4_l4_ftp_upload.py --upstream_port eth1 --radio wiphy0 32 candelaTech-wpa2-x2048-4-1 candelaTech-wpa2-x2048-4-1 wpa2 --radio wiphy1 64 candelaTech-wpa2-x2048-5-3 candelaTech-wpa2-x2048-5-3 wpa2 + + ''') + + parser.add_argument('--test_duration', help='--test_duration sets the duration of the test', default="5m") + parser.add_argument('--requests_per_ten', help='--requests_per_ten number of request per ten minutes', default=600) + parser.add_argument('--url', help='--url specifies upload/download, address, and dest', + default="ul ftp://10.40.0.1 /dev/null") + + args = parser.parse_args() + station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000, + radio=args.radio) + + ip_test = IPV4L4(args.mgr, lfjson_port, ssid=args.ssid, password=args.passwd, + security=args.security, station_list=station_list, url=args.url, test_duration=args.test_duration, + requests_per_ten=args.requests_per_ten, _debug_on=args.debug, upstream_port=args.upstream_port) + ip_test.cleanup(station_list) + ip_test.build() + if not ip_test.passes(): + print(ip_test.get_fail_message()) + exit(1) + ip_test.start(False, False) + ip_test.stop() + if not ip_test.passes(): + print(ip_test.get_fail_message()) + exit(1) + time.sleep(30) + ip_test.cleanup(station_list) + if ip_test.passes(): + print("Full test passed, all endpoints had increased bytes-rd throughout test duration") + + +if __name__ == "__main__": + main() diff --git a/py-scripts/test_ipv4_l4_ftp_urls_per_ten.py b/py-scripts/test_ipv4_l4_ftp_urls_per_ten.py new file mode 100755 index 00000000..2cd2fe6b --- /dev/null +++ b/py-scripts/test_ipv4_l4_ftp_urls_per_ten.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python3 + +import sys +import os +if sys.version_info[0] != 3: + print("This script requires Python 3") + exit(1) + +if 'py-json' not in sys.path: + sys.path.append(os.path.join(os.path.abspath('..'), 'py-json')) + +import argparse +from LANforge.lfcli_base import LFCliBase +from LANforge.LFUtils import * +from LANforge import LFUtils +import realm +import time +import datetime + + +class IPV4L4(LFCliBase): + def __init__(self, host, port, ssid, security, password, url, requests_per_ten, station_list, + target_requests_per_ten=60, number_template="00000", num_tests=1, radio="wiphy0", + _debug_on=False, upstream_port="eth1", + _exit_on_error=False, + _exit_on_fail=False): + super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) + self.host = host + self.port = port + self.radio = radio + self.upstream_port = upstream_port + self.ssid = ssid + self.security = security + self.password = password + self.url = url + self.requests_per_ten = requests_per_ten + self.number_template = number_template + self.sta_list = station_list + self.num_tests = num_tests + self.target_requests_per_ten = target_requests_per_ten + + self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port) + self.station_profile = self.local_realm.new_station_profile() + self.cx_profile = self.local_realm.new_l4_cx_profile() + + self.station_profile.lfclient_url = self.lfclient_url + self.station_profile.ssid = self.ssid + self.station_profile.ssid_pass = self.password, + self.station_profile.security = self.security + self.station_profile.number_template_ = self.number_template + self.station_profile.mode = 0 + self.cx_profile.url = self.url + self.cx_profile.requests_per_ten = self.requests_per_ten + + self.port_util = realm.PortUtils(self.local_realm) + + def __check_request_rate(self): + endp_list = self.json_get("layer4/list?fields=urls/s") + expected_passes = 0 + passes = 0 + if endp_list is not None and endp_list['endpoint'] is not None: + endp_list = endp_list['endpoint'] + for item in endp_list: + for name, info in item.items(): + if name in self.cx_profile.created_cx.keys(): + expected_passes += 1 + if info['urls/s'] * self.requests_per_ten >= self.target_requests_per_ten * .9: + # print(name, info['urls/s'], info['urls/s'] * self.requests_per_ten, self.target_requests_per_ten * .9) + passes += 1 + + return passes == expected_passes + + def build(self): + # Build stations + self.station_profile.use_security(self.security, self.ssid, self.password) + print("Creating stations") + self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) + self.station_profile.set_command_param("set_port", "report_timer", 1500) + self.station_profile.set_command_flag("set_port", "rpt_timer", 1) + self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug) + self._pass("PASS: Station build finished") + + self.cx_profile.create(ports=self.station_profile.station_names, sleep_time=.5, debug_=self.debug, suppress_related_commands_=None) + + def start(self, print_pass=False, print_fail=False): + self.port_util.set_ftp(port_name=self.local_realm.name_to_eid(self.upstream_port)[2], resource=1, on=True) + temp_stas = self.sta_list.copy() + temp_stas.append(self.local_realm.name_to_eid(self.upstream_port)[2]) + cur_time = datetime.datetime.now() + interval_time = cur_time + datetime.timedelta(minutes=10) + passes = 0 + expected_passes = 0 + self.station_profile.admin_up() + if self.local_realm.wait_for_ip(temp_stas): + self._pass("All stations got IPs", print_pass) + else: + self._fail("Stations failed to get IPs", print_fail) + exit(1) + self.cx_profile.start_cx() + print("Starting test") + for test in range(self.num_tests): + expected_passes += 1 + while cur_time < interval_time: + time.sleep(1) + cur_time = datetime.datetime.now() + + if self.cx_profile.check_errors(self.debug): + if self.__check_request_rate(): + passes += 1 + else: + self._fail("FAIL: Request rate did not exceed 90% target rate", print_fail) + break + else: + self._fail("FAIL: Errors found getting to %s " % self.url, print_fail) + break + interval_time = cur_time + datetime.timedelta(minutes=10) + if passes == expected_passes: + self._pass("PASS: All tests passes", print_pass) + + def stop(self): + self.cx_profile.stop_cx() + self.port_util.set_ftp(port_name=self.local_realm.name_to_eid(self.upstream_port)[2], resource=1, on=False) + self.station_profile.admin_down() + + def cleanup(self, sta_list): + self.cx_profile.cleanup() + self.station_profile.cleanup(sta_list) + LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=sta_list, + debug=self.debug) + + +def main(): + lfjson_port = 8080 + + parser = LFCliBase.create_basic_argparse( + prog='test_ipv4_l4_urls_per_ten', + # formatter_class=argparse.RawDescriptionHelpFormatter, + formatter_class=argparse.RawTextHelpFormatter, + epilog='''\ + Useful Information: + 1. TBD + ''', + + description='''\ + test_ipv4_l4_urls_per_ten.py: + -------------------- + TBD + + Generic command layout: + python ./test_ipv4_l4_urls_per_ten.py --upstream_port --radio --debug + + Note: multiple --radio switches may be entered up to the number of radios available: + --radio --radio + + python3 ./test_ipv4_l4_urls_per_ten.py --upstream_port eth1 --radio wiphy0 32 candelaTech-wpa2-x2048-4-1 candelaTech-wpa2-x2048-4-1 wpa2 --radio wiphy1 64 candelaTech-wpa2-x2048-5-3 candelaTech-wpa2-x2048-5-3 wpa2 + + ''') + + parser.add_argument('--requests_per_ten', help='--requests_per_ten number of request per ten minutes', default=600) + parser.add_argument('--num_tests', help='--num_tests number of tests to run. Each test runs 10 minutes', default=1) + parser.add_argument('--url', help='--url specifies upload/download, address, and dest', + default="dl http://10.40.0.1 /dev/null") + parser.add_argument('--target_per_ten', help='--target_per_ten target number of request per ten minutes. test will check for 90% this value', + default=600) + args = parser.parse_args() + + station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000, + radio=args.radio) + + ip_test = IPV4L4(args.mgr, lfjson_port, ssid=args.ssid, password=args.passwd, upstream_port=args.upstream_port, + security=args.security, station_list=station_list, url=args.url, num_tests=args.num_tests, + target_requests_per_ten=args.target_per_ten, + requests_per_ten=args.requests_per_ten) + ip_test.cleanup(station_list) + ip_test.build() + ip_test.start() + ip_test.stop() + if not ip_test.passes(): + print(ip_test.get_fail_message()) + exit(1) + time.sleep(30) + ip_test.cleanup(station_list) + if ip_test.passes(): + print("Full test passed, all endpoints met or exceeded 90% of the target rate") + + +if __name__ == "__main__": + main() diff --git a/py-scripts/test_ipv4_l4_urls_per_ten.py b/py-scripts/test_ipv4_l4_urls_per_ten.py index ee4cfdd0..d9d3b43e 100755 --- a/py-scripts/test_ipv4_l4_urls_per_ten.py +++ b/py-scripts/test_ipv4_l4_urls_per_ten.py @@ -20,13 +20,15 @@ import datetime class IPV4L4(LFCliBase): def __init__(self, host, port, ssid, security, password, url, requests_per_ten, station_list, - target_requests_per_ten=600, number_template="00000", resource=1, num_tests=1, - _debug_on=False, + target_requests_per_ten=60, number_template="00000", num_tests=1, radio="wiphy0", + _debug_on=False, upstream_port="eth1", _exit_on_error=False, _exit_on_fail=False): super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) self.host = host self.port = port + self.radio = radio + self.upstream_port = upstream_port self.ssid = ssid self.security = security self.password = password @@ -34,7 +36,6 @@ class IPV4L4(LFCliBase): self.requests_per_ten = requests_per_ten self.number_template = number_template self.sta_list = station_list - self.resource = resource self.num_tests = num_tests self.target_requests_per_ten = target_requests_per_ten @@ -51,18 +52,6 @@ class IPV4L4(LFCliBase): self.cx_profile.url = self.url self.cx_profile.requests_per_ten = self.requests_per_ten - def __set_all_cx_state(self, state, sleep_time=5): - print("Setting CX States to %s" % state) - for sta_name in self.sta_list: - req_url = "cli-json/set_cx_state" - data = { - "test_mgr": "default_tm", - "cx_name": "CX_" + sta_name + "_l4", - "cx_state": state - } - self.json_post(req_url, data) - time.sleep(sleep_time) - def __check_request_rate(self): endp_list = self.json_get("layer4/list?fields=urls/s") expected_passes = 0 @@ -70,39 +59,41 @@ class IPV4L4(LFCliBase): if endp_list is not None and endp_list['endpoint'] is not None: endp_list = endp_list['endpoint'] for item in endp_list: - expected_passes += 1 for name, info in item.items(): - if info['urls/s'] * 600 > 600 * .9: - passes += 1 + if name in self.cx_profile.created_cx.keys(): + expected_passes += 1 + if info['urls/s'] * self.requests_per_ten >= self.target_requests_per_ten * .9: + # print(name, info['urls/s'], info['urls/s'] * self.requests_per_ten, self.target_requests_per_ten * .9) + passes += 1 return passes == expected_passes def build(self): # Build stations self.station_profile.use_security(self.security, self.ssid, self.password) - self.station_profile.set_number_template(self.number_template) print("Creating stations") self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) self.station_profile.set_command_param("set_port", "report_timer", 1500) self.station_profile.set_command_flag("set_port", "rpt_timer", 1) - self.station_profile.create(resource=1, radio="wiphy0", sta_names_=self.sta_list, debug=self.debug) + self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug) self._pass("PASS: Station build finished") - temp_sta_list = [] - for station in range(len(self.sta_list)): - temp_sta_list.append(str(self.resource) + "." + self.sta_list[station]) - self.cx_profile.create(ports=temp_sta_list, sleep_time=.5, debug_=self.debug, suppress_related_commands_=None) + self.cx_profile.create(ports=self.station_profile.station_names, sleep_time=.5, debug_=self.debug, suppress_related_commands_=None) def start(self, print_pass=False, print_fail=False): temp_stas = self.sta_list.copy() - temp_stas.append("eth1") - self.local_realm.wait_for_ip(self.resource, temp_stas) - self.cx_profile.start_cx() + temp_stas.append(self.local_realm.name_to_eid(self.upstream_port)[2]) cur_time = datetime.datetime.now() interval_time = cur_time + datetime.timedelta(minutes=10) passes = 0 expected_passes = 0 - self.station_profile.admin_up(1) + self.station_profile.admin_up() + if self.local_realm.wait_for_ip(temp_stas): + self._pass("All stations got IPs", print_pass) + else: + self._fail("Stations failed to get IPs", print_fail) + exit(1) + self.cx_profile.start_cx() print("Starting test") for test in range(self.num_tests): expected_passes += 1 @@ -125,26 +116,57 @@ class IPV4L4(LFCliBase): def stop(self): self.cx_profile.stop_cx() - for sta_name in self.sta_list: - data = LFUtils.portDownRequest(1, sta_name) - url = "json-cli/set_port" - self.json_post(url, data) + self.station_profile.admin_down() def cleanup(self, sta_list): self.cx_profile.cleanup() - self.station_profile.cleanup(self.resource, sta_list) - LFUtils.wait_until_ports_disappear(resource_id=self.resource, base_url=self.lfclient_url, port_list=sta_list, + self.station_profile.cleanup(sta_list) + LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=sta_list, debug=self.debug) def main(): - lfjson_host = "localhost" lfjson_port = 8080 - station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000) - ip_test = IPV4L4(lfjson_host, lfjson_port, ssid="jedway-wpa2-x2048-4-4", password="jedway-wpa2-x2048-4-4", - security="wpa2", station_list=station_list, url="dl http://10.40.0.1 /dev/null", num_tests=1, - target_requests_per_ten=600, - requests_per_ten=600) + + parser = LFCliBase.create_basic_argparse( + prog='test_ipv4_l4_urls_per_ten', + # formatter_class=argparse.RawDescriptionHelpFormatter, + formatter_class=argparse.RawTextHelpFormatter, + epilog='''\ + Useful Information: + 1. TBD + ''', + + description='''\ + test_ipv4_l4_urls_per_ten.py: + -------------------- + TBD + + Generic command layout: + python ./test_ipv4_l4_urls_per_ten.py --upstream_port --radio --debug + + Note: multiple --radio switches may be entered up to the number of radios available: + --radio --radio + + python3 ./test_ipv4_l4_urls_per_ten.py --upstream_port eth1 --radio wiphy0 32 candelaTech-wpa2-x2048-4-1 candelaTech-wpa2-x2048-4-1 wpa2 --radio wiphy1 64 candelaTech-wpa2-x2048-5-3 candelaTech-wpa2-x2048-5-3 wpa2 + + ''') + + parser.add_argument('--requests_per_ten', help='--requests_per_ten number of request per ten minutes', default=600) + parser.add_argument('--num_tests', help='--num_tests number of tests to run. Each test runs 10 minutes', default=1) + parser.add_argument('--url', help='--url specifies upload/download, address, and dest', + default="dl http://10.40.0.1 /dev/null") + parser.add_argument('--target_per_ten', help='--target_per_ten target number of request per ten minutes. test will check for 90% this value', + default=600) + args = parser.parse_args() + + station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000, + radio=args.radio) + + ip_test = IPV4L4(args.mgr, lfjson_port, ssid=args.ssid, password=args.passwd, upstream_port=args.upstream_port, + security=args.security, station_list=station_list, url=args.url, num_tests=args.num_tests, + target_requests_per_ten=args.target_per_ten, + requests_per_ten=args.requests_per_ten) ip_test.cleanup(station_list) ip_test.build() ip_test.start() diff --git a/py-scripts/test_ipv4_variable_time.py b/py-scripts/test_ipv4_variable_time.py index ce45bbed..04a69d46 100755 --- a/py-scripts/test_ipv4_variable_time.py +++ b/py-scripts/test_ipv4_variable_time.py @@ -19,22 +19,24 @@ import datetime class IPV4VariableTime(LFCliBase): - def __init__(self, host, port, ssid, security, password, sta_list, name_prefix, resource=1, + def __init__(self, host, port, ssid, security, password, sta_list, name_prefix, upstream, radio, side_a_min_rate=56, side_a_max_rate=0, side_b_min_rate=56, side_b_max_rate=0, - number_template="00000", test_duration="5m", + number_template="00000", test_duration="5m", use_ht160=False, _debug_on=False, _exit_on_error=False, _exit_on_fail=False): super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) + self.upstream = upstream self.host = host self.port = port self.ssid = ssid self.sta_list = sta_list self.security = security self.password = password + self.radio = radio self.number_template = number_template - self.resource = resource + self.debug = _debug_on self.name_prefix = name_prefix self.test_duration = test_duration self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port) @@ -43,10 +45,13 @@ class IPV4VariableTime(LFCliBase): self.station_profile.lfclient_url = self.lfclient_url self.station_profile.ssid = self.ssid - self.station_profile.ssid_pass = self.password, + self.station_profile.ssid_pass = self.password self.station_profile.security = self.security self.station_profile.number_template_ = self.number_template - self.station_profile.mode = 0 + self.station_profile.debug = self.debug + self.station_profile.use_ht160 = use_ht160 + if self.station_profile.use_ht160: + self.station_profile.mode = 9 self.cx_profile.host = self.host self.cx_profile.port = self.port @@ -58,14 +63,15 @@ class IPV4VariableTime(LFCliBase): def __get_rx_values(self): - cx_list = self.json_get("endp?fields=name,rx+bytes", debug_=True) + cx_list = self.json_get("endp?fields=name,rx+bytes", debug_=self.debug) + # print(self.cx_profile.created_cx.values()) #print("==============\n", cx_list, "\n==============") cx_rx_map = {} for cx_name in cx_list['endpoint']: if cx_name != 'uri' and cx_name != 'handler': for item, value in cx_name.items(): for value_name, value_rx in value.items(): - if value_name == 'rx bytes': + if value_name == 'rx bytes' and item in self.cx_profile.created_cx.values(): cx_rx_map[item] = value_rx return cx_rx_map @@ -87,10 +93,14 @@ class IPV4VariableTime(LFCliBase): return False def start(self, print_pass=False, print_fail=False): - self.station_profile.admin_up(self.resource) - temp_stas = self.sta_list.copy() - temp_stas.append("eth1") - self.local_realm.wait_for_ip(self.resource, temp_stas) + self.station_profile.admin_up() + temp_stas = self.station_profile.station_names.copy() + temp_stas.append(self.upstream) + if self.local_realm.wait_for_ip(temp_stas): + self._pass("All stations got IPs", print_pass) + else: + self._fail("Stations failed to get IPs", print_fail) + exit(1) cur_time = datetime.datetime.now() old_cx_rx_values = self.__get_rx_values() end_time = self.local_realm.parse_time(self.test_duration) + cur_time @@ -122,45 +132,77 @@ class IPV4VariableTime(LFCliBase): def stop(self): self.cx_profile.stop_cx() - for sta_name in self.sta_list: - data = LFUtils.portDownRequest(1, sta_name) - url = "json-cli/set_port" - self.json_post(url, data) + self.station_profile.admin_down() - def cleanup(self, sta_list): + def pre_cleanup(self): + self.cx_profile.cleanup_prefix() + for sta in self.sta_list: + self.local_realm.rm_port(sta, check_exists=True) + + def cleanup(self): self.cx_profile.cleanup() - self.station_profile.cleanup(self.resource, sta_list) - LFUtils.wait_until_ports_disappear(resource_id=self.resource, base_url=self.lfclient_url, port_list=sta_list, + self.station_profile.cleanup() + LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=self.station_profile.station_names, debug=self.debug) def build(self): + self.station_profile.use_security(self.security, self.ssid, self.password) self.station_profile.set_number_template(self.number_template) print("Creating stations") self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) self.station_profile.set_command_param("set_port", "report_timer", 1500) self.station_profile.set_command_flag("set_port", "rpt_timer", 1) - temp_sta_list = [] - for station in range(len(self.sta_list)): - temp_sta_list.append(str(self.resource) + "." + self.sta_list[station]) - self.station_profile.create(resource=1, radio="wiphy0", sta_names_=self.sta_list, debug=False) - self.cx_profile.create(endp_type="lf_udp", side_a=temp_sta_list, side_b="1.eth1", sleep_time=.5) + self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug) + self.cx_profile.create(endp_type="lf_udp", side_a=self.station_profile.station_names, side_b=self.upstream, sleep_time=0) self._pass("PASS: Station build finished") def main(): - lfjson_host = "localhost" lfjson_port = 8080 - station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=4, padding_number_=10000) - ip_var_test = IPV4VariableTime(lfjson_host, lfjson_port, number_template="00", sta_list=station_list, - name_prefix="var_time", - ssid="jedway-wpa2-x2048-4-4", - password="jedway-wpa2-x2048-4-4", - resource=1, - security="wpa2", test_duration="5m", - side_a_min_rate=256, side_b_min_rate=256) - ip_var_test.cleanup(station_list) + parser = LFCliBase.create_basic_argparse( + prog='test_ipv4_variable_time.py', + #formatter_class=argparse.RawDescriptionHelpFormatter, + formatter_class=argparse.RawTextHelpFormatter, + epilog='''\ + Useful Information: + 1. TBD + ''', + + description='''\ +test_ipv4_variable_time.py: +-------------------- +TBD + +Generic command layout: +python ./test_ipv4_variable_time.py --upstream_port --radio --debug + +Note: multiple --radio switches may be entered up to the number of radios available: + --radio --radio + + python3 ./test_ipv4_variable_time.py --upstream_port eth1 --radio wiphy0 32 candelaTech-wpa2-x2048-4-1 candelaTech-wpa2-x2048-4-1 wpa2 --radio wiphy1 64 candelaTech-wpa2-x2048-5-3 candelaTech-wpa2-x2048-5-3 wpa2 + + ''') + + parser.add_argument('--a_min', help='--a_min bps rate minimum for side_a', default=256000) + parser.add_argument('--b_min', help='--b_min bps rate minimum for side_b', default=256000) + parser.add_argument('--test_duration', help='--test_duration sets the duration of the test', default="5m") + + args = parser.parse_args() + + station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000, radio=args.radio) + + ip_var_test = IPV4VariableTime(args.mgr, lfjson_port, number_template="00", sta_list=station_list, + name_prefix="VT", + upstream=args.upstream_port, + ssid=args.ssid, + password=args.passwd, + radio=args.radio, + security=args.security, test_duration=args.test_duration, use_ht160=False, + side_a_min_rate=args.a_min, side_b_min_rate=args.b_min, _debug_on=args.debug) + + ip_var_test.pre_cleanup() ip_var_test.build() if not ip_var_test.passes(): print(ip_var_test.get_fail_message()) @@ -171,7 +213,7 @@ def main(): print(ip_var_test.get_fail_message()) exit(1) time.sleep(30) - ip_var_test.cleanup(station_list) + ip_var_test.cleanup() if ip_var_test.passes(): print("Full test passed, all connections increased rx bytes") diff --git a/py-scripts/test_ipv6_connection.py b/py-scripts/test_ipv6_connection.py index 3b3ee89f..91823620 100755 --- a/py-scripts/test_ipv6_connection.py +++ b/py-scripts/test_ipv6_connection.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import sys - +import os if sys.version_info[0] != 3: print("This script requires Python 3") exit(1) @@ -11,28 +11,31 @@ if 'py-json' not in sys.path: import LANforge from LANforge.lfcli_base import LFCliBase from LANforge import LFUtils +import argparse import realm import time import pprint class IPv6Test(LFCliBase): - def __init__(self, host, port, ssid, security, password, resource=1, sta_list=None, num_stations=0, prefix="00000", - _debug_on=False, + def __init__(self, host, port, ssid, security, password, sta_list=None, num_stations=0, prefix="00000", + _debug_on=False, timeout=120, radio="wiphy0", _exit_on_error=False, - _exit_on_fail=False): + _exit_on_fail=False, + number_template="00"): super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) self.host = host self.port = port self.ssid = ssid + self.radio = radio self.security = security self.password = password self.num_stations = num_stations self.sta_list = sta_list - self.timeout = 120 - self.resource = resource + self.timeout = timeout self.prefix = prefix self.debug = _debug_on + self.number_template = number_template self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port) self.station_profile = self.local_realm.new_station_profile() @@ -45,22 +48,26 @@ class IPv6Test(LFCliBase): def build(self): self.station_profile.use_security(self.security, self.ssid, self.password) - self.profile.set_number_template(self.prefix) + self.station_profile.set_number_template(self.prefix) print("Creating stations") - self.profile.set_command_flag("add_sta", "create_admin_down", 1) - self.profile.set_command_param("set_port", "report_timer", 1500) - self.profile.set_command_flag("set_port", "rpt_timer", 1) - self.profile.create(resource=1, radio="wiphy0", sta_names_=self.sta_list, debug=False) + self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) + self.station_profile.set_command_param("set_port", "report_timer", 1500) + self.station_profile.set_command_flag("set_port", "rpt_timer", 1) + self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug) self._pass("PASS: Station build finished") def start(self, sta_list, print_pass, print_fail): - self.profile.admin_up(1) + self.station_profile.admin_up() associated_map = {} ip_map = {} print("Starting test...") for sec in range(self.timeout): for sta_name in sta_list: - sta_status = self.json_get("port/1/1/" + sta_name + "?fields=port,alias,ipv6+address,ap", debug_=self.debug) + shelf = self.local_realm.name_to_eid(sta_name)[0] + resource = self.local_realm.name_to_eid(sta_name)[1] + name = self.local_realm.name_to_eid(sta_name)[2] + sta_status = self.json_get("port/%s/%s/%s?fields=port,alias,ipv6+address,ap" % (shelf, resource, name), + debug_=self.debug) # print(sta_status) if sta_status is None or sta_status['interface'] is None or sta_status['interface']['ap'] is None: continue @@ -93,26 +100,52 @@ class IPv6Test(LFCliBase): def stop(self): # Bring stations down - for sta_name in self.sta_list: - data = LFUtils.portDownRequest(1, sta_name) - url = "json-cli/set_port" - # print(sta_name) - self.json_post(url, data) + self.station_profile.admin_down() def cleanup(self, sta_list): - self.profile.cleanup(self.resource, sta_list) - LFUtils.wait_until_ports_disappear(resource_id=self.resource, base_url=self.lfclient_url, port_list=sta_list, + self.station_profile.cleanup(sta_list) + LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=sta_list, debug=self.debug) def main(): - lfjson_host = "localhost" lfjson_port = 8080 - station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000) - ipv6_test = IPv6Test(lfjson_host, lfjson_port, ssid="jedway-wpa2-x2048-4-4", password="jedway-wpa2-x2048-4-4", - security="wpa2", sta_list=station_list) + + parser = LFCliBase.create_basic_argparse( + prog='test_ipv6_connection.py', + # formatter_class=argparse.RawDescriptionHelpFormatter, + formatter_class=argparse.RawTextHelpFormatter, + epilog='''\ + Useful Information: + 1. TBD + ''', + + description='''\ + test_ipv6_connection.py: + -------------------- + TBD + + Generic command layout: + python ./test_ipv6_connection.py --radio --debug + + Note: multiple --radio switches may be entered up to the number of radios available: + --radio --radio + + python3 ./test_ipv6_connection.py --upstream_port eth1 --radio wiphy0 32 candelaTech-wpa2-x2048-4-1 candelaTech-wpa2-x2048-4-1 wpa2 --radio wiphy1 64 candelaTech-wpa2-x2048-5-3 candelaTech-wpa2-x2048-5-3 wpa2 + + ''') + + + parser.add_argument('--timeout', help='--timeout sets the length of time to wait until a connection is successful', default=120) + + args = parser.parse_args() + + station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000, + radio=args.radio) + + ipv6_test = IPv6Test(args.mgr, lfjson_port, ssid=args.ssid, password=args.passwd, + security=args.security, sta_list=station_list) ipv6_test.cleanup(station_list) - ipv6_test.timeout = 60 ipv6_test.build() if not ipv6_test.passes(): print(ipv6_test.get_fail_message()) @@ -122,7 +155,7 @@ def main(): if not ipv6_test.passes(): print(ipv6_test.get_fail_message()) exit(1) - time.sleep(30) + time.sleep(10) ipv6_test.cleanup(station_list) if ipv6_test.passes(): print("Full test passed, all stations associated and got IP") diff --git a/py-scripts/test_ipv6_variable_time.py b/py-scripts/test_ipv6_variable_time.py index c647ab95..d3f5abbd 100755 --- a/py-scripts/test_ipv6_variable_time.py +++ b/py-scripts/test_ipv6_variable_time.py @@ -19,24 +19,25 @@ import datetime class IPV6VariableTime(LFCliBase): - def __init__(self, host, port, ssid, security, password, name_prefix, sta_list, + def __init__(self, host, port, ssid, security, password, sta_list, name_prefix, upstream, radio, side_a_min_rate=56, side_a_max_rate=0, side_b_min_rate=56, side_b_max_rate=0, - number_template="00000", test_duration="5m", - resource=1, + number_template="00000", test_duration="5m", use_ht160=False, _debug_on=False, _exit_on_error=False, _exit_on_fail=False): super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) + self.upstream = upstream self.host = host self.port = port self.ssid = ssid self.sta_list = sta_list - self.name_prefix = name_prefix self.security = security self.password = password + self.radio = radio self.number_template = number_template - self.resource = resource + self.debug = _debug_on + self.name_prefix = name_prefix self.test_duration = test_duration self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port) self.station_profile = self.local_realm.new_station_profile() @@ -44,10 +45,13 @@ class IPV6VariableTime(LFCliBase): self.station_profile.lfclient_url = self.lfclient_url self.station_profile.ssid = self.ssid - self.station_profile.ssid_pass = self.password, + self.station_profile.ssid_pass = self.password self.station_profile.security = self.security self.station_profile.number_template_ = self.number_template - self.station_profile.mode = 0 + self.station_profile.debug = self.debug + self.station_profile.use_ht160 = use_ht160 + if self.station_profile.use_ht160: + self.station_profile.mode = 9 self.cx_profile.host = self.host self.cx_profile.port = self.port @@ -57,17 +61,17 @@ class IPV6VariableTime(LFCliBase): self.cx_profile.side_b_min_bps = side_b_min_rate self.cx_profile.side_b_max_bps = side_b_max_rate - def __get_rx_values(self): - cx_list = self.json_get("endp?fields=name,rx+bytes", debug_=True) - #print("==============\n", cx_list, "\n==============") + cx_list = self.json_get("endp?fields=name,rx+bytes", debug_=self.debug) + # print(self.cx_profile.created_cx.values()) + # print("==============\n", cx_list, "\n==============") cx_rx_map = {} for cx_name in cx_list['endpoint']: if cx_name != 'uri' and cx_name != 'handler': for item, value in cx_name.items(): for value_name, value_rx in value.items(): - if value_name == 'rx bytes': - cx_rx_map[item] = value_rx + if value_name == 'rx bytes' and item in self.cx_profile.created_cx.values(): + cx_rx_map[item] = value_rx return cx_rx_map def __compare_vals(self, old_list, new_list): @@ -88,11 +92,14 @@ class IPV6VariableTime(LFCliBase): return False def start(self, print_pass=False, print_fail=False): - print("Starting test") - self.station_profile.admin_up(self.resource) - temp_stas = self.sta_list.copy() - temp_stas.append("eth1") - self.local_realm.wait_for_ip(self.resource, temp_stas, ipv6=True) + self.station_profile.admin_up() + temp_stas = self.station_profile.station_names.copy() + temp_stas.append(self.upstream) + if self.local_realm.wait_for_ip(temp_stas, ipv4=False, ipv6=True): + self._pass("All stations got IPs", print_pass) + else: + self._fail("Stations failed to get IPs", print_fail) + exit(1) cur_time = datetime.datetime.now() old_cx_rx_values = self.__get_rx_values() end_time = self.local_realm.parse_time(self.test_duration) + cur_time @@ -124,43 +131,79 @@ class IPV6VariableTime(LFCliBase): def stop(self): self.cx_profile.stop_cx() - for sta_name in self.sta_list: - data = LFUtils.portDownRequest(1, sta_name) - url = "json-cli/set_port" - self.json_post(url, data) + self.station_profile.admin_down() - def cleanup(self, sta_list): + def pre_cleanup(self): + self.cx_profile.cleanup_prefix() + for sta in self.sta_list: + self.local_realm.rm_port(sta, check_exists=True) + + def cleanup(self): self.cx_profile.cleanup() - self.station_profile.cleanup(self.resource, sta_list) - LFUtils.wait_until_ports_disappear(resource_id=self.resource, base_url=self.lfclient_url, port_list=sta_list, + self.station_profile.cleanup() + LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=self.station_profile.station_names, debug=self.debug) def build(self): + self.station_profile.use_security(self.security, self.ssid, self.password) self.station_profile.set_number_template(self.number_template) print("Creating stations") self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) self.station_profile.set_command_param("set_port", "report_timer", 1500) self.station_profile.set_command_flag("set_port", "rpt_timer", 1) - temp_sta_list = [] - for station in range(len(self.sta_list)): - temp_sta_list.append(str(self.resource) + "." + self.sta_list[station]) - self.station_profile.create(resource=1, radio="wiphy0", sta_names_=self.sta_list, debug=False) - self.cx_profile.create(endp_type="lf_udp6", side_a=temp_sta_list, side_b="1.eth1", sleep_time=.5) + self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug) + self.cx_profile.create(endp_type="lf_udp", side_a=self.station_profile.station_names, side_b=self.upstream, + sleep_time=0) self._pass("PASS: Station build finished") def main(): - lfjson_host = "localhost" lfjson_port = 8080 - station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000) - ip_var_test = IPV6VariableTime(lfjson_host, lfjson_port, number_template="00", sta_list=station_list, - name_prefix="var_time", - ssid="jedway-wpa2-x2048-4-4", - password="jedway-wpa2-x2048-4-4", - resource=1, security="wpa2", test_duration="5m", - side_a_min_rate=256, side_b_min_rate=256) - ip_var_test.cleanup(station_list) + + parser = LFCliBase.create_basic_argparse( + prog='test_ipv6_variable_time.py', + # formatter_class=argparse.RawDescriptionHelpFormatter, + formatter_class=argparse.RawTextHelpFormatter, + epilog='''\ + Useful Information: + 1. TBD + ''', + + description='''\ +test_ipv6_variable_time.py: +-------------------- +TBD + +Generic command layout: +python ./test_ipv6_variable_time.py --upstream_port --radio --debug + +Note: multiple --radio switches may be entered up to the number of radios available: + --radio --radio + + python3 ./test_ipv6_variable_time.py --upstream_port eth1 --radio wiphy0 32 candelaTech-wpa2-x2048-4-1 candelaTech-wpa2-x2048-4-1 wpa2 --radio wiphy1 64 candelaTech-wpa2-x2048-5-3 candelaTech-wpa2-x2048-5-3 wpa2 + + ''') + + parser.add_argument('--a_min', help='--a_min bps rate minimum for side_a', default=256000) + parser.add_argument('--b_min', help='--b_min bps rate minimum for side_b', default=256000) + parser.add_argument('--test_duration', help='--test_duration sets the duration of the test', default="5m") + + args = parser.parse_args() + + station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000, + radio=args.radio) + + ip_var_test = IPV6VariableTime(args.mgr, lfjson_port, number_template="00", sta_list=station_list, + name_prefix="VT", + upstream=args.upstream_port, + ssid=args.ssid, + password=args.passwd, + radio=args.radio, + security=args.security, test_duration=args.test_duration, use_ht160=False, + side_a_min_rate=args.a_min, side_b_min_rate=args.b_min, _debug_on=args.debug) + + ip_var_test.pre_cleanup() ip_var_test.build() if not ip_var_test.passes(): print(ip_var_test.get_fail_message()) @@ -171,7 +214,7 @@ def main(): print(ip_var_test.get_fail_message()) exit(1) time.sleep(30) - ip_var_test.cleanup(station_list) + ip_var_test.cleanup() if ip_var_test.passes(): print("Full test passed, all connections increased rx bytes") diff --git a/py-scripts/test_l3_WAN_LAN.py b/py-scripts/test_l3_WAN_LAN.py new file mode 100755 index 00000000..a58b7887 --- /dev/null +++ b/py-scripts/test_l3_WAN_LAN.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python3 + +import sys +import os + +if sys.version_info[0] != 3: + print("This script requires Python 3") + exit(1) + +if 'py-json' not in sys.path: + sys.path.append(os.path.join(os.path.abspath('..'), 'py-json')) + +import argparse +from LANforge.lfcli_base import LFCliBase +from LANforge import LFUtils +import realm +import time +import pprint +import datetime + +class L3LANtoWAN(LFCliBase): + def __init__(self, host, port, ssid, security, password, resource=1, sta_list=None, number_template="00000", _debug_on=True, + _exit_on_error=False, + _exit_on_fail=False): + super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) + self.host = host + self.port = port + self.ssid = ssid + self.security = security + self.password = password + self.sta_list = sta_list + self.resource = resource + self.timeout = 120 + self.number_template = number_template + self.debug = _debug_on + self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port) + + #build bridge and rdd pair + def build(self): + # Build bridge + req_url_br = "cli-json/add_br" + data_br = { + "shelf": 1, + "resource": 1, + "port": 'br0', + "network_devs": 'rd0a', + "br_flags": 0, + "br_priority": 65535, + "br_aging_time": -1, + "br_max_age": -1, + "br_hello_time": -1, + "br_forwarding_delay":-1 + + } + + super().json_post(req_url_br, data_br, debug_ = self.debug) + + #set port json post + req_url_set_port = "cli-json/set_port" + data_set_port = { + "shelf": 1, + "resource": 1, + "port": 'br0', + "current_flags": 131072, + "interest": 8548171804, + "report_timer": 3000, + "br_priority": 65535, + "br_aging_time": -1, + "br_max_age": -1, + "br_hello_time": -1, + "br_forwarding_delay":-1, + "br_port_cost": -1, + "br_port_priority":255, + "current_flags_msk": 135107988821114880 + } + super().json_post(req_url_set_port, data_set_port, debug_ = self.debug) + + #add_vrcx + req_url_add_vrcx= "cli-json/add_vcrx" + data_add_vrcx = { + "shelf": 1, + "resource": 1, + "vr_name": 'Router-0', + "local_dev": 'br-0', + "x": 583, + "y": 117, + "width": 10, + "height": 10, + "flags": 257, + "subnets": '5.0.0.0/16', + "nexthop":'10.40.11.202', + "dhcp_lease_time": 43200, + "dhcp_dns":'0.0.0.0', + "interface_cost": 1, + "rip_metric": 1, + "vrrp_ip_prefix": 25, + "vrrp_id":1, + "vrrp_priority":100, + "vrrp_interval":1 + } + super().json_post(req_url_add_vrcx, data_add_vrcx, debug_ = self.debug) + + #add_vrcx2 + req_url_add_vrcx2= "cli-json/add_vrcx2" + data_add_vrcx2 = { + "shelf": 1, + "resource": 1, + "vr_name": 'Router-0', + "local_dev": 'br-0', + } + super().json_post(req_url_add_vrcx2, data_add_vrcx2, debug_ = self.debug) + + + + def start(self, sta_list, print_pass, print_fail): + self.station_profile.admin_up(1) + associated_map = {} + ip_map = {} + print("Starting test...") + for sec in range(self.timeout): + for sta_name in sta_list: + sta_status = self.json_get("port/1/1/" + sta_name + "?fields=port,alias,ip,ap", debug_=self.debug) + # print(sta_status) + if sta_status is None or sta_status['interface'] is None or sta_status['interface']['ap'] is None: + continue + if len(sta_status['interface']['ap']) == 17 and sta_status['interface']['ap'][-3] == ':': + # print("Associated", sta_name, sta_status['interface']['ap'], sta_status['interface']['ip']) + associated_map[sta_name] = 1 + if sta_status['interface']['ip'] != '0.0.0.0': + # print("IP", sta_name, sta_status['interface']['ap'], sta_status['interface']['ip']) + ip_map[sta_name] = 1 + if (len(sta_list) == len(ip_map)) and (len(sta_list) == len(associated_map)): + break + else: + time.sleep(1) + + if self.debug: + print("sta_list", len(sta_list), sta_list) + print("ip_map", len(ip_map), ip_map) + print("associated_map", len(associated_map), associated_map) + if (len(sta_list) == len(ip_map)) and (len(sta_list) == len(associated_map)): + self._pass("PASS: All stations associated with IP", print_pass) + else: + self._fail("FAIL: Not all stations able to associate/get IP", print_fail) + print("sta_list", sta_list) + print("ip_map", ip_map) + print("associated_map", associated_map) + + return self.passes() + + def stop(self): + # Bring stations down + for sta_name in self.sta_list: + data = LFUtils.portDownRequest(1, sta_name) + url = "cli-json/set_port" + # print(sta_name) + self.json_post(url, data) + + def cleanup(self, sta_list): + self.station_profile.cleanup(self.resource, sta_list) + LFUtils.wait_until_ports_disappear(resource_id=self.resource, base_url=self.lfclient_url, port_list=sta_list, + debug=self.debug) + +def main(): + lfjson_host = "localhost" + lfjson_port = 8080 + station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=1, padding_number_=10000) + ip_test = L3LANtoWAN(lfjson_host, lfjson_port, ssid="jedway-open-1", password="[BLANK]", + security="open", sta_list=station_list,_debug_on=False) + #ip_test.cleanup(station_list) + ip_test.timeout = 60 + ip_test.build() + if not ip_test.passes(): + print(ip_test.get_fail_message()) + exit(1) + #ip_test.start(station_list, False, False) + #ip_test.stop() + #if not ip_test.passes(): + # print(ip_test.get_fail_message()) + # exit(1) + #time.sleep(30) + #ip_test.cleanup(station_list) + #if ip_test.passes(): + # print("Full test passed, all stations associated and got IP") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/py-scripts/test_l3_longevity.py b/py-scripts/test_l3_longevity.py old mode 100644 new mode 100755 index 413bcfa7..9245818b --- a/py-scripts/test_l3_longevity.py +++ b/py-scripts/test_l3_longevity.py @@ -16,49 +16,54 @@ from LANforge import LFUtils import realm import time import datetime +import subprocess +import re + class L3VariableTimeLongevity(LFCliBase): - def __init__(self, host, port, endp_type, side_b, radios, radio_name_list, number_of_stations_per_radio_list, - ssid_list, ssid_password_list, security, station_lists, name_prefix, resource=1, - side_a_min_rate=56, side_a_max_rate=0, - side_b_min_rate=56, side_b_max_rate=0, + 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, + 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", - _debug_on=False, _exit_on_error=False, _exit_on_fail=False): - super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) + super().__init__(host, port, _debug=debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) self.host = host self.port = port - self.endp_type = endp_type + self.tos = tos.split() + self.endp_types = endp_types.split() self.side_b = side_b self.ssid_list = ssid_list self.ssid_password_list = ssid_password_list self.station_lists = station_lists - self.security = security + self.ssid_security_list = ssid_security_list self.number_template = number_template - self.resource = resource self.name_prefix = name_prefix self.test_duration = test_duration - self.cx_stations_lists = station_lists self.radios = radios # from the command line self.radio_list = radio_name_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) + self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port, debug_=debug_on) self.cx_profile = self.local_realm.new_l3_cx_profile() + self.multicast_profile = self.local_realm.new_multicast_profile() + self.multicast_profile.name_prefix = "MLT-"; self.station_profiles = [] - + self.args = args + index = 0 for radio in radios: self.station_profile = self.local_realm.new_station_profile() self.station_profile.lfclient_url = self.lfclient_url self.station_profile.ssid = ssid_list[index] self.station_profile.ssid_pass = ssid_password_list[index] - self.station_profile.security = self.security + self.station_profile.security = ssid_security_list[index] self.station_profile.number_template = self.number_template self.station_profile.mode = 0 self.station_profiles.append(self.station_profile) index += 1 + self.multicast_profile.host = self.host self.cx_profile.host = self.host self.cx_profile.port = self.port self.cx_profile.name_prefix = self.name_prefix @@ -68,48 +73,116 @@ class L3VariableTimeLongevity(LFCliBase): self.cx_profile.side_b_max_bps = side_b_max_rate def __get_rx_values(self): - cx_list = self.json_get("endp?fields=name,rx+bytes", debug_=True) - cx_rx_map = {} - for cx_name in cx_list['endpoint']: - if cx_name != 'uri' and cx_name != 'handler': - for item, value in cx_name.items(): - for value_name, value_rx in value.items(): - if value_name == 'rx bytes': - cx_rx_map[item] = value_rx - return cx_rx_map + endp_list = self.json_get("endp?fields=name,rx+bytes", debug_=True) + endp_rx_map = {} + our_endps = {} + for e in self.multicast_profile.get_mc_names(): + our_endps[e] = e; + for e in self.cx_profile.created_endp.keys(): + 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(): + if item in our_endps: + for value_name, value_rx in value.items(): + if value_name == 'rx bytes': + endp_rx_map[item] = value_rx + return endp_rx_map def __compare_vals(self, old_list, new_list): passes = 0 expected_passes = 0 if len(old_list) == len(new_list): for item, value in old_list.items(): - expected_passes += 1 - if new_list[item] > old_list[item]: + expected_passes +=1 + if item.startswith("mtx"): + # We ignore the mcast transmitter. + # This is a hack based on naming and could be improved. passes += 1 + 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]) + if passes == expected_passes: return True else: return False 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) return False + def verify_controller(self): + if self.args == None: + return + + if self.args.cisco_ctlr == None: + return + + advanced = subprocess.run(["../cisco_wifi_ctl.py", "--scheme", "ssh", "-d", self.args.cisco_ctlr, "-u", + self.args.cisco_user, "-p", self.args.cisco_passwd, + "-a", self.args.cisco_ap, "--action", "summary"], capture_output=True) + pss = advanced.stdout.decode('utf-8', 'ignore'); + print(pss) + + # Find our station count + searchap = False + for line in pss.splitlines(): + if (line.startswith("---------")): + searchap = True + continue + + if (searchap): + pat = "%s\s+\S+\s+\S+\s+\S+\s+\S+.* \S+\s+\S+\s+(\S+)\s+\["%(self.args.cisco_ap) + #print("AP line: %s"%(line)) + m = re.search(pat, line) + if (m != None): + sta_count = m.group(1) + print("AP line: %s"%(line)) + print("sta-count: %s"%(sta_count)) + if (int(sta_count) != int(self.total_stas)): + print("WARNING: Cisco Controller reported %s stations, should be %s"%(sta_count, self.total_stas)) + + def start(self, print_pass=False, print_fail=False): print("Bringing up stations") + up_request = self.local_realm.admin_up(self.side_b) for station_profile in self.station_profiles: - print("Bringing up station {}".format(station_profile)) - station_profile.admin_up(self.resource) + for sta in station_profile.station_names: + print("Bringing up station %s"%(sta)) + up_request = self.local_realm.admin_up(sta) temp_stations_list = [] - for station_list in self.station_lists: - temp_station_list = station_list.copy() - temp_stations_list.append(temp_station_list) - temp_stations_list.append(self.side_b) - self.local_realm.wait_for_ip(self.resource, temp_station_list) + temp_stations_list.append(self.side_b) + for station_profile in self.station_profiles: + temp_stations_list.extend(station_profile.station_names.copy()) + + if self.local_realm.wait_for_ip(temp_stations_list, timeout_sec=120): + print("ip's acquired") + else: + print("print failed to get IP's") + + self.verify_controller() + + print("Starting multicast traffic (if any configured)") + self.multicast_profile.start_mc(debug_=self.debug) + self.multicast_profile.refresh_mc(debug_=self.debug) + print("Starting layer-3 traffic (if any configured)") + self.cx_profile.start_cx() + self.cx_profile.refresh_cx() cur_time = datetime.datetime.now() - old_cx_rx_values = self.__get_rx_values() + print("Getting initial values.") + old_rx_values = self.__get_rx_values() + end_time = self.local_realm.parse_time(self.test_duration) + cur_time - self.cx_profile.start_cx() + + print("Monitoring throughput for duration: %s"%(self.test_duration)) + passes = 0 expected_passes = 0 while cur_time < end_time: @@ -117,15 +190,16 @@ class L3VariableTimeLongevity(LFCliBase): while cur_time < interval_time: cur_time = datetime.datetime.now() time.sleep(1) + + new_rx_values = self.__get_rx_values() - new_cx_rx_values = self.__get_rx_values() expected_passes += 1 - if self.__compare_vals(old_cx_rx_values, new_cx_rx_values): + 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_cx_rx_values = new_cx_rx_values + old_rx_values = new_rx_values cur_time = datetime.datetime.now() if passes == expected_passes: @@ -133,58 +207,85 @@ class L3VariableTimeLongevity(LFCliBase): def stop(self): self.cx_profile.stop_cx() + self.multicast_profile.stop_mc() for station_list in self.station_lists: for station_name in station_list: - data = LFUtils.portDownRequest(1, station_name) - url = "json-cli/set_port" - self.json_post(url, data) + self.local_realm.admin_down(station_name) - def cleanup(self, resource): - resource = 1 - remove_all_endpoints = True - self.local_realm.remove_all_cxs(remove_all_endpoints) - self.local_realm.remove_all_stations(resource) + def pre_cleanup(self): + self.cx_profile.cleanup_prefix() + self.multicast_profile.cleanup_prefix() + self.total_stas = 0 + for station_list in self.station_lists: + for sta in station_list: + self.local_realm.rm_port(sta, check_exists=True) + self.total_stas += 1 + + # Make sure they are gone + count = 0 + while (count < 10): + more = False + for station_list in self.station_lists: + for sta in station_list: + rv = self.local_realm.rm_port(sta, check_exists=True) + if (rv): + more = True + if not more: + break + count += 1 + time.sleep(5) + + def cleanup(self): + self.cx_profile.cleanup() + self.multicast_profile.cleanup() + for station_profile in self.station_profiles: + station_profile.cleanup() def build(self): - resource = 1 - try: - data = LFUtils.port_dhcp_up_request(resource, self.side_b) - 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 no pass ".format(self.side_b)) + # 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)) - resource = 1 index = 0 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) print("Creating stations") - station_profile.set_command_flag("add_sta", "create_admin_down", 1) - station_profile.set_command_param("set_port", "report_timer", 1500) - station_profile.set_command_flag("set_port", "rpt_timer", 1) - temp_station_list = [] - index = 0 - for station_list in self.station_lists: - for station in range(len(station_list)): - temp_station_list.append(str(self.resource) + "." + station_list[station]) - station_profile.create(resource=1, radio=self.radio_list[index], sta_names_=station_list, debug=False ) - index += 1 - self.cx_profile.create(endp_type=self.endp_type, side_a=temp_station_list, side_b='1.'+self.side_b, sleep_time=.5) + station_profile.create(radio=self.radio_list[index], sta_names_=self.station_lists[index], debug=self.debug, sleep_time=0) + index += 1 + + for etype in self.endp_types: + if etype == "mc_udp" or etype == "mc_udp6": + 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"%(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 valid_endp_type(endp_type): - valid_endp_type=['lf_udp','lf_udp6','lf_tcp','lf_tcp6'] - if str(endp_type) in valid_endp_type: - return endp_type - else: - print('invalid endp_type. Valid types lf_udp, lf_udp6, lf_tcp, lf_tcp6') - exit(1) +def valid_endp_types(_endp_type): + etypes = _endp_type.split() + for endp_type in etypes: + valid_endp_type=['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_udp, lf_udp6, lf_tcp, lf_tcp6, mc_udp, mc_udp6' % endp_type) + exit(1) + return _endp_type def main(): lfjson_host = "localhost" lfjson_port = 8080 + endp_types = "lf_udp" + debug_on = False parser = argparse.ArgumentParser( prog='test_l3_longevity.py', @@ -195,38 +296,46 @@ def main(): 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 3. The tx/rx rates are fixed at 256000 bits per second - 4. Security is fixed at WPA2 - 5. Maximum stations per radio is 64 + 4. Maximum stations per radio is 64 ''', description='''\ - test_l3_longevity.py: - -------------------- - Basic Idea: 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 recieved. +test_l3_longevity.py: +-------------------- +Basic Idea: 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 recieved. - Test will exit on failure of not recieving traffice for one minute on any station. + Test will exit on failure of not recieving traffice for one minute on any station. - Scripts are executed from: ./lanforge/py-scripts + Scripts are executed from: ./lanforge/py-scripts - Generic command layout: - python3 .\\test_l3_longevity.py --test_duration --endp_type --radio + Stations start counting from zero, thus stations count from zero - number of las - Note: multiple --radio switches may be entered up to the number of radios available: - --radio --radio +Generic command layout: +python .\\test_l3_longevity.py --test_duration --endp_type --upstream_port --radio --debug - : number followed by one of the following - d - days - h - hours - m - minutes - s - seconds +Note: multiple --radio switches may be entered up to the number of radios available: + --radio --radio - : - lf_udp : IPv4 UDP traffic - lf_tcp : IPv4 TCP traffic - lf_udp6 : IPv6 UDP traffic - lf_tcp6 : IPv6 TCP traffic +: 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 + 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. + Example: 1. Test duration 4 minutes @@ -234,28 +343,43 @@ def main(): 3. Upstream-port eth1 4. Radio #1 wiphy0 has 32 stations, ssid = candelaTech-wpa2-x2048-4-1, ssid password = candelaTech-wpa2-x2048-4-1 5. Radio #2 wiphy1 has 64 stations, ssid = candelaTech-wpa2-x2048-5-3, ssid password = candelaTech-wpa2-x2048-5-3 + 6. Create connections with TOS of BK and VI Command: - python3 .\\test_l3_longevity.py --test_duration 4m --endp_type lf_tcp --upstream_port eth1 --radio wiphy0 32 candelaTech-wpa2-x2048-4-1 candelaTech-wpa2-x2048-4-1 --radio wiphy1 64 candelaTech-wpa2-x2048-5-3 candelaTech-wpa2-x2048-5-3 + python3 .\\test_l3_longevity.py --test_duration 4m --endp_type \"lf_tcp lf_udp mc_udp\" --tos \"BK VI\" --upstream_port eth1 --radio wiphy0 32 candelaTech-wpa2-x2048-4-1 candelaTech-wpa2-x2048-4-1 wpa2 --radio wiphy1 64 candelaTech-wpa2-x2048-5-3 candelaTech-wpa2-x2048-5-3 wpa2 ''') - + + parser.add_argument('--cisco_ctlr', help='--cisco_ctlr ',default=None) + parser.add_argument('--cisco_user', help='--cisco_user ',default="admin") + parser.add_argument('--cisco_passwd', help='--cisco_passwd ',default="Cisco123") + parser.add_argument('--cisco_prompt', help='--cisco_prompt ',default="\(Cisco Controller\) >") + parser.add_argument('--cisco_ap', help='--cisco_ap ',default="APA453.0E7B.CF9C") + + parser.add_argument('--mgr', help='--mgr ',default='localhost') parser.add_argument('-d','--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('-t', '--endp_type', help='--endp_type example --endp_type lf_udp, default: lf_udp , options: lf_udp, lf_udp6, lf_tcp, lf_tcp6', - default='lf_udp',type=valid_endp_type) + parser.add_argument('--tos', help='--tos: Support different ToS settings: BK | BE | VI | VO | numeric',default="BE") + parser.add_argument('--debug', help='--debug: Enable debugging',default=False) + 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') requiredNamed = parser.add_argument_group('required arguments') - requiredNamed.add_argument('-r','--radio', action='append', nargs=4, metavar=('', '','',''), - help ='--radio ',required=True) + requiredNamed.add_argument('-r', '--radio', action='append', nargs=5, metavar=('', '', '', '', 'security'), + help ='--radio ', required=True) args = parser.parse_args() + debug_on = args.debug + if args.test_duration: test_duration = args.test_duration if args.endp_type: - endp_type = args.endp_type + endp_types = args.endp_type + + if args.mgr: + lfjson_host = args.mgr if args.upstream_port: side_b = args.upstream_port @@ -267,6 +391,7 @@ def main(): number_of_stations_offset = 1 ssid_offset = 2 ssid_password_offset = 3 + ssid_security_offset = 4 MAX_NUMBER_OF_STATIONS = 64 @@ -274,8 +399,8 @@ def main(): number_of_stations_per_radio_list = [] ssid_list = [] ssid_password_list = [] + ssid_security_list = [] - index = 0 for radio in radios: radio_name = radio[radio_offset] radio_name_list.append(radio_name) @@ -283,51 +408,63 @@ def main(): number_of_stations_per_radio_list.append(number_of_stations_per_radio) ssid = radio[ssid_offset] ssid_list.append(ssid) - ssid_password = radio[ssid_password_offset] - ssid_password_list.append(ssid_password) - index += 1 + if (len(radio) >= (ssid_password_offset - 1)): + ssid_password_list.append(radio[ssid_password_offset]) + ssid_security_list.append(radio[ssid_security_offset]) + else: + ssid_password_list.append("NA") + ssid_security_list.append("open") index = 0 station_lists = [] for radio in radios: number_of_stations = int(number_of_stations_per_radio_list[index]) if number_of_stations > MAX_NUMBER_OF_STATIONS: - print("number of stations per radio exceeded") + print("number of stations per radio exceeded max of : {}".format(MAX_NUMBER_OF_STATIONS)) quit(1) - station_list = LFUtils.portNameSeries(prefix_="sta", start_id_= index*1000, end_id_= number_of_stations + index*1000, padding_number_=10000) + station_list = LFUtils.portNameSeries(prefix_="sta", start_id_= 1 + index*1000, end_id_= number_of_stations + index*1000, + padding_number_=10000, radio=radio[index]) station_lists.append(station_list) index += 1 - ip_var_test = L3VariableTimeLongevity(lfjson_host, - lfjson_port, + + #print("endp-types: %s"%(endp_types)) + + ip_var_test = L3VariableTimeLongevity(lfjson_host, + lfjson_port, + args=args, number_template="00", station_lists= station_lists, - name_prefix="var_time", - endp_type=endp_type, + name_prefix="LT-", + endp_types=endp_types, + tos=args.tos, side_b=side_b, radios=radios, radio_name_list=radio_name_list, number_of_stations_per_radio_list=number_of_stations_per_radio_list, ssid_list=ssid_list, ssid_password_list=ssid_password_list, - resource=1, - security="wpa2", test_duration=test_duration, - side_a_min_rate=256000, side_b_min_rate=256000) + ssid_security_list=ssid_security_list, test_duration=test_duration, + side_a_min_rate=256000, side_b_min_rate=256000, debug_on=debug_on) + + ip_var_test.pre_cleanup() - ip_var_test.cleanup(station_list) ip_var_test.build() if not ip_var_test.passes(): + print("build step failed.") print(ip_var_test.get_fail_message()) exit(1) ip_var_test.start(False, False) ip_var_test.stop() 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) - ip_var_test.cleanup(station_list) + ip_var_test.cleanup() if ip_var_test.passes(): print("Full test passed, all connections increased rx bytes") - if __name__ == "__main__": main() diff --git a/py-scripts/test_l3_unicast_traffic_gen.py b/py-scripts/test_l3_unicast_traffic_gen.py new file mode 100755 index 00000000..1e55a646 --- /dev/null +++ b/py-scripts/test_l3_unicast_traffic_gen.py @@ -0,0 +1,398 @@ +#!/usr/bin/env python3 + +import sys +import os + +if sys.version_info[0] != 3: + print("This script requires Python 3") + exit(1) + +if 'py-json' not in sys.path: + sys.path.append(os.path.join(os.path.abspath('..'), 'py-json')) + +import argparse +from LANforge.lfcli_base import LFCliBase +from LANforge import LFUtils +import realm +import time +import datetime + +class L3VariableTimeLongevity(LFCliBase): + def __init__(self, host, port, endp_type, side_b, radios, radio_name_list, number_of_stations_per_radio_list, + ssid_list, ssid_password_list, security, station_lists, name_prefix, resource=1, + side_a_min_rate=256000, side_a_max_rate=0, + side_b_min_rate=256000, side_b_max_rate=0, + number_template="00", test_duration="125s", + _debug_on=False, + _exit_on_error=False, + _exit_on_fail=False): + super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) + self.host = host + self.port = port + self.endp_type = endp_type + self.side_b = side_b + self.ssid_list = ssid_list + self.ssid_password_list = ssid_password_list + self.station_lists = station_lists + self.security = security + self.number_template = number_template + self.resource = resource + self.name_prefix = name_prefix + self.test_duration = test_duration + self.cx_stations_lists = station_lists + self.radios = radios # from the command line + self.radio_list = radio_name_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) + self.cx_profile = self.local_realm.new_l3_cx_profile() + self.station_profiles = [] + + index = 0 + for radio in radios: + self.station_profile = self.local_realm.new_station_profile() + self.station_profile.lfclient_url = self.lfclient_url + self.station_profile.ssid = ssid_list[index] + self.station_profile.ssid_pass = ssid_password_list[index] + self.station_profile.security = self.security + self.station_profile.number_template = self.number_template + self.station_profile.mode = 0 + self.station_profiles.append(self.station_profile) + index += 1 + + self.cx_profile.host = self.host + self.cx_profile.port = self.port + self.cx_profile.name_prefix = self.name_prefix + self.cx_profile.side_a_min_bps = side_a_min_rate + self.cx_profile.side_a_max_bps = side_a_max_rate + self.cx_profile.side_b_min_bps = side_b_min_rate + self.cx_profile.side_b_max_bps = side_b_max_rate + + def __get_rx_values(self): + cx_list = self.json_get("endp?fields=name,rx+bytes", debug_=False) + cx_rx_map = {} + for cx_name in cx_list['endpoint']: + if cx_name != 'uri' and cx_name != 'handler': + for item, value in cx_name.items(): + for value_name, value_rx in value.items(): + if value_name == 'rx bytes': + cx_rx_map[item] = value_rx + return cx_rx_map + + def __compare_vals(self, old_list, new_list): + passes = 0 + expected_passes = 0 + if len(old_list) == len(new_list): + 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], passes, expected_passes) + + if passes == expected_passes: + return True + else: + return False + else: + return False + + def start(self, print_pass=False, print_fail=False): + print("Bringing up stations") + + up_request = LFUtils.port_up_request(resource_id=self.resource, port_name=self.side_b) + self.local_realm.json_post("/cli-json/set_port", up_request) + for station_profile, station_list in zip(self.station_profiles, self.station_lists): + print("Bringing up station {}".format(station_profile)) + station_profile.admin_up(self.resource) + if self.local_realm.wait_for_ip(self.resource, station_list,timeout_sec=10*len(station_list)): + print("ip's aquired {}".format(station_list)) + else: + print("print failed to get IP's: {}".format(station_list)) + if self.local_realm.wait_for_ip(self.resource, station_list,timeout_sec=120): + print("tried again: print failed to get IP's: {}".format(station_list)) + exit(1) + + + + self.cx_profile.start_cx() + + cur_time = datetime.datetime.now() + old_rx_values = self.__get_rx_values() + filtered_old_rx_values = [] + filtered_old_rx_values = old_rx_values + + end_time = self.local_realm.parse_time(self.test_duration) + cur_time + + passes = 0 + expected_passes = 0 + while cur_time < end_time: + interval_time = cur_time + datetime.timedelta(minutes=1) + while cur_time < interval_time: + cur_time = datetime.datetime.now() + time.sleep(1) + + new_rx_values = self.__get_rx_values() + filtered_new_rx_values = [] + filtered_new_rx_values = new_rx_values + + expected_passes += 1 + if self.__compare_vals(filtered_old_rx_values, filtered_new_rx_values): + passes += 1 + else: + self._fail("FAIL: Not all stations increased traffic", print_fail) + break + old_rx_values = new_rx_values + cur_time = datetime.datetime.now() + + if passes == expected_passes: + self._pass("PASS: All tests passed", print_pass) + + def stop(self): + self.cx_profile.stop_cx() + for station_list in self.station_lists: + for station_name in station_list: + data = LFUtils.portDownRequest(1, station_name) + url = "cli-json/set_port" + self.json_post(url, data) + + def cleanup(self, resource): + resource = 1 + data = { + "name":"BLANK", + "action":"overwrite" + } + url = "cli-json/load" + self.json_post(url, data) + + timeout = 20 + done = False + while timeout > 0 and done == False: + time.sleep( 1) + port_r = self.json_get("/port/1/1/list?fields=alias") + print("port interfaces {}".format(port_r["interfaces"])) + for interface in port_r["interfaces"]: + if "sta" in interface: + print("interface {}".format(interface)) + else: + done = True + break + timeout -= 1 + + if timeout <= 0: + print("not all station ports removed {}".format(port_r["interfaces"])) + + def build(self): + # refactor in LFUtils.port_zero_request() + resource = 1 + + data ={ + 'shelf':1, + 'resource':1, + 'port':'eth1', + 'ip_addr':'0.0.0.0', + 'netmask':'0.0.0.0', + 'gateway':'0.0.0.0', + 'current_flags':0, + 'interest':402653212 + } + + url = "cli-json/set_port" + self.json_post(url, data) + + # refactor into LFUtils + data ={ + "shelf":1, + "resource": resource, + "port":"br0", + "network_devs":"eth1", + "br_flags":1 + } + url = "cli-json/add_br" + self.json_post(url, data) + + try: + data = LFUtils.port_dhcp_up_request(resource, self.side_b) + 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)) + + resource = 1 + index = 0 + for station_profile, station_list in zip(self.station_profiles, self.station_lists): + station_profile.use_security(station_profile.security, station_profile.ssid, station_profile.ssid_pass) + station_profile.set_number_template(station_profile.number_template) + print("radio: {} station_profile: {} Creating stations: {} ".format(self.radio_list[index],station_profile, station_list)) + + temp_station_list = [] + for station in range(len(station_list)): + temp_station_list.append(str(self.resource) + "." + station_list[station]) + station_profile.create(resource=1, radio=self.radio_list[index], sta_names_=station_list, debug=False ) + index += 1 + self.cx_profile.create(endp_type=self.endp_type, side_a=temp_station_list, side_b='1.'+self.side_b, sleep_time=.5) + self._pass("PASS: Stations build finished") + +def valid_endp_type(endp_type): + valid_endp_type=['lf_udp','lf_udp6','lf_tcp','lf_tcp6'] + if str(endp_type) in valid_endp_type: + return endp_type + else: + print('invalid endp_type. Valid types lf_udp, lf_udp6, lf_tcp, lf_tcp6') + exit(1) + +def main(): + lfjson_host = "localhost" + lfjson_port = 8080 + + parser = argparse.ArgumentParser( + prog='test_l3_longevity.py', + #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 exit when traffic has not changed on a station for 1 minute +3. The tx/rx rates are fixed at 256000 bits per second +4. Security is fixed at WPA2 +5. Maximum stations per radio is 64 + ''', + + description='''\ +test_l3_longevity.py: +-------------------- +Basic Idea: + +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 recieved. + +Test will exit on failure of not recieving traffice for one minute on any station. + +Scripts are executed from: ./lanforge/py-scripts + +Stations start counting form zero, thus stations count from zero - number of las + +Generic command layout: +python .\\test_l3_longevity.py --test_duration --endp_type --upstream_port + --radio + +Note: +multiple --radio switches may be entered up to the number of radios available: +--radio --radio + +: 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 + lf_tcp6 : IPv6 TCP traffic + +Example: + 1. Test duration 4 minutes + 2. Traffic IPv4 TCP + 3. Upstream-port eth1 + 4. Radio #1 wiphy0 has 32 stations, ssid = candelaTech-wpa2-x2048-4-1, ssid password = candelaTech-wpa2-x2048-4-1 + 5. Radio #2 wiphy1 has 64 stations, ssid = candelaTech-wpa2-x2048-5-3, ssid password = candelaTech-wpa2-x2048-5-3 + +Example: +python3 .\\test_l3_longevity.py --test_duration 4m --endp_type lf_tcp --upstream_port eth1 \ + --radio wiphy0 32 candelaTech-wpa2-x2048-4-1 candelaTech-wpa2-x2048-4-1 \ + --radio wiphy1 64 candelaTech-wpa2-x2048-5-3 candelaTech-wpa2-x2048-5-3 + + ''') + + + parser.add_argument('-d','--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('-t', '--endp_type', help='--endp_type example --endp_type lf_udp, default: lf_udp , options: lf_udp, lf_udp6, lf_tcp, lf_tcp6', + default='lf_udp',type=valid_endp_type) + parser.add_argument('-u', '--upstream_port', help='--upstream_port example: --upstream_port eth1',default='eth1') + + requiredNamed = parser.add_argument_group('required arguments') + requiredNamed.add_argument('-r','--radio', action='append', nargs=4, metavar=('', '','',''), + help ='--radio ',required=True) + args = parser.parse_args() + + if args.test_duration: + test_duration = args.test_duration + + if args.endp_type: + endp_type = args.endp_type + + side_b = args.upstream_port + + if args.radio: + radios = args.radio + + radio_offset = 0 + number_of_stations_offset = 1 + ssid_offset = 2 + ssid_password_offset = 3 + + MAX_NUMBER_OF_STATIONS = 64 + + radio_name_list = [] + number_of_stations_per_radio_list = [] + ssid_list = [] + ssid_password_list = [] + + index = 0 + for radio in radios: + radio_name = radio[radio_offset] + radio_name_list.append(radio_name) + number_of_stations_per_radio = radio[number_of_stations_offset] + number_of_stations_per_radio_list.append(number_of_stations_per_radio) + ssid = radio[ssid_offset] + ssid_list.append(ssid) + ssid_password = radio[ssid_password_offset] + ssid_password_list.append(ssid_password) + index += 1 + + index = 0 + station_lists = [] + for radio in radios: + number_of_stations = int(number_of_stations_per_radio_list[index]) + if number_of_stations > MAX_NUMBER_OF_STATIONS: + print("number of stations per radio exceeded max of : {}".format(MAX_NUMBER_OF_STATIONS)) + quit(1) + station_list = LFUtils.portNameSeries(prefix_="sta", start_id_= 1 + index*1000, end_id_= number_of_stations + index*1000, padding_number_=10000) + station_lists.append(station_list) + index += 1 + ip_var_test = L3VariableTimeLongevity(lfjson_host, + lfjson_port, + number_template="00", + station_lists= station_lists, + name_prefix="var_time", + endp_type=endp_type, + side_b=side_b, + radios=radios, + radio_name_list=radio_name_list, + number_of_stations_per_radio_list=number_of_stations_per_radio_list, + ssid_list=ssid_list, + ssid_password_list=ssid_password_list, + resource=1, + security="wpa2", test_duration=test_duration, + side_a_min_rate=256000, side_b_min_rate=256000) + + ip_var_test.cleanup(station_list) + ip_var_test.build() + if not ip_var_test.passes(): + print(ip_var_test.get_fail_message()) + exit(1) + ip_var_test.start(False, False) + ip_var_test.stop() + if not ip_var_test.passes(): + print(ip_var_test.get_fail_message()) + exit(1) + time.sleep(30) + ip_var_test.cleanup(station_list) + if ip_var_test.passes(): + print("Full test passed, all connections increased rx bytes") + + +if __name__ == "__main__": + main() diff --git a/py-scripts/test_open_connection.py b/py-scripts/test_open_connection.py old mode 100644 new mode 100755 diff --git a/py-scripts/test_wanlink.py b/py-scripts/test_wanlink.py old mode 100644 new mode 100755 diff --git a/py-scripts/test_wep_connection.py b/py-scripts/test_wep_connection.py index 8a825834..1f001a56 100755 --- a/py-scripts/test_wep_connection.py +++ b/py-scripts/test_wep_connection.py @@ -49,7 +49,7 @@ class IPv4Test(LFCliBase): self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) self.station_profile.set_command_param("set_port", "report_timer", 1500) self.station_profile.set_command_flag("set_port", "rpt_timer", 1) - self.station_profile.create(resource=1, radio="wiphy0", sta_names_=self.sta_list, debug=False) + self.station_profile.create(resource=1, radio="wiphy0", sta_names_=self.sta_list, debug=self.debug) self._pass("PASS: Station build finished") def start(self, sta_list, print_pass, print_fail): @@ -92,7 +92,7 @@ class IPv4Test(LFCliBase): # Bring stations down for sta_name in self.sta_list: data = LFUtils.portDownRequest(1, sta_name) - url = "json-cli/set_port" + url = "cli-json/set_port" # print(sta_name) self.json_post(url, data) diff --git a/py-scripts/test_wpa2_connection.py b/py-scripts/test_wpa2_connection.py index 2b1e1acb..085107cc 100755 --- a/py-scripts/test_wpa2_connection.py +++ b/py-scripts/test_wpa2_connection.py @@ -49,7 +49,7 @@ class IPv4Test(LFCliBase): self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) self.station_profile.set_command_param("set_port", "report_timer", 1500) self.station_profile.set_command_flag("set_port", "rpt_timer", 1) - self.station_profile.create(resource=1, radio="wiphy0", sta_names_=self.sta_list, debug=False) + self.station_profile.create(resource=1, radio="wiphy0", sta_names_=self.sta_list, debug=self.debug) self._pass("PASS: Station build finished") def start(self, sta_list, print_pass, print_fail): @@ -92,7 +92,7 @@ class IPv4Test(LFCliBase): # Bring stations down for sta_name in self.sta_list: data = LFUtils.portDownRequest(1, sta_name) - url = "json-cli/set_port" + url = "cli-json/set_port" # print(sta_name) self.json_post(url, data) diff --git a/py-scripts/test_wpa3_connection.py b/py-scripts/test_wpa3_connection.py index cd3660fb..a19dcf98 100755 --- a/py-scripts/test_wpa3_connection.py +++ b/py-scripts/test_wpa3_connection.py @@ -49,7 +49,7 @@ class IPv4Test(LFCliBase): self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) self.station_profile.set_command_param("set_port", "report_timer", 1500) self.station_profile.set_command_flag("set_port", "rpt_timer", 1) - self.station_profile.create(resource=1, radio="wiphy0", sta_names_=self.sta_list, debug=False) + self.station_profile.create(resource=1, radio="wiphy0", sta_names_=self.sta_list, debug=self.debug) self._pass("PASS: Station build finished") def start(self, sta_list, print_pass, print_fail): @@ -92,7 +92,7 @@ class IPv4Test(LFCliBase): # Bring stations down for sta_name in self.sta_list: data = LFUtils.portDownRequest(1, sta_name) - url = "json-cli/set_port" + url = "cli-json/set_port" # print(sta_name) self.json_post(url, data) diff --git a/py-scripts/test_wpa_connection.py b/py-scripts/test_wpa_connection.py index 4a10be14..b07d7527 100755 --- a/py-scripts/test_wpa_connection.py +++ b/py-scripts/test_wpa_connection.py @@ -49,7 +49,7 @@ class IPv4Test(LFCliBase): self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) self.station_profile.set_command_param("set_port", "report_timer", 1500) self.station_profile.set_command_flag("set_port", "rpt_timer", 1) - self.station_profile.create(resource=1, radio="wiphy0", sta_names_=self.sta_list, debug=False) + self.station_profile.create(resource=1, radio="wiphy0", sta_names_=self.sta_list, debug=self.debug) self._pass("PASS: Station build finished") def start(self, sta_list, print_pass, print_fail): @@ -92,7 +92,7 @@ class IPv4Test(LFCliBase): # Bring stations down for sta_name in self.sta_list: data = LFUtils.portDownRequest(1, sta_name) - url = "json-cli/set_port" + url = "cli-json/set_port" # print(sta_name) self.json_post(url, data) diff --git a/py-scripts/tip_station_powersave.py b/py-scripts/tip_station_powersave.py new file mode 100755 index 00000000..4adb10f6 --- /dev/null +++ b/py-scripts/tip_station_powersave.py @@ -0,0 +1,360 @@ +#!/usr/bin/env python3 +import sys +import pprint +import os + +if sys.version_info[0] != 3: + print("This script requires Python 3") + exit(1) + +if 'py-json' not in sys.path: + sys.path.append(os.path.join(os.path.abspath('..'),'py-json')) + +import argparse +from LANforge.lfcli_base import LFCliBase +from LANforge.LFUtils import * +from LANforge import LFUtils +import realm +import time +import datetime + +#Currently, this test can only be applied to UDP connections +class TIPStationPowersave(LFCliBase): + def __init__(self, host, port, + ssid=None, + security="open", + password="[BLANK]", + resource_=1, + channel_=0, + normal_station_list_=None, + normal_station_radio_=None, + powersave_station_list_=None, + powersave_station_radio_=None, + monitor_name_=None, + monitor_radio_=None, + side_a_min_rate_=56000, + side_b_min_rate_=56000, + side_a_max_rate_=0, + side_b_max_rate_=0, + pdu_size_=1000, + traffic_duration_="5s", + pause_duration_="2s", + debug_on_=False, + exit_on_error_=False, + exit_on_fail_=False): + super().__init__(host, port, _debug=debug_on_, _halt_on_error=exit_on_error_, _exit_on_fail=exit_on_fail_) + self.resource = resource_ + if (channel_ == 0): + raise ValueError("Please set your radio channel") + self.channel = channel_ + self.monitor_name = monitor_name_ + self.monitor_radio = monitor_radio_ + self.host = host + self.port = port + self.ssid = ssid + self.security = security + self.password = password + self.normal_sta_list = normal_station_list_ + self.normal_sta_radio = normal_station_radio_ + self.powersave_sta_list = powersave_station_list_ + self.powersave_sta_radio = powersave_station_radio_ + self.sta_mac_map = {} + self.debug = debug_on_ + self.local_realm = realm.Realm(lfclient_host=self.host, + lfclient_port=self.port, + debug_=self.debug, + halt_on_error_=self.exit_on_error) + + # background traffic + self.cx_prof_bg = self.local_realm.new_l3_cx_profile() + self.cx_prof_bg.side_a_min_bps = side_a_min_rate_ + self.cx_prof_bg.side_b_min_bps = side_a_min_rate_ + self.cx_prof_bg.side_a_max_bps = side_a_max_rate_ + self.cx_prof_bg.side_b_max_bps = side_a_min_rate_ + + #upload + self.cx_prof_upload = self.local_realm.new_l3_cx_profile() + self.cx_prof_upload.side_a_min_bps = side_a_min_rate_ + self.cx_prof_upload.side_b_min_bps = 0 + self.cx_prof_upload.side_a_max_bps = side_a_max_rate_ + self.cx_prof_upload.side_b_max_bps = 0 + + self.cx_prof_upload.side_a_min_pdu = pdu_size_ + self.cx_prof_upload.side_a_max_pdu = 0 + self.cx_prof_upload.side_b_min_pdu = pdu_size_ + self.cx_prof_upload.side_b_max_pdu = 0, + + #download + self.cx_prof_download = self.local_realm.new_l3_cx_profile() + self.cx_prof_download.side_a_min_bps = 0 + self.cx_prof_download.side_b_min_bps = side_b_min_rate_ + self.cx_prof_download.side_a_max_bps = 0 + self.cx_prof_download.side_b_max_bps = side_b_max_rate_ + + self.cx_prof_download.side_a_min_pdu = pdu_size_ + self.cx_prof_download.side_a_max_pdu = 0 + self.cx_prof_download.side_b_min_pdu = pdu_size_ + self.cx_prof_download.side_b_max_pdu = 0 + + self.pcap_file = None + self.test_duration = traffic_duration_ + if isinstance(self.test_duration, int): + self.test_duration = "%s"%traffic_duration_ + if isinstance(self.test_duration, str): + self.test_duration = self.local_realm.parse_time(self.test_duration) + + self.pause_duration = pause_duration_ + if isinstance(self.pause_duration, int): + self.pause_duration = "%s"%pause_duration_ + if isinstance(self.pause_duration, str): + self.pause_duration = self.local_realm.parse_time(self.pause_duration) + + self.sta_powersave_enabled_profile = self.local_realm.new_station_profile() + self.sta_powersave_disabled_profile = self.local_realm.new_station_profile() + self.wifi_monitor_profile = self.local_realm.new_wifi_monitor_profile() + + self.pcap_save_path = "/home/lanforge/lf_reports" + + def build(self): + self.sta_powersave_disabled_profile.use_security("open", ssid=self.ssid, passwd=self.password) + self.sta_powersave_disabled_profile.set_command_flag("add_sta", "create_admin_down", 1) + self.sta_powersave_disabled_profile.set_command_param("set_port", "report_timer", 5000) + self.sta_powersave_disabled_profile.set_command_flag("set_port", "rpt_timer", 1) + + self.sta_powersave_enabled_profile.use_security("open", ssid=self.ssid, passwd=self.password) + self.sta_powersave_enabled_profile.set_command_flag("add_sta", "create_admin_down", 1) + self.sta_powersave_enabled_profile.set_command_param("set_port", "report_timer", 5000) + self.sta_powersave_enabled_profile.set_command_flag("set_port", "rpt_timer", 1) + self.sta_powersave_enabled_profile.set_command_flag("add_sta", "power_save_enable", 1) + + self.wifi_monitor_profile.create(resource_=self.resource, + channel=self.channel, + radio_=self.monitor_radio, + name_=self.monitor_name) + + LFUtils.wait_until_ports_appear(base_url=self.local_realm.lfclient_url, + port_list=[self.monitor_name]) + time.sleep(0.2) + mon_j = self.json_get("/port/1/%s/%s"%(self.resource, self.monitor_name)) + if ("interface" not in mon_j): + raise ValueError("No monitor found") + + self.sta_powersave_disabled_profile.create(radio=self.normal_sta_radio, + sta_names_=self.normal_sta_list, + debug=self.debug, + suppress_related_commands_=True) + + self.sta_powersave_enabled_profile.create(radio=self.powersave_sta_radio, + sta_names_=self.powersave_sta_list, + debug=self.debug, + suppress_related_commands_=True) + temp_sta_map = {} + for name in self.powersave_sta_list + self.normal_sta_list: + temp_sta_map[name]=1 + print("Stations we want:") + pprint.pprint(temp_sta_map) + if len(temp_sta_map) < 1: + self._fail("Misconfigured build(), bye", print_=True) + exit(1) + self.local_realm.wait_until_ports_appear(temp_sta_map.keys()) + + if len(temp_sta_map) == (len(self.sta_powersave_disabled_profile.station_names) + len(self.sta_powersave_enabled_profile.station_names)): + self._pass("Stations created", print_=True) + else: + print("Stations we see created:") + pprint.pprint(temp_sta_map) + self._fail("Not all stations created", print_=True) + + bg_side_a_eids = [] + for port in self.normal_sta_list: + bg_side_a_eids.append( "%s.%s"%(self.resource, port)) + + ul_side_a_eids = [] + for port in self.normal_sta_list: + ul_side_a_eids.append( "%s.%s"%(self.resource, port)) + + dl_side_a_eids = [] + for port in self.normal_sta_list: + dl_side_a_eids.append( "%s.%s"%(self.resource, port)) + + print("Creating background cx profile ") + self.cx_prof_bg.name_prefix= "udp_bg" + self.cx_prof_bg.create(endp_type="lf_udp", + side_a=bg_side_a_eids, + side_b="1.eth1") + + print("Creating upload cx profile ") + self.cx_prof_upload.name_prefix = "udp_up" + self.cx_prof_upload.create(endp_type="lf_udp", + side_a=ul_side_a_eids, + side_b="1.eth1") + + print("Creating download cx profile") + self.cx_prof_download.name_prefix = "udp_down" + self.cx_prof_download.create(endp_type="lf_udp", + side_a=ul_side_a_eids, + side_b="1.eth1") + + print("Collecting lanforge eth0 IP...") + eth0_resp = self.json_get("/port/1/%s/eth0?fields=port,alias,ip"%self.resource, debug_=self.debug) + # would be nice to have a not_found() kind of method + if (eth0_resp is None) or ("items" in eth0_resp) or ("empty" in eth0_resp) or ("interface" not in eth0_resp): + self._fail("Unable to query %s.eth0"%self.resource, print_=True) + exit(1) + self.eth0_ip = eth0_resp["interface"]["ip"] + if self.eth0_ip == "0.0.0.0": + self._fail("eth0 is misconfigured or not our management port", print_=True) + exit(1) + + self.sta_mac_map = {} + + + def __get_rx_values(self): + cx_list = self.json_get("/endp/list?fields=name,rx+bytes", debug_=False) + #print("==============\n", cx_list, "\n==============") + cx_rx_map = {} + for cx_name in cx_list['endpoint']: + if cx_name != 'uri' and cx_name != 'handler': + for item, value in cx_name.items(): + for value_name, value_rx in value.items(): + if value_name == 'rx bytes': + cx_rx_map[item] = value_rx + return cx_rx_map + + + def start(self, print_pass=False, print_fail = False): + """ + This method is intended to start the monitor, the normal station (without powersave), + and the remaining power save stations. The powersave stations will transmit for tx duration, + pause, then the AP will pass along upstream traffic. This upstream traffic (download) should + express a beacon before actually delivering a buffer full of traffic in order to alert the + station it should wake up for incomming traffic. + :param print_pass: + :param print_fail: + :return: + """ + + #admin up on new monitor + self.wifi_monitor_profile.admin_up() + now = datetime.datetime.now() + date_time = now.strftime("%Y-%m-%d-%H%M%S") + curr_mon_name = self.wifi_monitor_profile.monitor_name + self.pcap_file = "%s/%s-%s.pcap"%(self.pcap_save_path, curr_mon_name, date_time) + + capture_duration = 2 * ( self.test_duration.total_seconds() + self.pause_duration.total_seconds() + 4) + self.wifi_monitor_profile.start_sniff(self.pcap_file, capture_duration) + time.sleep(0.05) + + self.sta_powersave_disabled_profile.admin_up() + self.sta_powersave_enabled_profile.admin_up() + + LFUtils.wait_until_ports_admin_up(base_url=self.local_realm.lfclient_url, + port_list=self.sta_powersave_disabled_profile.station_names + self.sta_powersave_enabled_profile.station_names) + self.local_realm.wait_for_ip(station_list=self.sta_powersave_disabled_profile.station_names + self.sta_powersave_enabled_profile.station_names) + time.sleep(2) + # collect BSSID of AP so we can tshark on it + uri = "/port/1/%s/%s?fields=alias,ip,mac,ap"%( + self.resource, + ",".join(self.sta_powersave_disabled_profile.station_names + self.sta_powersave_enabled_profile.station_names) + ) + port_info_r = self.json_get(uri) + if (port_info_r is None) or ("empty" in port_info_r): + self._fail("unable to query for mac addresses", print_=True) + exit(1) + self.sta_mac_map = LFUtils.portListToAliasMap(port_info_r) + + self.cx_prof_bg.start_cx() + print("Upload starts at: %d"%time.time()) + self.cx_prof_upload.start_cx() + + time.sleep(self.test_duration.total_seconds()) + self.cx_prof_upload.stop_cx() + print("Upload ends at: %d"%time.time()) + time.sleep(float(self.pause_duration.total_seconds())) + # here is where we should sleep long enough for station to go to sleep + print("Download begins at: %d"%time.time()) + self.cx_prof_download.start_cx() + time.sleep(float(self.test_duration.total_seconds())) + self.cx_prof_download.stop_cx() + print("Download ends at: %d"%time.time()) + + + def stop(self): + #switch off new monitor + self.wifi_monitor_profile.admin_down() + self.cx_prof_bg.stop_cx() + self.cx_prof_download.stop_cx() + self.cx_prof_upload.stop_cx() + self.sta_powersave_enabled_profile.admin_down() + self.sta_powersave_disabled_profile.admin_down() + + # check for that pcap file + if self.pcap_file is None: + self._fail("Did not configure pcap file", print_=True) + exit(1) + homepage_url = "http://%s/"%self.eth0_ip + webpage = LFRequest.plain_get(url_=homepage_url, debug_=True) + if webpage is None: + self._fail("Unable to find wepage for LANforge", print_=True) + exit(1) + homepage_url="http://%s/lf_reports/"%self.eth0_ip + webpage = LFRequest.plain_get(url_=homepage_url, debug_=True) + if webpage is None: + self._fail("Unable to find /lf_reports/ page", print_=True) + exit(1) + + pprint.pprint(self.sta_mac_map) + interesting_macs = {} + for eid,record in self.sta_mac_map.items(): + interesting_macs[record["mac"]] = 1 + interesting_macs[record["ap"]] = 1 + + mac_str = "-e wlan.addr ".join(interesting_macs.keys()) + tshark_filter = "tshark -e wlan.addr=="+mac_str+" -r "+self.pcap_file + # now check for the pcap file we just created + print("TSHARK COMMAND: "+tshark_filter) + self._fail("not done writing pcap logic", print_=True) + exit(1) + + + def cleanup(self): + self.wifi_monitor_profile.cleanup(desired_ports=[self.monitor_name]) + #self.cx_prof_download.cleanup() + self.local_realm.remove_all_cxs(remove_all_endpoints=True) + #self.cx_prof_upload.cleanup() + self.sta_powersave_enabled_profile.cleanup(desired_stations=self.powersave_sta_list) + self.sta_powersave_disabled_profile.cleanup(desired_stations=self.normal_sta_list) + +def main(): + lfjson_host = "localhost" + lfjson_port = 8080 + #station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=4, padding_number_=10000) + normal_station_list = ["sta1000" ] + powersave_station_list = ["sta0001"] #,"sta0002","sta0003","sta0004"] + ip_powersave_test = TIPStationPowersave(lfjson_host, lfjson_port, + ssid="jedway-open-x2048-5-1", + password="[BLANK]", + channel_=157, + normal_station_list_=normal_station_list, + normal_station_radio_="wiphy0", + powersave_station_list_=powersave_station_list, + powersave_station_radio_="wiphy0", + monitor_name_="moni0", + monitor_radio_="wiphy1", + side_a_min_rate_=56000, + side_b_min_rate_=56000, + traffic_duration_="5s", + pause_duration_="2s", + debug_on_=False, + exit_on_error_=True, + exit_on_fail_=True) + ip_powersave_test.cleanup() + ip_powersave_test.build() + ip_powersave_test.start() + ip_powersave_test.stop() + ip_powersave_test.cleanup() + +if __name__ == "__main__": + + main() +