From e41ae4d952e276d8497d38f5761806c14ea542d2 Mon Sep 17 00:00:00 2001 From: DmitriyEshenko Date: Wed, 9 Sep 2020 06:45:40 +0000 Subject: openconnect: T2036: Move CLI commands under vpn openconnect --- data/templates/ocserv/ocserv_config.tmpl | 2 +- data/templates/ocserv/radius_conf.tmpl | 2 +- data/templates/ocserv/radius_servers.tmpl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'data/templates') diff --git a/data/templates/ocserv/ocserv_config.tmpl b/data/templates/ocserv/ocserv_config.tmpl index 6aaeff693..328af0c0d 100644 --- a/data/templates/ocserv/ocserv_config.tmpl +++ b/data/templates/ocserv/ocserv_config.tmpl @@ -1,4 +1,4 @@ -### generated by vpn_anyconnect.py ### +### generated by vpn_openconnect.py ### tcp-port = {{ listen_ports.tcp }} udp-port = {{ listen_ports.udp }} diff --git a/data/templates/ocserv/radius_conf.tmpl b/data/templates/ocserv/radius_conf.tmpl index 2d19306a0..1712d83ef 100644 --- a/data/templates/ocserv/radius_conf.tmpl +++ b/data/templates/ocserv/radius_conf.tmpl @@ -1,4 +1,4 @@ -### generated by cpn_anyconnect.py ### +### generated by vpn_openconnect.py ### nas-identifier VyOS {% for srv in server %} {% if not "disable" in server[srv] %} diff --git a/data/templates/ocserv/radius_servers.tmpl b/data/templates/ocserv/radius_servers.tmpl index ba21fa074..7bacac992 100644 --- a/data/templates/ocserv/radius_servers.tmpl +++ b/data/templates/ocserv/radius_servers.tmpl @@ -1,4 +1,4 @@ -### generated by cpn_anyconnect.py ### +### generated by vpn_openconnect.py ### # server key {% for srv in server %} {% if not "disable" in server[srv] %} -- cgit v1.2.3 From 25136d9a9501dcc40c31f9db8e90be3eb5569d24 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 13 Sep 2020 13:17:03 +0200 Subject: ddclient: T2858: migrate to get_config_dict() --- data/templates/dynamic-dns/ddclient.conf.tmpl | 73 ++++----- interface-definitions/dns-dynamic.xml.in | 1 + src/conf_mode/dynamic_dns.py | 217 +++++++------------------- 3 files changed, 99 insertions(+), 192 deletions(-) (limited to 'data/templates') diff --git a/data/templates/dynamic-dns/ddclient.conf.tmpl b/data/templates/dynamic-dns/ddclient.conf.tmpl index 9c7219230..6fbbb50c3 100644 --- a/data/templates/dynamic-dns/ddclient.conf.tmpl +++ b/data/templates/dynamic-dns/ddclient.conf.tmpl @@ -3,44 +3,47 @@ daemon=1m syslog=yes ssl=yes -{% for interface in interfaces -%} +{% for iface in interface %} +# ddclient configuration for interface "{{ iface }}" +{% if interface[iface].use_web is defined and interface[iface].use_web is not none %} +{% set web_skip = ", web-skip='" + interface[iface].use_web.skip + "'" if interface[iface].use_web.skip is defined else '' %} +use=web, web='{{ interface[iface].use_web.url }}'{{ web_skip }} +{% else %} +use=if, if={{ iface }} +{% endif %} -# -# ddclient configuration for interface "{{ interface.interface }}": -# -{% if interface.web_url -%} -use=web, web='{{ interface.web_url}}' {%- if interface.web_skip %}, web-skip='{{ interface.web_skip }}'{% endif %} -{% else -%} -use=if, if={{ interface.interface }} -{% endif -%} - -{% for rfc in interface.rfc2136 -%} -{% for record in rfc.record %} -# RFC2136 dynamic DNS configuration for {{ record }}.{{ rfc.zone }} -server={{ rfc.server }} +{% if interface[iface].rfc2136 is defined and interface[iface].rfc2136 is not none %} +{% for rfc2136, config in interface[iface].rfc2136.items() %} +{% for dns_record in config.record if config.record is defined %} +# RFC2136 dynamic DNS configuration for {{ rfc2136 }}, {{ config.zone }}, {{ dns_record }} +server={{ config.server }} protocol=nsupdate -password={{ rfc.keyfile }} -ttl={{ rfc.ttl }} -zone={{ rfc.zone }} -{{ record }} -{% endfor -%} -{% endfor -%} +password={{ config.keyfile }} +ttl={{ config.ttl }} +zone={{ config.zone }} +{{ dns_record }} + +{% endfor %} +{% endfor %} +{% endif %} -{% for srv in interface.service %} -{% for host in srv.host %} -# DynDNS provider configuration for {{ host }} -protocol={{ srv.protocol }}, +{% if interface[iface].service is defined and interface[iface].service is not none %} +{% for service, config in interface[iface].service.items() %} +{% for dns_record in config.host_name %} +# DynDNS provider configuration for {{ service }}, {{ dns_record }} +protocol={{ config.protocol }}, max-interval=28d, -login={{ srv.login }}, -password='{{ srv.password }}', -{% if srv.server -%} -server={{ srv.server }}, -{% endif -%} -{% if srv.zone -%} -zone={{ srv.zone }}, -{% endif -%} -{{ host }} -{% endfor %} -{% endfor %} +login={{ config.login }}, +password='{{ config.password }}', +{% if config.server %} +server={{ config.server }}, +{% endif %} +{% if config.zone %} +zone={{ config.zone }}, +{% endif %} +{{ dns_record }} +{% endfor %} +{% endfor %} +{% endif %} {% endfor %} diff --git a/interface-definitions/dns-dynamic.xml.in b/interface-definitions/dns-dynamic.xml.in index 143c04ef6..34a31a7c5 100644 --- a/interface-definitions/dns-dynamic.xml.in +++ b/interface-definitions/dns-dynamic.xml.in @@ -58,6 +58,7 @@ + 600 diff --git a/src/conf_mode/dynamic_dns.py b/src/conf_mode/dynamic_dns.py index 57c910a68..93e995b78 100755 --- a/src/conf_mode/dynamic_dns.py +++ b/src/conf_mode/dynamic_dns.py @@ -17,14 +17,13 @@ import os from sys import exit -from copy import deepcopy -from stat import S_IRUSR, S_IWUSR from vyos.config import Config -from vyos import ConfigError -from vyos.util import call +from vyos.configdict import dict_merge from vyos.template import render - +from vyos.util import call +from vyos.xml import defaults +from vyos import ConfigError from vyos import airbag airbag.enable() @@ -45,197 +44,101 @@ default_service_protocol = { 'zoneedit': 'zoneedit1' } -default_config_data = { - 'interfaces': [], - 'deleted': False -} - def get_config(config=None): - dyndns = deepcopy(default_config_data) if config: conf = config else: conf = Config() - base_level = ['service', 'dns', 'dynamic'] + base_level = ['service', 'dns', 'dynamic'] if not conf.exists(base_level): - dyndns['deleted'] = True - return dyndns - - for interface in conf.list_nodes(base_level + ['interface']): - node = { - 'interface': interface, - 'rfc2136': [], - 'service': [], - 'web_skip': '', - 'web_url': '' - } - - # set config level to e.g. "service dns dynamic interface eth0" - conf.set_level(base_level + ['interface', interface]) - # Handle RFC2136 - Dynamic Updates in the Domain Name System - for rfc2136 in conf.list_nodes(['rfc2136']): - rfc = { - 'name': rfc2136, - 'keyfile': '', - 'record': [], - 'server': '', - 'ttl': '600', - 'zone': '' - } - - # set config level - conf.set_level(base_level + ['interface', interface, 'rfc2136', rfc2136]) - - if conf.exists(['key']): - rfc['keyfile'] = conf.return_value(['key']) - - if conf.exists(['record']): - rfc['record'] = conf.return_values(['record']) - - if conf.exists(['server']): - rfc['server'] = conf.return_value(['server']) - - if conf.exists(['ttl']): - rfc['ttl'] = conf.return_value(['ttl']) - - if conf.exists(['zone']): - rfc['zone'] = conf.return_value(['zone']) - - node['rfc2136'].append(rfc) - - # set config level to e.g. "service dns dynamic interface eth0" - conf.set_level(base_level + ['interface', interface]) - # Handle DynDNS service providers - for service in conf.list_nodes(['service']): - srv = { - 'provider': service, - 'host': [], - 'login': '', - 'password': '', - 'protocol': '', - 'server': '', - 'custom' : False, - 'zone' : '' - } - - # set config level - conf.set_level(base_level + ['interface', interface, 'service', service]) - - # preload protocol from default service mapping - if service in default_service_protocol.keys(): - srv['protocol'] = default_service_protocol[service] - else: - srv['custom'] = True - - if conf.exists(['login']): - srv['login'] = conf.return_value(['login']) - - if conf.exists(['host-name']): - srv['host'] = conf.return_values(['host-name']) - - if conf.exists(['protocol']): - srv['protocol'] = conf.return_value(['protocol']) - - if conf.exists(['password']): - srv['password'] = conf.return_value(['password']) - - if conf.exists(['server']): - srv['server'] = conf.return_value(['server']) - - if conf.exists(['zone']): - srv['zone'] = conf.return_value(['zone']) - elif srv['provider'] == 'cloudflare': - # default populate zone entry with bar.tld if - # host-name is foo.bar.tld - srv['zone'] = srv['host'][0].split('.',1)[1] - - node['service'].append(srv) - - # Set config back to appropriate level for these options - conf.set_level(base_level + ['interface', interface]) - - # Additional settings in CLI - if conf.exists(['use-web', 'skip']): - node['web_skip'] = conf.return_value(['use-web', 'skip']) - - if conf.exists(['use-web', 'url']): - node['web_url'] = conf.return_value(['use-web', 'url']) - - # set config level back to top level - conf.set_level(base_level) - - dyndns['interfaces'].append(node) + return None + + dyndns = conf.get_config_dict(base_level, key_mangling=('-', '_'), get_first_key=True) + + # We have gathered the dict representation of the CLI, but there are default + # options which we need to update into the dictionary retrived. + for interface in dyndns['interface']: + if 'service' in dyndns['interface'][interface]: + # 'Autodetect' protocol used by DynDNS service + for service in dyndns['interface'][interface]['service']: + if service in default_service_protocol: + dyndns['interface'][interface]['service'][service].update( + {'protocol' : default_service_protocol.get(service)}) + else: + dyndns['interface'][interface]['service'][service].update( + {'custom': ''}) + + if 'rfc2136' in dyndns['interface'][interface]: + default_values = defaults(base_level + ['interface', 'rfc2136']) + for rfc2136 in dyndns['interface'][interface]['rfc2136']: + dyndns['interface'][interface]['rfc2136'][rfc2136] = dict_merge( + default_values, dyndns['interface'][interface]['rfc2136'][rfc2136]) return dyndns def verify(dyndns): # bail out early - looks like removal from running config - if dyndns['deleted']: + if not dyndns: return None # A 'node' corresponds to an interface - for node in dyndns['interfaces']: + if 'interface' not in dyndns: + return None + for interface in dyndns['interface']: # RFC2136 - configuration validation - for rfc2136 in node['rfc2136']: - if not rfc2136['record']: - raise ConfigError('Set key for service "{0}" to send DDNS updates for interface "{1}"'.format(rfc2136['name'], node['interface'])) + if 'rfc2136' in dyndns['interface'][interface]: + for rfc2136, config in dyndns['interface'][interface]['rfc2136'].items(): - if not rfc2136['zone']: - raise ConfigError('Set zone for service "{0}" to send DDNS updates for interface "{1}"'.format(rfc2136['name'], node['interface'])) + for tmp in ['record', 'zone', 'server', 'key']: + if tmp not in config: + raise ConfigError(f'"{tmp}" required for rfc2136 based ' + f'DynDNS service on "{interface}"') - if not rfc2136['keyfile']: - raise ConfigError('Set keyfile for service "{0}" to send DDNS updates for interface "{1}"'.format(rfc2136['name'], node['interface'])) - else: - if not os.path.isfile(rfc2136['keyfile']): - raise ConfigError('Keyfile for service "{0}" to send DDNS updates for interface "{1}" does not exist'.format(rfc2136['name'], node['interface'])) - - if not rfc2136['server']: - raise ConfigError('Set server for service "{0}" to send DDNS updates for interface "{1}"'.format(rfc2136['name'], node['interface'])) + if not os.path.isfile(config['key']): + raise ConfigError(f'"key"-file not found for rfc2136 based ' + f'DynDNS service on "{interface}"') # DynDNS service provider - configuration validation - for service in node['service']: - if not service['host']: - raise ConfigError('Set host-name for service "{0}" to send DDNS updates for interface "{1}"'.format(service['provider'], node['interface'])) + if 'service' in dyndns['interface'][interface]: + for service, config in dyndns['interface'][interface]['service'].items(): + error_msg = f'required for DynDNS service "{service}" on "{interface}"' + if 'host_name' not in config: + raise ConfigError(f'"host-name" {error_msg}') - if not service['login']: - raise ConfigError('Set login for service "{0}" to send DDNS updates for interface "{1}"'.format(service['provider'], node['interface'])) + if 'login' not in config: + raise ConfigError(f'"login" (username) {error_msg}') - if not service['password']: - raise ConfigError('Set password for service "{0}" to send DDNS updates for interface "{1}"'.format(service['provider'], node['interface'])) + if 'password' not in config: + raise ConfigError(f'"password" {error_msg}') - if service['custom'] is True: - if not service['protocol']: - raise ConfigError('Set protocol for service "{0}" to send DDNS updates for interface "{1}"'.format(service['provider'], node['interface'])) + if 'zone' in config: + if service != 'cloudflare': + raise ConfigError(f'"zone" option only supported with CloudFlare') - if not service['server']: - raise ConfigError('Set server for service "{0}" to send DDNS updates for interface "{1}"'.format(service['provider'], node['interface'])) + if 'custom' in config: + if 'protocol' not in config: + raise ConfigError(f'"protocol" {error_msg}') - if service['zone']: - if service['provider'] != 'cloudflare': - raise ConfigError('Zone option not allowed for "{0}", it can only be used for CloudFlare'.format(service['provider'])) + if 'server' not in config: + raise ConfigError(f'"server" {error_msg}') return None def generate(dyndns): # bail out early - looks like removal from running config - if dyndns['deleted']: + if not dyndns: return None - render(config_file, 'dynamic-dns/ddclient.conf.tmpl', dyndns) - - # Config file must be accessible only by its owner - os.chmod(config_file, S_IRUSR | S_IWUSR) - + render(config_file, 'dynamic-dns/ddclient.conf.tmpl', dyndns, trim_blocks=True, permission=0o600) return None def apply(dyndns): - if dyndns['deleted']: + if not dyndns: call('systemctl stop ddclient.service') if os.path.exists(config_file): os.unlink(config_file) - else: call('systemctl restart ddclient.service') -- cgit v1.2.3 From eb8d51724236607baa91cc29d1d084dbc0e1762a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 16 Sep 2020 19:46:01 +0200 Subject: wireless: T2887: fix template renderint on ht and vht options --- data/templates/wifi/hostapd.conf.tmpl | 147 +++++++++++++++++++++------------- 1 file changed, 93 insertions(+), 54 deletions(-) (limited to 'data/templates') diff --git a/data/templates/wifi/hostapd.conf.tmpl b/data/templates/wifi/hostapd.conf.tmpl index a7efee6d5..b00515d76 100644 --- a/data/templates/wifi/hostapd.conf.tmpl +++ b/data/templates/wifi/hostapd.conf.tmpl @@ -124,38 +124,58 @@ ieee80211w=2 # DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set) # 40 MHz intolerant [40-INTOLERANT] (not advertised if not set) # L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set) -{% set output = '' %} -{% set output = output + '[40-INTOLERANT]' if capabilities.ht.fourtymhz_incapable is defined else '' %} -{% set output = output + '[DELAYED-BA]' if capabilities.ht.delayed_block_ack is defined else '' %} -{% set output = output + '[DSSS_CCK-40]' if capabilities.ht.dsss_cck_40 is defined else '' %} -{% set output = output + '[GF]' if capabilities.ht.greenfield is defined else '' %} -{% set output = output + '[LDPC]' if capabilities.ht.ldpc is defined else '' %} -{% set output = output + '[LSIG-TXOP-PROT]' if capabilities.ht.lsig_protection is defined else '' %} -{% set output = output + '[TX-STBC]' if capabilities.ht.stbc.tx is defined else '' %} -{% set output = output + '[RX-STBC-' + capabilities.ht.stbc.rx | upper + ']' if capabilities.ht.stbc.tx is defined else '' %} -{% set output = output + '[MAX-AMSDU-' + capabilities.ht.max_amsdu + ']' if capabilities.ht.max_amsdu is defined else '' %} -{% set output = output + '[SMPS-' + capabilities.ht.smps | upper + ']' if capabilities.ht.smps is defined else '' %} +{% set output = namespace(value='') %} + +{% if capabilities.ht.fourtymhz_incapable is defined %} +{% set output.value = output.value + '[40-INTOLERANT]' %} +{% endif %} +{% if capabilities.ht.delayed_block_ack is defined %} +{% set output.value = output.value + '[DELAYED-BA]' %} +{% endif %} +{% if capabilities.ht.dsss_cck_40 is defined %} +{% set output.value = output.value + '[DSSS_CCK-40]' %} +{% endif %} +{% if capabilities.ht.greenfield is defined %} +{% set output.value = output.value + '[GF]' %} +{% endif %} +{% if capabilities.ht.ldpc is defined %} +{% set output.value = output.value + '[LDPC]' %} +{% endif %} +{% if capabilities.ht.lsig_protection is defined %} +{% set output.value = output.value + '[LSIG-TXOP-PROT]' %} +{% endif %} +{% if capabilities.ht.stbc is defined and capabilities.ht.stbc.tx is defined %} +{% set output.value = output.value + '[TX-STBC]' %} +{% endif %} +{% if capabilities.ht.stbc is defined and capabilities.ht.stbc.rx is defined %} +{% set output.value = output.value + '[RX-STBC-' + capabilities.ht.stbc.rx | upper + ']' %} +{% endif %} +{% if capabilities.ht.max_amsdu is defined %} +{% set output.value = output.value + '[MAX-AMSDU-' + capabilities.ht.max_amsdu + ']' %} +{% endif %} +{% if capabilities.ht.smps is defined %} +{% set output.value = output.value + '[SMPS-' + capabilities.ht.smps | upper + ']' %} +{% endif %} {% if capabilities.ht.channel_set_width is defined %} {% for csw in capabilities.ht.channel_set_width %} -{% set output = output + '[' + csw | upper + ']' %} +{% set output.value = output.value + '[' + csw | upper + ']' %} {% endfor %} {% endif %} {% if capabilities.ht.short_gi is defined %} {% for short_gi in capabilities.ht.short_gi %} -{% set output = output + '[SHORT-GI-' + short_gi | upper + ']' %} +{% set output.value = output.value + '[SHORT-GI-' + short_gi | upper + ']' %} {% endfor %} {% endif %} -ht_capab={{ output }} +ht_capab={{ output.value }} -{% if capabilities.ht.auto_powersave is defined %} +{% if capabilities.ht.auto_powersave is defined %} # WMM-PS Unscheduled Automatic Power Save Delivery [U-APSD] # Enable this flag if U-APSD supported outside hostapd (eg., Firmware/driver) uapsd_advertisement_enabled=1 -{% endif %} - +{% endif %} {% endif %} # Required for full HT and VHT functionality @@ -286,14 +306,14 @@ require_ht=1 # 0 = Tx antenna pattern might change during the lifetime of an association # 1 = Tx antenna pattern does not change during the lifetime of an -{% if capabilities.vht.center_channel_freq.freq_1 is defined %} +{% if capabilities.vht.center_channel_freq is defined and capabilities.vht.center_channel_freq.freq_1 is defined %} # center freq = 5 GHz + (5 * index) # So index 42 gives center freq 5.210 GHz # which is channel 42 in 5G band vht_oper_centr_freq_seg0_idx={{ capabilities.vht.center_channel_freq.freq_1 }} {% endif %} -{% if capabilities.vht.center_channel_freq.freq_2 is defined %} +{% if capabilities.vht.center_channel_freq is defined and capabilities.vht.center_channel_freq.freq_2 is defined %} # center freq = 5 GHz + (5 * index) # So index 159 gives center freq 5.795 GHz # which is channel 159 in 5G band @@ -304,55 +324,74 @@ vht_oper_centr_freq_seg1_idx={{ capabilities.vht.center_channel_freq.freq_2 }} vht_oper_chwidth={{ capabilities.vht.channel_set_width }} {% endif %} -{% set output = '' %} -{% set output = output + '[TX-STBC-2BY1]' if capabilities.vht.stbc.tx is defined else '' %} -{% set output = output + '[RXLDPC]' if capabilities.vht.ldpc is defined else '' %} -{% set output = output + '[VHT-TXOP-PS]' if capabilities.vht.tx_powersave is defined else '' %} -{% set output = output + '[HTC-VHT]' if capabilities.vht.vht_cf is defined else '' %} -{% set output = output + '[RX-ANTENNA-PATTERN]' if capabilities.vht.antenna_pattern_fixed is defined else '' %} -{% set output = output + '[TX-ANTENNA-PATTERN]' if capabilities.vht.antenna_pattern_fixed is defined else '' %} - -{% set output = output + '[RX-STBC-' + capabilities.vht.stbc.rx + ']' if capabilities.vht.stbc.rx is defined else '' %} -{% set output = output + '[MAX-MPDU-' + capabilities.vht.max_mpdu + ']' if capabilities.vht.max_mpdu is defined else '' %} -{% set output = output + '[MAX-A-MPDU-LEN-EXP-' + capabilities.vht.max_mpdu_exp + ']' if capabilities.vht.max_mpdu_exp is defined else '' %} -{% set output = output + '[MAX-A-MPDU-LEN-EXP-' + capabilities.vht.max_mpdu_exp + ']' if capabilities.vht.max_mpdu_exp is defined else '' %} - -{% set output = output + '[VHT160]' if capabilities.vht.max_mpdu_exp is defined and capabilities.vht.max_mpdu_exp == '2' else '' %} -{% set output = output + '[VHT160-80PLUS80]' if capabilities.vht.max_mpdu_exp is defined and capabilities.vht.max_mpdu_exp == '3' else '' %} -{% set output = output + '[VHT-LINK-ADAPT2]' if capabilities.vht.link_adaptation is defined and capabilities.vht.link_adaptation == 'unsolicited' else '' %} -{% set output = output + '[VHT-LINK-ADAPT3]' if capabilities.vht.link_adaptation is defined and capabilities.vht.link_adaptation == 'both' else '' %} - -{% if capabilities.vht.short_gi is defined %} -{% for short_gi in capabilities.vht.short_gi %} -{% set output = output + '[SHORT-GI-' + short_gi | upper + ']' %} -{% endfor %} +{% set output = namespace(value='') %} +{% if capabilities.vht.stbc is defined and capabilities.vht.stbc.tx is defined %} +{% set output.value = output.value + '[TX-STBC-2BY1]' %} {% endif %} - -{% if capabilities.vht.beamform %} -{% for beamform in capabilities.vht.beamform %} -{% set output = output + '[SU-BEAMFORMER]' if beamform == 'single-user-beamformer' else '' %} -{% set output = output + '[SU-BEAMFORMEE]' if beamform == 'single-user-beamformee' else '' %} -{% set output = output + '[MU-BEAMFORMER]' if beamform == 'multi-user-beamformer' else '' %} -{% set output = output + '[MU-BEAMFORMEE]' if beamform == 'multi-user-beamformee' else '' %} -{% endfor %} +{% if capabilities.vht.stbc is defined and capabilities.vht.stbc.rx is defined %} +{% set output.value = output.value + '[RX-STBC-' + capabilities.vht.stbc.rx + ']' %} +{% endif %} +{% if capabilities.vht.ldpc is defined %} +{% set output.value = output.value + '[RXLDPC]' %} +{% endif %} +{% if capabilities.vht.tx_powersave is defined %} +{% set output.value = output.value + '[VHT-TXOP-PS]' %} +{% endif %} +{% if capabilities.vht.vht_cf is defined %} +{% 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]' %} +{% endif %} +{% if capabilities.vht.max_mpdu is defined %} +{% 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 + ']' %} {% endif %} +{% if capabilities.vht.max_mpdu_exp is defined and capabilities.vht.max_mpdu_exp == '2' %} +{% set output.value = output.value + '[VHT160]' %} +{% endif %} +{% if capabilities.vht.max_mpdu_exp is defined and capabilities.vht.max_mpdu_exp == '3' %} +{% set output.value = output.value + '[VHT160-80PLUS80]' %} +{% endif %} +{% if capabilities.vht.link_adaptation is defined and capabilities.vht.link_adaptation == 'unsolicited' %} +{% set output.value = output.value + '[VHT-LINK-ADAPT2]' %} +{% endif %} +{% if capabilities.vht.link_adaptation is defined and capabilities.vht.link_adaptation == 'both' %} +{% set output.value = output.value + '[VHT-LINK-ADAPT3]' %} +{% endif %} + +{% for short_gi in capabilities.vht.short_gi if capabilities.vht.short_gi is defined %} +{% set output.value = output.value + '[SHORT-GI-' + short_gi | upper + ']' %} +{% endfor %} + +{% for beamform in capabilities.vht.beamform if capabilities.vht.beamform is defined %} +{% set output.value = output.value + '[SU-BEAMFORMER]' if beamform == 'single-user-beamformer' else '' %} +{% set output.value = output.value + '[SU-BEAMFORMEE]' if beamform == 'single-user-beamformee' else '' %} +{% set output.value = output.value + '[MU-BEAMFORMER]' if beamform == 'multi-user-beamformer' else '' %} +{% set output.value = output.value + '[MU-BEAMFORMEE]' if beamform == 'multi-user-beamformee' else '' %} +{% endfor %} {% if capabilities.vht.antenna_count is defined and capabilities.vht.antenna_count|int > 1 %} {% if capabilities.vht.beamform %} {% if beamform == 'single-user-beamformer' %} {% if capabilities.vht.antenna_count is defined and capabilities.vht.antenna_count|int > 1 and capabilities.vht.antenna_count|int < 6 %} -{% set output = output + '[BF-ANTENNA-' + capabilities.vht.antenna_count|int -1 + ']' %} -{% set output = output + '[SOUNDING-DIMENSION-' + capabilities.vht.antenna_count|int -1 + ']' %} +{% 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 + ']' %} {% endif %} {% endif %} {% if capabilities.vht.antenna_count is defined and capabilities.vht.antenna_count|int > 1 and capabilities.vht.antenna_count|int < 5 %} -{% set output = output + '[BF-ANTENNA-' + capabilities.vht.antenna_count + ']' %} -{% set output = output + '[SOUNDING-DIMENSION-' + capabilities.vht.antenna_count+ ']' %} +{% 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 %} -vht_capab={{ output }} +vht_capab={{ output.value }} {% endif %} # ieee80211n: Whether IEEE 802.11n (HT) is enabled -- cgit v1.2.3 From 857c4c10248a4f74b9b73d302ed9776cb818ff1b Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 16 Sep 2020 21:25:40 +0200 Subject: wireless: T2887: hostapd template cleanup --- data/templates/wifi/hostapd.conf.tmpl | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'data/templates') diff --git a/data/templates/wifi/hostapd.conf.tmpl b/data/templates/wifi/hostapd.conf.tmpl index b00515d76..136942ca8 100644 --- a/data/templates/wifi/hostapd.conf.tmpl +++ b/data/templates/wifi/hostapd.conf.tmpl @@ -341,13 +341,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 + ']' %} -- cgit v1.2.3 From de5cfd35ba14b75b58da653643472de93577b434 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 16 Sep 2020 21:54:50 +0200 Subject: wireless: T2887: add smoketest for hostapd --- data/templates/wifi/hostapd.conf.tmpl | 4 -- smoketest/scripts/cli/test_interfaces_wireless.py | 87 +++++++++++++++++++++++ 2 files changed, 87 insertions(+), 4 deletions(-) (limited to 'data/templates') diff --git a/data/templates/wifi/hostapd.conf.tmpl b/data/templates/wifi/hostapd.conf.tmpl index 136942ca8..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 %} 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 . 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() -- cgit v1.2.3