diff mbox series

[2/5] tests: Add more EHT tests with various bandwidths and channels

Message ID 20231221064934.3887910-2-andrei.otcheretianski@intel.com
State Accepted
Headers show
Series None | expand

Commit Message

Andrei Otcheretianski Dec. 21, 2023, 6:49 a.m. UTC
Test EHT connection on 5Ghz band with channels 20-160Mhz and up to
320Mhz on 6Ghz band.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
---
 tests/hwsim/hostapd.py  |  44 +++++++++++
 tests/hwsim/test_eht.py | 165 ++++++++++++++++++++++++++++++++++++++++
 tests/hwsim/utils.py    |  24 ++++++
 3 files changed, 233 insertions(+)
diff mbox series

Patch

diff --git a/tests/hwsim/hostapd.py b/tests/hwsim/hostapd.py
index 205f15e9a4..65771ee007 100644
--- a/tests/hwsim/hostapd.py
+++ b/tests/hwsim/hostapd.py
@@ -898,6 +898,50 @@  def ht40_minus_params(channel="1", ssid=None, country=None):
     params['ht_capab'] = "[HT40-]"
     return params
 
+def he_params(ssid=None):
+    params = {"ssid": "he6ghz",
+              "ieee80211n": "1",
+              "ieee80211ac": "1",
+              "wmm_enabled": "1",
+              "channel": "5",
+              "op_class": "131",
+              "ieee80211ax": "1",
+              "hw_mode": "a",
+              "he_oper_centr_freq_seg0_idx": "15",
+              "he_oper_chwidth": "2",
+              "vht_oper_chwidth": "2"}
+    if ssid:
+        params["ssid"] = ssid
+
+    return params
+
+def he_wpa_params(ssid=None, passphrase=None):
+    params = he_params(ssid)
+    params["wpa"] = "1"
+    params["wpa_key_mgmt"] = "WPA-PSK"
+    params["wpa_pairwise"] = "TKIP"
+    if passphrase:
+        params["wpa_passphrase"] = passphrase
+
+    return params
+
+def he_wpa2_params(ssid=None, wpa_key_mgmt="SAE", rsn_pairwise="CCMP",
+                   group_cipher="CCMP", sae_pwe="1", passphrase=None):
+    params = he_params(ssid)
+    params["wpa"] = "2"
+    params["wpa_key_mgmt"] = wpa_key_mgmt
+    params["rsn_pairwise"] = rsn_pairwise
+    params["group_cipher"] = group_cipher
+    params["ieee80211w"] = "2"
+    if wpa_key_mgmt == "SAE":
+        params["sae_pwe"] = sae_pwe
+        params["sae_groups"] = "19"
+
+    if passphrase:
+        params["wpa_passphrase"] = passphrase
+
+    return params
+
 def cmd_execute(apdev, cmd, shell=False):
     hapd_global = HostapdGlobal(apdev)
     return hapd_global.cmd_execute(cmd, shell=shell)
diff --git a/tests/hwsim/test_eht.py b/tests/hwsim/test_eht.py
index b799fcd855..883099298b 100644
--- a/tests/hwsim/test_eht.py
+++ b/tests/hwsim/test_eht.py
@@ -1075,3 +1075,168 @@  def test_eht_ap_mld_proto(dev, apdev):
         mle += "3004010802040b160c12182432043048606c2d1afe131bffff000000000000000000000100000000000000000000ff16230178c81a400000bfce0000000000000000fafffaffff126c07007c0000feffff7f0100888888880000"
         hdr = "00000000" + bssid0 + mld_addr + bssid0 + "1000"
         send_check(hapd0, hdr + assocreq_start + mle + assocreq_end)
