diff options
-rw-r--r-- | data/templates/wifi/hostapd.conf.tmpl | 11 | ||||
-rw-r--r-- | interface-definitions/interfaces-wireless.xml.in | 2 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_interfaces_wireless.py | 87 | ||||
-rwxr-xr-x | smoketest/scripts/system/test_kernel_options.py | 2 | ||||
-rwxr-xr-x | src/conf_mode/interfaces-wireless.py | 6 |
5 files changed, 96 insertions, 12 deletions
diff --git a/data/templates/wifi/hostapd.conf.tmpl b/data/templates/wifi/hostapd.conf.tmpl index b00515d76..132c4ce40 100644 --- a/data/templates/wifi/hostapd.conf.tmpl +++ b/data/templates/wifi/hostapd.conf.tmpl @@ -51,10 +51,6 @@ ssid={{ ssid }} # (default: 0, i.e., not set) # Please note that some drivers do not use this value from hostapd and the # channel will need to be configured separately with iwconfig. -# -# If CONFIG_ACS build option is enabled, the channel can be selected -# automatically at run time by setting channel=acs_survey or channel=0, both of -# which will enable the ACS survey based algorithm. channel={{ channel }} {% endif %} @@ -341,13 +337,10 @@ vht_oper_chwidth={{ capabilities.vht.channel_set_width }} {% set output.value = output.value + '[HTC-VHT]' %} {% endif %} {% if capabilities.vht.antenna_pattern_fixed is defined %} -{% set output.value = output.value + '[RX-ANTENNA-PATTERN]' %} -{% endif %} -{% if capabilities.vht.antenna_pattern_fixed is defined %} -{% set output.value = output.value + '[TX-ANTENNA-PATTERN]' %} +{% set output.value = output.value + '[RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN]' %} {% endif %} {% if capabilities.vht.max_mpdu is defined %} -{% set output.value = output.value + '[MAX-MPDU-' + capabilities.vht.max_mpdu + ']' %} +{% set output.value = output.value + '[MAX-MPDU-' + capabilities.vht.max_mpdu + ']' %} {% endif %} {% if capabilities.vht.max_mpdu_exp is defined %} {% set output.value = output.value + '[MAX-A-MPDU-LEN-EXP-' + capabilities.vht.max_mpdu_exp + ']' %} diff --git a/interface-definitions/interfaces-wireless.xml.in b/interface-definitions/interfaces-wireless.xml.in index 6f0ec9e71..a0caf810f 100644 --- a/interface-definitions/interfaces-wireless.xml.in +++ b/interface-definitions/interfaces-wireless.xml.in @@ -110,7 +110,6 @@ <constraint> <regex>(3839|7935)</regex> </constraint> - <multi/> </properties> </leafNode> <leafNode name="short-gi"> @@ -150,7 +149,6 @@ <constraint> <regex>(static|dynamic)</regex> </constraint> - <multi/> </properties> </leafNode> <node name="stbc"> diff --git a/smoketest/scripts/cli/test_interfaces_wireless.py b/smoketest/scripts/cli/test_interfaces_wireless.py index fae233244..691f633b7 100755 --- a/smoketest/scripts/cli/test_interfaces_wireless.py +++ b/smoketest/scripts/cli/test_interfaces_wireless.py @@ -15,11 +15,19 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os +import re import unittest from base_interfaces_test import BasicInterfaceTest from psutil import process_iter + from vyos.util import check_kmod +from vyos.util import read_file + +def get_config_value(interface, key): + tmp = read_file(f'/run/hostapd/{interface}.conf') + tmp = re.findall(r'\n?{}=+(.*)'.format(key), tmp) + return tmp[0] class WirelessInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): @@ -53,6 +61,85 @@ class WirelessInterfaceTest(BasicInterfaceTest.BaseTest): else: self.assertTrue(False) + def test_hostapd_config(self): + """ Check if hostapd config is properly generated """ + + # Only set the hostapd (access-point) options + interface = 'wlan0' + phy = 'phy0' + ssid = 'ssid' + channel = '1' + + self.session.set(self._base_path + [interface, 'physical-device', phy]) + self.session.set(self._base_path + [interface, 'ssid', ssid]) + self.session.set(self._base_path + [interface, 'type', 'access-point']) + self.session.set(self._base_path + [interface, 'channel', channel]) + # auto-powersave is special + self.session.set(self._base_path + [interface, 'capabilities', 'ht', 'auto-powersave']) + + ht_opt = { + # VyOS CLI option hostapd - ht_capab setting + '40mhz-incapable' : '[40-INTOLERANT]', + 'delayed-block-ack' : '[DELAYED-BA]', + 'greenfield' : '[GF]', + 'ldpc' : '[LDPC]', + 'lsig-protection' : '[LSIG-TXOP-PROT]', + 'channel-set-width ht40+' : '[HT40+]', + 'stbc tx' : '[TX-STBC]', + 'stbc rx 123' : '[RX-STBC-123]', + 'max-amsdu 7935' : '[MAX-AMSDU-7935]', + 'smps static' : '[SMPS-STATIC]', + } + for key in ht_opt: + self.session.set(self._base_path + [interface, 'capabilities', 'ht'] + key.split()) + + vht_opt = { + # VyOS CLI option hostapd - ht_capab setting + '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]', + 'max-mpdu 11454' : '[MAX-MPDU-11454]', + 'max-mpdu-exp 2' : '[MAX-A-MPDU-LEN-EXP-2][VHT160]', + 'link-adaptation both' : '[VHT-LINK-ADAPT3]', + 'short-gi 80' : '[SHORT-GI-80]', + 'short-gi 160' : '[SHORT-GI-160]', + } + for key in vht_opt: + self.session.set(self._base_path + [interface, 'capabilities', 'vht'] + key.split()) + + self.session.commit() + + # + # Validate Config + # + + # ssid + tmp = get_config_value(interface, 'ssid') + self.assertEqual(ssid, tmp) + + # channel + tmp = get_config_value(interface, 'channel') + self.assertEqual(channel, tmp) + + # auto-powersave is special + tmp = get_config_value(interface, 'uapsd_advertisement_enabled') + self.assertEqual('1', 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) + + # Check for running process + self.assertIn('hostapd', (p.name() for p in process_iter())) + + if __name__ == '__main__': check_kmod('mac80211_hwsim') unittest.main() diff --git a/smoketest/scripts/system/test_kernel_options.py b/smoketest/scripts/system/test_kernel_options.py index 861132127..8c96d96fb 100755 --- a/smoketest/scripts/system/test_kernel_options.py +++ b/smoketest/scripts/system/test_kernel_options.py @@ -30,7 +30,7 @@ class TestKernelModules(unittest.TestCase): for option in ['CONFIG_AUDIT', 'CONFIG_HAVE_ARCH_AUDITSYSCALL', 'CONFIG_AUDITSYSCALL', 'CONFIG_AUDIT_WATCH', 'CONFIG_AUDIT_TREE', 'CONFIG_AUDIT_ARCH']: - self.asserIn(f'{option}=y', config) + self.assertIn(f'{option}=y', config) if __name__ == '__main__': unittest.main() diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py index 9861f72db..c6c843e7b 100755 --- a/src/conf_mode/interfaces-wireless.py +++ b/src/conf_mode/interfaces-wireless.py @@ -33,6 +33,7 @@ from vyos.configverify import verify_vrf from vyos.ifconfig import WiFiIf from vyos.template import render from vyos.util import call +from vyos.util import vyos_dict_search from vyos import ConfigError from vyos import airbag airbag.enable() @@ -213,6 +214,11 @@ def generate(wifi): mac.dialect = mac_unix_expanded wifi['mac'] = str(mac) + # XXX: Jinja2 can not operate on a dictionary key when it starts of with a number + if '40mhz_incapable' in (vyos_dict_search('capabilities.ht', wifi) or []): + wifi['capabilities']['ht']['fourtymhz_incapable'] = wifi['capabilities']['ht']['40mhz_incapable'] + del wifi['capabilities']['ht']['40mhz_incapable'] + # render appropriate new config files depending on access-point or station mode if wifi['type'] == 'access-point': render(hostapd_conf.format(**wifi), 'wifi/hostapd.conf.tmpl', wifi, trim_blocks=True) |