summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2024-07-22 20:14:14 +0200
committerGitHub <noreply@github.com>2024-07-22 20:14:14 +0200
commit163fdc33c2212d46309e442d299a894af279111d (patch)
tree4a59f4216f86c8db47279997873f06d7d0f6ff56
parenteb39342171b4767e483d616df16f4d94c86be108 (diff)
parentb93d880b379a5e423f6033e0c29a4950505615ae (diff)
downloadvyos-1x-163fdc33c2212d46309e442d299a894af279111d.tar.gz
vyos-1x-163fdc33c2212d46309e442d299a894af279111d.zip
Merge pull request #3848 from vyos/mergify/bp/circinus/pr-3576
wireless: T6425: Fixing VHT beamforming for 802.11ac (backport #3576)
-rw-r--r--data/templates/wifi/hostapd.conf.j232
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_wireless.py140
2 files changed, 156 insertions, 16 deletions
diff --git a/data/templates/wifi/hostapd.conf.j2 b/data/templates/wifi/hostapd.conf.j2
index 769325b49..e1a08f7e4 100644
--- a/data/templates/wifi/hostapd.conf.j2
+++ b/data/templates/wifi/hostapd.conf.j2
@@ -383,23 +383,25 @@ vht_oper_chwidth={{ capabilities.vht.channel_set_width }}
{% for short_gi in capabilities.vht.short_gi if capabilities.vht.short_gi is vyos_defined %}
{% set output.value = output.value ~ '[SHORT-GI-' ~ short_gi | upper ~ ']' %}
{% endfor %}
-{% for beamform in capabilities.vht.beamform if capabilities.vht.beamform is vyos_defined %}
-{% set output.value = output.value ~ '[SU-BEAMFORMER]' if beamform is vyos_defined('single-user-beamformer') else '' %}
-{% set output.value = output.value ~ '[SU-BEAMFORMEE]' if beamform is vyos_defined('single-user-beamformee') else '' %}
-{% set output.value = output.value ~ '[MU-BEAMFORMER]' if beamform is vyos_defined('multi-user-beamformer') else '' %}
-{% set output.value = output.value ~ '[MU-BEAMFORMEE]' if beamform is vyos_defined('multi-user-beamformee') else '' %}
-{% endfor %}
-{% if capabilities.vht.antenna_count is vyos_defined and capabilities.vht.antenna_count | int > 1 %}
-{% if capabilities.vht.beamform is vyos_defined %}
-{% if capabilities.vht.beamform == 'single-user-beamformer' %}
+{% if capabilities.vht.beamform is vyos_defined %}
+{% for bf in capabilities.vht.beamform %}
+{% set output.value = output.value ~ '[SU-BEAMFORMER]' if bf is vyos_defined('single-user-beamformer') else output.value %}
+{% set output.value = output.value ~ '[SU-BEAMFORMEE]' if bf is vyos_defined('single-user-beamformee') else output.value %}
+{% set output.value = output.value ~ '[MU-BEAMFORMER]' if bf is vyos_defined('multi-user-beamformer') else output.value %}
+{% set output.value = output.value ~ '[MU-BEAMFORMEE]' if bf is vyos_defined('multi-user-beamformee') else output.value %}
+{% endfor %}
+{% if capabilities.vht.antenna_count is vyos_defined and capabilities.vht.antenna_count | int > 1 %}
+{% if 'single-user-beamformer' in capabilities.vht.beamform %}
{% if capabilities.vht.antenna_count is vyos_defined and capabilities.vht.antenna_count | int > 1 and capabilities.vht.antenna_count | int < 6 %}
-{% set output.value = output.value ~ '[BF-ANTENNA-' ~ capabilities.vht.antenna_count | int -1 ~ ']' %}
-{% set output.value = output.value ~ '[SOUNDING-DIMENSION-' ~ capabilities.vht.antenna_count | int -1 ~ ']' %}
+{% set dimension = capabilities.vht.antenna_count | int - 1 %}
+{% set output.value = output.value ~ '[BF-ANTENNA-' ~ dimension ~ ']' %}
+{% set output.value = output.value ~ '[SOUNDING-DIMENSION-' ~ dimension ~ ']' %}
+{% endif %}
+{% else %}
+{% if capabilities.vht.antenna_count is vyos_defined and capabilities.vht.antenna_count | int > 1 and capabilities.vht.antenna_count | int < 5 %}
+{% set output.value = output.value ~ '[BF-ANTENNA-' ~ capabilities.vht.antenna_count ~ ']' %}
+{% set output.value = output.value ~ '[SOUNDING-DIMENSION-' ~ capabilities.vht.antenna_count ~ ']' %}
{% endif %}
-{% endif %}
-{% if capabilities.vht.antenna_count is vyos_defined and capabilities.vht.antenna_count | int > 1 and capabilities.vht.antenna_count | int < 5 %}
-{% set output.value = output.value ~ '[BF-ANTENNA-' ~ capabilities.vht.antenna_count ~ ']' %}
-{% set output.value = output.value ~ '[SOUNDING-DIMENSION-' ~ capabilities.vht.antenna_count ~ ']' %}
{% endif %}
{% endif %}
{% endif %}
diff --git a/smoketest/scripts/cli/test_interfaces_wireless.py b/smoketest/scripts/cli/test_interfaces_wireless.py
index b45754cae..5ade36e7d 100755
--- a/smoketest/scripts/cli/test_interfaces_wireless.py
+++ b/smoketest/scripts/cli/test_interfaces_wireless.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020-2023 VyOS maintainers and contributors
+# Copyright (C) 2020-2024 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -146,6 +146,144 @@ class WirelessInterfaceTest(BasicInterfaceTest.TestCase):
# Check for running process
self.assertTrue(process_named_running('hostapd'))
+ def test_wireless_hostapd_vht_mu_beamformer_config(self):
+ # Multi-User-Beamformer
+ interface = 'wlan1'
+ ssid = 'vht_mu-beamformer'
+ antennas = '3'
+
+ 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', '36'])
+
+ ht_opt = {
+ # VyOS CLI option hostapd - ht_capab setting
+ 'channel-set-width ht20' : '[HT20]',
+ 'channel-set-width ht40-' : '[HT40-]',
+ 'channel-set-width ht40+' : '[HT40+]',
+ 'dsss-cck-40' : '[DSSS_CCK-40]',
+ 'short-gi 20' : '[SHORT-GI-20]',
+ 'short-gi 40' : '[SHORT-GI-40]',
+ 'max-amsdu 7935' : '[MAX-AMSDU-7935]',
+ }
+ for key in ht_opt:
+ self.cli_set(self._base_path + [interface, 'capabilities', 'ht'] + key.split())
+
+ vht_opt = {
+ # VyOS CLI option hostapd - ht_capab setting
+ 'max-mpdu 11454' : '[MAX-MPDU-11454]',
+ 'max-mpdu-exp 2' : '[MAX-A-MPDU-LEN-EXP-2]',
+ 'stbc tx' : '[TX-STBC-2BY1]',
+ 'stbc rx 12' : '[RX-STBC-12]',
+ 'ldpc' : '[RXLDPC]',
+ 'tx-powersave' : '[VHT-TXOP-PS]',
+ 'vht-cf' : '[HTC-VHT]',
+ 'antenna-pattern-fixed' : '[RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN]',
+ 'link-adaptation both' : '[VHT-LINK-ADAPT3]',
+ 'short-gi 80' : '[SHORT-GI-80]',
+ 'short-gi 160' : '[SHORT-GI-160]',
+ 'beamform multi-user-beamformer' : '[MU-BEAMFORMER][BF-ANTENNA-3][SOUNDING-DIMENSION-3]',
+ }
+
+ self.cli_set(self._base_path + [interface, 'capabilities', 'vht', 'channel-set-width', '1'])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'vht', 'center-channel-freq', 'freq-1', '42'])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'vht', 'antenna-count', antennas])
+ for key in vht_opt:
+ self.cli_set(self._base_path + [interface, 'capabilities', 'vht'] + key.split())
+
+ 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)
+
+ # channel
+ tmp = get_config_value(interface, 'channel')
+ self.assertEqual('36', tmp)
+
+ tmp = get_config_value(interface, 'ht_capab')
+ for key, value in ht_opt.items():
+ self.assertIn(value, tmp)
+
+ tmp = get_config_value(interface, 'vht_capab')
+ for key, value in vht_opt.items():
+ self.assertIn(value, tmp)
+
+ def test_wireless_hostapd_vht_su_beamformer_config(self):
+ # Single-User-Beamformer
+ interface = 'wlan1'
+ ssid = 'vht_su-beamformer'
+ antennas = '3'
+
+ 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', '36'])
+
+ ht_opt = {
+ # VyOS CLI option hostapd - ht_capab setting
+ 'channel-set-width ht20' : '[HT20]',
+ 'channel-set-width ht40-' : '[HT40-]',
+ 'channel-set-width ht40+' : '[HT40+]',
+ 'dsss-cck-40' : '[DSSS_CCK-40]',
+ 'short-gi 20' : '[SHORT-GI-20]',
+ 'short-gi 40' : '[SHORT-GI-40]',
+ 'max-amsdu 7935' : '[MAX-AMSDU-7935]',
+ }
+ for key in ht_opt:
+ self.cli_set(self._base_path + [interface, 'capabilities', 'ht'] + key.split())
+
+ vht_opt = {
+ # VyOS CLI option hostapd - ht_capab setting
+ 'max-mpdu 11454' : '[MAX-MPDU-11454]',
+ 'max-mpdu-exp 2' : '[MAX-A-MPDU-LEN-EXP-2]',
+ 'stbc tx' : '[TX-STBC-2BY1]',
+ 'stbc rx 12' : '[RX-STBC-12]',
+ 'ldpc' : '[RXLDPC]',
+ 'tx-powersave' : '[VHT-TXOP-PS]',
+ 'vht-cf' : '[HTC-VHT]',
+ 'antenna-pattern-fixed' : '[RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN]',
+ 'link-adaptation both' : '[VHT-LINK-ADAPT3]',
+ 'short-gi 80' : '[SHORT-GI-80]',
+ 'short-gi 160' : '[SHORT-GI-160]',
+ 'beamform single-user-beamformer' : '[SU-BEAMFORMER][BF-ANTENNA-2][SOUNDING-DIMENSION-2]',
+ }
+
+ self.cli_set(self._base_path + [interface, 'capabilities', 'vht', 'channel-set-width', '1'])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'vht', 'center-channel-freq', 'freq-1', '42'])
+ self.cli_set(self._base_path + [interface, 'capabilities', 'vht', 'antenna-count', antennas])
+ for key in vht_opt:
+ self.cli_set(self._base_path + [interface, 'capabilities', 'vht'] + key.split())
+
+ 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)
+
+ # channel
+ tmp = get_config_value(interface, 'channel')
+ self.assertEqual('36', tmp)
+
+ tmp = get_config_value(interface, 'ht_capab')
+ for key, value in ht_opt.items():
+ self.assertIn(value, tmp)
+
+ tmp = get_config_value(interface, 'vht_capab')
+ for key, value in vht_opt.items():
+ self.assertIn(value, tmp)
+
def test_wireless_hostapd_wpa_config(self):
# Only set the hostapd (access-point) options
interface = 'wlan0'