+
+def _5ghz_chanwidth_to_bw(op):
+    return {
+        0: "40",
+        1: "80",
+        2: "160",
+        3: "80+80",
+    }.get(op, "20")
+
+def _test_eht_5ghz(dev, apdev, channel, chanwidth, ccfs1, ccfs2=0):
+    try:
+        params = {"ssid": "eht",
+                  "country_code": "US",
+                  "hw_mode": "a",
+                  "channel": str(channel),
+                  "ieee80211n": "1",
+                  "ieee80211ac": "1",
+                  "ieee80211ax": "1",
+                  "ieee80211be": "1",
+                  "vht_oper_chwidth": str(chanwidth),
+                  "vht_oper_centr_freq_seg0_idx": str(ccfs1),
+                  "vht_oper_centr_freq_seg1_idx": str(ccfs2),
+                  "he_oper_chwidth": str(chanwidth),
+                  "he_oper_centr_freq_seg1_idx": str(ccfs2),
+                  "he_oper_centr_freq_seg0_idx": str(ccfs1),
+                  "eht_oper_centr_freq_seg0_idx": str(ccfs1),
+                  "eht_oper_chwidth": str(chanwidth)}
+
+        if chanwidth == 0:
+            if channel == ccfs1:
+                  bw = "20"
+            elif channel < ccfs1:
+                  params["ht_capab"] = "[HT40+]"
+            else:
+                  params["ht_capab"] = "[HT40-]"
+        else:
+                  params["ht_capab"] = "[HT40+]"
+                  if chanwidth == 2:
+                      params["vht_capab"] = "[VHT160]"
+                  elif chanwidth == 3:
+                      params["vht_capab"] = "[VHT160-80PLUS80]"
+
+        freq = 5000 + channel * 5
+        if chanwidth != 0 or channel != ccfs1:
+            bw = _5ghz_chanwidth_to_bw(chanwidth)
+
+        hapd = hostapd.add_ap(apdev[0], params)
+        dev[0].connect("eht", key_mgmt="NONE", scan_freq=str(freq))
+
+        eht_verify_status(dev[0], hapd, freq, bw, is_ht=True, is_vht=True)
+        eht_verify_wifi_version(dev[0])
+        hwsim_utils.test_connectivity(dev[0], hapd)
+
+    finally:
+        dev[0].request("DISCONNECT")
+        set_world_reg(apdev[0], None, dev[0])
+
+def test_eht_5ghz_20mhz(dev, apdev):
+    """EHT with 20 MHz channel width on 5GHz"""
+    _test_eht_5ghz(dev, apdev, 36, 0, 36, 0)
+
+def test_eht_5ghz_40mhz_low(dev, apdev):
+    """EHT with 40 MHz channel width on 5GHz. Secondary channel above"""
+    _test_eht_5ghz(dev, apdev, 36, 0, 38, 0)
+
+def test_eht_5ghz_40mhz_high(dev, apdev):
+    """EHT with 80 MHz channel width on 5GHz. Secondary channel below"""
+    _test_eht_5ghz(dev, apdev, 40, 0, 38, 0)
+
+def test_eht_5ghz_80mhz_1(dev, apdev):
+    """EHT with 80 MHz channel width on 5GHz. Primary=149"""
+    _test_eht_5ghz(dev, apdev, 36, 1, 42, 0)
+
+def test_eht_5ghz_80mhz_2(dev, apdev):
+    """EHT with 80 MHz channel width on 5GHz. Primary=149"""
+    _test_eht_5ghz(dev, apdev, 149, 1, 155, 0)
+
+def test_eht_5ghz_80p80mhz(dev, apdev):
+    """EHT with 80+80 MHz channel width on 5GHz"""
+    _test_eht_5ghz(dev, apdev, 36, 3, 42, 155)
+
+def _6ghz_op_class_to_bw(op):
+    return {
+        131: "20",
+        132: "40",
+        133: "80",
+        134: "160",
+        137: "320",
+    }.get(op, "20")
+
+def _test_eht_6ghz(dev, apdev, channel, op_class, ccfs1):
+    check_sae_capab(dev[0])
+
+    # CA enables 320mhz channels without NO-IR restriction
+    dev[0].cmd_execute(['iw', 'reg', 'set', 'CA'])
+    wait_regdom_changes(dev[0])
+
+    try:
+        ssid = "eht_6ghz_sae"
+        passphrase = "12345678"
+        params = hostapd.he_wpa2_params(ssid=ssid, passphrase=passphrase)
+        params["ieee80211be"] = "1"
+        params["channel"] = str(channel)
+        params["op_class"] = str(op_class)
+        params["he_oper_centr_freq_seg0_idx"] = str(ccfs1)
+        params["eht_oper_centr_freq_seg0_idx"] = str(ccfs1)
+        params["country_code"] = "CA"
+
+        if not he_6ghz_supported():
+            raise HwsimSkip("6GHz frequency is not supported")
+        if op_class == 137 and not eht_320mhz_supported():
+            raise HwsimSkip("320Mhz channels are not supported")
+
+        hapd = hostapd.add_ap(apdev[0], params)
+        status = hapd.get_status()
+        logger.info("hostapd STATUS: " + str(status))
+        if hapd.get_status_field("ieee80211ax") != "1":
+            raise Exception("STATUS did not indicate ieee80211ax=1")
+
+        if hapd.get_status_field("ieee80211be") != "1":
+            raise Exception("STATUS did not indicate ieee80211be=1")
+
+        wpas = dev[0]
+        wpas.set("sae_pwe", "1")
+
+        freq = 5950 + channel * 5
+        bw = _6ghz_op_class_to_bw(op_class)
+
+        wpas.connect(ssid, key_mgmt="SAE", psk=passphrase, ieee80211w="2",
+                     scan_freq=str(freq))
+
+        eht_verify_status(wpas, hapd, freq, bw)
+        eht_verify_wifi_version(wpas)
+        hwsim_utils.test_connectivity(wpas, hapd)
+    finally:
+        dev[0].cmd_execute(['iw', 'reg', 'set', '00'])
+        wait_regdom_changes(dev[0])
+
+def test_eht_6ghz_20mhz(dev, apdev):
+    """EHT with 20 MHz channel width on 6GHz"""
+    _test_eht_6ghz(dev, apdev, 5, 131, 5)
+
+def test_eht_6ghz_40mhz(dev, apdev):
+    """EHT with 40 MHz channel width on 6GHz"""
+    _test_eht_6ghz(dev, apdev, 5, 132, 3)
+
+def test_eht_6ghz_80mhz(dev, apdev):
+    """EHT with 80 MHz channel width on 6GHz"""
+    _test_eht_6ghz(dev, apdev, 5, 133, 7)
+
+def test_eht_6ghz_160mhz(dev, apdev):
+    """EHT with 160 MHz channel width on 6GHz"""
+    _test_eht_6ghz(dev, apdev, 5, 134, 15)
+
+def test_eht_6ghz_320mhz(dev, apdev):
+    """EHT with 320 MHz channel width on 6GHz"""
+    _test_eht_6ghz(dev, apdev, 5, 137, 31)
+
+def test_eht_6ghz_320mhz_2(dev, apdev):
+    """EHT with 320 MHz channel width on 6GHz center 63"""
+    _test_eht_6ghz(dev, apdev, 37, 137, 63)
+
+def test_eht_6ghz_320mhz_3(dev, apdev):
+    """EHT with 320 MHz channel width on 6GHz center 31 primary 37"""
+    _test_eht_6ghz(dev, apdev, 37, 137, 31)
\ No newline at end of file
diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py
index d572bdc4c9..d01e1fbbfe 100644
--- a/tests/hwsim/utils.py
+++ b/tests/hwsim/utils.py
@@ -12,6 +12,7 @@  import subprocess
 import time
 import remotehost
 import logging
+import re
 logger = logging.getLogger()
 import hostapd
 
@@ -156,6 +157,29 @@  def vht_supported():
         return True
     return False
 
+def eht_320mhz_supported():
+    cmd = subprocess.Popen(["iw", "reg", "get"],
+                           stdout=subprocess.PIPE)
+    cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE)
+    reg = cmd.stdout.read().decode()
+    if "@ 320)" in reg:
+        return True
+    return False
+
+def he_6ghz_supported(freq=5975):
+    cmd = subprocess.Popen(["iw", "reg", "get"],
+                           stdout=subprocess.PIPE)
+    reg_rules = cmd.stdout.read().decode().splitlines()
+    for rule in reg_rules:
+        m = re.search(r"\s*\(\d+\s*-\s*\d+", rule)
+        if not m:
+            continue
+        freqs = re.findall(r"\d+", m.group(0))
+        if int(freqs[0]) <= freq and freq <= int(freqs[1]):
+            return True
+
+    return False
+
 # This function checks whether the provided dev, which may be either
 # WpaSupplicant or Hostapd supports CSA.
 def csa_supported(dev):