diff --git a/data/templates/wifi/hostapd.conf.j2 b/data/templates/wifi/hostapd.conf.j2
index 0459fbc69f..5f37572163 100644
--- a/data/templates/wifi/hostapd.conf.j2
+++ b/data/templates/wifi/hostapd.conf.j2
@@ -46,7 +46,14 @@ hw_mode=a
ieee80211h=1
ieee80211ac=1
{% elif mode is vyos_defined('ax') %}
+{#{% if capabilities.ht is vyos_defined and capabilities.vht not vyos_defined %}#}
+{% if capabilities.he.channel_set_width is vyos_defined('81') or capabilities.he.channel_set_width is vyos_defined('83') or capabilities.he.channel_set_width is vyos_defined('84') %}
+{# This is almost certainly a 2.4GHz network #}
+hw_mode=g
+{% else %}
+{# This is likely a 5GHz or 6GHz network #}
hw_mode=a
+{% endif %}
ieee80211h=1
ieee80211ax=1
{% else %}
@@ -202,7 +209,7 @@ require_he=1
{% else %}
ieee80211n={{ '1' if 'n' in mode or 'ac' in mode or 'ax' in mode else '0' }}
{% endif %}
-{# HE (802.11ax 6GHz) #}
+{# HE (802.11ax) #}
{% if capabilities.he is vyos_defined and mode in 'ax' %}
{# For now, hard-code power levels for indoor-only AP #}
he_6ghz_reg_pwr_type=0
@@ -220,6 +227,9 @@ op_class={{ capabilities.he.channel_set_width }}
{% if capabilities.he.bss_color is vyos_defined %}
he_bss_color={{ capabilities.he.bss_color }}
{% endif %}
+{% if capabilities.he.coding_scheme is vyos_defined %}
+he_basic_mcs_nss_set={{ capabilities.he.coding_scheme }}
+{% endif %}
he_6ghz_rx_ant_pat={{ '1' if capabilities.he.antenna_pattern_fixed is vyos_defined else '0' }}
he_su_beamformer={{ '1' if capabilities.he.beamform.single_user_beamformer is vyos_defined else '0' }}
he_su_beamformee={{ '1' if capabilities.he.beamform.single_user_beamformee is vyos_defined else '0' }}
diff --git a/interface-definitions/interfaces_wireless.xml.in b/interface-definitions/interfaces_wireless.xml.in
index d69daa485b..830bad1aa9 100644
--- a/interface-definitions/interfaces_wireless.xml.in
+++ b/interface-definitions/interfaces_wireless.xml.in
@@ -248,26 +248,26 @@
VHT operating channel center frequency - center freq 1 (for use with 80, 80+80 and 160 modes)
- u32:34-173
+ u32:34-177
5Ghz (802.11 a/h/j/n/ac) center channel index (use 42 for primary 80MHz channel 36)
-
+
- Channel center value must be between 34 and 173
+ Channel center value must be between 34 and 177
VHT operating channel center frequency - center freq 2 (for use with the 80+80 mode)
- u32:34-173
+ u32:34-177
5Ghz (802.11 ac) center channel index (use 58 for secondary 80MHz channel 52)
-
+
- Channel center value must be between 34 and 173
+ Channel center value must be between 34 and 177
@@ -436,30 +436,42 @@
https://w1.fi/cgit/hostap/tree/src/common/ieee802_11_common.c?id=195cc3d919503fb0d699d9a56a58a72602b25f51#n1525
802.11ax (WiFi-6e - HE) can use up to 160MHz bandwidth channels
-->
- 131 132 133 134 135
+ 81 83 84 131 132 133 134 135
+
+ 81
+ 2.4GHz, 20 MHz channel width
+
+
+ 83
+ 2.4GHz, 40 MHz channel width, secondary 20MHz channel above primary channel
+
+
+ 84
+ 2.4GHz, 40 MHz channel width, secondary 20MHz channel below primary channel
+
131
- 20 MHz channel width
+ 6GHz, 20 MHz channel width
132
- 40 MHz channel width
+ 6GHz, 40 MHz channel width
133
- 80 MHz channel width
+ 6GHz, 80 MHz channel width
134
- 160 MHz channel width
+ 6GHz, 160 MHz channel width
135
- 80+80 MHz channel width
+ 6GHz, 80+80 MHz channel width
- (131|132|133|134|135)
+ (81|83|84|131|132|133|134|135)
@@ -535,6 +547,30 @@
+
+
+ Spacial Stream and Modulation Coding Scheme settings
+
+ u32:0
+ HE-MCS 0-7
+
+
+ u32:1
+ HE-MCS 0-9
+
+
+ u32:2
+ HE-MCS 0-11
+
+
+ u32:3
+ HE-MCS is not supported
+
+
+
+
+
+
@@ -554,10 +590,10 @@
u32:1-14
- 2.4Ghz (802.11 b/g/n) Channel
+ 2.4Ghz (802.11 b/g/n/ax) Channel
- u32:34-173
+ u32:34-177
5Ghz (802.11 a/h/j/n/ac) Channel
@@ -565,7 +601,7 @@
6Ghz (802.11 ax) Channel
-
+
0
diff --git a/smoketest/scripts/cli/test_interfaces_wireless.py b/smoketest/scripts/cli/test_interfaces_wireless.py
index ba2f60a89f..86ddc9f4d4 100755
--- a/smoketest/scripts/cli/test_interfaces_wireless.py
+++ b/smoketest/scripts/cli/test_interfaces_wireless.py
@@ -303,7 +303,89 @@ def test_wireless_hostapd_vht_su_beamformer_config(self):
for key, value in vht_opt.items():
self.assertIn(value, tmp)
- def test_wireless_hostapd_he_config(self):
+ def test_wireless_hostapd_he_2ghz_config(self):
+ # Only set the hostapd (access-point) options - HE mode for 802.11ax at 2.4GHz
+ interface = self._interfaces[1] # wlan1
+ ssid = 'ssid'
+ channel = '1'
+ sae_pw = 'VyOSVyOSVyOS'
+ bss_color = '13'
+ channel_set_width = '81'
+
+ self.cli_set(self._base_path + [interface, 'ssid', ssid])
+ self.cli_set(self._base_path + [interface, 'type', 'access-point'])
+ self.cli_set(self._base_path + [interface, 'channel', channel])
+ self.cli_set(self._base_path + [interface, 'mode', 'ax'])
+ self.cli_set(self._base_path + [interface, 'security', 'wpa', 'mode', 'wpa2'])
+ self.cli_set(self._base_path + [interface, 'security', 'wpa', 'passphrase', sae_pw])
+ self.cli_set(self._base_path + [interface, 'security', 'wpa', 'cipher', 'CCMP'])
+ self.cli_set(self._base_path + [interface, 'security', 'wpa', 'cipher', 'GCMP'])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'ht', '40mhz-incapable'])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'ht', 'channel-set-width', 'ht20'])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'ht', 'channel-set-width', 'ht40+'])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'ht', 'channel-set-width', 'ht40-'])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'ht', 'short-gi', '20'])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'ht', 'short-gi', '40'])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'he', 'bss-color', bss_color])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'he', 'channel-set-width', channel_set_width])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'he', 'beamform', 'multi-user-beamformer'])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'he', 'beamform', 'single-user-beamformer'])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'he', 'beamform', 'single-user-beamformee'])
+
+ self.cli_commit()
+
+ #
+ # Validate Config
+ #
+ tmp = get_config_value(interface, 'interface')
+ self.assertEqual(interface, tmp)
+
+ # ssid
+ tmp = get_config_value(interface, 'ssid')
+ self.assertEqual(ssid, tmp)
+
+ # mode of operation resulting from [interface, 'mode', 'ax']
+ tmp = get_config_value(interface, 'hw_mode')
+ self.assertEqual('g', tmp)
+ tmp = get_config_value(interface, 'ieee80211h')
+ self.assertEqual('1', tmp)
+ tmp = get_config_value(interface, 'ieee80211ax')
+ self.assertEqual('1', tmp)
+
+ # channel and channel width
+ tmp = get_config_value(interface, 'channel')
+ self.assertEqual(channel, tmp)
+ tmp = get_config_value(interface, 'op_class')
+ self.assertEqual(channel_set_width, tmp)
+
+ # BSS coloring
+ tmp = get_config_value(interface, 'he_bss_color')
+ self.assertEqual(bss_color, tmp)
+
+ # sae_password
+ tmp = get_config_value(interface, 'wpa_passphrase')
+ self.assertEqual(sae_pw, tmp)
+
+ # WPA3 and dependencies
+ tmp = get_config_value(interface, 'wpa')
+ self.assertEqual('2', tmp)
+ tmp = get_config_value(interface, 'rsn_pairwise')
+ self.assertEqual('CCMP GCMP', tmp)
+ tmp = get_config_value(interface, 'wpa_key_mgmt')
+ self.assertEqual('WPA-PSK WPA-PSK-SHA256', tmp)
+
+ # beamforming
+ tmp = get_config_value(interface, 'he_mu_beamformer')
+ self.assertEqual('1', tmp)
+ tmp = get_config_value(interface, 'he_su_beamformee')
+ self.assertEqual('1', tmp)
+ tmp = get_config_value(interface, 'he_mu_beamformer')
+ self.assertEqual('1', tmp)
+
+ # Check for running process
+ self.assertTrue(process_named_running('hostapd'))
+
+ def test_wireless_hostapd_he_6ghz_config(self):
# Only set the hostapd (access-point) options - HE mode for 802.11ax at 6GHz
interface = self._interfaces[1] # wlan1
ssid = 'ssid'
@@ -327,6 +409,7 @@ def test_wireless_hostapd_he_config(self):
self.cli_set(self._base_path + [interface, 'capabilities', 'he', 'bss-color', bss_color])
self.cli_set(self._base_path + [interface, 'capabilities', 'he', 'channel-set-width', channel_set_width])
self.cli_set(self._base_path + [interface, 'capabilities', 'he', 'center-channel-freq', 'freq-1', center_channel_freq_1])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'he', 'antenna-pattern-fixed'])
self.cli_set(self._base_path + [interface, 'capabilities', 'he', 'beamform', 'multi-user-beamformer'])
self.cli_set(self._base_path + [interface, 'capabilities', 'he', 'beamform', 'single-user-beamformer'])
@@ -374,6 +457,10 @@ def test_wireless_hostapd_he_config(self):
tmp = get_config_value(interface, 'wpa_key_mgmt')
self.assertEqual('SAE', tmp)
+ # antenna pattern
+ tmp = get_config_value(interface, 'he_6ghz_rx_ant_pat')
+ self.assertEqual('1', tmp)
+
# beamforming
tmp = get_config_value(interface, 'he_mu_beamformer')
self.assertEqual('1', tmp)