mirror of
https://github.com/Telecominfraproject/wlan-lanforge-scripts.git
synced 2025-10-30 18:27:53 +00:00
5242 lines
290 KiB
Python
5242 lines
290 KiB
Python
import copy
|
|
import csv
|
|
import importlib
|
|
import json
|
|
import logging
|
|
import os
|
|
import sys
|
|
import time
|
|
import string
|
|
import random
|
|
import threading
|
|
from itertools import islice
|
|
import paramiko
|
|
from datetime import datetime
|
|
|
|
import allure
|
|
import pytest
|
|
import csv
|
|
from scp import SCPClient
|
|
from tabulate import tabulate
|
|
import re
|
|
|
|
import requests
|
|
|
|
sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../")))
|
|
lfcli_base = importlib.import_module("py-json.LANforge.lfcli_base")
|
|
LFCliBase = lfcli_base.LFCliBase
|
|
realm = importlib.import_module("py-json.realm")
|
|
cv_test_manager = importlib.import_module("py-json.cv_test_manager")
|
|
cv_test = cv_test_manager.cv_test
|
|
lf_cv_base = importlib.import_module("py-json.lf_cv_base")
|
|
ChamberViewBase = lf_cv_base.ChamberViewBase
|
|
create_chamberview_dut = importlib.import_module("py-scripts.create_chamberview_dut")
|
|
DUT = create_chamberview_dut.DUT
|
|
create_chamberview = importlib.import_module("py-scripts.create_chamberview")
|
|
CreateChamberview = create_chamberview.CreateChamberview
|
|
sta_connect2 = importlib.import_module("py-scripts.sta_connect2")
|
|
StaConnect2 = sta_connect2.StaConnect2
|
|
lf_library = importlib.import_module("lf_libs")
|
|
lf_libs = lf_library.lf_libs
|
|
profile_utility = importlib.import_module("py-json.profile_utility")
|
|
ProfileUtility = profile_utility.ProfileUtility
|
|
Report = lf_library.Report
|
|
SCP_File = lf_library.SCP_File
|
|
sniffradio = importlib.import_module("py-scripts.lf_sniff_radio")
|
|
SniffRadio = sniffradio.SniffRadio
|
|
stascan = importlib.import_module("py-scripts.sta_scan_test")
|
|
StaScan = stascan.StaScan
|
|
cv_test_reports = importlib.import_module("py-json.cv_test_reports")
|
|
lf_report = cv_test_reports.lanforge_reports
|
|
createstation = importlib.import_module("py-scripts.create_station")
|
|
CreateStation = createstation.CreateStation
|
|
wificapacitytest = importlib.import_module("py-scripts.lf_wifi_capacity_test")
|
|
WiFiCapacityTest = wificapacitytest.WiFiCapacityTest
|
|
csvtoinflux = importlib.import_module("py-scripts.csv_to_influx")
|
|
CSVtoInflux = csvtoinflux.CSVtoInflux
|
|
lf_dataplane_test = importlib.import_module("py-scripts.lf_dataplane_test")
|
|
DataplaneTest = lf_dataplane_test.DataplaneTest
|
|
ttlstest = importlib.import_module("py-scripts.test_ipv4_ttls")
|
|
TTLSTest = ttlstest.TTLSTest
|
|
tr398test = importlib.import_module("py-scripts.lf_tr398_test")
|
|
TR398Test = tr398test.TR398Test
|
|
tr398v2test = importlib.import_module("py-scripts.lf_tr398v2_test")
|
|
TR398v2Test = tr398v2test.TR398v2Test
|
|
rvr = importlib.import_module("py-scripts.lf_rvr_test")
|
|
rvr_test = rvr.RvrTest
|
|
lf_pcap = importlib.import_module("py-scripts.lf_pcap")
|
|
LfPcap = lf_pcap.LfPcap
|
|
lf_ap_auto_test = importlib.import_module("py-scripts.lf_ap_auto_test")
|
|
ApAutoTest = lf_ap_auto_test.ApAutoTest
|
|
roam_test = importlib.import_module("py-scripts.lf_hard_roam_test")
|
|
Roam = roam_test.Roam
|
|
wifi_mobility_test = importlib.import_module("py-scripts.lf_wifi_mobility_test")
|
|
WifiMobility = wifi_mobility_test.WifiMobility
|
|
modify_station = importlib.import_module("py-scripts.modify_station")
|
|
ModifyStation = modify_station.ModifyStation
|
|
station_profile = importlib.import_module("py-json.station_profile")
|
|
StationProfile = station_profile.StationProfile
|
|
|
|
|
|
class lf_tests(lf_libs):
|
|
"""
|
|
lf_tools is needed in lf_tests to do various operations needed by various tests
|
|
"""
|
|
|
|
def __init__(self, lf_data={}, dut_data={}, log_level=logging.DEBUG, run_lf=False, influx_params=None,
|
|
local_report_path="../reports/"):
|
|
super().__init__(lf_data, dut_data, run_lf, log_level)
|
|
self.local_report_path = local_report_path
|
|
self.influx_params = influx_params
|
|
|
|
def client_connectivity_test(self, ssid="[BLANK]", passkey="[BLANK]", bssid="[BLANK]", dut_data={},
|
|
security="open", extra_securities=[], client_type=0, pre_cleanup=True,
|
|
num_sta=1, mode="BRIDGE", vlan_id=[None], band="twog",
|
|
allure_attach=True, runtime_secs=40, extra_sta_rows= []):
|
|
if pre_cleanup:
|
|
self.pre_cleanup()
|
|
self.check_band_ap(band=band)
|
|
if self.run_lf:
|
|
dut_data = self.run_lf_dut_data()
|
|
logging.info("DUT Data:\n" + json.dumps(str(dut_data), indent=2))
|
|
allure.attach(name="DUT Data:\n", body=json.dumps(str(dut_data), indent=2),
|
|
attachment_type=allure.attachment_type.JSON)
|
|
|
|
data = self.setup_interfaces(ssid=ssid, bssid=bssid, passkey=passkey, encryption=security,
|
|
band=band, vlan_id=vlan_id, mode=mode, num_sta=num_sta, dut_data_=dut_data)
|
|
logging.info("Setup interface data:\n" + json.dumps(str(data), indent=2))
|
|
allure.attach(name="Interface Info: \n", body=json.dumps(str(data), indent=2),
|
|
attachment_type=allure.attachment_type.JSON)
|
|
if data == {}:
|
|
pytest.skip("Skipping This Test")
|
|
# list of multiple sta_connect objects
|
|
sta_connect_obj = []
|
|
for dut in data:
|
|
for radio in data[dut]["station_data"]:
|
|
obj_sta_connect = StaConnect2(self.manager_ip, self.manager_http_port, outfile="shivam",
|
|
_cleanup_on_exit=False)
|
|
|
|
obj_sta_connect.sta_mode = client_type
|
|
obj_sta_connect.upstream_resource = data[dut]["upstream_resource"]
|
|
obj_sta_connect.upstream_port = data[dut]["upstream"]
|
|
self.enable_verbose_debug(radio=radio, enable=True)
|
|
obj_sta_connect.radio = radio
|
|
obj_sta_connect.admin_down(obj_sta_connect.radio)
|
|
obj_sta_connect.admin_up(obj_sta_connect.radio)
|
|
obj_sta_connect.sta_prefix = data[dut]["sta_prefix"]
|
|
obj_sta_connect.resource = radio.split(".")[1]
|
|
obj_sta_connect.dut_ssid = data[dut]["ssid"]
|
|
obj_sta_connect.dut_passwd = data[dut]["passkey"]
|
|
obj_sta_connect.dut_security = data[dut]["encryption"]
|
|
obj_sta_connect.station_names = data[dut]["station_data"][radio]
|
|
obj_sta_connect.runtime_secs = runtime_secs
|
|
obj_sta_connect.bringup_time_sec = 80
|
|
obj_sta_connect.cleanup_on_exit = True
|
|
obj_sta_connect.download_bps = 128000
|
|
obj_sta_connect.upload_bps = 128000
|
|
obj_sta_connect.side_a_pdu = 1200
|
|
obj_sta_connect.side_b_pdu = 1500
|
|
|
|
# changed to auto channel
|
|
self.set_radio_channel(radio=radio, channel="AUTO")
|
|
logging.info("scan ssid radio: " + str(radio.split(".")[2]))
|
|
result = self.scan_ssid(radio=radio, ssid=data[dut]["ssid"])
|
|
logging.info("ssid scan data : " + str(result))
|
|
if not result:
|
|
# Sniffer required
|
|
for duts in self.dut_data:
|
|
identifier = duts["identifier"]
|
|
if dut_data.keys().__contains__(identifier):
|
|
if band == "twog":
|
|
if dict(dut_data.get(identifier)["radio_data"]).keys().__contains__("2G") and \
|
|
dict(dut_data.get(identifier)["radio_data"])["2G"] is not None:
|
|
channel = data[dut]["channel"]
|
|
if data[dut]["sniff_radio_2g"] is not None and channel is not None:
|
|
self.start_sniffer(radio_channel=channel,
|
|
radio=data[dut]["sniff_radio_2g"],
|
|
duration=10)
|
|
time.sleep(10)
|
|
self.stop_sniffer()
|
|
elif band == "fiveg":
|
|
if dict(dut_data.get(identifier)["radio_data"]).keys().__contains__("5G") and \
|
|
dict(dut_data.get(identifier)["radio_data"])["5G"] is not None:
|
|
channel = data[dut]["channel"]
|
|
if data[dut]["sniff_radio_5g"] is not None and channel is not None:
|
|
self.start_sniffer(radio_channel=channel,
|
|
radio=data[dut]["sniff_radio_5g"],
|
|
duration=10)
|
|
time.sleep(10)
|
|
self.stop_sniffer()
|
|
elif band == "sixg":
|
|
if dict(dut_data.get(identifier)["radio_data"]).keys().__contains__("6G") and \
|
|
dict(dut_data.get(identifier)["radio_data"])["6G"] is not None:
|
|
channel = self.lf_sixg_lookup_validation(int(data[dut]["channel"]))
|
|
logging.info("LF sixg channel: " + str(channel))
|
|
if data[dut]["sniff_radio_6g"] is not None and channel is not None:
|
|
self.start_sniffer(radio_channel=channel,
|
|
radio=data[dut]["sniff_radio_6g"],
|
|
duration=10)
|
|
time.sleep(10)
|
|
self.stop_sniffer()
|
|
if not result:
|
|
pytest.fail("SSID is not Available in Scan Result")
|
|
obj_sta_connect.setup(extra_securities=extra_securities)
|
|
sta_connect_obj.append(obj_sta_connect)
|
|
for dut_ in self.dut_data:
|
|
identifier = dut_["identifier"]
|
|
if dut_data.keys().__contains__(identifier):
|
|
if band == "twog":
|
|
if dict(dut_data.get(identifier)["radio_data"]).keys().__contains__("2G") and \
|
|
dict(dut_data.get(identifier)["radio_data"])["2G"] is not None:
|
|
channel = data[dut]["channel"]
|
|
if data[dut]["sniff_radio_2g"] is not None and channel is not None:
|
|
self.start_sniffer(radio_channel=channel,
|
|
radio=data[dut]["sniff_radio_2g"],
|
|
duration=runtime_secs)
|
|
logging.info("started-sniffer")
|
|
for obj in sta_connect_obj:
|
|
obj.start()
|
|
logging.info("napping %f sec" % runtime_secs)
|
|
time.sleep(runtime_secs)
|
|
logging.info("stopping-sniffer")
|
|
if data[dut]["sniff_radio_2g"] is not None and channel is not None:
|
|
self.stop_sniffer()
|
|
elif band == "fiveg":
|
|
if dict(dut_data.get(identifier)["radio_data"]).keys().__contains__("5G") and \
|
|
dict(dut_data.get(identifier)["radio_data"])["5G"] is not None:
|
|
channel = data[dut]["channel"]
|
|
if data[dut]["sniff_radio_5g"] is not None and channel is not None:
|
|
self.start_sniffer(radio_channel=channel,
|
|
radio=data[dut]["sniff_radio_5g"],
|
|
duration=runtime_secs)
|
|
for obj in sta_connect_obj:
|
|
obj.start()
|
|
logging.info("napping %f sec" % runtime_secs)
|
|
time.sleep(runtime_secs)
|
|
if data[dut]["sniff_radio_5g"] is not None and channel is not None:
|
|
self.stop_sniffer()
|
|
elif band == "sixg":
|
|
if dict(dut_data.get(identifier)["radio_data"]).keys().__contains__("6G") and \
|
|
dict(dut_data.get(identifier)["radio_data"])["6G"] is not None:
|
|
channel = self.lf_sixg_lookup_validation(int(data[dut]["channel"]))
|
|
logging.info("LF sixg channel: " + str(channel))
|
|
if data[dut]["sniff_radio_6g"] is not None and channel is not None:
|
|
self.start_sniffer(radio_channel=channel,
|
|
radio=data[dut]["sniff_radio_6g"],
|
|
duration=runtime_secs)
|
|
for obj in sta_connect_obj:
|
|
obj.start()
|
|
logging.info("napping %f sec" % runtime_secs)
|
|
time.sleep(runtime_secs)
|
|
if data[dut]["sniff_radio_6g"] is not None and channel is not None:
|
|
self.stop_sniffer()
|
|
else:
|
|
for obj in sta_connect_obj:
|
|
obj.start()
|
|
logging.info("napping %f sec" % runtime_secs)
|
|
time.sleep(runtime_secs)
|
|
pass_fail_result = []
|
|
for obj in sta_connect_obj:
|
|
sta_rows = ["4way time (us)", "channel", "ssid", "key/phrase", "cx time (us)", "dhcp (ms)", "ip", "signal",
|
|
"mac", "mode"]
|
|
if extra_sta_rows:
|
|
sta_rows = sta_rows + extra_sta_rows
|
|
station_data = self.get_station_data(sta_name=obj.station_names, rows=sta_rows,
|
|
allure_attach=False)
|
|
sta_table_dict = {}
|
|
sta_table_dict["station name"] = list(station_data.keys())
|
|
for i in sta_rows:
|
|
temp_list = []
|
|
for j in obj.station_names:
|
|
temp_list.append(station_data[j][i])
|
|
sta_table_dict[i] = temp_list
|
|
# pass fail
|
|
pass_fail_sta = []
|
|
for i in sta_table_dict["ip"]:
|
|
if i == "0.0.0.0":
|
|
pass_fail_sta.append("Fail")
|
|
else:
|
|
pass_fail_sta.append("Pass")
|
|
sta_table_dict["Pass/Fail"] = pass_fail_sta
|
|
if allure_attach:
|
|
self.attach_table_allure(data=sta_table_dict, allure_name="station data")
|
|
obj.stop()
|
|
cx_name = list(obj.l3_udp_profile.get_cx_names()) + list(
|
|
obj.l3_tcp_profile.get_cx_names())
|
|
cx_row = ["type", "bps rx a", "bps rx b"]
|
|
cx_data = self.get_cx_data(cx_name=cx_name, cx_data=cx_row, allure_attach=False)
|
|
cx_table_dict = {}
|
|
upstream = []
|
|
for i in range(len(obj.station_names)):
|
|
upstream.append(data[dut]["upstream_port"])
|
|
cx_table_dict["Upstream"] = upstream
|
|
cx_table_dict["Downstream"] = obj.station_names
|
|
cx_tcp_ul = []
|
|
cx_tcp_dl = []
|
|
cx_udp_ul = []
|
|
cx_udp_dl = []
|
|
for sta in obj.station_names:
|
|
for i in cx_data:
|
|
if sta.split(".")[2] in i:
|
|
if cx_data[i]["type"] == "LF/UDP":
|
|
cx_udp_dl.append(cx_data[i]["bps rx a"])
|
|
cx_udp_ul.append(cx_data[i]["bps rx b"])
|
|
elif cx_data[i]["type"] == "LF/TCP":
|
|
cx_tcp_dl.append(cx_data[i]["bps rx a"])
|
|
cx_tcp_ul.append(cx_data[i]["bps rx b"])
|
|
cx_table_dict["TCP DL"] = cx_tcp_dl
|
|
cx_table_dict["TCP UL"] = cx_tcp_ul
|
|
cx_table_dict["UDP DL"] = cx_udp_dl
|
|
cx_table_dict["UDP UL"] = cx_udp_ul
|
|
pass_fail_cx = []
|
|
for i, j, k, l in zip(cx_tcp_dl, cx_tcp_ul, cx_udp_dl, cx_udp_ul):
|
|
if i == 0 or j == 0 or k == 0 or l == 0:
|
|
pass_fail_cx.append("Fail")
|
|
else:
|
|
pass_fail_cx.append("Pass")
|
|
cx_table_dict["Pass/Fail"] = pass_fail_cx
|
|
if allure_attach:
|
|
self.attach_table_allure(data=cx_table_dict, allure_name="cx data")
|
|
obj.cleanup()
|
|
result = "PASS"
|
|
description = "Unknown error"
|
|
count = 0
|
|
temp_dict = {}
|
|
if "Fail" in pass_fail_sta:
|
|
count = count + 1
|
|
result = "FAIL"
|
|
description = "Station did not get an ip"
|
|
temp_dict[result] = description
|
|
pass_fail_result.append(temp_dict)
|
|
if count == 0:
|
|
if "Fail" in pass_fail_cx:
|
|
result = "FAIL"
|
|
description = "did not report traffic"
|
|
temp_dict[result] = description
|
|
pass_fail_result.append(temp_dict)
|
|
if obj.passes():
|
|
logging.info("client connection to" + str(obj.dut_ssid) + "successful. Test Passed")
|
|
result = "PASS"
|
|
temp_dict[result] = ""
|
|
pass_fail_result.append(temp_dict)
|
|
else:
|
|
logging.info("client connection to" + str(obj.dut_ssid) + "unsuccessful. Test Failed")
|
|
result = "FAIL"
|
|
for obj in sta_connect_obj:
|
|
try:
|
|
# print("1." + str(obj.resource) + "." + str(obj.radio))
|
|
self.get_supplicant_logs(radio=str(obj.radio))
|
|
except Exception as e:
|
|
logging.error("client_cpnnectivity_tests() -- Error in getting Supplicant Logs:" + str(e))
|
|
result = "PASS"
|
|
description = ""
|
|
for i in pass_fail_result:
|
|
if list(i.keys())[0] == "FAIL":
|
|
result = "FAIL"
|
|
description = i["FAIL"]
|
|
break
|
|
|
|
return result, description
|
|
|
|
|
|
|
|
|
|
def hot_config_reload_test(self, ssid="[BLANK]", security="wpa2", dut_data={}, passkey="[BLANK]", mode="BRIDGE",
|
|
band="fiveg", num_sta=1, vlan_id=[None], json_post_data='', get_testbed_details={},
|
|
tip_2x_obj=None, reconfig = None):
|
|
self.check_band_ap(band=band)
|
|
self.pre_cleanup()
|
|
pass_fail = "PASS"
|
|
description = ""
|
|
logging.info("DUT DATA: " + str(dut_data))
|
|
deauth_result = 0 #to check Deauthentication packet
|
|
for dut in self.dut_data:
|
|
station_result = self.client_connect_using_radio(ssid=ssid, passkey=passkey, security=security, mode=mode,
|
|
band=band, vlan_id=vlan_id, radio="1.1.wiphy4",
|
|
client_type=0,
|
|
station_name=["sta0000"],
|
|
dut_data=dut_data, attach_port_info=False)
|
|
sta = "sta0000"
|
|
sta_data = self.json_get(_req_url="port/1/1/%s" % sta)
|
|
self.allure_report_table_format(dict_data=sta_data["interface"], key="Station Data",
|
|
value="Value", name="%s info before Reconfiguration" % sta)
|
|
|
|
print("type of station_result", type(station_result))
|
|
print("station_result",station_result)
|
|
# allure.attach(name=f"Response - {resp.status_code} {resp.reason}", body=str(resp.json()))
|
|
|
|
if not station_result:
|
|
allure.attach(name="Test Result", body="TEST FAILED, due to station has no ip")
|
|
return "FAIL", "TEST FAILED, due to station has no ip"
|
|
logging.info("sta " + str(sta))
|
|
|
|
sta_channel = sta_data['interface']['channel']
|
|
|
|
current_config = tip_2x_obj.dut_library_object.get_active_config()
|
|
|
|
sniff_radio = self.setup_sniffer(band="fiveg", station_radio_data={"wiphy4": 1}) # to setup sniffer radio
|
|
print("------------------sniffer_radio", sniff_radio)
|
|
self.start_sniffer(radio_channel=sta_channel, radio=sniff_radio, test_name="hot_reload_sniff", duration=360)
|
|
print("------------------sniffer started-------------------")
|
|
|
|
serial_number = list(dut_data.keys())[0]
|
|
print("---------active config:", current_config)
|
|
sta_name = sta_data['interface']['device']
|
|
|
|
iwinfo = tip_2x_obj.dut_library_object.get_iwinfo()
|
|
# print("iwinfo before reconfiguration:", iwinfo)
|
|
|
|
# Reconfiguration
|
|
# Reconfiguring the AP, Modifying the Band parameter from 5G to 5G-upper
|
|
if reconfig == "band":
|
|
for radio in current_config['radios']:
|
|
if radio['band'] == '5G':
|
|
radio['band'] = '5G-upper'
|
|
|
|
# Reconfiguring the AP, Modifying the Channel Width parameter from 80 Mhz to 40 Mhz
|
|
if reconfig == "channel_width":
|
|
sta_mode = sta_data['interface']['mode']
|
|
#sta_mode = self.station_data_query(station_name=sta_name, query="mode")
|
|
print("Station mode before reconfiguration:", sta_mode)
|
|
new_radios = []
|
|
for radio in current_config['radios']:
|
|
if radio.get('band') == '5G':
|
|
radio['channel-width'] = 40
|
|
new_radios.append(radio)
|
|
current_config['radios'] = new_radios
|
|
|
|
# Reconfiguring the AP, Modifying the TX power parameter from 18 to 20
|
|
if reconfig == "tx_power":
|
|
# Extract the Tx-Power value using a regular expression
|
|
tx_power_value = re.search(r'Tx-Power:\s+(\d+)\s+dBm', iwinfo)
|
|
print(f"tx_power_value before reconfiguration: {int(tx_power_value.group(1))} dBm")
|
|
new_radios = []
|
|
for radio in current_config['radios']:
|
|
if radio.get('band') == '5G':
|
|
radio['tx-power'] = 20
|
|
new_radios.append(radio)
|
|
current_config['radios'] = new_radios
|
|
|
|
# Reconfiguring the AP, Modifying the dfs parameter (setting True for allow-dfs parameter)
|
|
if reconfig == "dfs":
|
|
res = tip_2x_obj.dut_library_object.get_uci_show(param='wireless')
|
|
for radio in current_config['radios']:
|
|
if radio['band'] == '5G':
|
|
radio['allow-dfs'] = True
|
|
|
|
# Reconfiguring the AP, Modifying the HE parameter (setting "he-settings": { "bss-color": 60 })
|
|
if reconfig == "he":
|
|
bss_color = sta_data['interface']['bss color']
|
|
print("bss_color before reconfiguration", bss_color)
|
|
for radio in current_config['radios']:
|
|
if radio['band'] == '5G':
|
|
radio['he-settings'] = {"bss-color": 60}
|
|
|
|
|
|
# modified current_config
|
|
print("---------Reconfiguration data---------:", current_config)
|
|
|
|
print("serial number:", serial_number)
|
|
path = "device/" + serial_number + "/configure"
|
|
|
|
uri = tip_2x_obj.controller_library_object.build_uri(path)
|
|
|
|
payload = {"configuration": json.dumps(current_config), "serialNumber": serial_number, "UUID": 2}
|
|
# Send the POST request with the current configuration
|
|
resp = requests.post(uri, data=json.dumps(payload, indent=2),
|
|
headers=tip_2x_obj.controller_library_object.make_headers(), verify=False,
|
|
timeout=120)
|
|
|
|
time.sleep(10)
|
|
print("resp",resp)
|
|
print(resp.status_code)
|
|
if resp.status_code == 200:
|
|
print("Reconfigured successfully")
|
|
allure.attach(name=f"Response for Reconfiguration - {resp.status_code} {resp.reason}", body=str(resp.json()))
|
|
else:
|
|
allure.attach(name=f"Response for Reconfiguration - {resp.status_code} {resp.reason}", body=f"TEST FAILED, Reconfiguration is not successful {str(resp.json())}")
|
|
# return "FAIL", "TEST FAILED, Reconfiguration is not successful."
|
|
|
|
|
|
time.sleep(10)
|
|
sta_data = self.json_get(_req_url="port/1/1/%s" % sta_name)
|
|
self.allure_report_table_format(dict_data=sta_data["interface"], key="Station Data",
|
|
value="Value", name="%s info after Reconfiguration" % sta)
|
|
|
|
pcap_name = self.stop_sniffer([sta_name])
|
|
print("------------------sniffer stopped-------------------")
|
|
print("pcap_name:", pcap_name)
|
|
|
|
timestamp = datetime.utcnow()
|
|
allure.attach(name="config after Reconfiguration",
|
|
body="TimeStamp: " + str(timestamp) + "\n" + str(json.dumps(current_config, indent=2)),
|
|
attachment_type=allure.attachment_type.JSON)
|
|
|
|
iwinfo = tip_2x_obj.dut_library_object.get_iwinfo()
|
|
|
|
# step-1 validation
|
|
pcap_obj = LfPcap(host=self.manager_ip, port=self.manager_http_port)
|
|
filter = 'wlan.fixed.reason_code == 0x0003' # wlan.fc.type_subtype == 12 is a filter for Deauthentication packet, wlan.fixed.reason_code == 0x0003 for client disruption deauthentication packet
|
|
pcap = pcap_obj.read_pcap(pcap_file=pcap_name, apply_filter=filter)
|
|
|
|
for packet in pcap:
|
|
print("packet:", packet)
|
|
if 'WLAN.MGT' in packet:
|
|
WLAN_MGT_layer = packet['WLAN.MGT']
|
|
if '0x0003' in WLAN_MGT_layer.wlan_fixed_reason_code:
|
|
print("Deauthentication packet detected.")
|
|
allure.attach(name=f"Deauthentication packet detected.",
|
|
body=str(packet))
|
|
deauth_result = 1
|
|
else:
|
|
print("Deauthentication packet is not detected.")
|
|
deauth_result = 0
|
|
|
|
if reconfig == "tx_power":
|
|
if deauth_result == 1:
|
|
allure.attach(name="Test Result", body="TEST FAILED, Deauthentication packet is detected. This response is not expected in Tx power parameter configuration.")
|
|
return "FAIL", "TEST FAILED, Deauthentication packet is detected, which is not expected in Tx power parameter configuration."
|
|
else:
|
|
allure.attach(name="Test Result",
|
|
body="TEST Passed, Deauthentication packet is not detected. This response is expected in Tx power parameter configuration.")
|
|
else:
|
|
if deauth_result == 0:
|
|
allure.attach(name="Test Result", body="TEST FAILED, Deauthentication packet is not detected")
|
|
return "FAIL", "TEST FAILED, Deauthentication packet is not detected"
|
|
|
|
|
|
#Step 2 validation
|
|
print("station_name", sta_name)
|
|
sta_data = self.json_get(_req_url="port/1/1/%s" % sta_name)
|
|
|
|
if reconfig == "band":
|
|
sta_channel = sta_data['interface']['channel']
|
|
print("channel of the station:", sta_channel)
|
|
sta_channel = int(sta_channel) # Convert sta_channel to an integer
|
|
if 100 <= sta_channel <= 165:
|
|
print("station channel is changed to upper band successfully") # upper band
|
|
else:
|
|
print("station channel is not changed to upper band")
|
|
pass_fail = 'FAIL'
|
|
allure.attach(name="Test Result", body="TEST FAILED, station channel is not changed to 5G-upper band")
|
|
return "FAIL", "TEST FAILED, station channel is not changed to 5G-upper band"
|
|
# Step 2 validation
|
|
if reconfig == "channel_width":
|
|
sta_mode = sta_data['interface']['mode']
|
|
print("mode of the station:", sta_mode)
|
|
if '40' in sta_mode:
|
|
print("channel-width changed to 40Mhz successfully")
|
|
else:
|
|
print("Test failed, channel-width is not changed to 40Mhz")
|
|
pass_fail = 'FAIL'
|
|
allure.attach(name="Test Result",
|
|
body="TEST FAILED, station channel-width is not changed to 40Mhz")
|
|
return "FAIL", "TEST FAILED, station channel-width is not changed to 40Mhz"
|
|
# Step 2 validation
|
|
if reconfig == "tx_power":
|
|
if "Tx-Power: 20 dBm" in iwinfo:
|
|
print("Tx-power is changed to 20dBm successfully")
|
|
else:
|
|
print("Test failed, Tx-power is not changed to 20dBm")
|
|
pass_fail = 'FAIL'
|
|
allure.attach(name="Test Result",
|
|
body="TEST FAILED, Tx-power is not changed to 20dBm")
|
|
return "FAIL", "TEST FAILED, Tx-power is not changed to 20dBm"
|
|
# Step 2 validation
|
|
if reconfig == "dfs":
|
|
res = tip_2x_obj.dut_library_object.get_uci_show(param = 'wireless')
|
|
if "wireless.radio1.acs_exclude_dfs='0'" in res:
|
|
print("dfs parameter is changed successfully")
|
|
else:
|
|
print("dfs parameter is not changed")
|
|
pass_fail = 'FAIL'
|
|
allure.attach(name="Test Result",
|
|
body="TEST FAILED, dfs parameter is not changed")
|
|
return "FAIL", "TEST FAILED, dfs parameter is not changed"
|
|
# Step 2 validation
|
|
if reconfig == "he":
|
|
bss_color = sta_data['interface']['bss color']
|
|
print("bss_color after reconfiguration", bss_color)
|
|
bss_color = int(bss_color) # Convert sta_channel to an integer
|
|
if bss_color == 60:
|
|
print("bss color is changed successfully") # upper band
|
|
else:
|
|
print("bss color is not changed")
|
|
pass_fail = 'FAIL'
|
|
allure.attach(name="Test Result", body="TEST FAILED, bss color is not changed")
|
|
return "FAIL", "TEST FAILED, bss color is not changed"
|
|
|
|
return pass_fail, description
|
|
|
|
|
|
|
|
def enterprise_client_connectivity_test(self, ssid="[BLANK]", passkey="[BLANK]", bssid="[BLANK]", dut_data={},
|
|
security="open", extra_securities=[], client_type=0, key_mgmt="WPA-EAP",
|
|
pairwise="NA", group="NA", wpa_psk="DEFAULT", ttls_passwd="nolastart",
|
|
ieee80211w=1, wep_key="NA", ca_cert="NA", eap="TTLS", identity="nolaradius",
|
|
d_vlan=False, cleanup=True, pre_cleanup=True,
|
|
num_sta=1, mode="BRIDGE", vlan_id=[None], band="twog",
|
|
allure_attach=True, runtime_secs=40, pk_passwd="whatever"):
|
|
|
|
if pre_cleanup:
|
|
self.pre_cleanup()
|
|
self.check_band_ap(band=band)
|
|
logging.info("DUT Data:\n" + json.dumps(str(dut_data), indent=2))
|
|
allure.attach(name="DUT Data:\n", body=json.dumps(str(dut_data), indent=2),
|
|
attachment_type=allure.attachment_type.JSON)
|
|
|
|
if self.run_lf:
|
|
dut_data = self.run_lf_dut_data()
|
|
data = self.setup_interfaces(ssid=ssid, bssid=bssid, passkey=passkey, encryption=security,
|
|
band=band, vlan_id=vlan_id, mode=mode, num_sta=num_sta, dut_data_=dut_data,
|
|
d_vlan=d_vlan)
|
|
|
|
logging.info("Setup interface data:\n" + json.dumps(str(data), indent=2))
|
|
allure.attach(name="Interface Info: \n", body=json.dumps(str(data), indent=2),
|
|
attachment_type=allure.attachment_type.JSON)
|
|
if data == {}:
|
|
pytest.skip("Skipping This Test")
|
|
# list of multiple eap_connect objects
|
|
eap_connect_objs = []
|
|
for dut in data:
|
|
for radio in data[dut]["station_data"]:
|
|
obj_eap_connect = TTLSTest(host=self.manager_ip, port=self.manager_http_port,
|
|
sta_list=data[dut]["station_data"][radio], vap=False, _debug_on=True)
|
|
obj_eap_connect.station_profile.sta_mode = client_type
|
|
obj_eap_connect.upstream_resource = data[dut]["upstream_resource"]
|
|
obj_eap_connect.l3_cx_obj_udp.upstream_resource = data[dut]["upstream_resource"]
|
|
obj_eap_connect.l3_cx_obj_tcp.upstream_resource = data[dut]["upstream_resource"]
|
|
obj_eap_connect.l3_cx_obj_udp.upstream = data[dut]["upstream"]
|
|
obj_eap_connect.l3_cx_obj_tcp.upstream = data[dut]["upstream"]
|
|
self.enable_verbose_debug(radio=radio, enable=True)
|
|
obj_eap_connect.radio = radio
|
|
obj_eap_connect.admin_down(radio)
|
|
obj_eap_connect.admin_up(radio)
|
|
# changed to auto channel
|
|
self.set_radio_channel(radio=radio, channel="AUTO")
|
|
logging.info("scan ssid radio: " + str(radio.split(".")[2]))
|
|
result = self.scan_ssid(radio=radio, ssid=data[dut]["ssid"])
|
|
logging.info("ssid scan data : " + str(result))
|
|
if not result:
|
|
# Sniffer required
|
|
for duts in self.dut_data:
|
|
identifier = duts["identifier"]
|
|
if dut_data.keys().__contains__(identifier):
|
|
if band == "twog":
|
|
if dict(dut_data.get(identifier)["radio_data"]).keys().__contains__("2G") and \
|
|
dict(dut_data.get(identifier)["radio_data"])["2G"] is not None:
|
|
channel = dict(dut_data.get(identifier)["radio_data"])["2G"]["channel"]
|
|
if data[dut]["sniff_radio_2g"] is not None and channel is not None:
|
|
self.start_sniffer(radio_channel=channel,
|
|
radio=data[dut]["sniff_radio_2g"],
|
|
duration=10)
|
|
time.sleep(10)
|
|
self.stop_sniffer()
|
|
elif band == "fiveg":
|
|
if dict(dut_data.get(identifier)["radio_data"]).keys().__contains__("5G") and \
|
|
dict(dut_data.get(identifier)["radio_data"])["5G"] is not None:
|
|
channel = dict(dut_data.get(identifier)["radio_data"])["5G"]["channel"]
|
|
if data[dut]["sniff_radio_5g"] is not None and channel is not None:
|
|
self.start_sniffer(radio_channel=channel,
|
|
radio=data[dut]["sniff_radio_5g"],
|
|
duration=10)
|
|
time.sleep(10)
|
|
self.stop_sniffer()
|
|
elif band == "sixg":
|
|
if dict(dut_data.get(identifier)["radio_data"]).keys().__contains__("6G") and \
|
|
dict(dut_data.get(identifier)["radio_data"])["6G"] is not None:
|
|
channel = dict(dut_data.get(identifier)["radio_data"])["6G"]["channel"]
|
|
if data[dut]["sniff_radio_6g"] is not None and channel is not None:
|
|
logging.info("sixg channel: " + str(data[dut]["channel"]))
|
|
channel = self.lf_sixg_lookup_validation(int(data[dut]["channel"]))
|
|
logging.info("LF sixg channel: " + str(channel))
|
|
self.start_sniffer(radio_channel=channel,
|
|
radio=data[dut]["sniff_radio_6g"],
|
|
duration=10)
|
|
time.sleep(10)
|
|
self.stop_sniffer()
|
|
if not result:
|
|
pytest.fail("SSID is not Available in Scan Result")
|
|
if eap == "TTLS":
|
|
obj_eap_connect.ieee80211w = ieee80211w
|
|
obj_eap_connect.key_mgmt = key_mgmt
|
|
obj_eap_connect.station_profile.set_command_flag("add_sta", "80211u_enable", 0)
|
|
obj_eap_connect.identity = identity
|
|
obj_eap_connect.ttls_passwd = ttls_passwd
|
|
obj_eap_connect.pairwise = pairwise
|
|
obj_eap_connect.group = group
|
|
if eap == "TLS":
|
|
obj_eap_connect.key_mgmt = key_mgmt
|
|
obj_eap_connect.station_profile.set_command_flag("add_sta", "80211u_enable", 0)
|
|
obj_eap_connect.eap = eap
|
|
obj_eap_connect.identity = identity
|
|
obj_eap_connect.ttls_passwd = ttls_passwd
|
|
obj_eap_connect.private_key = "/home/lanforge/client.p12"
|
|
obj_eap_connect.ca_cert = "/home/lanforge/ca.pem"
|
|
obj_eap_connect.pk_passwd = pk_passwd
|
|
obj_eap_connect.ieee80211w = 1
|
|
|
|
obj_eap_connect.ssid = data[dut]["ssid"]
|
|
obj_eap_connect.password = data[dut]["passkey"]
|
|
obj_eap_connect.security = data[dut]["encryption"]
|
|
obj_eap_connect.sta_list = data[dut]["station_data"][radio]
|
|
obj_eap_connect.build(extra_securities=extra_securities)
|
|
eap_connect_objs.append(obj_eap_connect)
|
|
for dut_ in self.dut_data:
|
|
identifier = dut_["identifier"]
|
|
if dut_data.keys().__contains__(identifier):
|
|
if band == "twog":
|
|
if dict(dut_data.get(identifier)["radio_data"]).keys().__contains__("2G") and \
|
|
dict(dut_data.get(identifier)["radio_data"])["2G"] is not None:
|
|
channel = dict(dut_data.get(identifier)["radio_data"])["2G"]["channel"]
|
|
if data[dut]["sniff_radio_2g"] is not None and channel is not None:
|
|
self.start_sniffer(radio_channel=channel,
|
|
radio=data[dut]["sniff_radio_2g"],
|
|
duration=runtime_secs)
|
|
logging.info("started-sniffer")
|
|
for obj in eap_connect_objs:
|
|
obj.start(obj.sta_list, True, True, wait_time=1)
|
|
logging.info("napping %f sec" % runtime_secs)
|
|
time.sleep(runtime_secs)
|
|
if data[dut]["sniff_radio_2g"] is not None and channel is not None:
|
|
self.stop_sniffer()
|
|
elif band == "fiveg":
|
|
if dict(dut_data.get(identifier)["radio_data"]).keys().__contains__("5G") and \
|
|
dict(dut_data.get(identifier)["radio_data"])["5G"] is not None:
|
|
channel = dict(dut_data.get(identifier)["radio_data"])["5G"]["channel"]
|
|
if data[dut]["sniff_radio_5g"] is not None and channel is not None:
|
|
self.start_sniffer(radio_channel=channel,
|
|
radio=data[dut]["sniff_radio_5g"],
|
|
duration=runtime_secs)
|
|
for obj in eap_connect_objs:
|
|
obj.start(obj.sta_list, True, True, wait_time=1)
|
|
logging.info("napping %f sec" % runtime_secs)
|
|
time.sleep(runtime_secs)
|
|
if data[dut]["sniff_radio_5g"] is not None and channel is not None:
|
|
self.stop_sniffer()
|
|
elif band == "sixg":
|
|
if dict(dut_data.get(identifier)["radio_data"]).keys().__contains__("6G") and \
|
|
dict(dut_data.get(identifier)["radio_data"])["6G"] is not None:
|
|
channel = dict(dut_data.get(identifier)["radio_data"])["6G"]["channel"]
|
|
if data[dut]["sniff_radio_6g"] is not None and channel is not None:
|
|
logging.info("sixg channel: " + str(data[dut]["channel"]))
|
|
channel = self.lf_sixg_lookup_validation(int(data[dut]["channel"]))
|
|
logging.info("LF sixg channel: " + str(channel))
|
|
self.start_sniffer(radio_channel=channel,
|
|
radio=data[dut]["sniff_radio_6g"],
|
|
duration=runtime_secs)
|
|
for obj in eap_connect_objs:
|
|
obj.start(obj.sta_list, True, True, wait_time=1)
|
|
logging.info("napping %f sec" % runtime_secs)
|
|
time.sleep(runtime_secs)
|
|
if data[dut]["sniff_radio_6g"] is not None and channel is not None:
|
|
self.stop_sniffer()
|
|
else:
|
|
for obj in eap_connect_objs:
|
|
obj.start(obj.sta_list, True, True, wait_time=1)
|
|
logging.info("napping %f sec" % runtime_secs)
|
|
time.sleep(runtime_secs)
|
|
pass_fail_result = []
|
|
for obj in eap_connect_objs:
|
|
sta_rows = ["4way time (us)", "channel", "ssid", "cx time (us)", "dhcp (ms)", "ip", "signal", "mac", "mode"]
|
|
self.station_data = self.get_station_data(sta_name=obj.sta_list, rows=sta_rows,
|
|
allure_attach=False)
|
|
sta_table_dict = {}
|
|
sta_table_dict["station name"] = list(self.station_data.keys())
|
|
for i in sta_rows:
|
|
temp_list = []
|
|
for j in obj.sta_list:
|
|
temp_list.append(self.station_data[j][i])
|
|
sta_table_dict[i] = temp_list
|
|
# pass fail
|
|
pass_fail_sta = []
|
|
for i in sta_table_dict["ip"]:
|
|
if i == "0.0.0.0":
|
|
pass_fail_sta.append("Fail")
|
|
else:
|
|
pass_fail_sta.append("Pass")
|
|
sta_table_dict["Pass/Fail"] = pass_fail_sta
|
|
if allure_attach:
|
|
self.attach_table_allure(data=sta_table_dict, allure_name="station data")
|
|
obj.stop()
|
|
cx_name = list(obj.l3_cx_obj_udp.cx_profile.get_cx_names()) + list(
|
|
obj.l3_cx_obj_tcp.cx_profile.get_cx_names())
|
|
cx_row = ["type", "bps rx a", "bps rx b"]
|
|
cx_data = self.get_cx_data(cx_name=cx_name, cx_data=cx_row, allure_attach=False)
|
|
cx_table_dict = {}
|
|
upstream = []
|
|
for i in range(len(obj.sta_list)):
|
|
upstream.append(data[dut]["upstream_port"])
|
|
cx_table_dict["Upstream"] = upstream
|
|
cx_table_dict["Downstream"] = obj.sta_list
|
|
cx_tcp_ul = []
|
|
cx_tcp_dl = []
|
|
cx_udp_ul = []
|
|
cx_udp_dl = []
|
|
for sta in obj.sta_list:
|
|
for i in cx_data:
|
|
if sta.split(".")[2] in i:
|
|
if cx_data[i]["type"] == "LF/UDP":
|
|
cx_udp_dl.append(cx_data[i]["bps rx a"])
|
|
cx_udp_ul.append(cx_data[i]["bps rx b"])
|
|
elif cx_data[i]["type"] == "LF/TCP":
|
|
cx_tcp_dl.append(cx_data[i]["bps rx a"])
|
|
cx_tcp_ul.append(cx_data[i]["bps rx b"])
|
|
cx_table_dict["TCP DL"] = cx_tcp_dl
|
|
cx_table_dict["TCP UL"] = cx_tcp_ul
|
|
cx_table_dict["UDP DL"] = cx_udp_dl
|
|
cx_table_dict["UDP UL"] = cx_udp_ul
|
|
pass_fail_cx = []
|
|
for i, j, k, l in zip(cx_tcp_dl, cx_tcp_ul, cx_udp_dl, cx_udp_ul):
|
|
if i == 0 or j == 0 or k == 0 or l == 0:
|
|
pass_fail_cx.append("Fail")
|
|
else:
|
|
pass_fail_cx.append("Pass")
|
|
cx_table_dict["Pass/Fail"] = pass_fail_cx
|
|
if allure_attach:
|
|
self.attach_table_allure(data=cx_table_dict, allure_name="cx data")
|
|
if cleanup:
|
|
obj.cleanup(obj.sta_list)
|
|
result = "PASS"
|
|
description = "Unknown error"
|
|
count = 0
|
|
temp_dict = {}
|
|
if "Fail" in pass_fail_sta:
|
|
count = count + 1
|
|
result = "FAIL"
|
|
description = "Station did not get an ip"
|
|
temp_dict[result] = description
|
|
pass_fail_result.append(temp_dict)
|
|
if count == 0:
|
|
if "Fail" in pass_fail_cx:
|
|
result = "FAIL"
|
|
description = "did not report traffic"
|
|
temp_dict[result] = description
|
|
pass_fail_result.append(temp_dict)
|
|
for obj in eap_connect_objs:
|
|
try:
|
|
# print("1." + str(obj.resource) + "." + str(obj.radio))
|
|
self.get_supplicant_logs(radio=str(obj.radio))
|
|
except Exception as e:
|
|
logging.error("client_cpnnectivity_tests() -- Error in getting Supplicant Logs:" + str(e))
|
|
result = "PASS"
|
|
description = ""
|
|
for i in pass_fail_result:
|
|
if list(i.keys())[0] == "FAIL":
|
|
result = "FAIL"
|
|
description = i["FAIL"]
|
|
break
|
|
|
|
return result, description
|
|
|
|
def multiband_performance_test(self):
|
|
pass
|
|
|
|
def multi_psk_test(self, band="twog", mpsk_data=None, ssid="OpenWifi", bssid="['BLANK']", passkey="OpenWifi",
|
|
encryption="wpa", mode="BRIDGE", num_sta=1, dut_data=None):
|
|
if mpsk_data is None:
|
|
mpsk_data = {100: {"num_stations": num_sta, "passkey": "OpenWifi1"},
|
|
200: {"num_stations": num_sta, "passkey": "OpenWifi2"}}
|
|
|
|
logging.info("Creating VLAN's as per MPSK data")
|
|
# create VLAN's
|
|
vlan_ids = list(mpsk_data.keys())
|
|
if "default" in vlan_ids:
|
|
vlan_ids.remove("default")
|
|
|
|
data = self.setup_interfaces(ssid=ssid, passkey=passkey, encryption=encryption,
|
|
band=band, vlan_id=vlan_ids, mode="VLAN", num_sta=num_sta, dut_data_=dut_data)
|
|
if data == {}:
|
|
pytest.skip("Skipping This Test")
|
|
|
|
logging.info("Setup interface data:\n" + json.dumps(str(data), indent=2))
|
|
|
|
# query and fetch vlan Ip Address
|
|
port_data = self.json_get(_req_url="/port?fields=alias,port+type,ip,mac")['interfaces']
|
|
# Fail if Vlan don't have IP
|
|
vlan_data = {}
|
|
for i in port_data:
|
|
for item in i:
|
|
if i[item]['port type'] == '802.1Q VLAN' and i[item]['ip'] == '0.0.0.0':
|
|
logging.error(f"VLAN Interface - {i[item]['alias']} do not have IP")
|
|
pytest.fail("VLAN do not have IP")
|
|
break
|
|
elif i[item]['port type'] == '802.1Q VLAN' and i[item]['ip'] != '0.0.0.0':
|
|
vlan_data[i[item]['alias'].split(".")[1]] = i[item]
|
|
else:
|
|
pass
|
|
|
|
# create stations
|
|
sta_data = {}
|
|
non_vlan_sta = ""
|
|
if mode == "BRIDGE" or mode == "NAT-WAN":
|
|
non_vlan_sta = "WAN Upstream"
|
|
upstream_port = self.dut_data[0]["wan_port"]
|
|
vlan_data[non_vlan_sta] = self.wan_ports[upstream_port]
|
|
if mode == "NAT-LAN":
|
|
non_vlan_sta = "LAN upstream"
|
|
upstream_port = self.dut_data[0]["lan_port"]
|
|
vlan_data[non_vlan_sta] = self.lan_ports[upstream_port]
|
|
for key in list(mpsk_data.keys()):
|
|
if key == "default":
|
|
sta_data[non_vlan_sta] = self.client_connect(ssid=ssid, passkey=passkey, security=encryption, mode=mode,
|
|
band=band, pre_cleanup=False,
|
|
vlan_id=[None], num_sta=num_sta, scan_ssid=True,
|
|
station_data=["ip", "alias", "mac", "port type"],
|
|
allure_attach=True, dut_data=dut_data)
|
|
self.client_disconnect(station_name=list(sta_data[non_vlan_sta].keys()))
|
|
else:
|
|
sta_data[key] = self.client_connect(ssid=ssid, passkey=mpsk_data[key]["passkey"], security=encryption,
|
|
mode=mode, band=band, pre_cleanup=False,
|
|
vlan_id=[None], num_sta=num_sta, scan_ssid=True,
|
|
station_data=["ip", "alias", "mac", "port type"],
|
|
allure_attach=True, dut_data=dut_data)
|
|
self.client_disconnect(station_name=list(sta_data[key].keys()))
|
|
|
|
logging.info("station data: " + str(sta_data))
|
|
|
|
for dut in dut_data.keys():
|
|
supplicants = list(data[str(dut)]['station_data'].keys())
|
|
try:
|
|
for supplicant in supplicants:
|
|
self.get_supplicant_logs(radio=str(supplicant))
|
|
except Exception as e:
|
|
logging.error(f"Error in getting Supplicant logs: {str(e)}")
|
|
|
|
# check Pass/Fail
|
|
table_heads = ["station name", "configured vlan-id", "expected IP Range", "allocated IP", "mac address",
|
|
'pass/fail']
|
|
table_data = []
|
|
pf = 'PASS'
|
|
for i in sta_data:
|
|
if (str(i) in vlan_data) and (str(i) != 'WAN Upstream' and str(i) != 'LAN Upstream'):
|
|
for item in sta_data[i]:
|
|
exp1 = sta_data[i][item]['ip'].split('.')
|
|
ip1 = vlan_data[str(i)]['ip'].split('.')
|
|
if exp1[0] == ip1[0] and exp1[1] == ip1[1]:
|
|
pf = 'PASS'
|
|
logging.info(f"PASS: Station got IP from vlan {i}")
|
|
else:
|
|
pf = 'FAIL'
|
|
logging.info(f"FAIL: Station did not got IP from vlan {i}")
|
|
table_data.append(
|
|
[sta_data[i][item]['alias'], str(i), f'{exp1[0]}.{exp1[1]}.X.X', sta_data[i][item]['ip'],
|
|
sta_data[i][item]['mac'],
|
|
f'{pf}'])
|
|
elif str(i) == "WAN Upstream" and mode == "BRIDGE":
|
|
for item in sta_data[i]:
|
|
exp2 = sta_data[i][item]['ip'].split('.')
|
|
ip2 = vlan_data[str(i)]['subnet'].split('.')
|
|
if exp2[0] == ip2[0] and exp2[1] == ip2[1]:
|
|
pf = 'PASS'
|
|
logging.info(f"PASS: Station got IP from WAN Upstream")
|
|
else:
|
|
pf = 'FAIL'
|
|
logging.info(f"FAIL: Station did not got IP from WAN Upstream")
|
|
table_data.append(
|
|
[sta_data[i][item]['alias'], str(i), vlan_data[str(i)]['subnet'],
|
|
sta_data[i][item]['ip'], sta_data[i][item]['mac'],
|
|
f'{pf}'])
|
|
elif str(i) == "WAN Upstream" and mode == "NAT-WAN":
|
|
for item in sta_data[i]:
|
|
exp3 = sta_data[i][item]['ip'].split('.')
|
|
if exp3[0] == '192' and exp3[1] == '168':
|
|
pf = 'PASS'
|
|
logging.info(f"PASS: Station got IP from WAN Upstream")
|
|
else:
|
|
pf = 'FAIL'
|
|
logging.info(f"FAIL: Station did not got IP from WAN Upstream")
|
|
table_data.append(
|
|
[sta_data[i][item]['alias'], 'WAN upstream', f'192.168.X.X', sta_data[i][item]['ip'],
|
|
sta_data[i][item]['mac'], f'{pf}'])
|
|
elif str(i) == "LAN Upstream":
|
|
for item in sta_data[i]:
|
|
exp3 = sta_data[i][item]['ip'].split('.')
|
|
if exp3[0] == '192' and exp3[1] == '168':
|
|
pf = 'PASS'
|
|
logging.info(f"PASS: Station got IP from LAN Upstream")
|
|
else:
|
|
pf = 'FAIL'
|
|
logging.info(f"FAIL: Station did not got IP from LAN Upstream")
|
|
table_data.append(
|
|
[sta_data[i][item]['alias'], 'LAN upstream', f'192.168.X.X', sta_data[i][item]['ip'],
|
|
sta_data[i][item]['mac'], f'{pf}'])
|
|
|
|
# attach test data in a table to allure
|
|
report_obj = Report()
|
|
table_info = report_obj.table2(table=table_data, headers=table_heads)
|
|
logging.info(str("\n") + str(table_info))
|
|
allure.attach(name="Test Results", body=table_info)
|
|
if pf == 'FAIL':
|
|
logging.info("Station did not get an ip or Obtained IP of Station is not in Expected Range")
|
|
pytest.fail("Expected IP and Obtained IP are Different")
|
|
else:
|
|
logging.info("ALL Stations got IP as Expected")
|
|
|
|
def empsk_test(self,ssid="[BLANK]", passkey="[BLANK]", security="wpa2", mode="BRIDGE", band="twog",
|
|
num_sta=None, scan_ssid=True, client_type=0, pre_cleanup=True,
|
|
allure_attach=True, identifier=None, allure_name="station data", dut_data={},
|
|
extra_securities = [], is_bw320=False):
|
|
|
|
if pre_cleanup:
|
|
self.pre_cleanup()
|
|
self.check_band_ap(band="sixg")
|
|
if self.run_lf:
|
|
dut_data = self.run_lf_dut_data()
|
|
logging.info("DUT Data:\n" + json.dumps(str(dut_data), indent=2))
|
|
allure.attach(name="DUT Data:\n", body=json.dumps(str(dut_data), indent=2),
|
|
attachment_type=allure.attachment_type.JSON)
|
|
|
|
dict_all_radios_6g = {"be200_radios": self.be200_radios, "ax210_radios": self.ax210_radios}
|
|
logging.info(f"dict_all_radios_6g:{dict_all_radios_6g}")
|
|
radio = (dict_all_radios_6g['be200_radios'] or dict_all_radios_6g['ax210_radios'])[0]
|
|
logging.info(f"radio:{radio}")
|
|
logging.info("creating station profile obj")
|
|
sta = "sta0000"
|
|
obj_sta_profile = StationProfile(self.local_realm.lfclient_url, self.local_realm)
|
|
obj_sta_profile.add_sta_data = {
|
|
"radio": radio,
|
|
"sta_name": sta,
|
|
"ssid": ssid,
|
|
"key": passkey,
|
|
"mode": 0,
|
|
"mac": "xx:xx:xx:xx:*:xx",
|
|
"flags": 1127003847656448, # enable wpa3 and wpa2 and be320
|
|
"flags_mask": 0
|
|
}
|
|
if extra_securities:
|
|
logging.info(f"extra_securities are provided:{extra_securities}")
|
|
if "wpa3" in extra_securities:
|
|
obj_sta_profile.add_security_extra(security="wpa3")
|
|
if is_bw320:
|
|
obj_sta_profile.set_command_flag("add_sta", "be320-enable", 1)
|
|
obj_sta_profile.set_command_flag("add_sta", "ht160_enable", 1)
|
|
obj_sta_profile.set_command_flag("add_sta", "disable_ht80", 0)
|
|
|
|
logging.info(f"creating station profile")
|
|
obj_sta_profile.create(radio=radio, num_stations=1)
|
|
time.sleep(30)
|
|
sta_data = self.json_get(_req_url="port/1/1/%s" % sta)
|
|
# Through station data we are getting wpa3 as security, but we need to show both wpa2 and wpa3 as we are enabling both the securities.
|
|
if sta_data["interface"]["security"] == "WPA3":
|
|
sta_data["interface"]["security"] = "WPA2 and WPA3"
|
|
self.allure_report_table_format(dict_data=sta_data["interface"], key="Station Data",
|
|
value="Value", name="station data for 2G/5G band")
|
|
logging.info(f"sta_data::{sta_data}")
|
|
station_list = ["1.1.sta0000"]
|
|
enable_flag = ["use-wpa3"]
|
|
disable_flag = ["wpa2_enable"]
|
|
obj_modify_sta = ModifyStation(_host=self.manager_ip, _port=self.manager_http_port,
|
|
_ssid=ssid,
|
|
_password=passkey,
|
|
_security=security,
|
|
_station_list=station_list,
|
|
_radio=radio,
|
|
_enable_flags=enable_flag,
|
|
_disable_flags=disable_flag,
|
|
_debug_on=True)
|
|
obj_modify_sta.set_station()
|
|
logging.info("Successfully changed encryption from WPA2 to WPA3")
|
|
allure.attach(name="Encryption changed:\n", body="Successfully changed encryption from WPA2 to WPA3")
|
|
time.sleep(10)
|
|
|
|
sta_data = self.json_get(_req_url="port/1/1/%s" % sta)
|
|
self.allure_report_table_format(dict_data=sta_data["interface"], key="Station Data",
|
|
value="Value", name="station data for 6G band")
|
|
|
|
logging.info(f"sta_data after security modification:{sta_data}")
|
|
|
|
# pass fail
|
|
pass_fail_sta = []
|
|
for i in range(len(station_list)):
|
|
if sta_data["interface"]["ip"] == "0.0.0.0" or sta_data["interface"]["ap"] == "Not-Associated":
|
|
pass_fail_sta.append("Fail")
|
|
else:
|
|
pass_fail_sta.append("Pass")
|
|
sta_data["Pass/Fail"] = pass_fail_sta
|
|
|
|
for i in range(len(station_list)):
|
|
if sta_data["interface"]["ip"] == "0.0.0.0":
|
|
logging.info("Station did not get an ip")
|
|
pytest.fail("Station did not get an ip")
|
|
else:
|
|
logging.info("Station got IP")
|
|
|
|
for i in range(len(station_list)):
|
|
if sta_data["interface"]["ap"] == "Not-Associated":
|
|
logging.info("Station did not associate to AP")
|
|
pytest.fail("Station did not associate to AP")
|
|
else:
|
|
logging.info("Station successfully associated to AP")
|
|
|
|
return sta_data
|
|
|
|
def band_steering_test(self, ssid="[BLANK]", passkey="[BLANK]", security="wpa2", mode="BRIDGE", band="twog",
|
|
num_sta=None, scan_ssid=True, client_type=0, pre_cleanup=True,
|
|
station_data=["ip", "alias", "mac", "channel", "port type", "security", "ap", "parent dev"],
|
|
allure_attach=True, dut_data={},get_target_object=None, get_testbed_details={}):
|
|
|
|
sta_data = self.client_connect(ssid=ssid, passkey=passkey, security=security,
|
|
mode=mode, band=band, pre_cleanup=False, num_sta=num_sta,
|
|
scan_ssid=True,
|
|
station_data=station_data,
|
|
allure_attach=True, dut_data=dut_data)
|
|
|
|
logging.info(f"sta_data in band_steer: {sta_data}")
|
|
# check ssid info in iwinfo
|
|
serial_number = list(dut_data.keys())[0]
|
|
ap_iwinfo = get_target_object.dut_library_object.get_iwinfo(attach_allure=True)
|
|
ap_data = dict()
|
|
bssid_list = list()
|
|
freqs_ = ""
|
|
|
|
if str(ap_iwinfo) != "Error: pop from empty list":
|
|
include_essid = ssid
|
|
re_obj = re.compile(
|
|
rf'(\S+)\s+ESSID: "{re.escape(include_essid)}".*?Access Point:\s+([0-9A-Fa-f:]+).*?Channel:\s+(\d+)\s+\(([\d.]+) GHz\)',
|
|
re.DOTALL
|
|
)
|
|
interface_matches = re_obj.finditer(ap_iwinfo)
|
|
radio_entries = []
|
|
|
|
for match in interface_matches:
|
|
interface_name = match.group(1)
|
|
access_point = match.group(2)
|
|
channel = match.group(3)
|
|
frequency = match.group(4).replace('.', '')
|
|
|
|
radio_entries.append({
|
|
'interface': interface_name,
|
|
'Access Point': access_point,
|
|
'Channel': channel,
|
|
'frequency': frequency
|
|
})
|
|
if radio_entries:
|
|
ap_data.update({serial_number: radio_entries})
|
|
logging.info(f"AP Data from iwinfo updated: {ap_data}")
|
|
else:
|
|
logging.warning("No matching radios found in iwinfo.")
|
|
elif ap_iwinfo == {}:
|
|
pytest.fail("Empty iwinfo reponse from AP through minicom")
|
|
else:
|
|
pytest.fail("Failed to get iwinfo from minicom")
|
|
|
|
for serial in ap_data:
|
|
for radio in ap_data[serial]:
|
|
bssid_list.append(radio['Access Point'])
|
|
freqs_ += radio['frequency']
|
|
|
|
|
|
pass_fail = True
|
|
message_parts = []
|
|
logging.info(f"bssid_list values:{bssid_list}")
|
|
logging.info(f"freqs_ values:{freqs_}")
|
|
|
|
sta_name = list(sta_data.keys())[0]
|
|
logging.info(f"sta_name:{sta_name}")
|
|
|
|
# Parse BSSID's as a lowercase string separated by ,
|
|
ap1_bssid = bssid_list[0].lower()
|
|
ap2_bssid = bssid_list[1].lower()
|
|
bssid_list = ap1_bssid + "," + ap2_bssid
|
|
|
|
wifi_mobility_obj = WifiMobility(lfclient_host=self.manager_ip,lf_port=self.manager_http_port,
|
|
ssh_port=self.manager_ssh_port,lf_user="lanforge",lf_password="lanforge",
|
|
blob_test="WiFi-Mobility-",instance_name="cv-inst-0",
|
|
config_name="roam_test_cfg",pull_report=True,load_old_cfg=False,
|
|
raw_lines=None,raw_lines_file="",enables=None,disables=None,sets=None,
|
|
cfg_options=None,sort="interleave",stations=sta_name,bssid_list=bssid_list,
|
|
gen_scan_freqs=freqs_,gen_sleep_interval="30000",gen_scan_sleep_interval="2000",
|
|
duration="300000",auto_verify="30000",default_sleep="250",max_rpt_time='500',
|
|
skip_roam_self='0',loop_check='1',clear_on_start='0',show_events='1',
|
|
report_dir="",graph_groups=None,test_rig="Testbed-01",test_tag="",
|
|
local_lf_report_dir="../reports/",verbosity="5"
|
|
)
|
|
|
|
if wifi_mobility_obj.instance_name.endswith('-0'):
|
|
wifi_mobility_obj.instance_name = wifi_mobility_obj.instance_name + str(random.randint(1, 9999))
|
|
|
|
def ping_runner_via_ssh(hostname, port, username, password, sta, ping_host="google.com",
|
|
ping_duration=300, ping_interval=1, output_file="ping_output.txt"):
|
|
logging.info(f"sta::{sta}")
|
|
ping_count = int(ping_duration / ping_interval)
|
|
# ping_command = f"ping -i {ping_interval} -c {ping_count} {ping_host}"
|
|
ping_command = f"/home/lanforge/vrf_exec.bash {sta} ping -c {ping_count} {ping_host}"
|
|
|
|
logging.info(f"ping_command:{ping_command}")
|
|
logging.info(f"SSH ping: {ping_command} on {sta}@{hostname}:{port}")
|
|
|
|
client = paramiko.SSHClient()
|
|
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
|
|
try:
|
|
client.connect(hostname, port=port, username=username, password=password)
|
|
stdin, stdout, stderr = client.exec_command(ping_command)
|
|
ping_output = stdout.read().decode()
|
|
client.close()
|
|
|
|
# Save to file
|
|
with open(output_file, "w") as f:
|
|
f.write(ping_output)
|
|
|
|
# Attach to Allure
|
|
allure.attach(ping_output, name="Ping Output", attachment_type=allure.attachment_type.TEXT)
|
|
|
|
# Analyze output
|
|
match = re.search(r'([\d.]+)% packet loss', ping_output)
|
|
if match:
|
|
packet_loss = float(match.group(1))
|
|
if packet_loss == 0:
|
|
logging.info("Ping successful — 0% packet loss.")
|
|
allure.attach(name="Ping Result: \n", body="Ping successful — 0% packet loss.")
|
|
else:
|
|
message_parts.append(f"Ping failed — {packet_loss}% packet loss")
|
|
pass_fail = False
|
|
logging.info(f"message_parts::{message_parts}")
|
|
logging.warning(f"Ping failed — {packet_loss}% packet loss, pass_fail::{pass_fail}")
|
|
allure.attach(name="Ping Result: \n", body=f"Ping failed — {packet_loss}% packet loss.")
|
|
else:
|
|
logging.warning("Could not find packet loss info in ping.")
|
|
allure.attach(name="Ping Result: \n", body="Could not find packet loss info in ping.")
|
|
|
|
except Exception as e:
|
|
logging.error(f"SSH ping failed: {e}")
|
|
|
|
logging.info(f"Ping output saved to {output_file}")
|
|
|
|
# SSH connection parameters
|
|
hostname = get_testbed_details["traffic_generator"]["details"]["manager_ip"]
|
|
port = get_testbed_details["traffic_generator"]["details"]["ssh_port"]
|
|
username = 'root'
|
|
password = 'lanforge'
|
|
# Create threads
|
|
wifi_mobility_thread = threading.Thread(target=wifi_mobility_obj.run)
|
|
wifi_capacity_thread = threading.Thread(target=self.wifi_capacity, kwargs={
|
|
"mode": mode,
|
|
"vlan_id": None,
|
|
"instance_name": "wct_instance",
|
|
"download_rate": "1Gbps",
|
|
"influx_tags": "",
|
|
"upload_rate": "56Kbps",
|
|
"protocol": "UDP",
|
|
"duration": "180000",
|
|
"stations": "",
|
|
"create_stations": False,
|
|
"sort": "interleave",
|
|
"raw_lines": [],
|
|
"move_to_influx": False,
|
|
"dut_data": dut_data,
|
|
"ssid_name": None,
|
|
"num_stations": {},
|
|
"add_stations": False
|
|
})
|
|
ping_thread = threading.Thread(target=ping_runner_via_ssh, kwargs={
|
|
"hostname": hostname,
|
|
"port": port,
|
|
"username": username,
|
|
"password": password,
|
|
"sta": list(sta_name.split("."))[-1],
|
|
"ping_host": "google.com",
|
|
"ping_duration": 300,
|
|
"ping_interval": 1,
|
|
"output_file": "ping_output.txt"
|
|
})
|
|
logging.info("All three threads (mobility, capacity, ping) are ready to start")
|
|
# Start all threads
|
|
wifi_mobility_thread.start()
|
|
wifi_capacity_thread.start()
|
|
ping_thread.start()
|
|
|
|
# Wait for all to finish
|
|
wifi_mobility_thread.join()
|
|
wifi_capacity_thread.join()
|
|
ping_thread.join()
|
|
|
|
logging.info("All wifi mobility, wifi capacity tests and ping are completed.")
|
|
|
|
report_name, wm_pass_fail_data = "", list()
|
|
if wifi_mobility_obj.report_name and len(wifi_mobility_obj.report_name) >= 1:
|
|
report_name = wifi_mobility_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1] + "/"
|
|
time.sleep(10)
|
|
logging.info("wifi mobility report_name: " + str(report_name))
|
|
self.attach_report_graphs(report_name=report_name, pdf_name="WiFi-Mobility (Roam Test) PDF Report")
|
|
else:
|
|
logging.error(f"PATH {wifi_mobility_obj.report_name} does not exist")
|
|
|
|
if wifi_mobility_obj.get_exists(wifi_mobility_obj.instance_name):
|
|
wifi_mobility_obj.delete_instance(wifi_mobility_obj.instance_name)
|
|
|
|
# fetch csv data from report data & attach pass fail results
|
|
if not report_name.endswith("/"):
|
|
report_name = report_name + "/"
|
|
if os.path.exists("../reports/" + report_name + "chart-csv-7.csv"):
|
|
with open("../reports/" + report_name + "chart-csv-7.csv", 'rb') as csv_file:
|
|
file_content = csv_file.read()
|
|
allure.attach(file_content, name=f"Roam Test Pass/Fail Data",
|
|
attachment_type=allure.attachment_type.CSV)
|
|
with open("../reports/" + report_name + "chart-csv-7.csv", 'r') as csv_file:
|
|
for row in csv.reader(csv_file):
|
|
wm_pass_fail_data.append(row)
|
|
else:
|
|
logging.info(f"{report_name} Does not exist.")
|
|
|
|
logging.info(f"pass_fail_data in wifi-mobility:{str(wm_pass_fail_data)}")
|
|
for i in wm_pass_fail_data[1:]:
|
|
if i[2] == 'FAIL':
|
|
message_parts.append("Roam Test Failed")
|
|
pass_fail = False
|
|
if message_parts:
|
|
if len(message_parts) == 1:
|
|
message = message_parts[0]
|
|
else:
|
|
message = " and ".join(message_parts)
|
|
else:
|
|
message = "Roam Test Passed"
|
|
|
|
return pass_fail, message
|
|
|
|
|
|
def client_connect(self, ssid="[BLANK]", passkey="[BLANK]", security="wpa2", mode="BRIDGE", band="twog",
|
|
vlan_id=[None], num_sta=None, scan_ssid=True, client_type=0, pre_cleanup=True,
|
|
station_data=["4way time (us)", "channel", "cx time (us)", "dhcp (ms)", "ip", "signal", "mode", "ap", "parent dev"],
|
|
allure_attach=True, identifier=None, allure_name="station data", dut_data={}):
|
|
# pre cleanup
|
|
if pre_cleanup:
|
|
self.pre_cleanup()
|
|
self.check_band_ap(band=band)
|
|
if identifier is None:
|
|
identifier = self.dut_data[0]["identifier"]
|
|
logging.info("Identifier: " + str(identifier))
|
|
else:
|
|
all_identifier_list = []
|
|
for dut in self.dut_data:
|
|
all_identifier_list.append(dut["identifier"])
|
|
print(all_identifier_list)
|
|
if identifier not in all_identifier_list:
|
|
logging.error("Identifier is missing")
|
|
pytest.fail("Identifier is missing")
|
|
if self.run_lf:
|
|
dut_data = self.run_lf_dut_data()
|
|
|
|
data = self.setup_interfaces(ssid=ssid, passkey=passkey, encryption=security,
|
|
band=band, vlan_id=vlan_id, mode=mode, num_sta=num_sta, dut_data_=dut_data)
|
|
|
|
logging.info("Setup interface data:\n" + json.dumps(str(data), indent=2))
|
|
allure.attach(name="Interface Info: \n", body=json.dumps(str(data), indent=2),
|
|
attachment_type=allure.attachment_type.JSON)
|
|
if data == {}:
|
|
pytest.skip("Skipping This Test")
|
|
client_connect_obj = []
|
|
station_data_all = {}
|
|
start_sniffer = False
|
|
for radio in data[identifier]["station_data"]:
|
|
if band == "twog":
|
|
if dict(dut_data.get(identifier)["radio_data"]).keys().__contains__("2G") and \
|
|
dict(dut_data.get(identifier)["radio_data"])["2G"] is not None:
|
|
sniffer_channel = dict(dut_data.get(identifier)["radio_data"])["2G"]["channel"]
|
|
if data[identifier]["sniff_radio_2g"] is not None and sniffer_channel is not None:
|
|
start_sniffer = True
|
|
self.start_sniffer(radio_channel=sniffer_channel,
|
|
test_name=f'{data[identifier]["station_data"][radio][0]}',
|
|
radio=data[identifier]["sniff_radio_2g"],
|
|
duration=120)
|
|
logging.info("started-sniffer")
|
|
if band == "fiveg":
|
|
if dict(dut_data.get(identifier)["radio_data"]).keys().__contains__("5G") and \
|
|
dict(dut_data.get(identifier)["radio_data"])["5G"] is not None:
|
|
sniffer_channel = dict(dut_data.get(identifier)["radio_data"])["5G"]["channel"]
|
|
if data[identifier]["sniff_radio_5g"] is not None and sniffer_channel is not None:
|
|
start_sniffer = True
|
|
self.start_sniffer(radio_channel=sniffer_channel,
|
|
radio=data[identifier]["sniff_radio_5g"],
|
|
duration=120)
|
|
logging.info("started-sniffer")
|
|
if band == "sixg":
|
|
if dict(dut_data.get(identifier)["radio_data"]).keys().__contains__("6G") and \
|
|
dict(dut_data.get(identifier)["radio_data"])["6G"] is not None:
|
|
sniffer_channel = self.lf_sixg_lookup_validation(
|
|
int(dict(dut_data.get(identifier)["radio_data"])["6G"]["channel"]))
|
|
logging.info("LF sixg channel: " + str(sniffer_channel))
|
|
if data[identifier]["sniff_radio_6g"] is not None and sniffer_channel is not None:
|
|
start_sniffer = True
|
|
self.start_sniffer(radio_channel=sniffer_channel,
|
|
radio=data[identifier]["sniff_radio_6g"],
|
|
duration=120)
|
|
logging.info("started-sniffer")
|
|
client_connect = CreateStation(_host=self.manager_ip, _port=self.manager_http_port,
|
|
_sta_list=data[identifier]["station_data"][radio],
|
|
_password=data[identifier]["passkey"],
|
|
_ssid=data[identifier]["ssid"],
|
|
_security=data[identifier]["encryption"])
|
|
client_connect.station_profile.sta_mode = client_type
|
|
client_connect.upstream_resource = data[identifier]["upstream_resource"]
|
|
client_connect.upstream_port = data[identifier]["upstream"]
|
|
client_connect.radio = radio
|
|
logging.info("scan ssid radio: " + str(client_connect.radio))
|
|
if scan_ssid:
|
|
self.data_scan_ssid = self.scan_ssid(radio=client_connect.radio, ssid=ssid)
|
|
logging.info("ssid scan data: " + str(self.data_scan_ssid))
|
|
client_connect_obj.append(client_connect)
|
|
pass_fail = []
|
|
for obj in client_connect_obj:
|
|
obj.build()
|
|
result = obj.wait_for_ip(station_list=obj.sta_list, timeout_sec=240)
|
|
pass_fail.append(result)
|
|
station_data_ = self.get_station_data(sta_name=obj.sta_list, rows=station_data,
|
|
allure_attach=False)
|
|
station_data_all.update(station_data_)
|
|
sta_table_dict = {}
|
|
sta_table_dict["station name"] = list(station_data_.keys())
|
|
for i in station_data:
|
|
temp_list = []
|
|
for j in obj.sta_list:
|
|
temp_list.append(station_data_[j][i])
|
|
sta_table_dict[i] = temp_list
|
|
# pass fail
|
|
pass_fail_sta = []
|
|
for i in sta_table_dict["ip"]:
|
|
if i == "0.0.0.0":
|
|
pass_fail_sta.append("Fail")
|
|
else:
|
|
pass_fail_sta.append("Pass")
|
|
sta_table_dict["Pass/Fail"] = pass_fail_sta
|
|
if allure_attach:
|
|
self.attach_table_allure(data=sta_table_dict, allure_name=allure_name)
|
|
|
|
# stop sniffer if active
|
|
logging.info(msg=str("Cleaning up sniffer interface If available on PORT Manager"))
|
|
port_data = self.json_get(_req_url="/port?fields=alias,parent+dev,port+type,ip,mac")['interfaces']
|
|
# for i in port_data:
|
|
# for item in i:
|
|
# if i[item]['port type'] == '802.1Q VLAN' and i[item]['ip'] == '0.0.0.0':
|
|
# logging.info('VLAN do not have IP')
|
|
if start_sniffer:
|
|
self.stop_sniffer()
|
|
|
|
logging.info("pass_fail result: " + str(pass_fail))
|
|
if False in pass_fail:
|
|
logging.info("Station did not get an ip")
|
|
for radio in data[identifier]["station_data"]:
|
|
self.get_supplicant_logs(radio=str(radio))
|
|
pytest.fail("Station did not get an ip")
|
|
else:
|
|
logging.info("ALL Stations got IP's")
|
|
for radio in data[identifier]["station_data"]:
|
|
self.get_supplicant_logs(radio=str(radio))
|
|
return station_data_all
|
|
|
|
def wifi_stats_comparison(self, ssid_list=[], passkey="[BLANK]", security="wpa3", mode="BRIDGE", bands=[],
|
|
num_sta=None, scan_ssid=True, client_type=0, pre_cleanup=True,
|
|
sta_rows=["ssid", "ip", "mode", "channel", "signal", "mac", "parent dev"],
|
|
allure_attach=True, identifier=None, allure_name="station data", dut_data={},
|
|
get_target_object=None):
|
|
|
|
all_passed = True
|
|
final_msg = []
|
|
|
|
if len(bands) == 3:
|
|
sta_names = ['sta000', 'sta001', 'sta002']
|
|
radio_port_data = list(self.get_radio_availabilities(num_stations_2g=1,num_stations_5g=1,num_stations_6g=1))
|
|
logging.info(f"radio_port_data:{radio_port_data}")
|
|
radio_dict_2g = list(radio_port_data[0].keys())[0]
|
|
radio_dict_5g = list(radio_port_data[1].keys())[0]
|
|
radio_dict_6g = list(radio_port_data[2].keys())[0]
|
|
|
|
radios_list = [radio_dict_2g, radio_dict_5g, radio_dict_6g]
|
|
else:
|
|
sta_names = ['sta000', 'sta001']
|
|
radio_port_data = list(self.get_radio_availabilities(num_stations_2g=1, num_stations_5g=1))
|
|
logging.info(f"radio_port_data:{radio_port_data}")
|
|
radio_dict_2g = list(radio_port_data[0].keys())[0]
|
|
radio_dict_5g = list(radio_port_data[1].keys())[0]
|
|
|
|
radios_list = [radio_dict_2g, radio_dict_5g]
|
|
|
|
logging.info(f"Available Radios: {radios_list}")
|
|
sta_data, sta_got_ip = {}, []
|
|
|
|
is_bw320 = False
|
|
for i in range(len(bands)):
|
|
ssid, band, radio, sta = ssid_list[i], bands[i], radios_list[i], sta_names[i]
|
|
if band == "sixg":
|
|
is_bw320 = True
|
|
sta_got_ip.append(self.client_connect_using_radio(
|
|
ssid=ssid, passkey=passkey, security=security, mode=mode,
|
|
band=band, radio=radio, station_name=[sta], dut_data=dut_data,
|
|
attach_port_info=False, attach_station_data=True, is_bw320=is_bw320
|
|
))
|
|
|
|
shelf = list(radio.split("."))[0]
|
|
resource = list(radio.split("."))[1]
|
|
sta = f"{shelf}.{resource}.{sta_names[i]}"
|
|
logging.info(f"sta_name::{sta}")
|
|
sta_data[i] = self.get_station_data(sta_name=[sta], rows=sta_rows, allure_attach=True,
|
|
allure_name=f"station data of {band}")
|
|
logging.info(f"{band} Station Data: {sta_data[i]}")
|
|
|
|
if not all(sta_got_ip):
|
|
pytest.fail("Some/All Stations didn't get IP address")
|
|
|
|
serial_number = next(iter(dut_data))
|
|
iwinfo_output = get_target_object.dut_library_object.get_iwinfo(attach_allure=False)
|
|
logging.info(f"iwinfo output:\n{iwinfo_output}")
|
|
|
|
if not iwinfo_output or iwinfo_output == "Error: pop from empty list":
|
|
pytest.fail("Failed to get iwinfo from minicom")
|
|
|
|
def parse_iwinfo(ssid, iwinfo):
|
|
regex = re.compile(
|
|
rf'(\S+)\s+ESSID: "{re.escape(ssid)}".*?Access Point:\s+([0-9A-Fa-f:]+).*?'
|
|
rf'Channel:\s+(\d+)\s+\(([\d.]+) GHz\).*?HT Mode:\s+([A-Z]*)(\d+)',
|
|
re.DOTALL
|
|
)
|
|
match = next(regex.finditer(iwinfo), None)
|
|
if not match:
|
|
return {}
|
|
return {
|
|
'interface': match.group(1),
|
|
'Access Point': match.group(2),
|
|
'Channel': match.group(3),
|
|
'frequency': match.group(4).replace('.', ''),
|
|
'bandwidth': match.group(6)
|
|
}
|
|
|
|
radio_entries = {ssid: parse_iwinfo(ssid, iwinfo_output) for ssid in ssid_list}
|
|
logging.info(f"Parsed iwinfo entries: {radio_entries}")
|
|
|
|
logging.info(f"waiting for 60 seconds before fetching statistics data from the controller")
|
|
time.sleep(60)
|
|
stats_resp = get_target_object.controller_library_object.get_device_statistics(serial_number,
|
|
query="?lastOnly=true")
|
|
if stats_resp.status_code != 200:
|
|
pytest.fail("Failed to fetch device statistics from controller")
|
|
|
|
stats_data = stats_resp.json()
|
|
allure.attach(json.dumps(stats_data, indent=4), name="device_statistics from the controller",
|
|
attachment_type=allure.attachment_type.JSON)
|
|
|
|
ssids_data = [s for i in stats_data.get("interfaces", []) for s in i.get("ssids", []) if isinstance(s, dict)]
|
|
|
|
logging.info(f"ssids_data::{ssids_data}")
|
|
|
|
def match_and_report_radio_config():
|
|
for ssid, iwinfo in radio_entries.items():
|
|
ctrl_entry = next((s for s in ssids_data if s.get("ssid") == ssid), None)
|
|
if not ctrl_entry:
|
|
self.attach_table_allure([{
|
|
"Parameter": "SSID", "iwinfo": ssid,
|
|
"controller": "not found", "match": "no"
|
|
}], allure_name=f"{ssid} Configuration Mismatch")
|
|
continue
|
|
|
|
ctrl_data = {
|
|
"iface": ctrl_entry.get("iface", "N/A"),
|
|
"bssid": ctrl_entry.get("bssid", "N/A"),
|
|
"frequency": str(ctrl_entry.get("frequency", ["N/A"])[0]),
|
|
"band": ctrl_entry.get("band", "N/A"),
|
|
"channel": "N/A", "channel_width": "N/A"
|
|
}
|
|
|
|
for r in stats_data.get("radios", []):
|
|
if str(r.get("frequency", [])[0]) == ctrl_data["frequency"]:
|
|
ctrl_data.update({
|
|
"channel": str(r.get("channel", "N/A")),
|
|
"channel_width": str(r.get("channel_width", "N/A"))
|
|
})
|
|
break
|
|
|
|
def compare(label, i_val, c_val, band=None):
|
|
nonlocal all_passed
|
|
match_result = "yes" if str(i_val).lower() == str(c_val).lower() else "no"
|
|
if match_result == "no":
|
|
all_passed = False
|
|
final_msg.append(f"{label} mismatch found on {band}")
|
|
return {
|
|
"Parameter": label,
|
|
"iwinfo": i_val,
|
|
"controller": c_val,
|
|
"match": match_result
|
|
}
|
|
|
|
band_label = ssid.split("_")[-1].upper()
|
|
table = [compare("Band", band_label, ctrl_data["band"], band_label)]
|
|
table += [compare(lbl, iwinfo.get(i_key, "N/A"), ctrl_data.get(c_key, "N/A"), band_label)
|
|
for lbl, i_key, c_key in [
|
|
("BSSID", "Access Point", "bssid"),
|
|
("Channel", "Channel", "channel"),
|
|
("Frequency", "frequency", "frequency")
|
|
]]
|
|
|
|
table.append(compare("Channel Width (MHz)", iwinfo.get("bandwidth", "N/A"), ctrl_data["channel_width"],
|
|
band_label))
|
|
self.attach_table_allure(data=table, allure_name=f"{ssid} Configuration Comparison")
|
|
|
|
match_and_report_radio_config()
|
|
|
|
# Flatten station data
|
|
client_data = {k: v for band in sta_data.values() for k, v in band.items()}
|
|
client_mac_map = {
|
|
d["mac"].lower(): {"ssid": d["ssid"], "ip": d["ip"], "mac": d["mac"]}
|
|
for d in client_data.values()
|
|
}
|
|
|
|
def compare_clients():
|
|
nonlocal all_passed
|
|
for interface in stats_data.get("interfaces", []):
|
|
for ssid in interface.get("ssids", []):
|
|
ssid_name, band = ssid.get("ssid", "N/A"), ssid.get("band", "N/A")
|
|
assoc = ssid.get("associations", [])
|
|
table = []
|
|
# Connected Clients row
|
|
controller_count = len(assoc)
|
|
client_count = sum(1 for c in client_data.values() if c["ssid"] == ssid_name)
|
|
client_match = "yes" if controller_count == client_count else "no"
|
|
if client_match == "no":
|
|
all_passed = False
|
|
final_msg.append(f"no.of connected clients mismatch found on {band}")
|
|
table.append({
|
|
"Parameter": "Connected Clients",
|
|
"controller data": str(controller_count),
|
|
"client data": str(client_count),
|
|
"match": client_match
|
|
})
|
|
|
|
for a in assoc:
|
|
mac = a.get("station", "").lower()
|
|
ip = a.get("ipaddr_v4", "N/A")
|
|
client = client_mac_map.get(mac)
|
|
|
|
params = [
|
|
("MAC", mac, client["mac"] if client else "not found", client is not None),
|
|
("IP", ip, client["ip"] if client else "not found", client and client["ip"] == ip),
|
|
("SSID", ssid_name, client["ssid"] if client else "not found",
|
|
client and client["ssid"] == ssid_name)
|
|
]
|
|
|
|
for param, ctrl_val, client_val, is_match in params:
|
|
match = "yes" if is_match else "no"
|
|
if match == "no":
|
|
all_passed = False
|
|
final_msg.append(f"{param} mismatch found on {band}")
|
|
table.append({
|
|
"Parameter": param,
|
|
"controller data": ctrl_val,
|
|
"client data": client_val,
|
|
"match": match
|
|
})
|
|
|
|
self.attach_table_allure(data=table, allure_name=f"{ssid_name} Client Association Check")
|
|
|
|
compare_clients()
|
|
|
|
if all_passed:
|
|
logging.info("All configuration and association validations passed.")
|
|
else:
|
|
logging.error("Mismatches found:\n" + "\n".join(final_msg))
|
|
pytest.fail("configuration/association mismatches detected:\n" + "\n".join(final_msg))
|
|
|
|
def dfs_test(self, ssid=None, security=None, passkey=None, mode=None,
|
|
band=None, num_sta=1, vlan_id=[None], dut_data={}, tip_2x_obj=None, channel=None):
|
|
"""DFS test"""
|
|
self.check_band_ap(band=band)
|
|
logging.info("DUT DATA: " + str(dut_data))
|
|
start_sniffer = False
|
|
for dut in self.dut_data:
|
|
sniffer_channel = channel
|
|
|
|
identifier = dut["identifier"]
|
|
station_data = self.client_connect(ssid=ssid, security=security, passkey=passkey, mode=mode,
|
|
band=band, num_sta=num_sta, vlan_id=vlan_id,
|
|
allure_name="Station data before simulate radar", identifier=identifier,
|
|
station_data=["4way time (us)", "channel", "cx time (us)", "dhcp (ms)",
|
|
"ip", "signal", "mode", "parent dev"], dut_data=dut_data)
|
|
logging.info(f"station_data:{station_data}")
|
|
|
|
station_list = list(station_data.keys())
|
|
table_dict = {}
|
|
sta_channel_before_dfs_list = []
|
|
sta_channel_after_dfs_list = []
|
|
pass_fail = []
|
|
sta_channel_after_dfs = None
|
|
sta_channel_before_dfs = None
|
|
logging.info("The configured channel is: " + str(channel))
|
|
sta_channel_before_dfs = station_data[station_list[0]]["channel"]
|
|
logging.info("station channel before dfs: " + str(sta_channel_before_dfs))
|
|
if str(channel) == str(sta_channel_before_dfs):
|
|
# start sniffer
|
|
for ssid in station_data:
|
|
sniffer_radio = station_data[ssid]['parent dev']
|
|
shelf = list(ssid.split('.'))[0]
|
|
resource = list(ssid.split('.'))[1]
|
|
sniffer_radio = f"{shelf}.{resource}.{sniffer_radio}"
|
|
logging.info(f"sniffer_radio:{sniffer_radio}")
|
|
|
|
start_sniffer = True
|
|
self.start_sniffer(radio_channel=sniffer_channel,
|
|
test_name="dfs_test_capture",
|
|
radio=sniffer_radio,
|
|
duration=300)
|
|
|
|
if tip_2x_obj is not None:
|
|
logging.info("AP idx: " + str(self.dut_data.index(dut)))
|
|
tip_2x_obj.simulate_radar(idx=self.dut_data.index(dut))
|
|
time.sleep(30)
|
|
else:
|
|
logging.error("tip_2x_obj is empty")
|
|
else:
|
|
logging.error("Station is not connected to the configured channel")
|
|
pytest.fail("Station is not connected to the configured channel")
|
|
self.get_station_data(
|
|
rows=["4way time (us)", "channel", "cx time (us)", "dhcp (ms)", "ip", "signal", "mode"],
|
|
sta_name=station_list, allure_name="Station data after simulate radar")
|
|
for i in range(5):
|
|
sta_channel_after_dfs = self.station_data_query(station_name=station_list[0], query="channel")
|
|
if sta_channel_after_dfs != sta_channel_before_dfs and str(sta_channel_after_dfs) != "-1":
|
|
break
|
|
else:
|
|
time.sleep(20)
|
|
sta_channel_before_dfs_list.append(sta_channel_before_dfs)
|
|
sta_channel_after_dfs_list.append(sta_channel_after_dfs)
|
|
table_dict["station name"] = station_list
|
|
table_dict["Before"] = sta_channel_before_dfs_list
|
|
table_dict["After"] = sta_channel_after_dfs_list
|
|
# pass fail checking
|
|
if str(sta_channel_before_dfs) != str(sta_channel_after_dfs):
|
|
pass_fail.append("Pass")
|
|
table_dict["Pass/Fail"] = pass_fail
|
|
else:
|
|
pass_fail.append("Fail")
|
|
table_dict["Pass/Fail"] = pass_fail
|
|
logging.info("dfs_table_data: " + str(table_dict))
|
|
self.attach_table_allure(data=table_dict, allure_name="Pass_Fail Table")
|
|
|
|
if start_sniffer:
|
|
self.stop_sniffer()
|
|
|
|
if sta_channel_before_dfs != sta_channel_after_dfs and str(sta_channel_after_dfs) != "-1":
|
|
logging.info("channel after dfs: " + str(sta_channel_after_dfs))
|
|
ret = tip_2x_obj.get_dfs_logs(idx=self.dut_data.index(dut))
|
|
allure.attach(name="Simulate Radar Logs ", body=ret)
|
|
else:
|
|
logging.error("5 Ghz channel didn't change after radar was detected")
|
|
pytest.fail("5 Ghz channel didn't change after radar was detected")
|
|
|
|
def update_dut_ssid(self, dut_data={}):
|
|
r_val = dict()
|
|
for dut in self.dut_data:
|
|
r_val[dut["identifier"]] = None
|
|
# updating ssids on all APS
|
|
for dut in self.dut_data:
|
|
ssid_data = []
|
|
identifier = dut["identifier"]
|
|
if r_val.keys().__contains__(identifier):
|
|
for idx_ in dut_data[identifier]["ssid_data"]:
|
|
if str(dut_data[identifier]["ssid_data"][idx_]["encryption"]).upper() == "OPEN":
|
|
ssid_data.append(
|
|
['ssid_idx=' + str(idx_) + ' ssid=' + dut_data[identifier]["ssid_data"][idx_]["ssid"]
|
|
+
|
|
' bssid=' + str(dut_data[identifier]["ssid_data"][idx_]["bssid"]).upper()])
|
|
else:
|
|
ssid_data.append(
|
|
['ssid_idx=' + str(idx_) + ' ssid=' + dut_data[identifier]["ssid_data"][idx_]["ssid"] +
|
|
' security=' + str(dut_data[identifier]["ssid_data"][idx_]["encryption"]).upper() +
|
|
' password=' + dut_data[identifier]["ssid_data"][idx_]["password"] +
|
|
' bssid=' + str(dut_data[identifier]["ssid_data"][idx_]["bssid"]).upper()])
|
|
self.update_duts(identifier=identifier, ssid_data=ssid_data)
|
|
|
|
def add_stations(self, is_wifi7=False, is_bw320=False, band="2G", num_stations=9, ssid_name="", dut_data={},
|
|
identifier=None, dual_band_flag=1, temp_radio_data={}):
|
|
dut_name = []
|
|
# for index in range(0, len(self.dut_data)):
|
|
# dut_name.append(self.dut_data[index]["identifier"])
|
|
self.check_band_ap(band=band)
|
|
if num_stations == 0:
|
|
logging.warning("0 Stations")
|
|
return
|
|
idx = None
|
|
r_val = dict()
|
|
for dut in self.dut_data:
|
|
r_val[dut["identifier"]] = None
|
|
# updating ssids on all APS
|
|
for dut in self.dut_data:
|
|
ssid_data = []
|
|
identifier = dut["identifier"]
|
|
if r_val.keys().__contains__(identifier):
|
|
for idx_ in dut_data[identifier]["ssid_data"]:
|
|
if str(dut_data[identifier]["ssid_data"][idx_]["encryption"]).upper() == "OPEN":
|
|
ssid_data.append(
|
|
['ssid_idx=' + str(idx_) + ' ssid=' + dut_data[identifier]["ssid_data"][idx_]["ssid"]
|
|
+
|
|
' bssid=' + str(dut_data[identifier]["ssid_data"][idx_]["bssid"]).upper()])
|
|
else:
|
|
ssid_data.append(
|
|
['ssid_idx=' + str(idx_) + ' ssid=' + dut_data[identifier]["ssid_data"][idx_]["ssid"] +
|
|
' security=' + str(dut_data[identifier]["ssid_data"][idx_]["encryption"]).upper() +
|
|
' password=' + dut_data[identifier]["ssid_data"][idx_]["password"] +
|
|
' bssid=' + str(dut_data[identifier]["ssid_data"][idx_]["bssid"]).upper()])
|
|
self.update_duts(identifier=identifier, ssid_data=ssid_data)
|
|
|
|
if is_wifi7:
|
|
dict_all_radios_2g = {"be200_radios": self.be200_radios}
|
|
dict_all_radios_5g = {"be200_radios": self.be200_radios}
|
|
dict_all_radios_6g = {"be200_radios": self.be200_radios}
|
|
else:
|
|
dict_all_radios_2g = {"be200_radios": self.be200_radios,
|
|
"ax210_radios": self.ax210_radios,
|
|
"ax200_radios": self.ax200_radios,
|
|
"mtk_radios": self.mtk_radios,
|
|
"wave2_2g_radios": self.wave2_2g_radios,
|
|
"wave1_radios": self.wave1_radios
|
|
}
|
|
dict_all_radios_5g = {"be200_radios": self.be200_radios,
|
|
"ax210_radios": self.ax210_radios,
|
|
"ax200_radios": self.ax200_radios,
|
|
"mtk_radios": self.mtk_radios,
|
|
"wave2_5g_radios": self.wave2_5g_radios,
|
|
"wave1_radios": self.wave1_radios,
|
|
}
|
|
dict_all_radios_6g = {"be200_radios": self.be200_radios, "ax210_radios": self.ax210_radios}
|
|
|
|
max_station_per_radio = {"wave2_2g_radios": 64, "wave2_5g_radios": 64, "wave1_radios": 64, "mtk_radios": 19,
|
|
"ax200_radios": 1, "ax210_radios": 1, "be200_radios": 1}
|
|
if dual_band_flag > 1:
|
|
logging.info("dual_band_flag is True, fetched 2g radio data")
|
|
logging.info(f"temp_radio_data:{temp_radio_data}")
|
|
temp_radio_data = temp_radio_data
|
|
|
|
radio_data = {}
|
|
sniff_radio = ""
|
|
|
|
|
|
for dut in dut_data:
|
|
for idx_ in dut_data[dut]["ssid_data"]:
|
|
temp_band = dut_data[dut]["ssid_data"][idx_]["band"]
|
|
if band == "2G":
|
|
if temp_band.lower() == "twog":
|
|
temp_band = "2G"
|
|
elif band == "5G":
|
|
if temp_band.lower() == "fiveg":
|
|
temp_band = "5G"
|
|
elif band == "6G":
|
|
if temp_band.lower() == "sixg":
|
|
temp_band = "6G"
|
|
if band == temp_band and ssid_name == \
|
|
dut_data[dut]["ssid_data"][idx_]["ssid"]:
|
|
idx = idx_
|
|
if band == "2G":
|
|
stations = None
|
|
if num_stations != "max":
|
|
if num_stations <= int(self.max_2g_stations):
|
|
stations = num_stations
|
|
else:
|
|
stations = int(self.max_2g_stations)
|
|
if num_stations == "max":
|
|
stations = int(self.max_2g_stations)
|
|
for j in dict_all_radios_2g:
|
|
max_station = max_station_per_radio[j]
|
|
if stations > 0:
|
|
if len(dict_all_radios_2g[j]) > 0:
|
|
diff = max_station - stations
|
|
for i in dict_all_radios_2g[j]:
|
|
if diff >= 0:
|
|
radio_data[i] = stations
|
|
stations = 0
|
|
break
|
|
elif diff < 0:
|
|
radio_data[i] = max_station
|
|
stations = stations - max_station
|
|
diff = max_station - stations
|
|
if band == "5G":
|
|
stations = None
|
|
if num_stations != "max":
|
|
if num_stations <= int(self.max_5g_stations):
|
|
stations = num_stations
|
|
else:
|
|
stations = int(self.max_5g_stations)
|
|
if num_stations == "max":
|
|
stations = int(self.max_5g_stations)
|
|
for j in dict_all_radios_5g:
|
|
max_station = max_station_per_radio[j]
|
|
if stations > 0:
|
|
if len(dict_all_radios_5g[j]) > 0:
|
|
diff = max_station - stations
|
|
for i in dict_all_radios_5g[j]:
|
|
if dual_band_flag > 1 and (i in temp_radio_data):
|
|
continue # Skip this radio
|
|
if diff >= 0:
|
|
radio_data[i] = stations
|
|
stations = 0
|
|
break
|
|
elif diff < 0:
|
|
radio_data[i] = max_station
|
|
stations = stations - max_station
|
|
diff = max_station - stations
|
|
|
|
|
|
if band == "6G":
|
|
stations = None
|
|
if num_stations != "max":
|
|
if num_stations <= int(self.max_6g_stations):
|
|
stations = num_stations
|
|
else:
|
|
stations = int(self.max_6g_stations)
|
|
if num_stations == "max":
|
|
stations = int(self.max_6g_stations)
|
|
|
|
# radio and station selection
|
|
for j in dict_all_radios_6g:
|
|
max_station = max_station_per_radio[j]
|
|
if stations > 0:
|
|
if len(dict_all_radios_6g[j]) > 0:
|
|
diff = max_station - stations
|
|
for i in dict_all_radios_6g[j]:
|
|
if diff >= 0:
|
|
radio_data[i] = stations
|
|
stations = 0
|
|
break
|
|
elif diff < 0:
|
|
radio_data[i] = max_station
|
|
stations = stations - max_station
|
|
diff = max_station - stations
|
|
|
|
logging.info("radio_data: " + str(radio_data))
|
|
|
|
temp_profile_name = " STA-AUTO "
|
|
if is_wifi7 and is_bw320:
|
|
bandwidth = "320"
|
|
data = {}
|
|
data["name"] = "STA-BE320"
|
|
data["profile_type"] = "sta"
|
|
data["instance_count"] = "1"
|
|
data["bandwidth"] = bandwidth
|
|
|
|
profile_utility_obj = ProfileUtility(lfclient_host=self.manager_ip, lfclient_port=self.manager_http_port)
|
|
try:
|
|
STA_BE320 = profile_utility_obj.check_profile(profile_name="STA-BE320")
|
|
# Checking availability of STA_BE320 profile
|
|
except Exception as e:
|
|
STA_BE320 = True
|
|
pass
|
|
if STA_BE320:
|
|
logging.info("STA_BE320 profile: Available")
|
|
profile_utility_obj.remove_profile(name="STA-BE320")
|
|
response = self.json_post("/cli-json/add_profile",data=data)
|
|
logging.info(f"response of add_profile:{response}")
|
|
else:
|
|
response = self.json_post("/cli-json/add_profile", data=data)
|
|
logging.info(f"response of add_profile:{response}")
|
|
|
|
temp_profile_name = " STA-BE320 "
|
|
|
|
for radio in radio_data:
|
|
if identifier is None:
|
|
logging.error("Identifier is None")
|
|
pytest.fail("Identifier is None")
|
|
station_data = ["profile_link " + radio.split(".")[0] + "." + radio.split(".")[1] +
|
|
temp_profile_name + str(radio_data[radio]) + " 'DUT: " + identifier + " Radio-" +
|
|
str(int(idx) + 1) + "'" + " NA " + radio.split(".")[2]]
|
|
self.temp_raw_lines.append(station_data)
|
|
print(self.temp_raw_lines)
|
|
|
|
return radio_data
|
|
|
|
def rate_limiting_test(self, mode="BRIDGE", vlan_id=100, batch_size="1,5,10,20,40,64,128",
|
|
instance_name="wct_instance", download_rate="1Gbps", influx_tags="",
|
|
upload_rate="1Gbps", protocol="TCP-IPv4", duration="60000", stations="",
|
|
create_stations=False,
|
|
sort="interleave", raw_lines=[], move_to_influx=False, dut_data={}, ssid_name=None,
|
|
num_stations={}, add_stations=True, passkey=None, up_rate=None, down_rate=None):
|
|
obj = self.wifi_capacity(mode=mode, vlan_id=vlan_id, batch_size=batch_size, instance_name=instance_name,
|
|
download_rate=download_rate,
|
|
influx_tags=influx_tags, upload_rate=upload_rate, protocol=protocol, duration=duration,
|
|
stations=stations, create_stations=create_stations, sort=sort, raw_lines=raw_lines,
|
|
move_to_influx=move_to_influx,
|
|
dut_data=dut_data, ssid_name=ssid_name, num_stations=num_stations,
|
|
add_stations=add_stations)
|
|
report_name = obj[0].report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1] + "/"
|
|
numeric_score = self.read_kpi_file(column_name=["numeric-score"], dir_name=report_name)
|
|
logging.info("Numeric-score: " + str(numeric_score))
|
|
download_rate = self.convert_to_gbps(download_rate)
|
|
logging.info("download_rate:- " + str(download_rate))
|
|
upload_rate = self.convert_to_gbps(upload_rate)
|
|
logging.info("upload_rate:- " + str(upload_rate))
|
|
|
|
if upload_rate > download_rate:
|
|
logging.info("rate limit ingress-rate:- " + str(up_rate))
|
|
actual_tht = int(numeric_score[1][0])
|
|
logging.info("Actual throughput:- " + str(actual_tht))
|
|
if actual_tht > up_rate:
|
|
pytest.fail(f"Expected Throughput should be less than {up_rate} Mbps")
|
|
elif upload_rate < download_rate:
|
|
logging.info("rate limit egress-rate:- " + str(down_rate))
|
|
actual_tht = int(numeric_score[0][0])
|
|
logging.info("Actual throughput:- " + str(actual_tht))
|
|
if actual_tht > down_rate:
|
|
pytest.fail(f"Expected Throughput should be less than {down_rate} Mbps")
|
|
elif upload_rate == download_rate:
|
|
# Pass fail logic for bidirectional
|
|
logging.info("rate limit ingress-rate:- " + str(up_rate))
|
|
logging.info("rate limit egress-rate:- " + str(down_rate))
|
|
actual_tht_dw = int(numeric_score[0][0])
|
|
actual_tht_up = int(numeric_score[1][0])
|
|
logging.info("Actual throughput download:- " + str(actual_tht_dw))
|
|
logging.info("Actual throughput upload:- " + str(actual_tht_up))
|
|
if actual_tht_dw > down_rate:
|
|
pytest.fail(f"Expected Throughput should be less than {down_rate} Mbps")
|
|
if actual_tht_up > up_rate:
|
|
pytest.fail(f"Expected Throughput should be less than {up_rate} Mbps")
|
|
|
|
def wifi_capacity(self, mode="BRIDGE", vlan_id=100, batch_size="1,5,10,20,40,64,128",
|
|
instance_name="wct_instance", download_rate="1Gbps", influx_tags="", sets_=[],
|
|
upload_rate="1Gbps", protocol="TCP-IPv4", duration="60000", stations="", create_stations=False,
|
|
sort="interleave", raw_lines=[], move_to_influx=False, dut_data={}, ssid_name=None,
|
|
num_stations={}, add_stations=True, create_vlan=True, pass_fail_criteria=False, is_wifi7=False, is_bw320=False):
|
|
wificapacity_obj_list = []
|
|
vlan_raw_lines = None
|
|
for dut in self.dut_data:
|
|
sets = [["DUT_NAME", dut["model"]]]
|
|
identifier = dut["identifier"]
|
|
instance_name = ''.join(random.choices(string.ascii_uppercase + string.digits, k=12))
|
|
if mode == "BRIDGE":
|
|
ret = self.get_wan_upstream_ports()
|
|
upstream_port = ret[identifier]
|
|
|
|
if mode == "NAT-WAN":
|
|
ret = self.get_wan_upstream_ports()
|
|
upstream_port = ret[identifier]
|
|
|
|
if mode == "NAT-LAN":
|
|
ret = self.get_lan_upstream_ports()
|
|
upstream_port = ret[identifier]
|
|
if mode == "VLAN":
|
|
if vlan_id is None:
|
|
logging.error("VLAN ID is Unspecified in the VLAN Case")
|
|
pytest.skip("VLAN ID is Unspecified in the VLAN Case")
|
|
else:
|
|
if create_vlan:
|
|
vlan_raw_lines = self.add_vlan(vlan_ids=vlan_id, build=True)
|
|
else:
|
|
vlan_raw_lines = self.add_vlan(vlan_ids=vlan_id, build=False)
|
|
ret = self.get_wan_upstream_ports()
|
|
upstream_port = ret[identifier] + "." + str(vlan_id[0])
|
|
logging.info("Upstream data: " + str(upstream_port))
|
|
sets = [["DUT_NAME", dut]]
|
|
sets.extend(sets_)
|
|
logging.info("sets:- " + str(sets))
|
|
|
|
if add_stations:
|
|
'''SINGLE WIFI CAPACITY using lf_wifi_capacity.py'''
|
|
self.temp_raw_lines = self.default_scenario_raw_lines.copy()
|
|
dual_band_flag = 0
|
|
for band_ in num_stations:
|
|
dual_band_flag = dual_band_flag+1
|
|
logging.info(f"dual_band_flag value:{dual_band_flag}")
|
|
temp_radio_data = {}
|
|
if dual_band_flag > 1:
|
|
temp_radio_data = radio_data
|
|
if band_ not in ["2G", "5G", "6G"]:
|
|
logging.error("Band is missing")
|
|
pytest.fail("band is missing")
|
|
|
|
if not isinstance(num_stations[band_], int):
|
|
if not num_stations[band_] == "max":
|
|
logging.error("Number of stations are wrong")
|
|
pytest.fail("Number of stations are wrong")
|
|
if ssid_name is None:
|
|
logging.error("ssid name is missing")
|
|
pytest.fail("ssid name is missing")
|
|
if self.run_lf:
|
|
dut_data = self.run_lf_dut_data()
|
|
for i in dut_data:
|
|
if mode != dut_data[i]["mode"]:
|
|
pytest.skip("Dut is not configured in mode: " + mode)
|
|
else:
|
|
for j in dut_data[i]["ssid_data"]:
|
|
if band_ == "2G":
|
|
temp_band = "twog"
|
|
elif band_ == "5G":
|
|
temp_band = "fiveg"
|
|
elif band_ == "6G":
|
|
temp_band = "sixg"
|
|
if temp_band == dut_data[i]["ssid_data"][j]["band"]:
|
|
ssid_name = dut_data[i]["ssid_data"][j]["ssid"]
|
|
|
|
radio_data = self.add_stations(band=band_, num_stations=num_stations[band_], ssid_name=ssid_name,
|
|
dut_data=dut_data,
|
|
identifier=identifier, is_wifi7=is_wifi7, is_bw320=is_bw320,
|
|
dual_band_flag = dual_band_flag, temp_radio_data=temp_radio_data)
|
|
if vlan_raw_lines is not None:
|
|
for i in vlan_raw_lines:
|
|
self.temp_raw_lines.append(i)
|
|
self.chamber_view(raw_lines="custom")
|
|
if pass_fail_criteria:
|
|
# Station data
|
|
self.band_sta = list(num_stations.keys())[0]
|
|
logging.info("band: " + str(self.band_sta))
|
|
if num_stations[self.band_sta] == 1:
|
|
logging.info("radio_data: " + str(radio_data))
|
|
sta_radio = list(radio_data.keys())[0]
|
|
logging.info("sta_radio: " + str(sta_radio))
|
|
sta_radio = sta_radio.split(".")
|
|
shelf = int(sta_radio[0])
|
|
resource = int(sta_radio[1])
|
|
radio_ = sta_radio[2]
|
|
# finding radio number for sta name e.g. for wiphy2 the radio num is 2. Sta name will be wlan2
|
|
radio_num = int(''.join(x for x in radio_ if x.isdigit()))
|
|
logging.info("radio_num: " + str(radio_num))
|
|
sta_name = f"{shelf}.{resource}.wlan{radio_num}"
|
|
logging.info("sta_name: " + str(sta_name))
|
|
self.local_realm.admin_up(sta_name)
|
|
sta_ip = self.local_realm.wait_for_ip([sta_name], timeout_sec=120)
|
|
sta_rows = ["4way time (us)", "channel", "ssid", "key/phrase", "cx time (us)", "dhcp (ms)",
|
|
"ip", "signal",
|
|
"mac", "mode"]
|
|
if str(self.band_sta) != "6G" or is_bw320:
|
|
allure_attach = True
|
|
else:
|
|
allure_attach = False
|
|
self.get_station_data(sta_name=[sta_name], rows=sta_rows,
|
|
allure_attach=allure_attach)
|
|
if sta_ip:
|
|
logging.info("ip's acquired")
|
|
self.sta_mode_ = \
|
|
self.json_get(f'/port/{shelf}/{resource}/wlan{radio_num}?fields=mode')['interface'][
|
|
'mode']
|
|
logging.info("sta_mode:- " + str(self.sta_mode_))
|
|
else:
|
|
logging.info("Stations Failed to get IP's")
|
|
pytest.fail("Stations Failed to get IP's")
|
|
ssid = self.json_get(f'/port/{shelf}/{resource}/wlan{radio_num}?fields=ssid')['interface'][
|
|
'ssid']
|
|
logging.info("ssid:- " + str(ssid))
|
|
passkey = \
|
|
self.json_get(f'/port/{shelf}/{resource}/wlan{radio_num}?fields=key/phrase')[
|
|
'interface'][
|
|
'key/phrase']
|
|
logging.info("passkey:- " + str(passkey))
|
|
if ("160" in self.sta_mode_ or str(self.band_sta) == "6G") and ("320" not in self.sta_mode_):
|
|
self.client_disconnect(station_name=[sta_name])
|
|
logging.info("DUT Data: " + str(dut_data))
|
|
encryption_value = None
|
|
# Finding sta security
|
|
for ssid_info in dut_data[identifier]['ssid_data'].values():
|
|
if ssid_info['ssid'] == ssid:
|
|
encryption_value = ssid_info['encryption']
|
|
if encryption_value.lower() == "open":
|
|
security_ = "[BLANK]"
|
|
else:
|
|
security_ = encryption_value
|
|
break
|
|
|
|
client_connect = CreateStation(_host=self.manager_ip, _port=self.manager_http_port,
|
|
_sta_list=[sta_name],
|
|
_password=passkey,
|
|
_ssid=ssid,
|
|
_security=security_)
|
|
client_connect.station_profile.sta_mode = 0
|
|
client_connect.station_profile.use_ht160 = True
|
|
client_connect.upstream_resource = int(upstream_port.split(".")[1])
|
|
client_connect.upstream_port = str(upstream_port.split(".")[2])
|
|
client_connect.radio = sta_radio
|
|
client_connect.build()
|
|
result = client_connect.wait_for_ip(station_list=[sta_name], timeout_sec=240)
|
|
self.get_station_data(sta_name=[sta_name], rows=sta_rows,
|
|
allure_attach=True)
|
|
if result:
|
|
logging.info("ip's acquired")
|
|
self.sta_mode_ = \
|
|
self.json_get(f'/port/{shelf}/{resource}/wlan{radio_num}?fields=mode')[
|
|
'interface'][
|
|
'mode']
|
|
logging.info("sta_mode_vht_160_enable:- " + str(self.sta_mode_))
|
|
else:
|
|
logging.info("Stations Failed to get IP's")
|
|
pytest.fail("Stations Failed to get IP's")
|
|
|
|
wificapacity_obj = WiFiCapacityTest(lfclient_host=self.manager_ip,
|
|
lf_port=self.manager_http_port,
|
|
ssh_port=self.manager_ssh_port,
|
|
lf_user="lanforge",
|
|
lf_password="lanforge",
|
|
local_lf_report_dir=self.local_report_path,
|
|
instance_name=instance_name,
|
|
config_name="wifi_config",
|
|
upstream=upstream_port,
|
|
batch_size=batch_size,
|
|
loop_iter="1",
|
|
protocol=protocol,
|
|
duration=duration,
|
|
pull_report=True,
|
|
load_old_cfg=False,
|
|
upload_rate=upload_rate,
|
|
download_rate=download_rate,
|
|
sort=sort,
|
|
stations=stations,
|
|
create_stations=create_stations,
|
|
radio=None,
|
|
security=None,
|
|
paswd=None,
|
|
ssid=None,
|
|
enables=[],
|
|
disables=[],
|
|
raw_lines=raw_lines,
|
|
raw_lines_file="",
|
|
test_tag=influx_tags,
|
|
sets=sets)
|
|
wificapacity_obj.setup()
|
|
wificapacity_obj.run()
|
|
if move_to_influx:
|
|
try:
|
|
report_name = "../reports/" + \
|
|
wificapacity_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[
|
|
-1] + "/"
|
|
influx = CSVtoInflux(influx_host=self.influx_params["influx_host"],
|
|
influx_port=self.influx_params["influx_port"],
|
|
influx_org=self.influx_params["influx_org"],
|
|
influx_token=self.influx_params["influx_token"],
|
|
influx_bucket=self.influx_params["influx_bucket"],
|
|
path=report_name)
|
|
|
|
influx.glob()
|
|
except Exception as e:
|
|
print(e)
|
|
pass
|
|
report_name = wificapacity_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1] + "/"
|
|
time.sleep(15)
|
|
logging.info("report_name: " + str(report_name))
|
|
self.attach_report_graphs(report_name=report_name)
|
|
self.attach_report_kpi(report_name=report_name)
|
|
numeric_score = self.read_kpi_file(column_name=["numeric-score"], dir_name=report_name)
|
|
logging.info("Numeric-score: " + str(numeric_score))
|
|
max_num_stations = int(sum(num_stations.values()))
|
|
logging.info("Max num stations: " + str(max_num_stations))
|
|
try:
|
|
# Admin down
|
|
exist_sta = []
|
|
for u in self.json_get("/port/?fields=port+type,alias")['interfaces']:
|
|
if list(u.values())[0]['port type'] not in ['Ethernet', 'WIFI-Radio', 'NA']:
|
|
exist_sta.append(list(u.values())[0]['alias'])
|
|
if len(exist_sta) == 0:
|
|
logging.info("Existing stations are not available")
|
|
else:
|
|
for port_eid in exist_sta:
|
|
# admin down
|
|
self.local_realm.admin_down(port_eid)
|
|
time.sleep(0.3)
|
|
except Exception as e:
|
|
print(e)
|
|
pass
|
|
if len(numeric_score) < 5:
|
|
if int(numeric_score[0][0]) < max_num_stations and int(numeric_score[1][0]) < max_num_stations and int(
|
|
numeric_score[-1][0]) > 0 and int(numeric_score[-2][0]) > 0:
|
|
pytest.fail("Station did not get an ip")
|
|
else:
|
|
if int(numeric_score[0][0]) == 0 and int(numeric_score[1][0]) == 0 and int(
|
|
numeric_score[2][0]) == 0:
|
|
pytest.fail("Did not report traffic")
|
|
if pass_fail_criteria:
|
|
if add_stations:
|
|
if num_stations[self.band_sta] == 1:
|
|
current_directory = os.getcwd()
|
|
file_path = current_directory + "/e2e/basic/performance_tests/performance_pass_fail.json"
|
|
logging.info("performance_pass file config path:- " + str(file_path))
|
|
with open(file_path, 'r') as file:
|
|
json_string = file.read()
|
|
all_pass_fail_data = json.loads(json_string)
|
|
logging.info("All Testbed pass fail data:- " + str(all_pass_fail_data))
|
|
# validate config json data
|
|
try:
|
|
json_object = json.dumps(all_pass_fail_data)
|
|
except ValueError as e:
|
|
logging.info("Performance Pass/Fail data is invalid")
|
|
pytest.fail("Performance Pass/Fail data is invalid")
|
|
logging.info("DUT Data: " + str(self.dut_data))
|
|
model = self.dut_data[0]["model"]
|
|
if model in all_pass_fail_data["AP Models"]:
|
|
pass_fail_values = all_pass_fail_data["AP Models"][model]
|
|
else:
|
|
logging.error("AP model is not available in performance_pass_fail.json file")
|
|
logging.info(str(model) + " All Benchmark throughput:- " + str(pass_fail_values))
|
|
split_mode = self.sta_mode_.split(" ")
|
|
key = f"{self.band_sta} {split_mode[2]} {split_mode[1]}MHz"
|
|
logging.info("key:- " + str(key))
|
|
proto = None
|
|
if "TCP" in protocol:
|
|
proto = "TCP"
|
|
else:
|
|
proto = "UDP"
|
|
logging.info("Proto:- " + str(proto))
|
|
logging.info("Given LF download_rate:- " + str(download_rate))
|
|
logging.info("Given LF upload_rate:- " + str(upload_rate))
|
|
pass_fail_value = None
|
|
if "BE" in str(self.sta_mode_):
|
|
logging.info("In BE pass fail")
|
|
pass_fail_value = pass_fail_values["BE"][key][proto]
|
|
elif "AX" in str(self.sta_mode_):
|
|
logging.info("In AX pass fail")
|
|
pass_fail_value = pass_fail_values["AX"][key][proto]
|
|
# pass_fail_value = pass_fail_values[key][proto]
|
|
download_rate = self.convert_to_gbps(download_rate)
|
|
logging.info("download_rate:- " + str(download_rate))
|
|
upload_rate = self.convert_to_gbps(upload_rate)
|
|
logging.info("upload_rate:- " + str(upload_rate))
|
|
# Pass fail logic for Upload. validating download rate because providing some value during Upload
|
|
if upload_rate > download_rate:
|
|
logging.info("Benchmark throughput:- " + str(pass_fail_value) + "+")
|
|
allure.attach(name="Benchmark throughput: ",
|
|
body=str(pass_fail_value) + "+ Mbps")
|
|
actual_tht = int(numeric_score[1][0])
|
|
logging.info("Actual throughput:- " + str(actual_tht))
|
|
allure.attach(name="Actual throughput: ",
|
|
body=str(actual_tht) + " Mbps")
|
|
if actual_tht < pass_fail_value:
|
|
pytest.fail(
|
|
f"Benchmark throughput:- {pass_fail_value}+ Mbps, Actual throughput:- {actual_tht} Mbps")
|
|
elif upload_rate < download_rate:
|
|
# Pass fail logic for Download. validating upload rate because providing some value during download
|
|
logging.info("Benchmark throughput:- " + str(pass_fail_value) + "+")
|
|
allure.attach(name="Benchmark throughput: ",
|
|
body=str(pass_fail_value) + "+ Mbps")
|
|
actual_tht = int(numeric_score[0][0])
|
|
logging.info("Actual throughput:- " + str(actual_tht))
|
|
allure.attach(name="Actual throughput: ",
|
|
body=str(actual_tht) + " Mbps")
|
|
if actual_tht < pass_fail_value:
|
|
pytest.fail(
|
|
f"Benchmark throughput:- {pass_fail_value}+ Mbps, Actual throughput:- {actual_tht} Mbps")
|
|
elif upload_rate == download_rate:
|
|
# Pass fail logic for bidirectional
|
|
pass_fail_value = pass_fail_value * 2
|
|
logging.info("Benchmark throughput:- " + str(pass_fail_value) + "+")
|
|
allure.attach(name="Benchmark throughput: ",
|
|
body=str(pass_fail_value) + "+ Mbps")
|
|
actual_tht = int(numeric_score[2][0])
|
|
logging.info("Actual throughput:- " + str(actual_tht))
|
|
allure.attach(name="Actual throughput: ",
|
|
body=str(actual_tht) + " Mbps")
|
|
if actual_tht < pass_fail_value:
|
|
pytest.fail(
|
|
f"Benchmark throughput:- {pass_fail_value}+ Mbps, Actual throughput:- {actual_tht} Mbps")
|
|
|
|
wificapacity_obj_list.append(wificapacity_obj)
|
|
|
|
return wificapacity_obj_list
|
|
|
|
def dataplane_throughput_test(self, ssid="[BLANK]", passkey="[BLANK]", security="wpa2", num_sta=1, mode="BRIDGE",
|
|
vlan_id=[None], ap_mode ="wifi6",
|
|
download_rate="85%", band="twog", scan_ssid=True,
|
|
upload_rate="0", duration="15s", path_loss=10, instance_name="test_demo", raw_lines=None,
|
|
influx_tags="",
|
|
move_to_influx=False,
|
|
station_data=["4way time (us)", "channel", "cx time (us)", "dhcp (ms)", "ip",
|
|
"signal", "mode"],
|
|
allure_attach=True, allure_name="station data", client_type=0, dut_data={}):
|
|
instance_name = ''.join(random.choices(string.ascii_uppercase + string.digits, k=12))
|
|
dataplane_obj_list = []
|
|
radio_mode = ""
|
|
for dut in self.dut_data:
|
|
identifier = dut["identifier"]
|
|
if mode == "BRIDGE":
|
|
ret = self.get_wan_upstream_ports()
|
|
upstream_port = ret[identifier]
|
|
|
|
if mode == "NAT-WAN":
|
|
ret = self.get_wan_upstream_ports()
|
|
upstream_port = ret[identifier]
|
|
|
|
if mode == "NAT-LAN":
|
|
ret = self.get_lan_upstream_ports()
|
|
upstream_port = ret[identifier]
|
|
if mode == "VLAN":
|
|
if vlan_id is None:
|
|
logging.error("VLAN ID is Unspecified in the VLAN Case")
|
|
pytest.skip("VLAN ID is Unspecified in the VLAN Case")
|
|
else:
|
|
# self.add_vlan(vlan_ids=vlan_id)
|
|
ret = self.get_wan_upstream_ports()
|
|
upstream_port = ret[identifier] + "." + str(vlan_id[0])
|
|
logging.info("Upstream data: " + str(upstream_port))
|
|
station_data = self.client_connect(ssid=ssid, passkey=passkey, security=security, mode=mode, band=band,
|
|
vlan_id=vlan_id, num_sta=num_sta, scan_ssid=scan_ssid,
|
|
station_data=station_data,
|
|
allure_attach=allure_attach, identifier=identifier,
|
|
allure_name=allure_name, client_type=client_type, dut_data=dut_data)
|
|
if ap_mode=="wifi7":
|
|
if band=="twog":
|
|
radio_mode = "802.11bgn-BE"
|
|
if band=="fiveg":
|
|
radio_mode = "802.11an-BE"
|
|
if band=="sixg":
|
|
radio_mode = "802.11a-BE"
|
|
else:
|
|
if band=="twog":
|
|
radio_mode = "802.11bgn-AX"
|
|
if band=="fiveg":
|
|
radio_mode = "802.11an-AX"
|
|
if band=="sixg":
|
|
radio_mode = "802.11a-AX"
|
|
|
|
logging.info(f"radio_mode {radio_mode}")
|
|
|
|
if raw_lines is None:
|
|
raw_lines = [['pkts: 142;256;512;1024;MTU;4000'], ['directions: DUT Transmit'], ['modes: ' + str(radio_mode)],
|
|
['traffic_types: UDP;TCP'],
|
|
["show_3s: 1"], ["show_ll_graphs: 1"], ["show_log: 1"]]
|
|
sets = [['Maximize Unused Attenuators', '0']]
|
|
|
|
dataplane_obj = DataplaneTest(lf_host=self.manager_ip,
|
|
lf_port=self.manager_http_port,
|
|
ssh_port=self.manager_ssh_port,
|
|
local_lf_report_dir=self.local_report_path,
|
|
lf_user="lanforge",
|
|
lf_password="lanforge",
|
|
instance_name=instance_name,
|
|
config_name="dpt_config",
|
|
upstream=upstream_port,
|
|
pull_report=True,
|
|
load_old_cfg=False,
|
|
download_speed=download_rate,
|
|
upload_speed=upload_rate,
|
|
duration=duration,
|
|
path_loss=path_loss,
|
|
dut=identifier,
|
|
station=list(station_data.keys())[0],
|
|
test_tag=influx_tags,
|
|
sets=sets,
|
|
raw_lines=raw_lines)
|
|
|
|
dataplane_obj.setup()
|
|
dataplane_obj.run()
|
|
if move_to_influx:
|
|
report_name = "../reports/" + \
|
|
dataplane_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1] + "/"
|
|
try:
|
|
influx = CSVtoInflux(influx_host=self.influx_params["influx_host"],
|
|
influx_port=self.influx_params["influx_port"],
|
|
influx_org=self.influx_params["influx_org"],
|
|
influx_token=self.influx_params["influx_token"],
|
|
influx_bucket=self.influx_params["influx_bucket"],
|
|
path=report_name)
|
|
|
|
influx.glob()
|
|
except Exception as e:
|
|
print(e)
|
|
pass
|
|
report_name = dataplane_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1] + "/"
|
|
self.attach_report_graphs(report_name=report_name, pdf_name="Dataplane Throughput Test - TCP-UDP 5G")
|
|
self.attach_report_kpi(report_name=report_name)
|
|
logging.info("Test Completed... Cleaning up Stations")
|
|
self.client_disconnect(station_name=list(station_data.keys()))
|
|
dataplane_obj_list.append(dataplane_obj)
|
|
return dataplane_obj_list
|
|
|
|
def multi_asso_disasso(self, band="2G", num_stations=16, dut_data={}, idx=0, mode="BRIDGE", vlan=1,
|
|
instance_name="wct_instance", traffic_direction="upload", traffic_rate="0Mbps"):
|
|
try:
|
|
def thread_fun(station_list):
|
|
time.sleep(60)
|
|
for i in station_list:
|
|
self.local_realm.admin_down(i)
|
|
logging.info("stations down")
|
|
time.sleep(10)
|
|
for i in station_list:
|
|
self.local_realm.admin_up(i)
|
|
logging.info("stations up")
|
|
|
|
# clean l3 traffics which won't get cleaned by deleting old scenario in CV
|
|
self.client_disconnect(clean_l3_traffic=True)
|
|
all_radio_5g = (self.be200_radios + self.ax210_radios + self.ax200_radios +
|
|
+ self.mtk_radios + self.wave2_5g_radios + self.wave1_radios)
|
|
logging.info("All 5g radios" + str(all_radio_5g))
|
|
all_radio_2g = (self.be200_radios + self.ax210_radios + self.ax200_radios +
|
|
+ self.mtk_radios + self.wave2_2g_radios + self.wave1_radios)
|
|
logging.info("All 2g radios" + str(all_radio_2g))
|
|
radio = all_radio_5g[:2] if band == "5G" else all_radio_2g[:2]
|
|
logging.info("Radios: " + str(radio))
|
|
upld_rate, downld_rate, val = "0Gbps", "0Gbps", []
|
|
if traffic_direction == "upload":
|
|
upld_rate = traffic_rate
|
|
val = [['ul_rate_sel: Per-Station Upload Rate:']]
|
|
elif traffic_direction == "download":
|
|
downld_rate = traffic_rate
|
|
val = [['dl_rate_sel: Per-Station Download Rate:']]
|
|
per_radio_sta = int(num_stations / len(radio))
|
|
rem = num_stations % len(radio)
|
|
logging.info("Total stations per radio: " + str(per_radio_sta))
|
|
num_stations = lambda rem: per_radio_sta + rem if rem else per_radio_sta
|
|
identifier = list(dut_data.keys())[0]
|
|
allure.attach(name="Definition",
|
|
body="Multiple association/disassociation stability test intends to measure stability of Wi-Fi device " \
|
|
"under a dynamic environment with frequent change of connection status.")
|
|
allure.attach(name="Procedure",
|
|
body=f"This test case definition states that we Create 16 stations on {band} radio and" \
|
|
" Run Wifi-capacity test for first 8 stations. 8 stations are picked for sending/receiving packets "
|
|
"while the other 8 STAs are picked to do a dis-association/re-association process during the test" \
|
|
f" Enable {traffic_direction} {traffic_rate} Mbps UDP flow from DUT to each of the 8 traffic stations" \
|
|
"Disassociate the other 8 stations. Wait for 30 seconds, after that Re-associate the 8 stations.")
|
|
self.temp_raw_lines = self.default_scenario_raw_lines.copy()
|
|
|
|
if mode == "VLAN":
|
|
self.add_vlan(vlan_ids=vlan)
|
|
for i in radio:
|
|
station_data = ["profile_link " + i.split(".")[0] + "." + i.split(".")[1] +
|
|
" STA-AUTO " + str(num_stations(rem)) + " 'DUT: " + identifier + " Radio-" +
|
|
str(int(idx) + 1) + "'" + " NA " + i.split(".")[2]]
|
|
rem = 0
|
|
self.temp_raw_lines.append(station_data)
|
|
logging.debug("Raw Line : " + str(station_data))
|
|
# update the dut ssid in CV
|
|
self.update_dut_ssid(dut_data=dut_data)
|
|
self.chamber_view(raw_lines="custom")
|
|
sta_list = []
|
|
for rad in radio:
|
|
self.set_radio_channel(radio=rad, antenna=4)
|
|
for u in self.json_get("/port/?fields=port+type,alias")['interfaces']:
|
|
if list(u.values())[0]['port type'] in ['WIFI-STA']:
|
|
sta_list.append(list(u.keys())[0])
|
|
|
|
for i in sta_list:
|
|
self.local_realm.admin_up(i)
|
|
sel_stations = ",".join(sta_list[0:8])
|
|
thr1 = threading.Thread(target=thread_fun, args=(sta_list[8:16],))
|
|
thr1.start()
|
|
wct_obj = self.wifi_capacity(instance_name=instance_name, mode=mode, vlan_id=vlan,
|
|
download_rate=downld_rate, add_stations=False,
|
|
stations=sel_stations, raw_lines=val, batch_size="8", upload_rate=upld_rate,
|
|
protocol="UDP-IPv4", duration="120000", create_stations=False,
|
|
dut_data=dut_data, create_vlan=False,
|
|
sort="interleave", )
|
|
|
|
report_name = wct_obj[0].report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1] + "/"
|
|
file_name = "/csv-data/data-Combined_bps__60_second_running_average-1.csv"
|
|
if not os.path.exists(f"../reports/{report_name}{file_name}"):
|
|
file_name = file_name.replace('_bps__', '_Mbps__')
|
|
csv_val = self.read_csv_individual_station_throughput(dir_name=report_name, option=traffic_direction,
|
|
file_name=file_name)
|
|
logging.info(csv_val)
|
|
pass_value = int(traffic_rate[0]) * 0.99
|
|
logging.info(csv_val)
|
|
allure.attach(name="Pass Fail Criteria",
|
|
body=f"UDP traffic rate is at least 99% of the configured rate for each station. Here configured " \
|
|
f"traffic rate is {traffic_rate[0]} Mbps so traffic for each station should be {pass_value} Mbps ")
|
|
if not csv_val:
|
|
return False, "csv file does not exist"
|
|
else:
|
|
pass_fail = [1 if i >= pass_value else 0 for i in csv_val.values()]
|
|
allure.attach.file(source="../reports/" + report_name + file_name, name="Throughput CSV file",
|
|
attachment_type=allure.attachment_type.CSV)
|
|
self.allure_report_table_format(dict_data=csv_val, key="Stations", value="Throughput values",
|
|
name="Test_results")
|
|
if pass_fail.count(0) == 0:
|
|
return True, "Test passed"
|
|
else:
|
|
return False, "Test failed due to lesser value"
|
|
except Exception as e:
|
|
logging.error(f"{e}")
|
|
return False, f"{e}"
|
|
finally:
|
|
try:
|
|
self.client_disconnect(clear_all_sta=True, clean_l3_traffic=True)
|
|
except Exception as e:
|
|
logging.error(f"{e}")
|
|
return False, f"{e}"
|
|
|
|
def country_code_channel_division(self, ssid="[BLANK]", passkey='[BLANK]', security="wpa2", mode="BRIDGE",
|
|
band='twog', num_sta=1, vlan_id=100, channel='1', channel_width=20,
|
|
country_num=392, country='United States(US)', dut_data={}):
|
|
try:
|
|
radio = self.wave2_5g_radios[0] if band == "fiveg" else self.wave2_2g_radios[0]
|
|
self.set_radio_channel(radio=radio, channel=0, country=country_num)
|
|
station = self.client_connect(ssid=ssid, passkey=passkey, security=security, mode=mode, band=band,
|
|
num_sta=num_sta, vlan_id=vlan_id, dut_data=dut_data)
|
|
allure.attach(name="Definition",
|
|
body="Country code channel test intends to verify stability of Wi-Fi device " \
|
|
"where the AP is configured with different countries with different channels.")
|
|
allure.attach(name="Procedure",
|
|
body=f"This test case definition states that we need to push the basic {mode.lower()} mode config on the AP to "
|
|
f"be tested by configuring it with {country} on {channel_width}MHz channel width and "
|
|
f"channel {channel}. Create a client on {'5' if band == 'fiveg' else '2.4'} GHz radio. Pass/ fail criteria: "
|
|
f"The client created on {'5' if band == 'fiveg' else '2.4'} GHz radio should get associated to the AP")
|
|
allure.attach(name="Details",
|
|
body=f"Country code : {country[country.find('(') + 1:-1]}\n"
|
|
f"Bandwidth : {channel_width}Mhz\n"
|
|
f"Channel : {channel}\n")
|
|
if station[list(station.keys())[0]]['ip'] != '0.0.0.0':
|
|
if str(station[list(station.keys())[0]]['channel']) != str(channel):
|
|
logging.warning(f"Station Falling back to channel {station[list(station.keys())[0]]['channel']}")
|
|
return False
|
|
else:
|
|
logging.info(f"Station connected to channel {station[list(station.keys())[0]]['channel']}")
|
|
return True
|
|
else:
|
|
logging.warning(f"Station didn't get IP")
|
|
return False
|
|
except Exception as e:
|
|
logging.error(f"{e}")
|
|
return False
|
|
finally:
|
|
try:
|
|
self.client_disconnect(clear_all_sta=True)
|
|
self.set_radio_channel(radio=radio, country=840)
|
|
except Exception as e:
|
|
logging.error(f"{e}")
|
|
return False
|
|
|
|
def tr398v2(self, mode="BRIDGE",
|
|
vlan_id=1, skip_2g=False, skip_5g=False, test=None,
|
|
move_to_influx=False,
|
|
dut_data={},
|
|
create_vlan=True, testbed=None, extra_raw_lines=[[]]):
|
|
current_directory = os.getcwd()
|
|
file_path = current_directory + "/e2e/advanced/advanced-config.json"
|
|
logging.info("Advanced file config path:- " + str(file_path))
|
|
with open(file_path, 'r') as file:
|
|
json_string = file.read()
|
|
all_config_data = json.loads(json_string)
|
|
logging.info("Advanced testbeds config data:- " + str(all_config_data))
|
|
# validate config json data
|
|
try:
|
|
json_object = json.dumps(all_config_data)
|
|
except ValueError as e:
|
|
logging.info("Advanced config data is invalid")
|
|
pytest.fail("Advanced config data is invalid")
|
|
testbed_ = testbed[:-1]
|
|
testbed_config_data = all_config_data["TESTBEDS"][testbed_]
|
|
logging.info(str(testbed_) + " Testbed config data:- " + str(testbed_config_data))
|
|
self.client_disconnect(clean_l3_traffic=True)
|
|
if type(test) == str:
|
|
test = test.split(",")
|
|
# DUT Name
|
|
dut_name = list(dut_data.keys())[0]
|
|
logging.info("DUT name:- " + str(dut_name))
|
|
""" 2G and 5G channel """
|
|
channel_2g = dut_data[dut_name]["radio_data"]["2G"]["channel"]
|
|
channel_5g = dut_data[dut_name]["radio_data"]["5G"]["channel"]
|
|
logging.info("2g_channel:- " + str(channel_2g))
|
|
logging.info("5g_channel:- " + str(channel_5g))
|
|
logging.info("DUT data:- " + str(dut_data))
|
|
virtual_sta_radios = {}
|
|
virtual_sta_rssi_0_2 = {}
|
|
virtual_sta_rssi_0_5 = {}
|
|
virtual_sta_atten = {}
|
|
ax_radios = {}
|
|
ax_rssi_0_2 = {}
|
|
ax_rssi_0_5 = {}
|
|
ax_atten = {}
|
|
raw_line = []
|
|
k = 0
|
|
""" Logic for virtual sta radios """
|
|
# find out virtual sta radios and make raw lines
|
|
config_data = testbed_config_data["Virtual Sta Radio Settings"]
|
|
for i in config_data:
|
|
for j in config_data[i]:
|
|
virtual_sta_radios["radio-" + str(k)] = config_data[i]["5Ghz"]
|
|
k = k + 1
|
|
virtual_sta_radios["radio-" + str(k)] = config_data[i]["2.4Ghz"]
|
|
break
|
|
k = k + 1
|
|
logging.info("virtual_sta_radios:- " + str(virtual_sta_radios))
|
|
raw_line_list = [[f"{key}: {value}"] for key, value in virtual_sta_radios.items()]
|
|
raw_line.extend(raw_line_list)
|
|
# find out virtual sta virtual_sta_rssi_0_2, virtual_sta_rssi_0_5, virtual_sta_atten and make raw lines
|
|
c1 = 0
|
|
c2 = 0
|
|
c3 = 0
|
|
config_data = testbed_config_data["Virtual Sta Radio Settings"]
|
|
for i in config_data:
|
|
for j in config_data[i]:
|
|
if j == "2.4Ghz RSSI 0 Atten":
|
|
for k in config_data[i]["2.4Ghz RSSI 0 Atten"]:
|
|
virtual_sta_rssi_0_2["rssi_0_2-" + str(c1)] = k
|
|
c1 = c1 + 1
|
|
if j == "5Gh RSSI 0 Atten":
|
|
for l in config_data[i]["5Gh RSSI 0 Atten"]:
|
|
virtual_sta_rssi_0_5["rssi_0_5-" + str(c2)] = l
|
|
c2 = c2 + 1
|
|
if j == "Attenuator Modules":
|
|
for m in config_data[i]["Attenuator Modules"]:
|
|
virtual_sta_atten["atten-" + str(c3)] = m
|
|
c3 = c3 + 1
|
|
|
|
logging.info("virtual_sta_rssi_0_2:- " + str(virtual_sta_rssi_0_2))
|
|
logging.info("virtual_sta_rssi_0_5:- " + str(virtual_sta_rssi_0_5))
|
|
logging.info("virtual_sta_atten:- " + str(virtual_sta_atten))
|
|
raw_line_list = [[f"{key}: {value}"] for key, value in virtual_sta_rssi_0_2.items()]
|
|
raw_line.extend(raw_line_list)
|
|
raw_line_list = [[f"{key}: {value}"] for key, value in virtual_sta_rssi_0_5.items()]
|
|
raw_line.extend(raw_line_list)
|
|
raw_line_list = [[f"{key}: {value}"] for key, value in virtual_sta_atten.items()]
|
|
raw_line.extend(raw_line_list)
|
|
""" Logic for Ax radio setting """
|
|
c1 = 0
|
|
c2 = 0
|
|
c3 = 0
|
|
c4 = 0
|
|
config_data = testbed_config_data["802.11AX Settings"]
|
|
for i in config_data:
|
|
for j in config_data[i]:
|
|
if j == "Radios":
|
|
for k in config_data[i]["Radios"]:
|
|
ax_radios["ax_radio-" + str(c1)] = k
|
|
c1 = c1 + 1
|
|
if j == "2.4Ghz RSSI 0 Atten":
|
|
for l in config_data[i]["2.4Ghz RSSI 0 Atten"]:
|
|
ax_rssi_0_2["ax_rssi_0_2-" + str(c2)] = l
|
|
c2 = c2 + 1
|
|
if j == "5Ghz RSSI 0 Atten":
|
|
for m in config_data[i]["5Ghz RSSI 0 Atten"]:
|
|
ax_rssi_0_5["ax_rssi_0_5-" + str(c3)] = m
|
|
c3 = c3 + 1
|
|
if j == "Attenuator Modules":
|
|
for m in config_data[i]["Attenuator Modules"]:
|
|
if m != "":
|
|
ax_atten["ax_atten-" + str(c4)] = m
|
|
if c4 >= 12:
|
|
c4 = c4 + 2
|
|
else:
|
|
c4 = c4 + 1
|
|
|
|
logging.info("ax_radios:- " + str(ax_radios))
|
|
logging.info("ax_rssi_0_2:- " + str(ax_rssi_0_2))
|
|
logging.info("ax_rssi_0_5:- " + str(ax_rssi_0_5))
|
|
logging.info("ax_atten:- " + str(ax_atten))
|
|
raw_line_list = [[f"{key}: {value}"] for key, value in ax_radios.items()]
|
|
raw_line.extend(raw_line_list)
|
|
raw_line_list = [[f"{key}: {value}"] for key, value in ax_rssi_0_2.items()]
|
|
raw_line.extend(raw_line_list)
|
|
raw_line_list = [[f"{key}: {value}"] for key, value in ax_rssi_0_5.items()]
|
|
raw_line.extend(raw_line_list)
|
|
raw_line_list = [[f"{key}: {value}"] for key, value in ax_atten.items()]
|
|
raw_line.extend(raw_line_list)
|
|
|
|
# Fetch 2g_dut and 5g_dut
|
|
dut_2g = None
|
|
dut_5g = None
|
|
for i in dut_data[dut_name]['ssid_data']:
|
|
self.dut_idx_mapping[str(i)] = list(dut_data[dut_name]['ssid_data'][i].values())
|
|
if self.dut_idx_mapping[str(i)][3] == "2G":
|
|
dut_2g = dut_name + ' ' + self.dut_idx_mapping[str(i)][0] + ' ' \
|
|
'' + self.dut_idx_mapping[str(i)][
|
|
4].lower() + f' (1)'
|
|
if self.dut_idx_mapping[str(i)][3] == "5G":
|
|
dut_5g = dut_name + ' ' + self.dut_idx_mapping[str(i)][0] + ' ' \
|
|
'' + \
|
|
self.dut_idx_mapping[str(i)][4].lower() + f' (2)'
|
|
logging.info("dut_2g:- " + str(dut_2g))
|
|
logging.info("dut_5g:- " + str(dut_5g))
|
|
skip_twog, skip_fiveg = '1' if skip_2g else '0', '1' if skip_5g else '0'
|
|
if mode == "BRIDGE" or mode == "NAT-WAN":
|
|
upstream_port = list(self.lanforge_data['wan_ports'].keys())[0]
|
|
if mode == "VLAN":
|
|
if vlan_id is None:
|
|
logging.error("VLAN ID is Unspecified in the VLAN Case")
|
|
pytest.skip("VLAN ID is Unspecified in the VLAN Case")
|
|
else:
|
|
if create_vlan:
|
|
vlan_raw_lines = self.add_vlan(vlan_ids=vlan_id, build=True)
|
|
upstream_port = list(self.lanforge_data['wan_ports'].keys())[0] + "." + str(vlan_id[0])
|
|
logging.info("Upstream data: " + str(upstream_port))
|
|
skip_bandv2 = [['Skip 2.4Ghz Tests', f'{skip_twog}'], ['Skip 5Ghz Tests', f'{skip_fiveg}'],
|
|
['2.4Ghz Channel', f'{channel_2g}'], ['5Ghz Channel', f'{channel_5g}'],
|
|
["Use Issue-3 Behaviour", "0"], ["Skip 6Ghz Tests", "1"], ["Calibrate against LANforge AP", "0"]]
|
|
enable_tests = [['rxsens: 0'], ['max_cx: 0'], ['max_tput: 0'], ['peak_perf: 0'], ['max_tput_bi: 0'],
|
|
['dual_band_tput: 0'], ['multi_band_tput: 0'], ['atf: 0'], ['atf3: 0'], ['qos3: 0'],
|
|
['lat3: 0'], ['mcast3: 0'], ['rvr: 0'], ['spatial: 0'], ['multi_sta: 0'], ['reset: 0'],
|
|
['mu_mimo: 0'], ['stability: 0'], ['ap_coex: 0'], ['acs: 0']]
|
|
if testbed_ == "advanced-3":
|
|
logging.info("In advanced-3")
|
|
skip_bandv2.extend([["Use Virtual AX Stations", "0"], ["Use AX Radios for AC tests", "1"]])
|
|
else:
|
|
skip_bandv2.extend([["Use Virtual AX Stations", "1"], ["Use AX Radios for AC tests", "0"]])
|
|
if testbed_ == "advanced-1":
|
|
logging.info("In advanced-1")
|
|
""" Multi-Conn """
|
|
raw_line.append(["mconn: 100"])
|
|
else:
|
|
""" Multi-Conn """
|
|
raw_line.append(["mconn: 10"])
|
|
|
|
for t in test:
|
|
if [f"{t}: 0"] in enable_tests:
|
|
enable_tests[enable_tests.index([f"{t}: 0"])] = [f"{t}: 1"]
|
|
else:
|
|
logging.info(f"Unable to find the {t} test in selected run")
|
|
raise ValueError(f"Unable to find the {t} test in selected run")
|
|
raw_line.extend(enable_tests)
|
|
update_cv_dut = {}
|
|
try:
|
|
for i in dut_data:
|
|
update_cv_dut[i] = dict.fromkeys(dut_data[i], {})
|
|
for j in dut_data[i]:
|
|
if j == 'ssid_data':
|
|
for k in dut_data[i][j]:
|
|
if (dut_data[i][j][k]['band'] == '5G' and dut_5g != ""
|
|
) or (dut_data[i][j][k]['band'] == '2G' and dut_2g != ""):
|
|
update_cv_dut[i][j][k] = dut_data[i][j][k].copy()
|
|
else:
|
|
update_cv_dut[i][j] = dut_data[i][j].copy()
|
|
except Exception as e:
|
|
logging.error(f"{e}")
|
|
logging.info("update cv dut:- " + str(update_cv_dut))
|
|
self.update_dut_ssid(dut_data=update_cv_dut)
|
|
instance_name = "tr398v2-instance-{}".format(str(random.randint(0, 100000)))
|
|
|
|
# if not os.path.exists("tr398-test-config.txt"):
|
|
# with open("tr398v2-test-config.txt", "wt") as f:
|
|
# for i in raw_line:
|
|
# f.write(str(i[0]) + "\n")
|
|
# f.close()
|
|
""" Test duration 60 sec """
|
|
raw_line.append(["dur120: 60"])
|
|
"""Add turn table"""
|
|
raw_line.append(["turn_table: DUT-Chamber"])
|
|
"""Adding extra raw lines """
|
|
if extra_raw_lines[0]:
|
|
raw_line.extend(extra_raw_lines)
|
|
logging.info("raw lines:- " + str(raw_line))
|
|
cvtest_obj = TR398v2Test(lf_host=self.manager_ip,
|
|
lf_port=self.manager_http_port,
|
|
lf_user="lanforge",
|
|
lf_password="lanforge",
|
|
instance_name=instance_name,
|
|
upstream=upstream_port,
|
|
pull_report=True,
|
|
local_lf_report_dir=self.local_report_path,
|
|
load_old_cfg=False,
|
|
dut2=dut_2g,
|
|
dut5=dut_5g,
|
|
enables=[],
|
|
disables=[],
|
|
raw_lines=raw_line,
|
|
sets=skip_bandv2,
|
|
test_rig=dut_name)
|
|
# self.cvtest_obj.test_name, self.cvtest_obj.blob_text = "TR-398 Issue 2", "TR-398v2-"
|
|
# self.cvtest_obj.result = True
|
|
cvtest_obj.setup()
|
|
cvtest_obj.run()
|
|
# if os.path.exists("tr398v2-test-config.txt"):
|
|
# os.remove("tr398v2-test-config.txt")
|
|
if move_to_influx:
|
|
try:
|
|
report_name = "../reports/" + \
|
|
cvtest_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1]
|
|
influx = CSVtoInflux(influx_host=self.influx_params["influx_host"],
|
|
influx_port=self.influx_params["influx_port"],
|
|
influx_org=self.influx_params["influx_org"],
|
|
influx_token=self.influx_params["influx_token"],
|
|
influx_bucket=self.influx_params["influx_bucket"],
|
|
path=report_name)
|
|
|
|
influx.glob()
|
|
except Exception as e:
|
|
print(e)
|
|
pass
|
|
report_name = cvtest_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1] + "/"
|
|
time.sleep(10)
|
|
self.attach_report_graphs(report_name=report_name, pdf_name=str(test[0]) + " Test PDF Report")
|
|
result = self.read_kpi_file(column_name=["pass/fail"], dir_name=report_name)
|
|
logging.info("result: " + str(result))
|
|
numeric_score = self.read_kpi_file(column_name=["numeric-score"], dir_name=report_name)
|
|
logging.info("Numeric-score: " + str(numeric_score))
|
|
test_details = self.read_kpi_file(column_name=["test details"], dir_name=report_name)
|
|
logging.info("test_details: " + str(test_details))
|
|
self.attach_report_kpi(report_name=report_name)
|
|
self.client_disconnect(clear_all_sta=True, clean_l3_traffic=True)
|
|
if result[0][0] == "PASS":
|
|
return True, "Test Passed"
|
|
else:
|
|
return False, f"Test is Failed. Candela Score:- {numeric_score[0][0]}. Test Details:- {test_details[0][0]}."
|
|
|
|
def tr398(self, radios_2g=[], radios_5g=[], radios_ax=[], dut_name="TIP", dut_5g="", dut_2g="", mode="BRIDGE",
|
|
vlan_id=1, skip_2g=True, skip_5g=False, instance_name="", test=None, move_to_influx=False, dut_data={},
|
|
ssid_name='', security_key='[BLANK]', security="open", sniff_packets=False, create_vlan=True,
|
|
tr398v2=True, tr398=False):
|
|
# User can select one or more TR398 tests
|
|
try:
|
|
if type(test) == str:
|
|
test = test.split(",")
|
|
self.client_disconnect(clean_l3_traffic=True)
|
|
raw_line = []
|
|
skip_twog, skip_fiveg = '1' if skip_2g else '0', '1' if skip_5g else '0'
|
|
channel = 149 if skip_twog else 11
|
|
sniff_radio = 'wiphy0'
|
|
if mode == "BRIDGE" or mode == "NAT-WAN":
|
|
upstream_port = list(self.lanforge_data['wan_ports'].keys())[0]
|
|
if mode == "VLAN":
|
|
if vlan_id is None:
|
|
logging.error("VLAN ID is Unspecified in the VLAN Case")
|
|
pytest.skip("VLAN ID is Unspecified in the VLAN Case")
|
|
else:
|
|
if create_vlan:
|
|
vlan_raw_lines = self.add_vlan(vlan_ids=vlan_id, build=True)
|
|
upstream_port = list(self.lanforge_data['wan_ports'].keys())[0] + "." + str(vlan_id[0])
|
|
logging.info("Upstream data: " + str(upstream_port))
|
|
|
|
# atten_serial = self.attenuator_serial_radio(ssid=ssid_name, passkey=security_key, security=security,
|
|
# sta_mode=0, station_name=['sta0000'], radio=self.wave2_2g_radios[0] if skip_5g else
|
|
# self.wave2_5g_radios[0])
|
|
|
|
atten_serial = self.attenuator_serial()
|
|
|
|
if tr398v2:
|
|
enable_tests = [['rxsens: 0'], ['max_cx: 0'], ['max_tput: 0'], ['peak_perf: 0'], ['max_tput_bi: 0'],
|
|
['dual_band_tput: 0'], ['multi_band_tput: 0'], ['atf: 0'], ['atf3: 0'], ['qos3: 0'],
|
|
['lat3: 0'], ['mcast3: 0'], ['rvr: 0'], ['spatial: 0'], ['multi_sta: 0'], ['reset: 0'],
|
|
['mu_mimo: 0'], ['stability: 0'], ['ap_coex: 0'], ['acs: 0']]
|
|
elif tr398:
|
|
enable_tests = [['rxsens: 0'], ['max_cx: 0'], ['max_tput: 0'], ['atf: 0'], ['rvr: 0'], ['spatial: 0'],
|
|
['multi_sta: 0'], ['reset: 0'], ['mu_mimo: 0'], ['stability: 0'], ['ap_coex: 0']]
|
|
for t in test:
|
|
if [f"{t}: 0"] in enable_tests:
|
|
enable_tests[enable_tests.index([f"{t}: 0"])] = [f"{t}: 1"]
|
|
else:
|
|
logging.info(f"Unable to find the {t} test in selected run")
|
|
raise ValueError(f"Unable to find the {t} test in selected run")
|
|
|
|
rad_atten = [[f'atten-0: {atten_serial[0]}.0'], [f'atten-1: {atten_serial[0]}.1'],
|
|
[f'atten-2: {atten_serial[0]}.2'],
|
|
[f'atten-3: {atten_serial[0]}.3'], [f'atten-4: {atten_serial[1]}.0'],
|
|
[f'atten-5: {atten_serial[1]}.1'],
|
|
[f'atten-8: {atten_serial[1]}.2'], [f'atten-9: {atten_serial[1]}.3']]
|
|
|
|
skip_band = [['Skip 2.4Ghz Tests', f'{skip_twog}'], ['Skip 5Ghz Tests', f'{skip_fiveg}'],
|
|
['2.4Ghz Channel', 'AUTO'], ['5Ghz Channel', 'AUTO']]
|
|
|
|
skip_bandv2 = [['Skip 2.4Ghz Tests', f'{skip_twog}'], ['Skip 5Ghz Tests', f'{skip_fiveg}'],
|
|
['2.4Ghz Channel', 'AUTO'], ['5Ghz Channel', 'AUTO'], ['Skip AX Tests', '1']]
|
|
|
|
if len(radios_2g) >= 3 and len(radios_5g) >= 3:
|
|
for i in range(6):
|
|
if i == 0 or i == 2:
|
|
raw_line.append([f'radio-{i}: {radios_5g[0] if i == 0 else radios_5g[1]}'])
|
|
if i == 1 or i == 3:
|
|
raw_line.append([f'radio-{i}: {radios_2g[0] if i == 1 else radios_2g[1]}'])
|
|
if i == 4 or i == 5:
|
|
raw_line.append([f'radio-{i}: {radios_5g[2] if i == 4 else radios_2g[2]}'])
|
|
if sniff_packets:
|
|
if len(radios_ax) >= 1:
|
|
temp_ax = str(radios_ax[0]).split(" ")
|
|
if len(temp_ax) == 2:
|
|
sniff_radio = str(temp_ax[1])
|
|
elif skip_2g:
|
|
temp = str(radios_5g[0]).split(" ")
|
|
if len(temp) == 2:
|
|
sniff_radio = str(temp[1])
|
|
elif skip_5g:
|
|
temp = str(radios_2g[0]).split(" ")
|
|
if len(temp) == 2:
|
|
sniff_radio = str(temp[1])
|
|
elif len(radios_2g) >= 2 and len(radios_5g) >= 2 and len(radios_ax) >= 2:
|
|
if len(radios_2g) >= 3 and len(radios_5g) >= 3:
|
|
for i in range(6):
|
|
if i == 0 or i == 2:
|
|
raw_line.append([f'radio-{i}: {radios_5g[0] if i == 0 else radios_5g[1]}'])
|
|
if i == 1 or i == 3:
|
|
raw_line.append([f'radio-{i}: {radios_2g[0] if i == 1 else radios_2g[1]}'])
|
|
if i == 4 or i == 5:
|
|
raw_line.append([f'radio-{i}: {radios_5g[2] if i == 4 else radios_2g[2]}'])
|
|
if sniff_packets:
|
|
if len(radios_ax) >= 1:
|
|
temp_ax = str(radios_ax[0]).split(" ")
|
|
if len(temp_ax) == 2:
|
|
sniff_radio = str(temp_ax[1])
|
|
else:
|
|
for i in range(6):
|
|
if i == 0 or i == 2:
|
|
raw_line.append([f'radio-{i}: {radios_5g[0] if i == 0 else radios_5g[1]}'])
|
|
if i == 1 or i == 3:
|
|
raw_line.append([f'radio-{i}: {radios_2g[0] if i == 1 else radios_2g[1]}'])
|
|
if i == 4 or i == 5:
|
|
raw_line.append([f'radio-{i}: {radios_ax[0] if i == 4 else radios_ax[1]}'])
|
|
elif len(radios_2g) == 0 and len(radios_5g) == 0 and len(radios_ax) >= 3 and len(radios_ax) >= 6:
|
|
for i in range(6):
|
|
raw_line.append([f'radio-{i}: {radios_ax[i]}'])
|
|
|
|
if len(raw_line) != 6:
|
|
raw_line = [['radio-0: 1.1.5 wiphy1'], ['radio-1: 1.1.4 wiphy0'], ['radio-2: 1.1.7 wiphy3'],
|
|
['radio-3: 1.1.6 wiphy2'], ['radio-4: 1.1.8 wiphy4'], ['radio-5: 1.1.9 wiphy5']]
|
|
raw_line.extend(enable_tests + rad_atten)
|
|
update_cv_dut = {}
|
|
try:
|
|
for i in dut_data:
|
|
update_cv_dut[i] = dict.fromkeys(dut_data[i], {})
|
|
for j in dut_data[i]:
|
|
if j == 'ssid_data':
|
|
for k in dut_data[i][j]:
|
|
if (dut_data[i][j][k]['band'] == '5G' and dut_5g != ""
|
|
) or (dut_data[i][j][k]['band'] == '2G' and dut_2g != ""):
|
|
update_cv_dut[i][j][k] = dut_data[i][j][k].copy()
|
|
else:
|
|
update_cv_dut[i][j] = dut_data[i][j].copy()
|
|
except Exception as e:
|
|
logging.error(f"{e}")
|
|
self.update_dut_ssid(dut_data=update_cv_dut)
|
|
instance_name = "tr398-instance-{}".format(str(random.randint(0, 100000)))
|
|
|
|
# if not os.path.exists("tr398-test-config.txt"):
|
|
with open("tr398-test-config.txt", "wt") as f:
|
|
for i in raw_line:
|
|
f.write(str(i[0]) + "\n")
|
|
f.close()
|
|
|
|
if tr398v2:
|
|
self.cvtest_obj = TR398v2Test(lf_host=self.manager_ip,
|
|
lf_port=self.manager_http_port,
|
|
lf_user="lanforge",
|
|
lf_password="lanforge",
|
|
instance_name=instance_name,
|
|
config_name="cv_dflt_cfg",
|
|
upstream=upstream_port,
|
|
pull_report=True,
|
|
local_lf_report_dir=self.local_report_path,
|
|
load_old_cfg=False,
|
|
dut2=dut_2g,
|
|
dut5=dut_5g,
|
|
raw_lines_file="tr398-test-config.txt",
|
|
enables=[],
|
|
disables=[],
|
|
raw_lines=[],
|
|
sets=skip_bandv2,
|
|
test_rig=dut_name)
|
|
self.cvtest_obj.test_name, self.cvtest_obj.blob_text = "TR-398 Issue 2", "TR-398v2-"
|
|
elif tr398:
|
|
self.cvtest_obj = TR398Test(lf_host=self.lanforge_ip,
|
|
lf_port=self.lanforge_port,
|
|
lf_user="lanforge",
|
|
lf_password="lanforge",
|
|
instance_name=instance_name,
|
|
config_name="cv_dflt_cfg",
|
|
upstream="1.1." + upstream_port,
|
|
pull_report=True,
|
|
local_lf_report_dir=self.local_report_path,
|
|
load_old_cfg=False,
|
|
dut2=dut_2g,
|
|
dut5=dut_5g,
|
|
raw_lines_file="mu-mimo-config.txt",
|
|
enables=[],
|
|
disables=[],
|
|
raw_lines=[],
|
|
sets=skip_band,
|
|
test_rig=dut_name
|
|
)
|
|
self.cvtest_obj.test_name, self.cvtest_obj.blob_text = "TR-398", "TR-398-"
|
|
self.cvtest_obj.result = True
|
|
self.cvtest_obj.setup()
|
|
if sniff_packets:
|
|
self.pcap_obj = LfPcap(host=self.manager_ip, port=self.manager_http_port)
|
|
t1 = threading.Thread(target=self.cvtest_obj.run)
|
|
t1.start()
|
|
t2 = threading.Thread(target=self.pcap_obj.sniff_packets, args=(sniff_radio, "mu-mimo", channel, 40))
|
|
if t1.is_alive():
|
|
time.sleep(375)
|
|
t2.start()
|
|
while t1.is_alive():
|
|
time.sleep(1)
|
|
else:
|
|
self.cvtest_obj.run()
|
|
if os.path.exists("tr398-test-config.txt"):
|
|
os.remove("tr398-test-config.txt")
|
|
|
|
if move_to_influx:
|
|
try:
|
|
report_name = "../reports/" + \
|
|
self.cvtest_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1]
|
|
influx = CSVtoInflux(influx_host=self.influx_params["influx_host"],
|
|
influx_port=self.influx_params["influx_port"],
|
|
influx_org=self.influx_params["influx_org"],
|
|
influx_token=self.influx_params["influx_token"],
|
|
influx_bucket=self.influx_params["influx_bucket"],
|
|
path=report_name)
|
|
|
|
influx.glob()
|
|
except Exception as e:
|
|
print(e)
|
|
pass
|
|
report_name = self.cvtest_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1] + "/"
|
|
self.attach_report_graphs(report_name=report_name)
|
|
result = self.read_kpi_file(column_name=["pass/fail"], dir_name=report_name)
|
|
allure.attach.file(source="../reports/" + report_name + "/kpi.csv",
|
|
name=f"{test}_test_report.csv", attachment_type=allure.attachment_type.CSV)
|
|
if result[0][0] == "PASS":
|
|
return True, "Test Passed"
|
|
else:
|
|
return False, "Test Failed"
|
|
except Exception as e:
|
|
logging.error(f"{e}")
|
|
return False, f"{e}"
|
|
finally:
|
|
try:
|
|
self.client_disconnect(clear_all_sta=True, clean_l3_traffic=True)
|
|
except Exception as e:
|
|
logging.error(f"{e}")
|
|
return False, f"{e}"
|
|
|
|
def air_time_fairness(self, ssid="[BLANK]", passkey='[BLANK]', security="wpa2", mode="BRIDGE", band='twog',
|
|
vlan_id=100, atn=100, pass_value=None, dut_data={}):
|
|
try:
|
|
allure.attach(name="Definition",
|
|
body="Airtime Fairness test intends to verify the capacity of Wi-Fi device to ensure the fairness of " \
|
|
"airtime usage.")
|
|
allure.attach(name="Procedure",
|
|
body="This test case definition states that Create 2 stations of greenfeild mode and 1 station of legacy mode"
|
|
" on 2.4/5Ghz radio. Run TCP download for station_1 as throughpt_1, station_2 as throughpt_2, "
|
|
"station_2 with attenuation as throughpt_3, station_3 as throughpt_4, UDP download for station_1 + station_2"
|
|
"of data_rates 40% of throughput_1 and 40% of throughput_2 as throughput_5, station_1 + station_2 with attenuation"
|
|
"of data_rates 40% of throughput_1 and 40% of throughput_3 as throughput_6, station_1 + station_3"
|
|
"of data_rates 40% of throughput_1 and 40% of throughput_4 as throughput_7")
|
|
self.client_disconnect(clear_all_sta=True, clean_l3_traffic=True)
|
|
sta = list(map(lambda i: f"sta000{i}", range(3)))
|
|
all_radio_5g = (self.be200_radios + self.ax210_radios + self.ax200_radios +
|
|
+ self.mtk_radios + self.wave2_5g_radios + self.wave1_radios)
|
|
logging.info("All 5g radios" + str(all_radio_5g))
|
|
all_radio_2g = (self.be200_radios + self.ax210_radios + self.ax200_radios +
|
|
+ self.mtk_radios + self.wave2_2g_radios + self.wave1_radios)
|
|
logging.info("All 2g radios" + str(all_radio_2g))
|
|
if len(all_radio_5g) < 3:
|
|
pytest.fail("3 Radios are not available")
|
|
else:
|
|
radio_5g = all_radio_5g[:3]
|
|
if len(all_radio_2g) < 3:
|
|
pytest.fail("3 Radios are not available")
|
|
else:
|
|
radio_2g = all_radio_2g[:3]
|
|
radios, sta_mode = (radio_5g, [1, 9]) if band == "fiveg" else (radio_2g, [2, 11])
|
|
thrpt = {"sta0_tcp_dl": None, "sta1_tcp_dl": None, "sta1_tcp_dl_atn": None, "sta2_tcp_dl": None,
|
|
"sta0+1_udp": None, "sta0+1_udp_atn": None, "sta0+2": None}
|
|
no_of_iter = list(thrpt.keys())
|
|
|
|
atten_serial = self.attenuator_serial_radio(ssid=ssid, passkey=passkey, security=security, radio=radios[1],
|
|
station_name=[sta[0]])
|
|
atten_serial_split = atten_serial[0].split(".")
|
|
self.attenuator_modify("all", 'all', 100)
|
|
for i in range(len(radios)):
|
|
if i == 2:
|
|
# mode = 2/1 will create legacy client
|
|
create_sta = self.client_connect_using_radio(ssid=ssid, passkey=passkey, security=security,
|
|
radio=radios[i], station_name=[sta[i]],
|
|
client_type=sta_mode[0])
|
|
else:
|
|
# mode = 11/9 will create bgn-AC/an-AC client
|
|
create_sta = self.client_connect_using_radio(ssid=ssid, passkey=passkey, security=security,
|
|
radio=radios[i], station_name=[sta[i]],
|
|
client_type=sta_mode[1])
|
|
if create_sta == False:
|
|
logging.info(f"Test failed due to no IP for {sta[i]}")
|
|
assert False, f"Test failed due to no IP for {sta[i]}"
|
|
else:
|
|
lf_sta = list(create_sta.station_map().keys())
|
|
|
|
def wifi_cap(sta=None, down=None, up=0, proto=None, thrpt_key=None, wifi_cap=False, atn=None,
|
|
l3_trf=False):
|
|
if atn:
|
|
for i in range(2):
|
|
self.attenuator_modify(int(atten_serial_split[2]), i, int(atn))
|
|
time.sleep(0.5)
|
|
if wifi_cap:
|
|
wct_obj = self.wifi_capacity(mode=mode, add_stations=False, vlan_id=vlan_id, download_rate=down,
|
|
batch_size="1", stations=f"{sta}", create_stations=False,
|
|
upload_rate=up, protocol=proto, duration="60000", sort="linear",
|
|
dut_data=dut_data)
|
|
report_name = wct_obj[0].report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1]
|
|
# self.attach_report_graphs(report_name=report_name)
|
|
entries = os.listdir("../reports/" + report_name + '/')
|
|
if "kpi.csv" in entries:
|
|
thrpt[thrpt_key] = \
|
|
self.read_kpi_file(column_name=["numeric-score"], dir_name=report_name)[0][0]
|
|
if l3_trf:
|
|
self.client_disconnect(clean_l3_traffic=True)
|
|
for i in sta[0:1]:
|
|
self.local_realm.admin_up(i)
|
|
time.sleep(0.3)
|
|
self.create_layer3(sta_list=sta[0:1], traffic_type=proto, side_a_min_rate=0,
|
|
side_b_min_rate=int(down[0]), start_cx=False)
|
|
for i in sta[1:2]:
|
|
self.local_realm.admin_up(i)
|
|
time.sleep(0.3)
|
|
self.create_layer3(sta_list=sta[1:2], traffic_type=proto, side_a_min_rate=0,
|
|
side_b_min_rate=int(down[1]), start_cx=False)
|
|
created_cx = {}
|
|
cx_list = [created_cx.setdefault(i, "Endpoints") for i in self.get_cx_list() if
|
|
i not in created_cx]
|
|
self.start_cx_list(created_cx=created_cx, check_run_status=True)
|
|
thrpt[thrpt_key] = \
|
|
self.monitor(duration_sec=int(60) + 10, monitor_interval=1, created_cx=created_cx.keys(),
|
|
col_names=['bps rx a', 'bps rx b'], iterations=0, side_a_min_rate=0,
|
|
side_b_min_rate=down)[0]
|
|
|
|
# station_0 TCP down throughtput
|
|
wifi_cap(down="1Gbps", sta=f"{lf_sta[0]}", up="0Gbps", proto="TCP-IPv4", thrpt_key=f"{no_of_iter[0]}",
|
|
wifi_cap=True)
|
|
# station_1 TCP down throughtput
|
|
wifi_cap(down="1Gbps", sta=f"{lf_sta[1]}", up="0Gbps", proto="TCP-IPv4", thrpt_key=f"{no_of_iter[1]}",
|
|
wifi_cap=True)
|
|
# station_1 with medium distance TCP down throughtput
|
|
wifi_cap(down="1Gbps", sta=f"{lf_sta[1]}", up="0Gbps", proto="TCP-IPv4", thrpt_key=f"{no_of_iter[2]}",
|
|
wifi_cap=True, atn=atn)
|
|
# station_2 TCP down throughtput
|
|
wifi_cap(down="1Gbps", sta=f"{lf_sta[2]}", up="0Gbps", proto="TCP-IPv4", thrpt_key=f"{no_of_iter[3]}",
|
|
wifi_cap=True, atn=100)
|
|
# UDP traffic for station_0 of data-rate 40% of sta0_data_rate and station_1 of data-rate 40% of sta1_data_rate
|
|
wifi_cap(down=[(thrpt["sta0_tcp_dl"] * 0.01) * 4E7, (thrpt["sta1_tcp_dl"] * 0.01) * 4E7], sta=sta[0:2],
|
|
up="0Gbps", thrpt_key=f"{no_of_iter[4]}", l3_trf=True, proto="lf_udp")
|
|
# UDP traffic for station_0 of data-rate 40% of sta0_data_rate and medium distance station_1 of data-rate 40% of sta1_data_rate
|
|
wifi_cap(down=[(thrpt["sta0_tcp_dl"] * 0.01) * 4E7, (thrpt["sta1_tcp_dl_atn"] * 0.01) * 4E7],
|
|
sta=sta[0:2],
|
|
up="0Gbps", thrpt_key=f"{no_of_iter[5]}", l3_trf=True, atn=atn, proto="lf_udp")
|
|
# UDP traffic for station_0 of data-rate 40% of sta0_data_rate and station_2 of data-rate 40% of sta2_data_rate
|
|
wifi_cap(down=[(thrpt["sta0_tcp_dl"] * 0.01) * 4E7, (thrpt["sta2_tcp_dl"] * 0.01) * 4E7],
|
|
sta=sta[0:3:2],
|
|
up="0Gbps", thrpt_key=f"{no_of_iter[6]}", l3_trf=True, atn=100, proto="lf_udp")
|
|
logging.info("Throughput values: \n", thrpt)
|
|
self.allure_report_table_format(dict_data=thrpt, key="Station combination", value="Throughput values",
|
|
name="Test_results")
|
|
if pass_value:
|
|
if sum(thrpt["sta0+1_udp"]) >= pass_value[0] and sum(thrpt["sta0+1_udp_atn"]) >= pass_value[1] and \
|
|
sum(thrpt["sta0+2"]) >= pass_value[2]:
|
|
return True, "Test Passed"
|
|
else:
|
|
return False, "Failed due to Lesser value"
|
|
else:
|
|
return True, "Test Passed without pass-fail verification"
|
|
except Exception as e:
|
|
logging.error(f"{e}")
|
|
return False, f"{e}"
|
|
finally:
|
|
try:
|
|
self.client_disconnect(clear_all_sta=True, clean_l3_traffic=True)
|
|
except Exception as e:
|
|
logging.error(f"{e}")
|
|
return False, f"{e}"
|
|
|
|
def rate_vs_range_test(self, station_name=None, mode="BRIDGE", vlan_id=100, download_rate="85%", dut_name="TIP",
|
|
upload_rate="0", duration="1m", instance_name="test_demo", raw_lines=None,
|
|
move_to_influx=False, create_vlan=True):
|
|
for dut in self.dut_data:
|
|
if mode == "BRIDGE" or mode == "NAT-WAN":
|
|
upstream_port = dut["wan_port"]
|
|
elif mode == "NAT-LAN":
|
|
upstream_port = dut["lan_port"]
|
|
elif mode == "VLAN":
|
|
if vlan_id is None:
|
|
logging.error("VLAN ID is Unspecified in the VLAN Case")
|
|
pytest.skip("VLAN ID is Unspecified in the VLAN Case")
|
|
else:
|
|
if create_vlan:
|
|
self.add_vlan(vlan_ids=vlan_id, build=True)
|
|
else:
|
|
self.add_vlan(vlan_ids=vlan_id, build=False)
|
|
upstream_port = dut["wan_port"] + "." + str(vlan_id[0])
|
|
logging.info("Upstream data: " + str(upstream_port))
|
|
|
|
rvr_obj = rvr_test(lf_host=self.manager_ip,
|
|
lf_port=self.manager_http_port,
|
|
ssh_port=self.manager_ssh_port,
|
|
lf_user="lanforge",
|
|
local_lf_report_dir="../reports/",
|
|
lf_password="lanforge",
|
|
instance_name=instance_name,
|
|
config_name="rvr_config",
|
|
upstream=upstream_port,
|
|
pull_report=True,
|
|
load_old_cfg=False,
|
|
upload_speed=upload_rate,
|
|
download_speed=download_rate,
|
|
duration=duration,
|
|
station=station_name,
|
|
dut=dut_name,
|
|
raw_lines=raw_lines)
|
|
rvr_obj.run()
|
|
if move_to_influx:
|
|
try:
|
|
report_name = self.rvr_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1]
|
|
influx = CSVtoInflux(influx_host=self.influx_params["influx_host"],
|
|
influx_port=self.influx_params["influx_port"],
|
|
influx_org=self.influx_params["influx_org"],
|
|
influx_token=self.influx_params["influx_token"],
|
|
influx_bucket=self.influx_params["influx_bucket"],
|
|
path=report_name)
|
|
|
|
influx.glob()
|
|
except Exception as e:
|
|
print(e)
|
|
pass
|
|
# fetch the report
|
|
report_name = rvr_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1]
|
|
time.sleep(10)
|
|
logging.info("report_name: " + str(report_name))
|
|
self.attach_report_graphs(report_name=report_name, pdf_name="Rate vs Range Test PDF Report")
|
|
self.attach_report_kpi(report_name=report_name)
|
|
|
|
return rvr_obj, report_name
|
|
|
|
def dual_band_performance_test(self, ssid_5G="[BLANK]", ssid_2G="[BLANK]", mode="BRIDGE", vlan_id=100,
|
|
dut_name="TIP",
|
|
instance_name="test_demo", dut_5g="", dut_2g="", influx_tags="",
|
|
move_to_influx=False,
|
|
create_vlan=True, dut_data={}):
|
|
try:
|
|
instance_name = ''.join(random.choices(string.ascii_uppercase + string.digits, k=12))
|
|
|
|
if mode == "BRIDGE" or mode == "NAT-WAN":
|
|
upstream_port = list(self.lanforge_data['wan_ports'].keys())[0]
|
|
if mode == "VLAN":
|
|
if vlan_id is None:
|
|
logging.error("VLAN ID is Unspecified in the VLAN Case")
|
|
pytest.skip("VLAN ID is Unspecified in the VLAN Case")
|
|
else:
|
|
if create_vlan:
|
|
vlan_raw_lines = self.add_vlan(vlan_ids=vlan_id, build=True)
|
|
upstream_port = list(self.lanforge_data['wan_ports'].keys())[0] + "." + str(vlan_id[0])
|
|
logging.info("Upstream data: " + str(upstream_port))
|
|
|
|
self.update_dut_ssid(dut_data=dut_data)
|
|
self.dualbandptest_obj = ApAutoTest(lf_host=self.manager_ip,
|
|
lf_port=self.manager_http_port,
|
|
lf_user="lanforge",
|
|
lf_password="lanforge",
|
|
ssh_port=self.manager_ssh_port,
|
|
instance_name=instance_name,
|
|
config_name="dbp_config",
|
|
upstream=upstream_port,
|
|
pull_report=True,
|
|
dut5_1=dut_5g,
|
|
dut2_1=dut_2g,
|
|
load_old_cfg=False,
|
|
local_lf_report_dir=self.local_report_path,
|
|
max_stations_2=64,
|
|
max_stations_5=64,
|
|
max_stations_dual=64,
|
|
radio2=[self.wave2_2g_radios],
|
|
radio5=[self.wave2_5g_radios],
|
|
raw_lines=[['modes: AUTO'], ['dur20: 60']],
|
|
# test_tag=influx_tags,
|
|
sets=[['Basic Client Connectivity', '0'],
|
|
['Multi Band Throughput', '1'],
|
|
['Capacity', '0'],
|
|
['Skip 2.4Ghz Tests', '0'],
|
|
['Channel Switching', '0'],
|
|
['Skip 5Ghz Tests', '0'],
|
|
['Skip 6Ghz Tests', '1'],
|
|
['Skip 5Ghz-B Tests', '1'],
|
|
['Skip Tri-Band Tests', '1'],
|
|
['Skip Tri-Band (2.4, 5-low, 5-high) Tests', '1'],
|
|
['Stability', '0'],
|
|
['Band Steering', '0'],
|
|
['Multi STA Throughput vs Pkt Size', '0'],
|
|
['Single STA Throughput vs Pkt Size', '0'],
|
|
['Long Term', '0']]
|
|
)
|
|
self.dualbandptest_obj.setup()
|
|
self.dualbandptest_obj.run()
|
|
if move_to_influx:
|
|
report_name = "../reports/" + \
|
|
self.dualbandptest_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1]
|
|
try:
|
|
influx = CSVtoInflux(influx_host=self.influx_params["influx_host"],
|
|
influx_port=self.influx_params["influx_port"],
|
|
influx_org=self.influx_params["influx_org"],
|
|
influx_token=self.influx_params["influx_token"],
|
|
influx_bucket=self.influx_params["influx_bucket"],
|
|
path=report_name)
|
|
|
|
influx.glob()
|
|
except Exception as e:
|
|
print(e)
|
|
pass
|
|
report_name = self.dualbandptest_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1] + "/"
|
|
self.attach_report_graphs(report_name=report_name, pdf_name="Dual Band Performance Test")
|
|
result = self.read_kpi_file(column_name=["pass/fail"], dir_name=report_name)
|
|
allure.attach.file(source="../reports/" + report_name + "/kpi.csv",
|
|
name=f"dual_band_CSV", attachment_type="CSV")
|
|
# if result[0][0] == "PASS":
|
|
# return True, "Test Passed"
|
|
# else:
|
|
# return False, "Test Failed"
|
|
|
|
except Exception as e:
|
|
logging.error(f"{e}")
|
|
return False, f"{e}"
|
|
return self.dualbandptest_obj
|
|
|
|
def multi_band_performance_test(self, ssid_5G="[BLANK]", ssid_2G="[BLANK]", ssid_6G="[BLANK]", mode="BRIDGE",
|
|
vlan_id=100,
|
|
dut_name="TIP",
|
|
instance_name="test_demo", dut_5g="", dut_2g="", dut_6g="", influx_tags="",
|
|
move_to_influx=False,
|
|
create_vlan=True, dut_data={}):
|
|
try:
|
|
instance_name = ''.join(random.choices(string.ascii_uppercase + string.digits, k=12))
|
|
|
|
if mode == "BRIDGE" or mode == "NAT-WAN":
|
|
upstream_port = list(self.lanforge_data['wan_ports'].keys())[0]
|
|
if mode == "VLAN":
|
|
if vlan_id is None:
|
|
logging.error("VLAN ID is Unspecified in the VLAN Case")
|
|
pytest.skip("VLAN ID is Unspecified in the VLAN Case")
|
|
else:
|
|
if create_vlan:
|
|
vlan_raw_lines = self.add_vlan(vlan_ids=vlan_id, build=True)
|
|
upstream_port = list(self.lanforge_data['wan_ports'].keys())[0] + "." + str(vlan_id[0])
|
|
logging.info("Upstream data: " + str(upstream_port))
|
|
|
|
self.update_dut_ssid(dut_data=dut_data)
|
|
|
|
if dut_6g:
|
|
logging.info(f"dut_6g data:{dut_6g}")
|
|
band = "sixg"
|
|
self.check_band_ap(band=band)
|
|
self.multibandptest_obj = ApAutoTest(lf_host=self.manager_ip,
|
|
lf_port=self.manager_http_port,
|
|
lf_user="lanforge",
|
|
lf_password="lanforge",
|
|
ssh_port=self.manager_ssh_port,
|
|
instance_name=instance_name,
|
|
config_name="dbp_config",
|
|
upstream=upstream_port,
|
|
pull_report=True,
|
|
dut5_1=dut_5g,
|
|
dut2_1=dut_2g,
|
|
dut6_1=dut_6g,
|
|
load_old_cfg=False,
|
|
local_lf_report_dir=self.local_report_path,
|
|
max_stations_2=64,
|
|
max_stations_5=64,
|
|
max_stations_6=64,
|
|
max_stations_tri=64,
|
|
max_bandwidth=320,
|
|
radio2=[[self.be200_radios[0]]],
|
|
radio5=[[self.be200_radios[1]]],
|
|
radio6=[[self.be200_radios[2]]],
|
|
raw_lines=[['modes: AUTO'], ['dur20: 60']],
|
|
# test_tag=influx_tags,
|
|
sets=[['Basic Client Connectivity', '0'],
|
|
['Multi Band Throughput', '1'],
|
|
['Capacity', '0'],
|
|
['Skip 2.4Ghz Tests', '0'],
|
|
['Channel Switching', '0'],
|
|
['Skip 5Ghz Tests', '0'],
|
|
['Skip 6Ghz Tests', '0'],
|
|
['Skip 5Ghz-B Tests', '1'],
|
|
['Skip Tri-Band Tests', '0'],
|
|
['Skip Tri-Band (2.4, 5-low, 5-high) Tests', '1'],
|
|
['Stability', '0'],
|
|
['Band Steering', '0'],
|
|
['Multi STA Throughput vs Pkt Size', '0'],
|
|
['Single STA Throughput vs Pkt Size', '0'],
|
|
['Long Term', '0']]
|
|
)
|
|
else:
|
|
dict_all_radios_2g = {"be200_radios": self.be200_radios,
|
|
"ax210_radios": self.ax210_radios, "ax200_radios": self.ax200_radios,
|
|
"mtk_radios": self.mtk_radios,
|
|
"wave2_2g_radios": self.wave2_2g_radios,
|
|
"wave1_radios": self.wave1_radios
|
|
}
|
|
dict_all_radios_5g = {"be200_radios": self.be200_radios,
|
|
"ax210_radios": self.ax210_radios, "ax200_radios": self.ax200_radios,
|
|
"mtk_radios": self.mtk_radios,
|
|
"wave2_5g_radios": self.wave2_5g_radios,
|
|
"wave1_radios": self.wave1_radios
|
|
}
|
|
radio5 = []
|
|
for radio_list in dict_all_radios_5g.values():
|
|
if radio_list:
|
|
radio5.append(radio_list[0])
|
|
break
|
|
logging.info(f"Selected Radio for radio5:{radio5}")
|
|
radio2 = []
|
|
for radio_list in dict_all_radios_2g.values():
|
|
for radio in radio_list:
|
|
if radio not in radio5: # Ensure it's not the same as radio5
|
|
radio2.append(radio)
|
|
break
|
|
if radio2: # Stop checking further lists if a radio is assigned
|
|
break
|
|
logging.info(f"Selected Radio for radio2: {radio2}")
|
|
|
|
self.multibandptest_obj = ApAutoTest(lf_host=self.manager_ip,
|
|
lf_port=self.manager_http_port,
|
|
lf_user="lanforge",
|
|
lf_password="lanforge",
|
|
ssh_port=self.manager_ssh_port,
|
|
instance_name=instance_name,
|
|
config_name="dbp_config",
|
|
upstream=upstream_port,
|
|
pull_report=True,
|
|
dut5_1=dut_5g,
|
|
dut2_1=dut_2g,
|
|
load_old_cfg=False,
|
|
local_lf_report_dir=self.local_report_path,
|
|
max_stations_2=64,
|
|
max_stations_5=64,
|
|
max_stations_dual=64,
|
|
max_bandwidth=80,
|
|
radio2=[radio2],
|
|
radio5=[radio5],
|
|
raw_lines=[['modes: AUTO'], ['dur20: 60']],
|
|
# test_tag=influx_tags,
|
|
sets=[['Basic Client Connectivity', '0'],
|
|
['Multi Band Throughput', '1'],
|
|
['Capacity', '0'],
|
|
['Skip 2.4Ghz Tests', '0'],
|
|
['Channel Switching', '0'],
|
|
['Skip 5Ghz Tests', '0'],
|
|
['Skip 6Ghz Tests', '1'],
|
|
['Skip 5Ghz-B Tests', '1'],
|
|
['Skip Tri-Band Tests', '1'],
|
|
['Skip Tri-Band (2.4, 5-low, 5-high) Tests', '1'],
|
|
['Stability', '0'],
|
|
['Band Steering', '0'],
|
|
['Multi STA Throughput vs Pkt Size', '0'],
|
|
['Single STA Throughput vs Pkt Size', '0'],
|
|
['Long Term', '0']]
|
|
)
|
|
self.multibandptest_obj.setup()
|
|
self.multibandptest_obj.run()
|
|
if move_to_influx:
|
|
report_name = "../reports/" + \
|
|
self.multibandptest_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1]
|
|
try:
|
|
influx = CSVtoInflux(influx_host=self.influx_params["influx_host"],
|
|
influx_port=self.influx_params["influx_port"],
|
|
influx_org=self.influx_params["influx_org"],
|
|
influx_token=self.influx_params["influx_token"],
|
|
influx_bucket=self.influx_params["influx_bucket"],
|
|
path=report_name)
|
|
|
|
influx.glob()
|
|
except Exception as e:
|
|
print(e)
|
|
pass
|
|
report_name = self.multibandptest_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[
|
|
-1] + "/"
|
|
self.attach_report_graphs(report_name=report_name, pdf_name="Multi Band Performance Test")
|
|
result = self.read_kpi_file(column_name=["pass/fail"], dir_name=report_name)
|
|
logging.info(f"result of pass/fail:{result}")
|
|
allure.attach.file(source="../reports/" + report_name + "/kpi.csv",
|
|
name=f"Multi_band_CSV", attachment_type="CSV")
|
|
|
|
except Exception as e:
|
|
logging.error(f"{e}")
|
|
return False, f"{e}"
|
|
return self.multibandptest_obj
|
|
|
|
def multi_station_performance(self, ssid_name=None, security_key=None, mode="BRIDGE", vlan=1, band="twog",
|
|
antenna=1,
|
|
instance_name="", set_att_db="10db", download_rate="0Gbps", upload_rate="1Gbps",
|
|
batch_size="", protocol="UDP-IPv4", duration="120000", expected_throughput=35,
|
|
traffic_type="udp_upload", sniff_radio=False, create_vlan=True, dut_data=None):
|
|
global station_name, radio_prefix, set_value, set_value1, type
|
|
self.chamber_view()
|
|
self.client_disconnect(clean_l3_traffic=True)
|
|
batch_size = batch_size
|
|
if band == "twog":
|
|
station_name = self.twog_prefix
|
|
radio_prefix = (self.be200_radios + self.ax210_radios + self.ax200_radios +
|
|
+ self.mtk_radios + self.wave2_2g_radios + self.wave1_radios)
|
|
elif band == "fiveg":
|
|
station_name = self.fiveg_prefix
|
|
radio_prefix = (self.be200_radios + self.ax210_radios + self.ax200_radios +
|
|
+ self.mtk_radios + self.wave2_5g_radios + self.wave1_radios)
|
|
print("station_name:", station_name)
|
|
print("radio:", radio_prefix)
|
|
|
|
# setting attenuator serial
|
|
atten_sr = self.attenuator_serial()
|
|
print(atten_sr)
|
|
atten_sr1 = atten_sr[1].split(".")
|
|
atten_sr2 = atten_sr[0].split(".")
|
|
print(atten_sr1, atten_sr2)
|
|
|
|
# creating stations
|
|
if batch_size == "3":
|
|
radio_name = radio_prefix[0]
|
|
print("radio:", radio_name)
|
|
values = radio_name.split(".")
|
|
shelf = int(values[0])
|
|
resource = int(values[1])
|
|
print(shelf, resource)
|
|
sta = []
|
|
for i in range(3):
|
|
sta.append(station_name + str(i))
|
|
print(sta)
|
|
data = {"shelf": shelf, "resource": resource, "radio": values[2], "antenna": antenna}
|
|
self.json_post(_req_url="cli-json/set_wifi_radio", data=data)
|
|
sta_ip = self.client_connect_using_radio(ssid=ssid_name, passkey=security_key, mode=mode, band=band,
|
|
radio=radio_name, station_name=sta, vlan_id=[vlan],
|
|
dut_data=dut_data, sniff_radio=sniff_radio)
|
|
if not sta_ip:
|
|
logging.info("Test Failed, due to station has no ip")
|
|
return False, "TEST FAILED, due to station has no ip"
|
|
|
|
elif batch_size == "3,6" or batch_size == "3,6,9":
|
|
sta = []
|
|
list_three_sta = []
|
|
count = batch_size.split(',')
|
|
n, j = 0, 0
|
|
if len(count) == 2:
|
|
n, j = 6, 2
|
|
elif len(count) == 3:
|
|
n, j = 9, 3
|
|
print("number_of_stations:%s & iterations : %s" % (n, j))
|
|
for i in range(n):
|
|
list_three_sta.append(station_name + str(i))
|
|
if (i != 0) and (((i + 1) % 3) == 0):
|
|
sta.append(list_three_sta)
|
|
list_three_sta = []
|
|
print(sta)
|
|
for i in range(j):
|
|
radio_name = radio_prefix[i]
|
|
print(radio_name)
|
|
print(station_name)
|
|
values = radio_name.split(".")
|
|
shelf = int(values[0])
|
|
resource = int(values[1])
|
|
print(shelf, resource)
|
|
data = {"shelf": shelf, "resource": resource, "radio": values[2], "antenna": antenna}
|
|
self.json_post(_req_url="cli-json/set_wifi_radio", data=data)
|
|
time.sleep(0.5)
|
|
sta_ip = self.client_connect_using_radio(ssid=ssid_name, passkey=security_key, mode=mode, band=band,
|
|
radio=radio_name, station_name=sta[i], vlan_id=[vlan],
|
|
dut_data=dut_data, sniff_radio=sniff_radio,
|
|
create_vlan=create_vlan)
|
|
create_vlan = False
|
|
if not sta_ip:
|
|
logging.info("Test Failed, due to station has no ip")
|
|
return False, "TEST FAILED, due to station has no ip"
|
|
time.sleep(0.5)
|
|
# attenuator setup for different db
|
|
if set_att_db == "10db":
|
|
for i in range(4):
|
|
self.attenuator_modify(int(atten_sr1[2]), i, 100)
|
|
time.sleep(0.5)
|
|
elif set_att_db == "10db,38db" or "10db,25db":
|
|
for i in range(4):
|
|
self.attenuator_modify(int(atten_sr1[2]), i, 100)
|
|
time.sleep(0.5)
|
|
if "25db" in set_att_db:
|
|
set_value = 250
|
|
elif "38db" in set_att_db:
|
|
set_value = 380
|
|
print(set_value)
|
|
for i in range(2):
|
|
self.attenuator_modify(int(atten_sr2[2]), i, set_value)
|
|
time.sleep(0.5)
|
|
elif set_att_db == "10db,38db,48db" or "10db,25db,35db":
|
|
for i in range(4):
|
|
self.attenuator_modify(int(atten_sr1[2]), i, 100)
|
|
time.sleep(0.5)
|
|
if "25db" and "35db" in set_att_db:
|
|
set_value = 250
|
|
set_value1 = 350
|
|
elif "38db" and "48db" in set_att_db:
|
|
set_value = 380
|
|
set_value1 = 480
|
|
print(set_value, set_value1)
|
|
for i in range(4):
|
|
self.attenuator_modify(int(atten_sr2[2]), i, set_value)
|
|
time.sleep(0.5)
|
|
if i >= 2:
|
|
self.attenuator_modify(int(atten_sr2[2]), i, set_value1)
|
|
time.sleep(0.5)
|
|
# wifi_capacity test
|
|
wct_obj = self.wifi_capacity(instance_name=instance_name, mode=mode, vlan_id=[vlan],
|
|
download_rate=download_rate, batch_size=batch_size,
|
|
upload_rate=upload_rate, protocol=protocol, duration=duration,
|
|
sort="linear", create_vlan=False)
|
|
report_name = wct_obj[0].report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1]
|
|
csv_val = self.read_csv_individual_station_throughput(dir_name=report_name, option=None,
|
|
individual_station_throughput=False,
|
|
kpi_csv=True,
|
|
file_name="/kpi.csv", batch_size=batch_size)
|
|
print(csv_val)
|
|
# considering the 70% from the expected throughput
|
|
pass_value = (expected_throughput * 0.7)
|
|
print("pass value ", pass_value)
|
|
self.client_disconnect(clear_all_sta=True, clean_l3_traffic=True)
|
|
if not csv_val:
|
|
print("csv file does not exist, Test failed")
|
|
allure.attach(name="Csv Data", body="csv file does not exist, Test failed")
|
|
return False, "CSV file does not exist, Test failed"
|
|
else:
|
|
if traffic_type == "udp_upload":
|
|
type = "Up"
|
|
elif traffic_type == "udp_download":
|
|
type = "Down"
|
|
print("Traffic type", type)
|
|
if list(csv_val[type].values())[-1] >= pass_value:
|
|
allure.attach(name="Csv Data", body="Throughput value : " + str(list(csv_val[type].values())[-1]))
|
|
logging.info("Test passed successfully")
|
|
return True, "TEST PASSED"
|
|
else:
|
|
allure.attach(name="Csv Data", body="Throughput value : " + str(list(csv_val[type].values())[-1]))
|
|
logging.info("TEST FAILED, Actual throughput is lesser than Expected.")
|
|
return False, "TEST FAILED, Actual throughput (%sMbps) is lesser than Expected (%sMbps)" % (
|
|
str(list(csv_val[type].values())[-1]), str(pass_value))
|
|
|
|
def spatial_consistency(self, ssid_name=None, security_key=None, security="wpa2", mode="BRIDGE", band="twog",
|
|
vlan=1, dut_data=None, num_sta=1, download_rate="100%", upload_rate="0", spatial_streams=1,
|
|
instance_name="", pass_value=None, attenuations=None, create_vlan=True):
|
|
logging.info("Cleanup existing clients and traffic")
|
|
chamber_view_obj = self.chamber_view()
|
|
dut_name = list(dut_data.keys())[0]
|
|
logging.info("DUT name: " + str(dut_name))
|
|
self.client_disconnect(clean_l3_traffic=True)
|
|
# client connect
|
|
station = self.client_connect(ssid=ssid_name, security=security, passkey=security_key, mode=mode,
|
|
band=band, num_sta=num_sta, vlan_id=[vlan], dut_data=dut_data)
|
|
sta_name = list(station.keys())
|
|
ser_no = self.attenuator_serial()
|
|
print(ser_no)
|
|
val = [['modes: Auto'], ['pkts: MTU'], ['directions: DUT Transmit'], ['traffic_types:UDP'],
|
|
['bandw_options: AUTO'], ['spatial_streams: ' + str(spatial_streams)],
|
|
['attenuator: ' + str(ser_no[0])],
|
|
['attenuator2: ' + str(ser_no[1])],
|
|
['attenuations: 100 380 480'], ['attenuations2: 100 380 480'], ['chamber: DUT-Chamber'],
|
|
['tt_deg: 0..+60..300']]
|
|
if station:
|
|
# rvr test
|
|
rvr_o, report_name = self.rate_vs_range_test(station_name=sta_name[0], mode=mode,
|
|
download_rate=download_rate,
|
|
upload_rate=upload_rate, instance_name=instance_name,
|
|
duration="60000",
|
|
vlan_id=[vlan], dut_name=dut_name, raw_lines=val,
|
|
create_vlan=create_vlan)
|
|
entries = os.listdir("../reports/" + report_name + '/')
|
|
print("entries", entries)
|
|
self.client_disconnect(clear_all_sta=True, clean_l3_traffic=True)
|
|
logging.info("Test Completed... Cleaning up Stations")
|
|
kpi = "kpi.csv"
|
|
pass_value = pass_value
|
|
atn, deg = attenuations, [0, 60, 120, 180, 240, 300]
|
|
if kpi in entries:
|
|
kpi_val = self.read_kpi_file(column_name=["numeric-score"], dir_name=report_name)
|
|
print("kpi_calue :", kpi_val)
|
|
if str(kpi_val) == "empty":
|
|
logging.info("TEST FAILED, Throughput value from kpi.csv is empty.")
|
|
allure.attach(name="CSV Data", body="TEST FAILED, Throughput value from kpi.csv is empty.")
|
|
return False, "TEST FAILED, Throughput value from kpi.csv is empty."
|
|
else:
|
|
allure.attach(name="CSV Data", body="Throughput value : " + str(kpi_val))
|
|
start, thrpt_val, pass_fail = 0, {}, []
|
|
for i in pass_value:
|
|
count = 0
|
|
for j in range(start, len(kpi_val), len(atn)):
|
|
thrpt_val[f"{atn[start]}atn-{deg[count]}deg"] = kpi_val[j][0]
|
|
if kpi_val[j][0] >= pass_value[i]:
|
|
pass_fail.append("PASS")
|
|
else:
|
|
pass_fail.append("FAIL")
|
|
count += 1
|
|
# start += 6
|
|
print(thrpt_val, "\n", pass_fail)
|
|
if "FAIL" in pass_fail:
|
|
logging.info("TEST FAILED, Actual throughput is lesser than Expected.")
|
|
return False, "TEST FAILED, Actual throughput is lesser than Expected."
|
|
else:
|
|
logging.info("Test passed successfully")
|
|
return True, "TEST PASSED"
|
|
else:
|
|
logging.info("csv file does not exist, TEST FAILED.")
|
|
allure.attach(name="CSV Data", body="csv file does not exist")
|
|
return False, "TEST FAILED, , CSV file does not exist"
|
|
else:
|
|
logging.info("Test Failed, due to station has no ip")
|
|
return False, "TEST FAILED, due to station has no ip"
|
|
|
|
def rate_vs_range(self, ssid_name=None, security_key=None, security="wpa2", mode="BRIDGE", band="twog", vlan=1,
|
|
dut_data=None, num_sta=1, spatial_streams=2, direction="DUT Transmit", instance_name="",
|
|
pass_value=None, attenuations=None, create_vlan=True):
|
|
logging.info("Cleanup existing clients and traffic")
|
|
chamber_view_obj = self.chamber_view()
|
|
dut_name = list(dut_data.keys())[0]
|
|
logging.info("DUT name: " + str(dut_name))
|
|
self.client_disconnect(clean_l3_traffic=True)
|
|
# client connect
|
|
station = self.client_connect(ssid=ssid_name, security=security, passkey=security_key, mode=mode, band=band,
|
|
num_sta=num_sta, vlan_id=[vlan], dut_data=dut_data)
|
|
sta_name = list(station.keys())
|
|
ser_no = self.attenuator_serial()
|
|
print("ser no", ser_no)
|
|
atn2 = ser_no[1].split(".")[2]
|
|
print(f"antenuation-2 : {atn2}")
|
|
val = [['modes: Auto'], ['pkts: MTU'], ['directions: ' + str(direction)], ['traffic_types:TCP'],
|
|
['bandw_options: AUTO'], ['spatial_streams: 2'], ['attenuator: ' + str(ser_no[0])],
|
|
['attenuator2: 0'], ['attenuations: 0 60 120 180 240 300 360 390 410 430 450 470 490'],
|
|
['attenuations2: 0 60 120 180 240 300 360 390 410 430 450 470 490'],
|
|
['chamber: 0'], ['tt_deg: 0']]
|
|
if station:
|
|
# rvr test
|
|
rvr_o, report_name = self.rate_vs_range_test(station_name=sta_name[0], mode=mode, download_rate="100%",
|
|
duration='30000', instance_name=instance_name, vlan_id=[vlan],
|
|
dut_name=dut_name, raw_lines=val, create_vlan=create_vlan)
|
|
entries = os.listdir("../reports/" + report_name + '/')
|
|
print("entries", entries)
|
|
print("Test Completed... Cleaning up Stations")
|
|
self.client_disconnect(clear_all_sta=True, clean_l3_traffic=True)
|
|
kpi = "kpi.csv"
|
|
pass_value = pass_value
|
|
atn = attenuations
|
|
if kpi in entries:
|
|
kpi_val = self.read_kpi_file(column_name=["numeric-score"], dir_name=report_name)
|
|
print(kpi_val)
|
|
if str(kpi_val) == "empty":
|
|
logging.info("Throughput value from kpi.csv is empty, TEST FAILED, ")
|
|
allure.attach(name="CSV Data", body="Throughput value from kpi.csv is empty, TEST FAILED, ")
|
|
return False, "Throughput value from kpi.csv is empty, TEST FAILED, "
|
|
else:
|
|
allure.attach(name="CSV Data", body="Throughput value : " + str(kpi_val))
|
|
start, thrpt_val, pass_fail = 0, {}, []
|
|
for i in pass_value:
|
|
# count = 0
|
|
# direction = "DUT-TX"
|
|
for j in range(start, len(kpi_val), len(atn)):
|
|
thrpt_val[f"{atn[start]}"] = kpi_val[j][0]
|
|
if kpi_val[j][0] >= pass_value[i]:
|
|
pass_fail.append("PASS")
|
|
break
|
|
else:
|
|
pass_fail.append("FAIL")
|
|
break
|
|
# count += 1
|
|
# direction = "DUT-RX"
|
|
start += 6
|
|
print(pass_fail, "\nThroughput value-->", thrpt_val)
|
|
allure.attach(name="Throughput value", body=str(thrpt_val))
|
|
if "FAIL" in pass_fail:
|
|
logging.info("TEST FAILED, Actual throughput is lesser than Expected")
|
|
return False, "TEST FAILED, Actual throughput is lesser than Expected"
|
|
else:
|
|
logging.info("TEST PASSED successfully")
|
|
return True, "TEST PASSED"
|
|
else:
|
|
logging.info("csv file does not exist, TEST FAILED.")
|
|
allure.attach(name="CSV Data", body="csv file does not exist")
|
|
return False, "TEST FAILED, CSV file does not exist"
|
|
else:
|
|
logging.info("Test Failed, due to station has no ip")
|
|
return False, "TEST FAILED, due to station has no ip"
|
|
|
|
def client_isolation(self, ssid1=None, ssid2=None, passkey=None, security=None, mode="BRIDGE", band_2g=False,
|
|
band_5g=False, dut_data=None, num_sta=None, side_a_min_rate=None, side_a_max_rate=None,
|
|
side_b_min_rate=None, side_b_max_rate=None, sniff_radio=True):
|
|
copy_num_sta = num_sta
|
|
|
|
# selecting radio(s) based on the requested bands of the client(s)
|
|
dict_all_radios_2g = {"be200_radios": self.be200_radios,
|
|
"ax210_radios": self.ax210_radios, "ax200_radios": self.ax200_radios,
|
|
"mtk_radios": self.mtk_radios,
|
|
"wave2_2g_radios": self.wave2_2g_radios,
|
|
"wave1_radios": self.wave1_radios
|
|
}
|
|
dict_all_radios_5g = {"be200_radios": self.be200_radios,
|
|
"ax210_radios": self.ax210_radios, "ax200_radios": self.ax200_radios,
|
|
"mtk_radios": self.mtk_radios,
|
|
"wave2_5g_radios": self.wave2_5g_radios,
|
|
"wave1_radios": self.wave1_radios
|
|
}
|
|
max_station_per_radio = {"wave2_2g_radios": 64, "wave2_5g_radios": 64, "wave1_radios": 64, "mtk_radios": 19,
|
|
"ax200_radios": 1, "ax210_radios": 1, "be200_radios": 1}
|
|
radio_name_2g = []
|
|
radio_name_5g = []
|
|
if band_2g is True and band_5g is True: # a 2G and a 5G station
|
|
for type_of_radio in dict_all_radios_2g:
|
|
if len(dict_all_radios_2g[type_of_radio]) > 0:
|
|
radio_name_2g.append(dict_all_radios_2g[type_of_radio][0])
|
|
max_station_per_radio[type_of_radio] -= 1
|
|
break
|
|
for type_of_radio in dict_all_radios_5g:
|
|
if len(dict_all_radios_5g[type_of_radio]) > 0 and max_station_per_radio[type_of_radio] > 0:
|
|
radio_name_5g.append(dict_all_radios_5g[type_of_radio][0])
|
|
break
|
|
|
|
if len(radio_name_2g) == 0 or len(radio_name_5g) == 0:
|
|
logging.info("Looks like the langforge radios can't support creating a 2G and a 5G station, "
|
|
"simultaneously.")
|
|
pytest.skip("Looks like the langforge radios can't support creating a 2G and a 5G station, "
|
|
"simultaneously.")
|
|
|
|
station_name_2g = "sta_2g"
|
|
station_name_5g = "sta_5g"
|
|
|
|
band = ["twog", "fiveg"]
|
|
elif band_2g is True: # only 2g bands but num_sta can be 1 or 2
|
|
if self.max_2g_stations < num_sta:
|
|
logging.info(f"Looks like the langforge radios can't support creating {num_sta} 2G stations.")
|
|
raise ValueError(f"Looks like the langforge radios can't support creating {num_sta} 2G stations.")
|
|
band = "twog"
|
|
enough_radios = False
|
|
for type_of_radio in dict_all_radios_2g:
|
|
if len(dict_all_radios_2g[type_of_radio]) > 0:
|
|
for i in range(len(dict_all_radios_2g[type_of_radio])):
|
|
radio_name_2g.append(dict_all_radios_2g[type_of_radio][i])
|
|
if num_sta <= max_station_per_radio[type_of_radio]:
|
|
num_sta = 0
|
|
enough_radios = True
|
|
break
|
|
else:
|
|
num_sta -= max_station_per_radio[type_of_radio]
|
|
if enough_radios:
|
|
break
|
|
station_name = "sta_2g"
|
|
elif band_5g is True: # only 5g bands but num_sta can be 1 or 2
|
|
if self.max_5g_stations < num_sta:
|
|
logging.info(f"Looks like the langforge radios can't support creating {num_sta} 5G stations.")
|
|
raise ValueError(f"Looks like the langforge radios can't support creating {num_sta} 5G stations.")
|
|
band = "fiveg"
|
|
enough_radios = False
|
|
for type_of_radio in dict_all_radios_5g:
|
|
if len(dict_all_radios_5g[type_of_radio]) > 0:
|
|
for i in range(len(dict_all_radios_5g[type_of_radio])):
|
|
radio_name_5g.append(dict_all_radios_5g[type_of_radio][i])
|
|
if num_sta <= max_station_per_radio[type_of_radio]:
|
|
num_sta = 0
|
|
enough_radios = True
|
|
break
|
|
else:
|
|
num_sta -= max_station_per_radio[type_of_radio]
|
|
if enough_radios:
|
|
break
|
|
station_name = "sta_5g"
|
|
|
|
logging.info("Clearing any existing stations and Layer-3 traffics before starting the test...")
|
|
self.pre_cleanup() # clear any existing stations and traffic
|
|
|
|
sta = []
|
|
num_sta = copy_num_sta
|
|
sta_got_ip = []
|
|
if num_sta > 1: # between 2 stations
|
|
if band_2g is True and band_5g is True: # a 2G and a 5G station
|
|
sta_got_ip.append(self.client_connect_using_radio(ssid=ssid1, passkey=passkey, security=security,
|
|
mode=mode, band="twog", radio=radio_name_2g[0],
|
|
station_name=[station_name_2g], dut_data=dut_data,
|
|
sniff_radio=sniff_radio, attach_port_info=False,
|
|
attach_station_data=False))
|
|
sta_got_ip.append(self.client_connect_using_radio(ssid=ssid2, passkey=passkey, security=security,
|
|
mode=mode, band="fiveg", radio=radio_name_5g[0],
|
|
station_name=[station_name_5g], dut_data=dut_data,
|
|
sniff_radio=sniff_radio, attach_port_info=False,
|
|
attach_station_data=False))
|
|
|
|
self.create_layer3(side_a_min_rate=side_a_min_rate, side_a_max_rate=side_a_max_rate,
|
|
side_b_min_rate=side_b_min_rate, side_b_max_rate=side_b_max_rate,
|
|
traffic_type="lf_udp", sta_list=[station_name_2g], side_b=station_name_5g)
|
|
else: # else both are either 2G or 5G stations
|
|
ssids = [ssid1, ssid2]
|
|
radio_name = radio_name_2g + radio_name_5g
|
|
if len(radio_name) == 1:
|
|
radio_name.append(radio_name[0])
|
|
for i in range(2):
|
|
sta.append(station_name + "_" + str(i + 1))
|
|
sta_got_ip.append(self.client_connect_using_radio(ssid=ssids[i], passkey=passkey, band=band,
|
|
security=security, mode=mode, radio=radio_name[i],
|
|
station_name=[sta[i]], dut_data=dut_data,
|
|
sniff_radio=sniff_radio, attach_port_info=False,
|
|
attach_station_data=False))
|
|
self.create_layer3(side_a_min_rate=side_a_min_rate, side_a_max_rate=side_a_max_rate,
|
|
side_b_min_rate=side_b_min_rate, side_b_max_rate=side_b_max_rate,
|
|
traffic_type="lf_udp", sta_list=[sta[0]], side_b=sta[1])
|
|
elif num_sta == 1: # else between a 2G/5G station and uplink port
|
|
radio_name = radio_name_2g if band_2g is True else radio_name_5g
|
|
sta_got_ip.append(self.client_connect_using_radio(ssid=ssid1, passkey=passkey, band=band, security=security,
|
|
mode=mode, radio=radio_name[0],
|
|
station_name=[station_name],
|
|
dut_data=dut_data, sniff_radio=sniff_radio,
|
|
attach_port_info=False, attach_station_data=False))
|
|
self.create_layer3(side_a_min_rate=side_a_min_rate, side_a_max_rate=side_a_max_rate,
|
|
side_b_min_rate=side_b_min_rate, side_b_max_rate=side_b_max_rate,
|
|
traffic_type="lf_udp", sta_list=[station_name], side_b="")
|
|
|
|
if False in sta_got_ip:
|
|
self.pre_cleanup()
|
|
logging.info("TEST FAILED, due to station has no ip")
|
|
return False, "TEST FAILED, due to station has no ip"
|
|
|
|
logging.info("Running Traffic for 60 seconds...")
|
|
time.sleep(60)
|
|
|
|
logging.info("Getting Layer-3 and Endpoints Data...")
|
|
cx_list = self.get_cx_list()
|
|
rx_data = self.json_get(_req_url=f"cx/{cx_list[0]}")
|
|
|
|
rx_drop_a = rx_data[cx_list[0]]["rx drop % a"]
|
|
rx_drop_b = rx_data[cx_list[0]]["rx drop % b"]
|
|
|
|
sta = []
|
|
for u in self.json_get("/port/?fields=port+type,alias,ssid")['interfaces']:
|
|
if (list(u.values())[0]['port type'] in ['WIFI-STA']
|
|
and list(u.values())[0]['ssid'] in [ssid1, ssid2]):
|
|
sta.append(list(u.keys())[0])
|
|
|
|
if len(sta) == 1:
|
|
sta.append(list(self.get_wan_upstream_ports().values())[0])
|
|
|
|
sta_rows = ["ssid", "ip", "mode", "channel", "signal", "mac", "parent dev"]
|
|
sta_dict = self.get_station_data(sta_name=sta, rows=sta_rows, allure_attach=False)
|
|
station_table_dict = {"station name": list(sta_dict.keys()),
|
|
"Min/Max Tx rate": [f"{side_a_min_rate} bytes", f"{side_b_min_rate} bytes"],
|
|
"rx drop %": [rx_drop_a, rx_drop_b]}
|
|
for col in sta_rows:
|
|
temp_list = []
|
|
for port in sta:
|
|
temp_list.append(sta_dict[port][col])
|
|
station_table_dict[col] = temp_list
|
|
|
|
logging.info("Attaching to the allure report...")
|
|
self.attach_table_allure(data=station_table_dict, allure_name="Endpoints Data")
|
|
self.allure_report_table_format(dict_data=rx_data[cx_list[0]], key="Layer-3 Column", value="Value",
|
|
name="Layer-3 Data")
|
|
|
|
logging.info("Traffic ran, Clearing stations and Layer-3 traffic...")
|
|
self.pre_cleanup()
|
|
|
|
return True, {"drop_a": rx_drop_a, "drop_b": rx_drop_b}
|
|
|
|
def ax_capacity_test(self, instance_name="", dut_data=None, mode="BRIDGE", download_rate="10Gbps",
|
|
upload_rate="0Gbps", dut_mode="", protocol="UDP-IPv4", num_stations={}, vlan_id=None):
|
|
if self.max_ax_stations == 0:
|
|
logging.info("This test needs AX radios, looks like no AX radios are available on the Lanforge system.")
|
|
pytest.skip("AX radios are not available on the Lanforge, so skipping this test.")
|
|
|
|
if dut_mode.lower() == "wifi5":
|
|
logging.info("AP does not support AX mode, so skipping this test.")
|
|
pytest.skip("AP does not support AX mode, so skipping this test")
|
|
|
|
dict_all_radios_ax = {"be200_radios": self.be200_radios,
|
|
"ax210_radios": self.ax210_radios,
|
|
"ax200_radios": self.ax200_radios,
|
|
"mtk_radios": self.mtk_radios,
|
|
}
|
|
selected_ax_radio = None
|
|
for radio in dict_all_radios_ax:
|
|
if len(dict_all_radios_ax[radio]) > 0:
|
|
selected_ax_radio = dict_all_radios_ax[radio][0]
|
|
break
|
|
logging.info("Selected AX Radio: {}".format(selected_ax_radio))
|
|
|
|
for data in self.dut_data:
|
|
identifier = data["identifier"]
|
|
ssid_name = dut_data[identifier]["ssid_data"][0]["ssid"]
|
|
passkey = dut_data[identifier]["ssid_data"][0]["password"]
|
|
band = list(num_stations.keys())[0]
|
|
|
|
try:
|
|
self.set_radio_channel(radio=selected_ax_radio, antenna="AUTO")
|
|
values = selected_ax_radio.split(".")
|
|
shelf = int(values[0])
|
|
resource = int(values[1])
|
|
self.pre_cleanup()
|
|
sta_name = [f"{shelf}.{resource}.ax_station"]
|
|
logging.info("sta_name:- " + str(sta_name))
|
|
sta_ip = self.client_connect_using_radio(ssid=ssid_name, passkey=passkey, mode=mode, station_name=sta_name,
|
|
radio=selected_ax_radio, vlan_id=vlan_id, create_vlan=True)
|
|
time.sleep(0.5)
|
|
|
|
sta_rows = ["ip", "mode", "channel", "signal", "parent dev", "mac"]
|
|
station_data = self.get_station_data(sta_name=sta_name, rows=sta_rows, allure_attach=True,
|
|
allure_name="Station Data")
|
|
logging.info("station_data:- " + str(station_data))
|
|
if not sta_ip:
|
|
logging.info("Test Failed, due to station has no ip")
|
|
pytest.fail("Station did not get an ip")
|
|
|
|
sta_mode = station_data[sta_name[0]]["mode"]
|
|
logging.info("sta_mode:- " + str(sta_mode))
|
|
wifi_capacity_obj_list = self.wifi_capacity(instance_name=instance_name, mode=mode,
|
|
download_rate=download_rate, upload_rate=upload_rate,
|
|
protocol=protocol, duration="60000", ssid_name=ssid_name,
|
|
batch_size="1", num_stations=num_stations, stations=sta_name[0],
|
|
dut_data=dut_data, vlan_id=vlan_id, add_stations=False,
|
|
create_vlan=False)
|
|
|
|
report = wifi_capacity_obj_list[0].report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1] + "/"
|
|
numeric_score = self.read_kpi_file(column_name=["numeric-score"], dir_name=report)
|
|
current_directory = os.getcwd()
|
|
file_path = current_directory + "/e2e/basic/performance_tests/performance_pass_fail.json"
|
|
logging.info("performance_pass file config path:- " + str(file_path))
|
|
with open(file_path, 'r') as file:
|
|
json_string = file.read()
|
|
all_pass_fail_data = json.loads(json_string)
|
|
logging.info("All Testbed pass fail data:- " + str(all_pass_fail_data))
|
|
# validate config json data
|
|
try:
|
|
json_object = json.dumps(all_pass_fail_data)
|
|
except ValueError as e:
|
|
logging.info("Performance Pass/Fail data is invalid")
|
|
pytest.fail("Performance Pass/Fail data is invalid")
|
|
logging.info("DUT Data: " + str(self.dut_data))
|
|
model = self.dut_data[0]["model"]
|
|
if model in all_pass_fail_data["AP Models"]:
|
|
pass_fail_values = all_pass_fail_data["AP Models"][model]
|
|
else:
|
|
logging.error("AP model is not available in performance_pass_fail.json file")
|
|
logging.info(str(model) + " All Benchmark throughput:- " + str(pass_fail_values))
|
|
split_mode = sta_mode.split(" ")
|
|
key = f"{band} {split_mode[2]} {split_mode[1]}MHz"
|
|
logging.info("key:- " + str(key))
|
|
proto = None
|
|
if "TCP" in protocol:
|
|
proto = "TCP"
|
|
else:
|
|
proto = "UDP"
|
|
logging.info("Proto:- " + str(proto))
|
|
logging.info("Given LF download_rate:- " + str(download_rate))
|
|
logging.info("Given LF upload_rate:- " + str(upload_rate))
|
|
pass_fail_value = None
|
|
if "BE" in sta_mode:
|
|
logging.info("In BE pass fail")
|
|
pass_fail_value = pass_fail_values["BE"][key][proto]
|
|
elif "AX" in sta_mode:
|
|
logging.info("In AX pass fail")
|
|
pass_fail_value = pass_fail_values["AX"][key][proto]
|
|
logging.info("pass_fail value:- " + str(pass_fail_value))
|
|
download_rate = self.convert_to_gbps(download_rate)
|
|
logging.info("download_rate:- " + str(download_rate))
|
|
upload_rate = self.convert_to_gbps(upload_rate)
|
|
logging.info("upload_rate:- " + str(upload_rate))
|
|
# Pass fail logic for Upload. validating download rate because providing some value during Upload
|
|
if upload_rate > download_rate:
|
|
logging.info("Benchmark throughput:- " + str(pass_fail_value) + "+")
|
|
allure.attach(name="Benchmark throughput: ",
|
|
body=str(pass_fail_value) + "+ Mbps")
|
|
actual_tht = int(numeric_score[1][0])
|
|
logging.info("Actual throughput:- " + str(actual_tht))
|
|
allure.attach(name="Actual throughput: ",
|
|
body=str(actual_tht) + " Mbps")
|
|
if actual_tht < pass_fail_value:
|
|
pytest.fail(
|
|
f"Benchmark throughput:- {pass_fail_value}+ Mbps, Actual throughput:- {actual_tht} Mbps")
|
|
elif upload_rate < download_rate:
|
|
# Pass fail logic for Download. validating upload rate because providing some value during download
|
|
logging.info("Benchmark throughput:- " + str(pass_fail_value) + "+")
|
|
allure.attach(name="Benchmark throughput: ",
|
|
body=str(pass_fail_value) + "+ Mbps")
|
|
actual_tht = int(numeric_score[0][0])
|
|
logging.info("Actual throughput:- " + str(actual_tht))
|
|
allure.attach(name="Actual throughput: ",
|
|
body=str(actual_tht) + " Mbps")
|
|
if actual_tht < pass_fail_value:
|
|
pytest.fail(
|
|
f"Benchmark throughput:- {pass_fail_value}+ Mbps, Actual throughput:- {actual_tht} Mbps")
|
|
elif upload_rate == download_rate:
|
|
# Pass fail logic for bidirectional
|
|
pass_fail_value = pass_fail_value * 2
|
|
logging.info("Benchmark throughput:- " + str(pass_fail_value) + "+")
|
|
allure.attach(name="Benchmark throughput: ",
|
|
body=str(pass_fail_value) + "+ Mbps")
|
|
actual_tht = int(numeric_score[2][0])
|
|
logging.info("Actual throughput:- " + str(actual_tht))
|
|
allure.attach(name="Actual throughput: ",
|
|
body=str(actual_tht) + " Mbps")
|
|
if actual_tht < pass_fail_value:
|
|
pytest.fail(
|
|
f"Benchmark throughput:- {pass_fail_value}+ Mbps, Actual throughput:- {actual_tht} Mbps")
|
|
|
|
finally:
|
|
self.set_radio_channel(radio=selected_ax_radio, antenna="0")
|
|
|
|
def be_capacity_test(self, instance_name="", dut_data=None, mode="BRIDGE", download_rate="10Gbps",
|
|
upload_rate="0Gbps", dut_mode="", protocol="UDP-IPv4", num_stations={}, vlan_id=None):
|
|
if self.max_be_stations == 0:
|
|
logging.info("This test needs BE radios, looks like no BE radios are available on the Lanforge system.")
|
|
pytest.skip("BE radios are not available on the Lanforge, so skipping this test.")
|
|
|
|
if dut_mode.lower() == "wifi6":
|
|
logging.info("AP does not support BE mode, so skipping this test.")
|
|
pytest.skip("AP does not support BE mode, so skipping this test")
|
|
|
|
dict_all_radios_be = {"be200_radios": self.be200_radios}
|
|
selected_be_radio = None
|
|
for radio in dict_all_radios_be:
|
|
if len(dict_all_radios_be[radio]) > 0:
|
|
selected_be_radio = dict_all_radios_be[radio][0]
|
|
break
|
|
logging.info("Selected BE Radio: {}".format(selected_be_radio))
|
|
|
|
for data in self.dut_data:
|
|
identifier = data["identifier"]
|
|
ssid_name = dut_data[identifier]["ssid_data"][0]["ssid"]
|
|
passkey = dut_data[identifier]["ssid_data"][0]["password"]
|
|
band = list(num_stations.keys())[0]
|
|
|
|
try:
|
|
self.set_radio_channel(radio=selected_be_radio, antenna="AUTO")
|
|
values = selected_be_radio.split(".")
|
|
shelf = int(values[0])
|
|
resource = int(values[1])
|
|
self.pre_cleanup()
|
|
sta_name = [f"{shelf}.{resource}.be_station"]
|
|
logging.info("sta_name:- " + str(sta_name))
|
|
sta_ip = self.client_connect_using_radio(ssid=ssid_name, passkey=passkey, mode=mode, station_name=sta_name,
|
|
radio=selected_be_radio, vlan_id=vlan_id, create_vlan=True)
|
|
time.sleep(0.5)
|
|
|
|
sta_rows = ["ip", "mode", "channel", "signal", "parent dev", "mac"]
|
|
station_data = self.get_station_data(sta_name=sta_name, rows=sta_rows, allure_attach=True,
|
|
allure_name="Station Data")
|
|
logging.info("station_data:- " + str(station_data))
|
|
if not sta_ip:
|
|
logging.info("Test Failed, due to station has no ip")
|
|
pytest.fail("Station did not get an ip")
|
|
|
|
sta_mode = station_data[sta_name[0]]["mode"]
|
|
logging.info("sta_mode:- " + str(sta_mode))
|
|
wifi_capacity_obj_list = self.wifi_capacity(instance_name=instance_name, mode=mode,
|
|
download_rate=download_rate, upload_rate=upload_rate,
|
|
protocol=protocol, duration="60000", ssid_name=ssid_name,
|
|
batch_size="1", num_stations=num_stations, stations=sta_name[0],
|
|
dut_data=dut_data, vlan_id=vlan_id, add_stations=False,
|
|
create_vlan=False)
|
|
|
|
report = wifi_capacity_obj_list[0].report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1] + "/"
|
|
numeric_score = self.read_kpi_file(column_name=["numeric-score"], dir_name=report)
|
|
current_directory = os.getcwd()
|
|
file_path = current_directory + "/e2e/basic/performance_tests/performance_pass_fail.json"
|
|
logging.info("performance_pass file config path:- " + str(file_path))
|
|
with open(file_path, 'r') as file:
|
|
json_string = file.read()
|
|
all_pass_fail_data = json.loads(json_string)
|
|
logging.info("All Testbed pass fail data:- " + str(all_pass_fail_data))
|
|
# validate config json data
|
|
try:
|
|
json_object = json.dumps(all_pass_fail_data)
|
|
except ValueError as e:
|
|
logging.info("Performance Pass/Fail data is invalid")
|
|
pytest.fail("Performance Pass/Fail data is invalid")
|
|
logging.info("DUT Data: " + str(self.dut_data))
|
|
model = self.dut_data[0]["model"]
|
|
if model in all_pass_fail_data["AP Models"]:
|
|
pass_fail_values = all_pass_fail_data["AP Models"][model]
|
|
else:
|
|
logging.error("AP model is not available in performance_pass_fail.json file")
|
|
logging.info(str(model) + " All Benchmark throughput:- " + str(pass_fail_values))
|
|
split_mode = sta_mode.split(" ")
|
|
key = f"{band} {split_mode[2]} {split_mode[1]}MHz"
|
|
logging.info("key:- " + str(key))
|
|
proto = None
|
|
if "TCP" in protocol:
|
|
proto = "TCP"
|
|
else:
|
|
proto = "UDP"
|
|
logging.info("Proto:- " + str(proto))
|
|
logging.info("Given LF download_rate:- " + str(download_rate))
|
|
logging.info("Given LF upload_rate:- " + str(upload_rate))
|
|
pass_fail_value = None
|
|
if "BE" in sta_mode:
|
|
logging.info("In BE pass fail")
|
|
pass_fail_value = pass_fail_values["BE"][key][proto]
|
|
elif "AX" in sta_mode:
|
|
logging.info("In AX pass fail")
|
|
pass_fail_value = pass_fail_values["AX"][key][proto]
|
|
logging.info("pass_fail value:- " + str(pass_fail_value))
|
|
download_rate = self.convert_to_gbps(download_rate)
|
|
logging.info("download_rate:- " + str(download_rate))
|
|
upload_rate = self.convert_to_gbps(upload_rate)
|
|
logging.info("upload_rate:- " + str(upload_rate))
|
|
# Pass fail logic for Upload. validating download rate because providing some value during Upload
|
|
if upload_rate > download_rate:
|
|
logging.info("Benchmark throughput:- " + str(pass_fail_value) + "+")
|
|
allure.attach(name="Benchmark throughput: ",
|
|
body=str(pass_fail_value) + "+ Mbps")
|
|
actual_tht = int(numeric_score[1][0])
|
|
logging.info("Actual throughput:- " + str(actual_tht))
|
|
allure.attach(name="Actual throughput: ",
|
|
body=str(actual_tht) + " Mbps")
|
|
if actual_tht < pass_fail_value:
|
|
pytest.fail(
|
|
f"Benchmark throughput:- {pass_fail_value}+ Mbps, Actual throughput:- {actual_tht} Mbps")
|
|
elif upload_rate < download_rate:
|
|
# Pass fail logic for Download. validating upload rate because providing some value during download
|
|
logging.info("Benchmark throughput:- " + str(pass_fail_value) + "+")
|
|
allure.attach(name="Benchmark throughput: ",
|
|
body=str(pass_fail_value) + "+ Mbps")
|
|
actual_tht = int(numeric_score[0][0])
|
|
logging.info("Actual throughput:- " + str(actual_tht))
|
|
allure.attach(name="Actual throughput: ",
|
|
body=str(actual_tht) + " Mbps")
|
|
if actual_tht < pass_fail_value:
|
|
pytest.fail(
|
|
f"Benchmark throughput:- {pass_fail_value}+ Mbps, Actual throughput:- {actual_tht} Mbps")
|
|
elif upload_rate == download_rate:
|
|
# Pass fail logic for bidirectional
|
|
pass_fail_value = pass_fail_value * 2
|
|
logging.info("Benchmark throughput:- " + str(pass_fail_value) + "+")
|
|
allure.attach(name="Benchmark throughput: ",
|
|
body=str(pass_fail_value) + "+ Mbps")
|
|
actual_tht = int(numeric_score[2][0])
|
|
logging.info("Actual throughput:- " + str(actual_tht))
|
|
allure.attach(name="Actual throughput: ",
|
|
body=str(actual_tht) + " Mbps")
|
|
if actual_tht < pass_fail_value:
|
|
pytest.fail(
|
|
f"Benchmark throughput:- {pass_fail_value}+ Mbps, Actual throughput:- {actual_tht} Mbps")
|
|
|
|
finally:
|
|
self.set_radio_channel(radio=selected_be_radio, antenna="0")
|
|
|
|
def multi_ssid_test(self, setup_params_general: dict, no_of_2g_and_5g_stations: int = 2, mode: str = "BRIDGE",
|
|
security_key: str = "something", security: str = "wpa2") -> None:
|
|
sta_names_2g, sta_names_5g = [], []
|
|
for i in range(no_of_2g_and_5g_stations):
|
|
sta_names_2g.append(f"sta_2g_{i + 1}")
|
|
sta_names_5g.append(f"sta_5g_{i + 1}")
|
|
|
|
cx_sta_list = [sta_names_2g[-2], sta_names_2g[-1], sta_names_5g[-2], sta_names_5g[-1]]
|
|
|
|
radio_dict_2g, radio_dict_5g = self.get_radio_availabilities(num_stations_2g=len(sta_names_2g),
|
|
num_stations_5g=len(sta_names_5g))
|
|
logging.info(f"Radio-2G-Stations dict : {radio_dict_2g}")
|
|
logging.info(f"Radio-5G-Stations dict : {radio_dict_5g}")
|
|
|
|
security_mode = 'wpa2_personal'
|
|
for security_mode_ in setup_params_general["ssid_modes"]:
|
|
security_mode = security_mode_
|
|
|
|
sta_got_ip = []
|
|
allure.attach(name="ssid info", body=str(setup_params_general["ssid_modes"][security_mode]))
|
|
|
|
self.pre_cleanup()
|
|
no_of_ssids = len(setup_params_general["ssid_modes"][security_mode])
|
|
logging.info(f"A total of {no_of_2g_and_5g_stations} 2G and {no_of_2g_and_5g_stations} 5G stations will be "
|
|
f"created for {no_of_ssids} SSIDs, i.e., a 2G and a 5G stations on each SSID.")
|
|
|
|
for i in range(no_of_2g_and_5g_stations):
|
|
ssid_name = setup_params_general["ssid_modes"][security_mode][i % no_of_ssids]["ssid_name"]
|
|
logging.info(f"Creating a 2G station on {ssid_name} ssid...")
|
|
radio = None
|
|
for _radio in radio_dict_2g:
|
|
radio = _radio
|
|
if radio_dict_2g[radio] == 1:
|
|
del radio_dict_2g[radio]
|
|
else:
|
|
radio_dict_2g[radio] -= 1
|
|
break
|
|
sta_got_ip.append(self.client_connect_using_radio(ssid=ssid_name, security=security,
|
|
passkey=security_key, mode=mode,
|
|
radio=radio,
|
|
station_name=[sta_names_2g[i]],
|
|
attach_station_data=False,
|
|
attach_port_info=False))
|
|
logging.info(f"Creating a 5G station on {ssid_name} ssid...")
|
|
for _radio in radio_dict_5g:
|
|
radio = _radio
|
|
if radio_dict_5g[radio] == 1:
|
|
del radio_dict_5g[radio]
|
|
else:
|
|
radio_dict_5g[radio] -= 1
|
|
break
|
|
sta_got_ip.append(self.client_connect_using_radio(ssid=ssid_name, security=security,
|
|
passkey=security_key, mode=mode,
|
|
radio=radio,
|
|
station_name=[sta_names_5g[i]],
|
|
attach_station_data=False,
|
|
attach_port_info=False))
|
|
|
|
port_data = self.json_get(_req_url="port?fields=ip")
|
|
port_info = {key: value for d in port_data["interfaces"] for key, value in d.items()}
|
|
self.allure_report_table_format(dict_data=port_info, key="Port Names", value="ip",
|
|
name="Port info after creating all stations")
|
|
|
|
dict_table_2g_1st = {}
|
|
dict_table_2g_2nd = {}
|
|
dict_table_5g_1st = {}
|
|
dict_table_5g_2nd = {}
|
|
for sta in sta_names_2g + sta_names_5g:
|
|
result = self.json_get(_req_url="port/1/1/%s" % sta)
|
|
if "Key" not in dict_table_2g_1st:
|
|
dict_table_2g_1st["Key"] = list(result["interface"].keys())
|
|
dict_table_2g_2nd["Key"] = list(result["interface"].keys())
|
|
dict_table_5g_1st["Key"] = list(result["interface"].keys())
|
|
dict_table_5g_2nd["Key"] = list(result["interface"].keys())
|
|
if '_2g_' in sta:
|
|
if len(dict_table_2g_1st) < 5:
|
|
dict_table_2g_1st[f"Value ({sta})"] = list(result["interface"].values())
|
|
else:
|
|
dict_table_2g_2nd[f"Value ({sta})"] = list(result["interface"].values())
|
|
else:
|
|
if len(dict_table_5g_1st) < 5:
|
|
dict_table_5g_1st[f"Value ({sta})"] = list(result["interface"].values())
|
|
else:
|
|
dict_table_5g_2nd[f"Value ({sta})"] = list(result["interface"].values())
|
|
|
|
data_table_2g_1st = tabulate(dict_table_2g_1st, headers='keys', tablefmt='fancy_grid')
|
|
data_table_2g_2nd = tabulate(dict_table_2g_2nd, headers='keys', tablefmt='fancy_grid')
|
|
data_table_5g_1st = tabulate(dict_table_5g_1st, headers='keys', tablefmt='fancy_grid')
|
|
data_table_5g_2nd = tabulate(dict_table_5g_2nd, headers='keys', tablefmt='fancy_grid')
|
|
|
|
logging.info(f"2G Stations Data (1-{min(4, no_of_2g_and_5g_stations)}): \n{data_table_2g_1st}\n")
|
|
allure.attach(name=f"2G Stations Data (1-{min(4, no_of_2g_and_5g_stations)})", body=str(data_table_2g_1st))
|
|
if no_of_2g_and_5g_stations > 4:
|
|
logging.info(f"2G Stations Data (5-{no_of_2g_and_5g_stations}): \n{data_table_2g_2nd}\n")
|
|
allure.attach(name=f"2G Stations Data (5-{no_of_2g_and_5g_stations})", body=str(data_table_2g_2nd))
|
|
|
|
logging.info(f"5G Stations Data (1-{min(4, no_of_2g_and_5g_stations)}): \n{data_table_5g_1st}\n")
|
|
allure.attach(name=f"5G Stations Data (1-{min(4, no_of_2g_and_5g_stations)})", body=str(data_table_5g_1st))
|
|
if no_of_2g_and_5g_stations > 4:
|
|
logging.info(f"5G Stations Data (5-{no_of_2g_and_5g_stations}): \n{data_table_5g_2nd}\n")
|
|
allure.attach(name=f"5G Stations Data (5-{no_of_2g_and_5g_stations})", body=str(data_table_5g_2nd))
|
|
|
|
if False in sta_got_ip:
|
|
logging.info("Some/All Stations didn't get IP address")
|
|
pytest.fail("Some/All Stations didn't get IP address")
|
|
logging.info("All 2G/5G Stations got IP address")
|
|
|
|
# create Layer 3 and check data path
|
|
for i in range(3):
|
|
self.create_layer3(side_a_min_rate=6291456, side_a_max_rate=0,
|
|
side_b_min_rate=6291456, side_b_max_rate=0,
|
|
traffic_type="lf_tcp", sta_list=[cx_sta_list[i]],
|
|
side_b=cx_sta_list[i + 1], start_cx=True,
|
|
prefix=f"{cx_sta_list[i][4:]}-{cx_sta_list[i + 1][4:]}:t")
|
|
logging.info(f"CX with TCP traffic created between "
|
|
f"endpoint-a = {cx_sta_list[i]} and endpoint-b = {cx_sta_list[i + 1]}.")
|
|
time.sleep(2)
|
|
self.create_layer3(side_a_min_rate=6291456, side_a_max_rate=0,
|
|
side_b_min_rate=6291456, side_b_max_rate=0,
|
|
traffic_type="lf_udp", sta_list=[cx_sta_list[i]],
|
|
side_b=cx_sta_list[i + 1], start_cx=True,
|
|
prefix=f"{cx_sta_list[i][4:]}-{cx_sta_list[i + 1][4:]}:u")
|
|
logging.info(f"CX with UDP traffic created between "
|
|
f"endpoint-a = {cx_sta_list[i]} and endpoint-b = {cx_sta_list[i + 1]}.")
|
|
time.sleep(2)
|
|
|
|
logging.info("Running Layer3 traffic for 40 sec ...")
|
|
time.sleep(40)
|
|
|
|
cx_list = self.get_cx_list()
|
|
dict_table_cx_tcp = {}
|
|
dict_table_cx_udp = {}
|
|
pass_fail_data = []
|
|
for i in range(len(cx_list)):
|
|
cx_data = self.json_get(_req_url=f"cx/{cx_list[i]}")
|
|
cx_name = f"sta_{cx_list[i].split(':')[0].split('-')[0]} <==> sta_{cx_list[i].split(':')[0].split('-')[1]}"
|
|
|
|
if "L3 CX Column" not in dict_table_cx_tcp:
|
|
dict_table_cx_tcp["L3 CX Column"] = list(cx_data[f"{cx_list[i]}"].keys())
|
|
dict_table_cx_udp["L3 CX Column"] = list(cx_data[f"{cx_list[i]}"].keys())
|
|
if "TCP" in cx_data[f"{cx_list[i]}"]['type']:
|
|
dict_table_cx_tcp[f"values ({cx_name})"] = list(cx_data[f"{cx_list[i]}"].values())
|
|
else:
|
|
dict_table_cx_udp[f"values ({cx_name})"] = list(cx_data[f"{cx_list[i]}"].values())
|
|
|
|
if cx_data[cx_list[i]]['bps rx a'] != 0 and cx_data[cx_list[i]]['bps rx a'] != 0:
|
|
res = True
|
|
else:
|
|
res = False
|
|
pass_fail_data.append(
|
|
[f"{cx_list[i]}", f"{cx_data[cx_list[i]]['bps rx a']}", f"{cx_data[cx_list[i]]['bps rx b']}", res])
|
|
|
|
# attach l3 cx data to allure
|
|
data_table_cx_tcp = tabulate(dict_table_cx_tcp, headers='keys', tablefmt='fancy_grid')
|
|
data_table_cx_udp = tabulate(dict_table_cx_udp, headers='keys', tablefmt='fancy_grid')
|
|
logging.info(f"L3 cross-connects Data (TCP): \n{data_table_cx_tcp}\n")
|
|
logging.info(f"L3 cross-connects Data (UDP): \n{data_table_cx_udp}\n")
|
|
allure.attach(name="L3 cross-connects Data (TCP)", body=str(data_table_cx_tcp))
|
|
allure.attach(name="L3 cross-connects Data (UDP)", body=str(data_table_cx_udp))
|
|
|
|
# attach pass fail data to allure
|
|
result_table = tabulate(pass_fail_data,
|
|
headers=["Data Path", "Tx Rate (bps)", "Rx Rate (bps)", "Pass/Fail"],
|
|
tablefmt='fancy_grid')
|
|
logging.info(f"Test Result Table: \n{result_table}\n")
|
|
allure.attach(name="Test Result Table", body=str(result_table))
|
|
|
|
# cleanup Layer3 data
|
|
self.client_disconnect(station_name=sta_names_2g + sta_names_5g, clean_l3_traffic=True, clear_all_sta=True)
|
|
|
|
test_result = True
|
|
for pf in pass_fail_data:
|
|
if pf[3] is False:
|
|
test_result = False
|
|
|
|
if not test_result:
|
|
pytest.fail("DataPath check failed, Traffic didn't reported on some endpoints")
|
|
|
|
def max_ssid(self, setup_params_general: dict, mode: str = 'BRIDGE', vlan_id: list = None) -> None:
|
|
self.pre_cleanup()
|
|
|
|
ssid_2g_list = []
|
|
ssid_5g_list = []
|
|
for security, ssids in setup_params_general["ssid_modes"].items():
|
|
for ssid in ssids:
|
|
ssid_dict = {
|
|
'ssid_name': ssid["ssid_name"],
|
|
'security': security.split("_")[0],
|
|
'password': ssid.get("security_key", "[BLANK]"),
|
|
}
|
|
if "2G" in ssid["appliedRadios"]:
|
|
ssid_2g_list.append(ssid_dict)
|
|
elif "5G" in ssid["appliedRadios"]:
|
|
ssid_5g_list.append(ssid_dict)
|
|
|
|
no_of_sta_2g = len(ssid_2g_list)
|
|
no_of_sta_5g = len(ssid_5g_list)
|
|
sta_names_2g = [f"sta_2g_{i + 1}" for i in range(no_of_sta_2g)]
|
|
sta_names_5g = [f"sta_5g_{i + 1}" for i in range(no_of_sta_5g)]
|
|
|
|
radio_dict_2g, radio_dict_5g = self.get_radio_availabilities(num_stations_2g=no_of_sta_2g,
|
|
num_stations_5g=no_of_sta_5g)
|
|
if len(radio_dict_2g) > 0:
|
|
logging.info(f"Radio-Stations dict : {radio_dict_2g}")
|
|
if len(radio_dict_5g) > 0:
|
|
logging.info(f"Radio-Stations dict : {radio_dict_5g}")
|
|
|
|
if no_of_sta_2g > 0:
|
|
logging.info(f"A total of {no_of_sta_2g} 2G stations will be created for {no_of_sta_2g} SSIDs, "
|
|
f"i.e., one 2G stations on each SSID.")
|
|
if no_of_sta_5g > 0:
|
|
logging.info(f"A total of {no_of_sta_5g} 5G stations will be created for {no_of_sta_5g} SSIDs, "
|
|
f"i.e., one 5G stations on each SSID.")
|
|
|
|
upstream_port = ""
|
|
if mode == 'VLAN':
|
|
self.add_vlan(vlan_ids=vlan_id, build=True)
|
|
up = self.get_wan_upstream_ports()
|
|
upstream = list(up.values())
|
|
upstream_port = upstream[0] + "." + str(vlan_id[0])
|
|
|
|
radio = None
|
|
timeout_sec = 1
|
|
for i in range(no_of_sta_2g):
|
|
logging.info(f"Creating a 2G station on {ssid_2g_list[i]['ssid_name']} ssid...")
|
|
for _radio in radio_dict_2g:
|
|
radio = _radio
|
|
if radio_dict_2g[radio] == 1:
|
|
del radio_dict_2g[radio]
|
|
else:
|
|
radio_dict_2g[radio] -= 1
|
|
break
|
|
self.client_connect_using_radio(ssid=ssid_2g_list[i]['ssid_name'],
|
|
security=ssid_2g_list[i]['security'],
|
|
passkey=ssid_2g_list[i]['password'],
|
|
mode=mode,
|
|
radio=radio,
|
|
station_name=[sta_names_2g[i]],
|
|
attach_station_data=False,
|
|
attach_port_info=False,
|
|
timeout_sec=timeout_sec,
|
|
vlan_id=vlan_id,
|
|
create_vlan=False)
|
|
for i in range(no_of_sta_5g):
|
|
logging.info(f"Creating a 5G station on {ssid_5g_list[i]['ssid_name']} ssid...")
|
|
for _radio in radio_dict_5g:
|
|
radio = _radio
|
|
if radio_dict_5g[radio] == 1:
|
|
del radio_dict_5g[radio]
|
|
else:
|
|
radio_dict_5g[radio] -= 1
|
|
break
|
|
self.client_connect_using_radio(ssid=ssid_5g_list[i]['ssid_name'],
|
|
security=ssid_5g_list[i]['security'],
|
|
passkey=ssid_5g_list[i]['password'],
|
|
mode=mode,
|
|
radio=radio,
|
|
station_name=[sta_names_5g[i]],
|
|
attach_station_data=False,
|
|
attach_port_info=False,
|
|
timeout_sec=timeout_sec,
|
|
vlan_id=vlan_id,
|
|
create_vlan=False)
|
|
|
|
logging.info("Sleeping 60 seconds to let stations get IP address...")
|
|
time.sleep(60)
|
|
|
|
logging.info("Fetching port info after all stations created")
|
|
port_data = self.json_get(_req_url="port?fields=ip")
|
|
port_info = {key: value for d in port_data["interfaces"] for key, value in d.items()}
|
|
self.allure_report_table_format(dict_data=port_info, key="Port Names", value="ip",
|
|
name="Port info after creating all stations")
|
|
|
|
logging.info("Adding Station Data to the report")
|
|
dict_table_sta = {}
|
|
start_sta, end_sta = 1, 0
|
|
failed = False
|
|
for index, sta in enumerate(sta_names_2g):
|
|
end_sta += 1
|
|
result = self.json_get(_req_url="port/1/1/%s" % sta)
|
|
if ((no_of_sta_2g <= 8 and result['interface']['ip'] == '0.0.0.0')
|
|
or (no_of_sta_2g > 8 and result['interface']['ip'] != '0.0.0.0')):
|
|
failed = True
|
|
if "Key" not in dict_table_sta:
|
|
dict_table_sta["Key"] = list(result["interface"].keys())
|
|
dict_table_sta[f"Value ({sta})"] = list(result["interface"].values())
|
|
|
|
if end_sta - start_sta == 3 or index == len(sta_names_2g) - 1:
|
|
data_table_sta = tabulate(dict_table_sta, headers='keys', tablefmt='fancy_grid')
|
|
logging.info(f"2G-Stations Data ({start_sta}-{end_sta}): \n{data_table_sta}\n")
|
|
allure.attach(name=f"2G-Stations Data ({start_sta}-{end_sta})", body=str(data_table_sta))
|
|
start_sta = end_sta + 1
|
|
dict_table_sta.clear()
|
|
|
|
start_sta, end_sta = 1, 0
|
|
for index, sta in enumerate(sta_names_5g):
|
|
end_sta += 1
|
|
result = self.json_get(_req_url="port/1/1/%s" % sta)
|
|
if ((no_of_sta_5g <= 8 and result['interface']['ip'] == '0.0.0.0')
|
|
or (no_of_sta_5g > 8 and result['interface']['ip'] != '0.0.0.0')):
|
|
failed = True
|
|
if "Key" not in dict_table_sta:
|
|
dict_table_sta["Key"] = list(result["interface"].keys())
|
|
dict_table_sta[f"Value ({sta})"] = list(result["interface"].values())
|
|
|
|
if end_sta - start_sta == 3 or index == len(sta_names_5g) - 1:
|
|
data_table_sta = tabulate(dict_table_sta, headers='keys', tablefmt='fancy_grid')
|
|
logging.info(f"5G-Stations Data ({start_sta}-{end_sta}): \n{data_table_sta}\n")
|
|
allure.attach(name=f"5G-Stations Data ({start_sta}-{end_sta})", body=str(data_table_sta))
|
|
start_sta = end_sta + 1
|
|
dict_table_sta.clear()
|
|
|
|
if no_of_sta_2g > 8 or no_of_sta_5g > 8:
|
|
self.pre_cleanup()
|
|
if failed:
|
|
logging.info("Some/All stations got the IP when more than 8 SSIDs were configured on a single band!")
|
|
pytest.fail("Some/All stations got the IP when more than 8 SSIDs were configured on a single band!")
|
|
else:
|
|
logging.info("As expected, None of the stations got the IP when more than 8 SSIDs were configured "
|
|
"on a single band!")
|
|
return
|
|
|
|
if failed:
|
|
self.pre_cleanup()
|
|
logging.info("Some/All Stations didn't get IP address")
|
|
pytest.fail("Some/All Stations didn't get IP address")
|
|
logging.info("All Stations got IP address")
|
|
|
|
logging.info("Creating Layer3 traffic on stations...")
|
|
for sta in sta_names_2g + sta_names_5g:
|
|
self.create_layer3(side_a_min_rate=6291456, side_a_max_rate=0,
|
|
side_b_min_rate=6291456, side_b_max_rate=0,
|
|
traffic_type="lf_tcp", sta_list=[sta], side_b=upstream_port,
|
|
start_cx=True, prefix=f"t-")
|
|
logging.info(f"CX with TCP traffic created between endpoint-a = {sta} and endpoint-b = upstream port.")
|
|
time.sleep(2)
|
|
self.create_layer3(side_a_min_rate=6291456, side_a_max_rate=0,
|
|
side_b_min_rate=6291456, side_b_max_rate=0,
|
|
traffic_type="lf_udp", sta_list=[sta], side_b=upstream_port,
|
|
start_cx=True, prefix=f"u-")
|
|
logging.info(f"CX with UDP traffic created between endpoint-a = {sta} and endpoint-b = upstream port.")
|
|
time.sleep(2)
|
|
|
|
logging.info("Running Layer3 traffic for 40 sec ...")
|
|
time.sleep(40)
|
|
|
|
logging.info("Fetching CX data and adding it to the report...")
|
|
cx_list = self.get_cx_list()
|
|
dict_table_cx_tcp = {}
|
|
dict_table_cx_udp = {}
|
|
pass_fail_data = []
|
|
overall_test = True
|
|
start_tcp, start_udp = 1, 1
|
|
end_tcp, end_udp = 0, 0
|
|
for i in range(len(cx_list)):
|
|
cx_data = self.json_get(_req_url=f"cx/{cx_list[i]}")
|
|
cx_name = f"{cx_list[i].split('-')[1]}"
|
|
|
|
if "L3 CX Column" not in dict_table_cx_tcp:
|
|
dict_table_cx_tcp["L3 CX Column"] = list(cx_data[f"{cx_list[i]}"].keys())
|
|
if "L3 CX Column" not in dict_table_cx_udp:
|
|
dict_table_cx_udp["L3 CX Column"] = list(cx_data[f"{cx_list[i]}"].keys())
|
|
if "TCP" in cx_data[f"{cx_list[i]}"]['type']:
|
|
end_tcp += 1
|
|
dict_table_cx_tcp[f"values ({cx_name})"] = list(cx_data[f"{cx_list[i]}"].values())
|
|
else:
|
|
end_udp += 1
|
|
dict_table_cx_udp[f"values ({cx_name})"] = list(cx_data[f"{cx_list[i]}"].values())
|
|
|
|
if cx_data[cx_list[i]]['bps rx a'] != 0 and cx_data[cx_list[i]]['bps rx a'] != 0:
|
|
res = True
|
|
else:
|
|
overall_test = False
|
|
res = False
|
|
pass_fail_data.append(
|
|
[f"{cx_list[i][:-2]}", f"{cx_data[cx_list[i]]['bps rx a']}", f"{cx_data[cx_list[i]]['bps rx b']}", res])
|
|
|
|
# attach l3 cx data to allure
|
|
if end_tcp - start_tcp == 3 or (i == len(cx_list) - 1 and start_tcp <= end_tcp):
|
|
data_table_cx_tcp = tabulate(dict_table_cx_tcp, headers='keys', tablefmt='fancy_grid')
|
|
logging.info(f"L3 cross-connects Data (TCP) ({start_tcp} - {end_tcp}): \n{data_table_cx_tcp}\n")
|
|
allure.attach(name=f"L3 cross-connects Data (TCP) ({start_tcp} - {end_tcp})",
|
|
body=str(data_table_cx_tcp))
|
|
start_tcp = end_tcp + 1
|
|
dict_table_cx_tcp.clear()
|
|
if end_udp - start_udp == 3 or (i == len(cx_list) - 1 and start_udp <= end_udp):
|
|
data_table_cx_udp = tabulate(dict_table_cx_udp, headers='keys', tablefmt='fancy_grid')
|
|
logging.info(f"L3 cross-connects Data (UDP) ({start_udp} - {end_udp}): \n{data_table_cx_udp}\n")
|
|
allure.attach(name=f"L3 cross-connects Data (UDP) ({start_udp} - {end_udp})",
|
|
body=str(data_table_cx_udp))
|
|
start_udp = end_udp + 1
|
|
dict_table_cx_udp.clear()
|
|
|
|
logging.info("Attaching pass/fail data to the report...")
|
|
result_table = tabulate(pass_fail_data,
|
|
headers=["Data Path", "Tx Rate (bps)", "Rx Rate (bps)", "Pass/Fail"],
|
|
tablefmt='fancy_grid')
|
|
logging.info(f"Test Result Table: \n{result_table}\n")
|
|
allure.attach(name="Test Result Table", body=str(result_table))
|
|
|
|
self.pre_cleanup()
|
|
|
|
if overall_test is False:
|
|
pytest.fail("DataPath check failed, Traffic didn't reported on some endpoints")
|
|
logging.info("All Traffic reported on all endpoints, test successful!")
|
|
|
|
def strict_forwarding(self, ssids=[], num_stations_per_ssid=1, security="wpa2", dut_data={}, passkey="[BLANK]",
|
|
mode="BRIDGE", side_a_min_rate=6291456, side_a_max_rate=6291456, side_b_min_rate=0,
|
|
side_b_max_rate=0,
|
|
band="twog", vlan_id=[None]):
|
|
self.check_band_ap(band=band)
|
|
self.pre_cleanup()
|
|
# Dict for per ssid station list
|
|
ssid_num_sta = {}
|
|
sta_list = []
|
|
k = 0
|
|
# logic for creting dict of per ssid sta list
|
|
for i in ssids:
|
|
for j in range(num_stations_per_ssid):
|
|
sta_list.append("sta000" + str(k))
|
|
k = k + 1
|
|
ssid_num_sta[i] = sta_list
|
|
sta_list = []
|
|
logging.info("DUT DATA: " + str(dut_data))
|
|
allure.attach(name="Min Tx rate -A", body=f"{side_a_min_rate} bytes")
|
|
allure.attach(name="Min Tx rate -B", body=f"{side_b_min_rate} bytes")
|
|
i = 0
|
|
sta_list = []
|
|
for dut in self.dut_data:
|
|
for ssid in ssids:
|
|
if num_stations_per_ssid > 1:
|
|
station_result = self.client_connect(ssid=ssid, passkey=passkey, security=security, mode=mode,
|
|
band=band, vlan_id=vlan_id,
|
|
client_type=0, pre_cleanup=True,
|
|
num_sta=len(ssid_num_sta[ssid]),
|
|
dut_data=dut_data)
|
|
sta_list = sta_list + list(station_result.keys())
|
|
else:
|
|
all_radio_5g = (self.be200_radios + self.ax210_radios + self.ax200_radios +
|
|
+ self.mtk_radios + self.wave2_5g_radios + self.wave1_radios)
|
|
logging.info("All 5g radios" + str(all_radio_5g))
|
|
all_radio_2g = (self.be200_radios + self.ax210_radios + self.ax200_radios +
|
|
+ self.mtk_radios + self.wave2_2g_radios + self.wave1_radios)
|
|
logging.info("All 2g radios" + str(all_radio_2g))
|
|
if band == "twog":
|
|
radio_prefix = all_radio_2g
|
|
elif band == "fiveg":
|
|
radio_prefix = all_radio_5g
|
|
logging.info("Radio: " + str(radio_prefix[i]))
|
|
station_result = self.client_connect_using_radio(ssid=ssid, passkey=passkey, security=security,
|
|
mode=mode,
|
|
band=band, vlan_id=vlan_id,
|
|
client_type=0, radio=radio_prefix[i],
|
|
station_name=ssid_num_sta[ssid],
|
|
dut_data=dut_data)
|
|
sta = ssid_num_sta[ssid][0]
|
|
logging.info("sta: " + str(sta))
|
|
shelf = radio_prefix[i].split(".")[0]
|
|
resource = radio_prefix[i].split(".")[1]
|
|
logging.info("shelf: " + str(shelf))
|
|
logging.info("resource: " + str(resource))
|
|
sta_data = self.json_get(_req_url="port/" + str(shelf) + "/" + str(resource) + "/%s" % sta)
|
|
self.allure_report_table_format(dict_data=sta_data["interface"], key="Station Data",
|
|
value="Value", name="%s info" % sta)
|
|
if not station_result:
|
|
allure.attach(name="Test Result", body="TEST FAILED, due to station has no ip")
|
|
return False, "TEST FAILED, due to station has no ip"
|
|
i = i + 1
|
|
sta_list = sta_list + ssid_num_sta[ssid]
|
|
logging.info("station data: " + str(sta_list))
|
|
layer3_result = self.create_layer3(side_a_min_rate=side_a_min_rate, side_a_max_rate=side_a_max_rate,
|
|
side_b_min_rate=side_b_min_rate, side_b_max_rate=side_b_max_rate,
|
|
traffic_type="lf_tcp", sta_list=[sta_list[0]],
|
|
side_b=sta_list[1])
|
|
logging.info("waiting for 20 seconds")
|
|
time.sleep(20)
|
|
cx_list = self.get_cx_list()
|
|
rx_data = self.json_get(_req_url=f"cx/{cx_list[0]}")
|
|
rx_drop_a = rx_data[f"{cx_list[0]}"]["rx drop % a"]
|
|
rx_drop_b = rx_data[f"{cx_list[0]}"]["rx drop % b"]
|
|
bps_rx_a = rx_data[f"{cx_list[0]}"]["bps rx a"]
|
|
bps_rx_b = rx_data[f"{cx_list[0]}"]["bps rx b"]
|
|
table_columns = [sta_list[0], sta_list[1]]
|
|
self.allure_report_table_format(dict_data=rx_data[f"{cx_list[0]}"], key="layer3 column names",
|
|
value="Values",
|
|
name="Layer-3 Data")
|
|
table_data = {"Station Name": table_columns, "bps rx a": [bps_rx_a, bps_rx_b],
|
|
"rx drop %": [rx_drop_a, rx_drop_b]}
|
|
table = tabulate(table_data, headers='keys', tablefmt='fancy_grid', showindex=True)
|
|
logging.info(str(table))
|
|
self.client_disconnect(clear_all_sta=True, clean_l3_traffic=True)
|
|
if bps_rx_a == 0 and bps_rx_b == 0 and rx_drop_a == 0 and rx_drop_b == 0:
|
|
allure.attach(name="Test Result", body="TEST PASSED" + "\n\n" + str(table))
|
|
return True, "TEST PASS"
|
|
else:
|
|
allure.attach(name="Test Result",
|
|
body="TEST FAILED, Stations should not ping each other" + "\n\n" + str(table))
|
|
return False, "TEST FAILED, Stations should not ping each other"
|
|
|
|
def advanced_captive_portal(self, ssid="[BLANK]", security="wpa2", dut_data={}, passkey="[BLANK]", mode="BRIDGE",
|
|
band="twog", num_sta=1, vlan_id=[None], json_post_data='', get_testbed_details={},
|
|
tip_2x_obj=None, enable_owe=False, is_bw320=False, is_ht160=False):
|
|
self.check_band_ap(band=band)
|
|
self.pre_cleanup()
|
|
pass_fail = "PASS"
|
|
description = ""
|
|
logging.info("DUT DATA: " + str(dut_data))
|
|
|
|
if band == "twog":
|
|
radio_port_name = list(self.get_radio_availabilities(num_stations_2g=1)[0].keys())[0]
|
|
elif band == "fiveg":
|
|
radio_port_name = list(self.get_radio_availabilities(num_stations_5g=1)[0].keys())[0]
|
|
else:
|
|
radio_port_name = list(self.get_radio_availabilities(num_stations_6g=1)[0].keys())[0]
|
|
|
|
for dut in self.dut_data:
|
|
station_result = self.client_connect_using_radio(ssid=ssid, passkey=passkey, security=security, mode=mode,
|
|
band=band, vlan_id=vlan_id, radio=radio_port_name,
|
|
client_type=0,station_name=["sta0000"],
|
|
dut_data=dut_data, enable_owe = enable_owe,
|
|
is_bw320=is_bw320, is_ht160=is_ht160)
|
|
sta = "sta0000"
|
|
sta_data = self.json_get(_req_url="port/1/1/%s" % sta)
|
|
self.allure_report_table_format(dict_data=sta_data["interface"], key="Station Data",
|
|
value="Value", name="%s info" % sta)
|
|
if not station_result:
|
|
allure.attach(name="Test Result", body="TEST FAILED, due to station has no ip")
|
|
return "FAIL", "TEST FAILED, due to station has no ip"
|
|
logging.info("sta " + str(sta))
|
|
# Finding captive portal url ip
|
|
if tip_2x_obj is not None:
|
|
logging.info("AP idx: " + str(self.dut_data.index(dut)))
|
|
cmd_output = tip_2x_obj.get_dut_library_object().run_generic_command(cmd="ifconfig up0v0",
|
|
idx=self.dut_data.index(dut),
|
|
attach_allure=False)
|
|
logging.info("cmd output: " + str(cmd_output))
|
|
ip_pattern = re.compile(r"inet addr:(\d+\.\d+\.\d+\.\d+)")
|
|
match = ip_pattern.search(cmd_output)
|
|
inet_ip_addr = match.group(1)
|
|
logging.info("inet ip addr: " + str(inet_ip_addr))
|
|
cmd = f'/home/lanforge/vrf_exec.bash {sta} curl -X POST -H "Content-Type:application/json" -d "{json_post_data}" http://{inet_ip_addr}/hotspot'
|
|
logging.info("cmd: " + str(cmd))
|
|
# SSH connection parameters
|
|
hostname = get_testbed_details["traffic_generator"]["details"]["manager_ip"]
|
|
port = get_testbed_details["traffic_generator"]["details"]["ssh_port"]
|
|
username = 'root'
|
|
password = 'lanforge'
|
|
ping_host = "google.com"
|
|
ping_count = 10
|
|
logging.info(
|
|
f"hostname: {hostname} port: {port} username: {username} password: {password} ping_host: {ping_host}")
|
|
ping_command = f"/home/lanforge/vrf_exec.bash {sta} ping -c {ping_count} {ping_host}"
|
|
validate_captive_string = '<div class="card-header">uCentral - Captive Portal</div>'
|
|
validate_captive_connection = '<h1> Connected </h1>'
|
|
validate_ping_string = " 0% packet loss"
|
|
client = paramiko.SSHClient()
|
|
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
try:
|
|
client.connect(hostname, port=port, username=username, password=password)
|
|
# Before captive portal Validate client internet connectivity
|
|
logging.info("cmd: " + str(ping_command))
|
|
stdin, stdout, stderr = client.exec_command(ping_command)
|
|
before_captive_ping_output = stdout.read().decode()
|
|
logging.info("Before_captive_ping_output: " + str(before_captive_ping_output))
|
|
allure.attach(name="Before captive portal authentication station ping response (google.com)",
|
|
body=str(before_captive_ping_output))
|
|
if "100% packet loss" in before_captive_ping_output:
|
|
logging.info("Before captive portal authentication client do not have internet connectivity")
|
|
elif validate_ping_string in before_captive_ping_output:
|
|
pytest.fail("Before captive portal authentication client already has internet access")
|
|
logging.info("cmd: " + str(cmd))
|
|
stdin, stdout, stderr = client.exec_command(cmd)
|
|
time.sleep(5)
|
|
captive_output = stdout.read().decode()
|
|
logging.info("Captive portal authentication logs: " + str(captive_output))
|
|
allure.attach(name="Response from captive portal: ",
|
|
body=captive_output, attachment_type=allure.attachment_type.HTML)
|
|
if (validate_captive_string in captive_output and "Invalid credentials" not in captive_output and
|
|
validate_captive_connection in captive_output):
|
|
logging.info("Captive portal authentication successful")
|
|
else:
|
|
if "Invalid credentials" in captive_output:
|
|
pytest.fail("Invalid credentials")
|
|
pytest.fail("Captive portal authentication Failed")
|
|
logging.info("cmd: " + str(ping_command))
|
|
stdin, stdout, stderr = client.exec_command(ping_command)
|
|
after_captive_ping_output = stdout.read().decode()
|
|
logging.info("After captive portal authentication station ping response (google.com: " + str(
|
|
after_captive_ping_output))
|
|
allure.attach(name="After captive portal authentication station ping response (google.com)",
|
|
body=str(after_captive_ping_output))
|
|
if validate_ping_string in after_captive_ping_output:
|
|
logging.info("Client got internet access")
|
|
else:
|
|
pytest.fail("After captive portal authentication doesn't have internet connectivity")
|
|
# Close the SSH connection
|
|
client.close()
|
|
except Exception as e:
|
|
logging.error(f"{e}")
|
|
pass_fail = "FAIL"
|
|
description = f"{e}"
|
|
return pass_fail, description
|
|
|
|
def roam_test(self, ap1_bssid="90:3c:b3:6c:46:dd", ap2_bssid="90:3c:b3:6c:47:2d", fiveg_radio=None,
|
|
twog_radio=None, sixg_radio=None, scan_freq="5180,5180",
|
|
band="twog", sniff_radio_="1.1.wiphy7", num_sta=1, security="wpa2", security_key="Openwifi",
|
|
ssid="OpenWifi", upstream="1.1.eth1", duration=None, iteration=1, channel="11", option="ota",
|
|
dut_name=["edgecore_eap101", "edgecore_eap102"], traffic_type="lf_udp", eap_method="TLS",
|
|
eap_identity="user", eap_password="password", pairwise_cipher="NA", groupwise_cipher="NA",
|
|
private_key="NA", pk_passwd="NA", ca_cert="NA", eap_phase1=None, eap_phase2=None,
|
|
soft_roam=False, sta_type="11r"):
|
|
|
|
bands = [b.strip().lower() for b in band.split(",")]
|
|
logging.info(f"bands:{bands}")
|
|
|
|
sta_radio = next((r for r in [fiveg_radio, twog_radio, sixg_radio] if r is not None), None)
|
|
|
|
if sta_radio is None:
|
|
logging.error("station radio is None")
|
|
|
|
logging.info(f"Selected station radio: {sta_radio}")
|
|
|
|
logging.info(f"twog_radio:{twog_radio}, fiveg_radio:{fiveg_radio}, sixg_radio:{sixg_radio}")
|
|
|
|
# create monitor and start sniffer & run test in parallel
|
|
if "1.1." in sniff_radio_:
|
|
sniff_radio_.strip("1.1.")
|
|
t1 = threading.Thread(target=self.start_sniffer, args=(channel, sniff_radio_, "11r-roam-test-capture", 300))
|
|
t1.start()
|
|
logging.info(f"sniffer started")
|
|
roam_obj = Roam(lanforge_ip=self.manager_ip,
|
|
port=self.manager_http_port,
|
|
band=band,
|
|
sniff_radio=sniff_radio_,
|
|
num_sta=num_sta,
|
|
security=security,
|
|
password=security_key,
|
|
ssid=ssid,
|
|
upstream=upstream,
|
|
duration=duration,
|
|
option=option,
|
|
iteration_based=True,
|
|
eap_method=eap_method,
|
|
eap_identity=eap_identity,
|
|
eap_password=eap_password,
|
|
pairwise_cipher=pairwise_cipher,
|
|
groupwise_cipher=groupwise_cipher,
|
|
private_key=private_key,
|
|
pk_passwd=pk_passwd,
|
|
ca_cert=ca_cert,
|
|
softroam=soft_roam,
|
|
sta_type=sta_type,
|
|
ieee80211w="1",
|
|
)
|
|
create_sta = False
|
|
logging.info(f"first band:{bands[0]}")
|
|
|
|
self.local_realm.reset_port(sta_radio)
|
|
roam_obj.station_radio = sta_radio
|
|
if bands[0] == "twog":
|
|
roam_obj.band = '2G'
|
|
create_sta = roam_obj.create_clients(sta_prefix="roam")
|
|
if bands[0] == "fiveg":
|
|
roam_obj.band = '5G'
|
|
create_sta = roam_obj.create_clients(sta_prefix="roam")
|
|
if bands[0] == "sixg":
|
|
roam_obj.band = '6G'
|
|
create_sta = roam_obj.create_clients(sta_prefix="roam")
|
|
|
|
self.get_supplicant_logs(radio=str(sta_radio))
|
|
if not create_sta:
|
|
# stop sniffer if station is not created
|
|
try:
|
|
self.stop_sniffer(['11r-roam-test-capture'])
|
|
except Exception as e:
|
|
logging.error(f"error {e} : Packet Capture failed.")
|
|
return False, "Stations failed to get IP address"
|
|
time.sleep(10)
|
|
|
|
port_data = self.json_get("/port/?fields=port+type,alias")['interfaces']
|
|
|
|
# fetch roam station data from port data
|
|
sta_name = ""
|
|
for port in range(len(port_data)):
|
|
for key, val in port_data[port].items():
|
|
if "roam" in key:
|
|
sta_name = key
|
|
break
|
|
|
|
# enable over the ds in generate script if passed
|
|
if option == "otd":
|
|
gen_ds = 1
|
|
else:
|
|
gen_ds = 0
|
|
|
|
# Parse BSSID's as a lowercase string separated by ,
|
|
|
|
ap1_bssid = ap1_bssid.lower()
|
|
ap2_bssid = ap2_bssid.lower()
|
|
bssid_list = ap1_bssid + "," + ap2_bssid
|
|
|
|
wifi_mobility_obj = WifiMobility(lfclient_host=self.manager_ip,
|
|
lf_port=self.manager_http_port,
|
|
ssh_port=self.manager_ssh_port,
|
|
lf_user="lanforge",
|
|
lf_password="lanforge",
|
|
blob_test="WiFi-Mobility-",
|
|
instance_name="cv-inst-0",
|
|
config_name="roam_test_cfg",
|
|
pull_report=True,
|
|
load_old_cfg=False,
|
|
raw_lines=None,
|
|
raw_lines_file="",
|
|
enables=None,
|
|
disables=None,
|
|
sets=None,
|
|
cfg_options=None,
|
|
sort="interleave",
|
|
stations=sta_name,
|
|
bssid_list=bssid_list,
|
|
gen_scan_freqs=scan_freq,
|
|
gen_sleep_interval="5000",
|
|
gen_scan_sleep_interval="1000",
|
|
gen_ds=gen_ds,
|
|
duration="60000",
|
|
default_sleep="250",
|
|
auto_verify="10000",
|
|
max_rpt_time='1000',
|
|
skip_roam_self='1',
|
|
loop_check='1',
|
|
clear_on_start='1',
|
|
show_events='1',
|
|
report_dir="",
|
|
graph_groups=None,
|
|
test_rig="Testbed-01",
|
|
test_tag="",
|
|
local_lf_report_dir="../reports/",
|
|
verbosity="5"
|
|
)
|
|
|
|
if wifi_mobility_obj.instance_name.endswith('-0'):
|
|
wifi_mobility_obj.instance_name = wifi_mobility_obj.instance_name + str(random.randint(1, 999))
|
|
|
|
t2 = threading.Thread(target=wifi_mobility_obj.run)
|
|
t2.start()
|
|
|
|
# wait until the completion of mobility test and sniffer
|
|
t2.join()
|
|
t1.join()
|
|
|
|
# stop sniffer and attach pcap
|
|
try:
|
|
self.stop_sniffer(['11r-roam-test-capture'])
|
|
except Exception as e:
|
|
logging.error(f"error {e} : Packet Capture failed.")
|
|
report_name, pass_fail_data = "", list()
|
|
if wifi_mobility_obj.report_name and len(wifi_mobility_obj.report_name) >= 1:
|
|
report_name = wifi_mobility_obj.report_name[0]['LAST']["response"].split(":::")[1].split("/")[-1] + "/"
|
|
time.sleep(10)
|
|
logging.info("report_name: " + str(report_name))
|
|
self.attach_report_graphs(report_name=report_name, pdf_name="WiFi-Mobility (Roam Test) PDF Report")
|
|
else:
|
|
logging.error(f"PATH {wifi_mobility_obj.report_name} does not exist")
|
|
|
|
if wifi_mobility_obj.get_exists(wifi_mobility_obj.instance_name):
|
|
wifi_mobility_obj.delete_instance(wifi_mobility_obj.instance_name)
|
|
|
|
# fetch csv data from report data & attach pass fail results
|
|
if not report_name.endswith("/"):
|
|
report_name = report_name + "/"
|
|
if os.path.exists("../reports/" + report_name + "chart-csv-7.csv"):
|
|
with open("../reports/" + report_name + "chart-csv-7.csv", 'rb') as csv_file:
|
|
file_content = csv_file.read()
|
|
allure.attach(file_content, name=f"Roam Test (11r) Pass/Fail Data",
|
|
attachment_type=allure.attachment_type.CSV)
|
|
with open("../reports/" + report_name + "chart-csv-7.csv", 'r') as csv_file:
|
|
for row in csv.reader(csv_file):
|
|
pass_fail_data.append(row)
|
|
else:
|
|
logging.info(f"{report_name} Does not exist.")
|
|
|
|
logging.info(str(pass_fail_data))
|
|
# prepare pass fail data to be displayed in a table
|
|
if len(pass_fail_data) > 1:
|
|
message = tabulate(pass_fail_data, headers="firstrow", tablefmt="rounded_grid")
|
|
else:
|
|
message = "Test Passed"
|
|
# return false when any of the roam result is 'FAIL' in pass fail data
|
|
for i in pass_fail_data[1:]:
|
|
if i[2] == 'FAIL':
|
|
return False, message
|
|
else:
|
|
return True, message
|
|
|
|
|
|
if __name__ == '__main__':
|
|
basic = {
|
|
"target": "tip_2x",
|
|
"controller": {
|
|
"url": "https://sec-qa01.cicd.lab.wlan.tip.build:16001",
|
|
"username": "tip@ucentral.com",
|
|
"password": "OpenWifi%123"
|
|
},
|
|
"device_under_tests": [{
|
|
"model": "edgecore_eap101",
|
|
"supported_bands": ["2G", "5G"],
|
|
"supported_modes": ["BRIDGE", "NAT", "VLAN"],
|
|
"wan_port": "1.1.eth3",
|
|
"lan_port": None,
|
|
"ssid": {
|
|
"mode": "BRIDGE",
|
|
"ssid_data": {
|
|
"0": {
|
|
"ssid": "OpenWifi",
|
|
"encryption": "wpa2",
|
|
"password": "OpenWifi",
|
|
"band": "fiveg",
|
|
"bssid": "90:3C:B3:6C:43:04"
|
|
},
|
|
"1": {
|
|
"ssid": "OpenWifi",
|
|
"encryption": "wpa2",
|
|
"password": "OpenWifi",
|
|
"band": "twog",
|
|
"bssid": "90:3C:B3:6C:43:04"
|
|
}
|
|
},
|
|
"radio_data": {
|
|
"2G": {
|
|
"channel": 1,
|
|
"bandwidth": 20,
|
|
"frequency": 2437
|
|
},
|
|
"5G": {
|
|
"channel": 52,
|
|
"bandwidth": 20,
|
|
"frequency": 5260
|
|
},
|
|
"6G": {
|
|
"channel": None,
|
|
"bandwidth": None,
|
|
"frequency": None
|
|
}
|
|
}
|
|
},
|
|
"mode": "wifi6",
|
|
"identifier": "903cb36c4301",
|
|
"method": "serial",
|
|
"host_ip": "192.168.52.89",
|
|
"host_username": "lanforge",
|
|
"host_password": "lanforge",
|
|
"host_ssh_port": 22,
|
|
"serial_tty": "/dev/ttyUSB0",
|
|
"firmware_version": "next-latest"
|
|
}],
|
|
"traffic_generator": {
|
|
"name": "lanforge",
|
|
"testbed": "basic",
|
|
"scenario": "dhcp-bridge",
|
|
"details": {
|
|
"manager_ip": "localhost",
|
|
"http_port": 8840,
|
|
"ssh_port": 8841,
|
|
"setup": {"method": "build", "DB": "Test_Scenario_Automation"},
|
|
"wan_ports": {
|
|
"1.1.eth3": {"addressing": "dhcp-server", "subnet": "172.16.0.1/16", "dhcp": {
|
|
"lease-first": 10,
|
|
"lease-count": 10000,
|
|
"lease-time": "6h"
|
|
}
|
|
}
|
|
},
|
|
"lan_ports": {
|
|
|
|
},
|
|
"uplink_nat_ports": {
|
|
"1.1.eth2": {
|
|
"addressing": "static",
|
|
"ip": "192.168.52.150",
|
|
"gateway_ip": "192.168.52.1/24",
|
|
"ip_mask": "255.255.255.0",
|
|
"dns_servers": "BLANK"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
obj = lf_tests(lf_data=dict(basic["traffic_generator"]), dut_data=list(basic["device_under_tests"]),
|
|
log_level=logging.DEBUG, run_lf=True)
|
|
l = obj.run_lf_dut_data()
|
|
print(l)
|
|
# obj.add_stations()
|
|
# obj.add_stations(band="5G")
|
|
# obj.chamber_view(raw_lines="custom")
|
|
# dut = {'0000c1018812': {"ssid_data": {
|
|
# 0: {"ssid": 'TestSSID-2G', "encryption": 'wpa2', "password": 'OpenWifi', "band": '2G',
|
|
# "bssid": '00:00:C1:01:88:15'},
|
|
# 1: {"ssid": 'TestSSID-5G', "encryption": 'wpa2', "password": 'OpenWifi', "band": '5G',
|
|
# "bssid": '00:00:C1:01:88:14'}}, "radio_data": {'2G': [1, 40, 2422], '5G': [36, 80, 5210], '6G': None}}}
|
|
# obj.wifi_capacity(instance_name="test_client_wpa2_BRIDGE_udp_bi", mode="BRIDGE",
|
|
# vlan_id=[100],
|
|
# download_rate="1Gbps", batch_size="1,5,10,20,40,64,128,256",
|
|
# influx_tags="Jitu",
|
|
# upload_rate="1Gbps", protocol="UDP-IPv4", duration="60000",
|
|
# move_to_influx=False, dut_data=dut, ssid_name="OpenWifi",
|
|
# num_stations={"2G": 10, "5G": 10})
|
|
# A =obj.setup_interfaces(band="fiveg", vlan_id=100, mode="NAT-WAN", num_sta=1)
|
|
# print(A)
|
|
# obj.setup_relevent_profiles()
|
|
# obj.client_connect(ssid="OpenWifi", passkey="OpenWifi", security="wpa2", mode="BRIDGE", band="twog",
|
|
# vlan_id=[None], num_sta=65, scan_ssid=True,
|
|
# station_data=["4way time (us)", "channel", "cx time (us)", "dhcp (ms)", "ip", "signal"],
|
|
# allure_attach=True)
|
|
# obj.multi_psk_test(band="twog", mpsk_data=None, ssid="OpenWifi", bssid="['00:00:c1:01:88:12']", passkey="OpenWifi",
|
|
# encryption="wpa", mode="BRIDGE", num_sta=1)
|
|
# obj.add_vlan(vlan_iFds=[100])
|
|
# obj.create_dhcp_external()obj.add_vlan(vlan_ids=[100, 200, 300, 400, 500, 600])
|
|
# obj.get_cx_data()
|
|
# obj.chamber_view()
|
|
dut = {'903cb36c4301':
|
|
{'ssid_data': {
|
|
0: {'ssid': 'ssid_wpa_2g_br', 'encryption': 'wpa', 'password': 'something', 'band': '2G',
|
|
'bssid': '90:3C:B3:6C:43:04'}}, 'radio_data': {'2G': {'channel': 6, 'bandwidth': 20, 'frequency': 2437},
|
|
'5G': {'channel': None, 'bandwidth': None,
|
|
'frequency': None},
|
|
'6G': {'channel': None, 'bandwidth': None,
|
|
'frequency': None}}}}
|
|
|
|
passes, result = obj.client_connectivity_test(ssid="ssid_wpa_2g_br", passkey="something", security="wpa",
|
|
extra_securities=[],
|
|
num_sta=1, mode="BRIDGE", dut_data=dut,
|
|
band="fiveg")
|
|
# print(passes == "PASS", result)
|
|
# # obj.start_sniffer(radio_channel=1, radio="wiphy7", test_name="sniff_radio", duration=30)
|
|
# print("started")
|
|
# time.sleep(30)
|
|
# obj.stop_sniffer()
|
|
# lf_report.pull_reports(hostname="10.28.3.28", port=22, username="lanforge",
|
|
# password="lanforge",
|
|
# report_location="/home/lanforge/" + "sniff_radio.pcap",
|
|
# report_dir=".")
|
|
# def start_sniffer(self, radio_channel=None, radio=None, test_name="sniff_radio", duration=60):
|
|
#
|
|
# obj.get_cx_data()
|
|
# obj.chamber_view()
|
|
# obj.client_connectivity_test(ssid="wpa2_5g", passkey="something", security="wpa2", extra_securities=[],
|
|
# num_sta=1, mode="BRIDGE", vlan_id=1,
|
|
# # band="fiveg", ssid_channel=36)
|
|
# obj.chamber_view()
|
|
# obj.setup_relevent_profiles()
|
|
# obj.add_vlan(vlan_ids=[100, 200, 300])
|
|
# # obj.chamber_view()
|
|
# obj.setup_relevent_profiles()
|
|
|
|
# dut = {'903cb36c46ad':
|
|
# {'ssid_data': {
|
|
# 0: {'ssid': 'OpenWifi', 'encryption': 'wpa2', 'password': 'OpenWifi', 'band': '5G',
|
|
# 'bssid': '90:3C:B3:6C:46:B1'}}, 'radio_data': {
|
|
# '5G': {'channel': 52, 'bandwidth': None,
|
|
# 'frequency': None}}}}
|
|
#
|
|
# passes, result = obj.hot_config_reload_test(ssid="OpenWifi", passkey="OpenWifi", security="wpa2",
|
|
# extra_securities=[],
|
|
# num_sta=1, mode="BRIDGE", dut_data=dut,
|
|
# band="fiveg") |