diff options
120 files changed, 2646 insertions, 2201 deletions
@@ -31,9 +31,8 @@ interface_definitions: $(config_xml_obj) rm -rf $(TMPL_DIR)/vpn/ipsec/remote-access/radius/source-address # T4284 neq QoS implementation is not yet live - find $(TMPL_DIR)/interfaces -name traffic-policy -type d -exec rm -rf {} \; find $(TMPL_DIR)/interfaces -name redirect -type d -exec rm -rf {} \; - rm -rf $(TMPL_DIR)/traffic-policy + rm -rf $(TMPL_DIR)/qos rm -rf $(TMPL_DIR)/interfaces/input # XXX: test if there are empty node.def files - this is not allowed as these diff --git a/data/templates/accel-ppp/ipoe.config.tmpl b/data/templates/accel-ppp/ipoe.config.tmpl index 1cf2ab0be..92c2d5715 100644 --- a/data/templates/accel-ppp/ipoe.config.tmpl +++ b/data/templates/accel-ppp/ipoe.config.tmpl @@ -25,11 +25,21 @@ level=5 verbose=1 {% for interface in interfaces %} {% if interface.vlan_mon %} -interface=re:{{ interface.name }}\.\d+,{% else %}interface={{ interface.name }},{% endif %}shared={{ interface.shared }},mode={{ interface.mode }},ifcfg={{ interface.ifcfg }},range={{ interface.range }},start={{ interface.sess_start }},ipv6=1 +interface=re:{{ interface.name }}\.\d+,{% else %}interface={{ interface.name }},{% endif %}shared={{ interface.shared }},mode={{ interface.mode }},ifcfg={{ interface.ifcfg }}{{ ',range=' + interface.range if interface.range is defined and interface.range is not none }},start={{ interface.sess_start }},ipv6=1 {% endfor %} -{% if auth_mode == 'noauth' %} +{% if auth_mode == 'noauth' %} noauth=1 -{% elif auth_mode == 'local' %} +{% if client_named_ip_pool %} +{% for pool in client_named_ip_pool %} +{% if pool.subnet is defined %} +ip-pool={{ pool.name }} +{% endif %} +{% if pool.gateway_address is defined %} +gw-ip-address={{ pool.gateway_address }}/{{ pool.subnet.split('/')[1] }} +{% endif %} +{% endfor%} +{% endif %} +{% elif auth_mode == 'local' %} username=ifname password=csid {% endif %} @@ -61,6 +71,18 @@ verbose=1 [ipv6-dhcp] verbose=1 +{% if client_named_ip_pool %} +[ip-pool] +{% for pool in client_named_ip_pool %} +{% if pool.subnet is defined %} +{{ pool.subnet }},name={{ pool.name }} +{% endif %} +{% if pool.gateway_address is defined %} +gw-ip-address={{ pool.gateway_address }}/{{ pool.subnet.split('/')[1] }} +{% endif %} +{% endfor%} +{% endif %} + {% if client_ipv6_pool %} [ipv6-pool] {% for p in client_ipv6_pool %} diff --git a/data/templates/bcast-relay/udp-broadcast-relay.tmpl b/data/templates/bcast-relay/udp-broadcast-relay.tmpl index 73e9acad4..7b2b9b1a2 100644 --- a/data/templates/bcast-relay/udp-broadcast-relay.tmpl +++ b/data/templates/bcast-relay/udp-broadcast-relay.tmpl @@ -1,7 +1,5 @@ ### Autogenerated by bcast_relay.py ### # UDP broadcast relay configuration for instance {{ id }} -{% if description %} -# Comment: {{ description }} -{% endif %} -DAEMON_ARGS="{{ '-s ' + address if address is defined }} {{ instance }} {{ port }} {{ interface | join(' ') }}" +{{ '# ' ~ description if description is vyos_defined }} +DAEMON_ARGS="{{ '-s ' ~ address if address is defined }} {{ instance }} {{ port }} {{ interface | join(' ') }}" diff --git a/data/templates/conntrack/nftables-ct.tmpl b/data/templates/conntrack/nftables-ct.tmpl index c0fe5297d..cebc1a54e 100644 --- a/data/templates/conntrack/nftables-ct.tmpl +++ b/data/templates/conntrack/nftables-ct.tmpl @@ -10,31 +10,27 @@ flush chain raw {{ nft_ct_timeout_name }} table raw { chain {{ nft_ct_ignore_name }} { -{% if ignore is defined and ignore.rule is defined and ignore.rule is not none %} +{% if ignore.rule is vyos_defined %} {% for rule, rule_config in ignore.rule.items() %} # rule-{{ rule }} {{ '- ' ~ rule_config.description if rule_config.description is defined and rule_config.description is not none }} {% set nft_command = '' %} -{% if rule_config.inbound_interface is defined and rule_config.inbound_interface is not none %} +{% if rule_config.inbound_interface is vyos_defined %} {% set nft_command = nft_command ~ ' iifname ' ~ rule_config.inbound_interface %} {% endif %} -{% if rule_config.protocol is defined and rule_config.protocol is not none %} +{% if rule_config.protocol is vyos_defined %} {% set nft_command = nft_command ~ ' ip protocol ' ~ rule_config.protocol %} {% endif %} -{% if rule_config.destination is defined and rule_config.destination is not none %} -{% if rule_config.destination.address is defined and rule_config.destination.address is not none %} -{% set nft_command = nft_command ~ ' ip daddr ' ~ rule_config.destination.address %} -{% endif %} -{% if rule_config.destination.port is defined and rule_config.destination.port is not none %} -{% set nft_command = nft_command ~ ' ' ~ rule_config.protocol ~ ' dport { ' ~ rule_config.destination.port ~ ' }' %} -{% endif %} +{% if rule_config.destination.address is vyos_defined %} +{% set nft_command = nft_command ~ ' ip daddr ' ~ rule_config.destination.address %} {% endif %} -{% if rule_config.source is defined and rule_config.source is not none %} -{% if rule_config.source.address is defined and rule_config.source.address is not none %} -{% set nft_command = nft_command ~ ' ip saddr ' ~ rule_config.source.address %} -{% endif %} -{% if rule_config.source.port is defined and rule_config.source.port is not none %} -{% set nft_command = nft_command ~ ' ' ~ rule_config.protocol ~ ' sport { ' ~ rule_config.source.port ~ ' }' %} -{% endif %} +{% if rule_config.destination.port is vyos_defined %} +{% set nft_command = nft_command ~ ' ' ~ rule_config.protocol ~ ' dport { ' ~ rule_config.destination.port ~ ' }' %} +{% endif %} +{% if rule_config.source.address is vyos_defined %} +{% set nft_command = nft_command ~ ' ip saddr ' ~ rule_config.source.address %} +{% endif %} +{% if rule_config.source.port is vyos_defined %} +{% set nft_command = nft_command ~ ' ' ~ rule_config.protocol ~ ' sport { ' ~ rule_config.source.port ~ ' }' %} {% endif %} {{ nft_command }} counter notrack comment ignore-{{ rule }} {% endfor %} @@ -42,7 +38,7 @@ table raw { return } chain {{ nft_ct_timeout_name }} { -{% if timeout is defined and timeout.custom is defined and timeout.custom.rule is defined and timeout.custom.rule is not none %} +{% if timeout.custom.rule is vyos_defined %} {% for rule, rule_config in timeout.custom.rule.items() %} # rule-{{ rule }} {{ '- ' ~ rule_config.description if rule_config.description is defined and rule_config.description is not none }} {% endfor %} diff --git a/data/templates/conntrack/sysctl.conf.tmpl b/data/templates/conntrack/sysctl.conf.tmpl index 9e97c3286..075402c04 100644 --- a/data/templates/conntrack/sysctl.conf.tmpl +++ b/data/templates/conntrack/sysctl.conf.tmpl @@ -6,7 +6,7 @@ net.netfilter.nf_conntrack_max = {{ table_size }} net.ipv4.tcp_max_syn_backlog = {{ tcp.half_open_connections }} -net.netfilter.nf_conntrack_tcp_loose = {{ '1' if tcp.loose == 'enable' else '0' }} +net.netfilter.nf_conntrack_tcp_loose = {{ '1' if tcp.loose is vyos_defined('enable') else '0' }} net.netfilter.nf_conntrack_tcp_max_retrans = {{ tcp.max_retrans }} net.netfilter.nf_conntrack_icmp_timeout = {{ timeout.icmp }} diff --git a/data/templates/containers/registry.tmpl b/data/templates/containers/registry.tmpl index 0347de673..0cbd9ecc2 100644 --- a/data/templates/containers/registry.tmpl +++ b/data/templates/containers/registry.tmpl @@ -1,5 +1,5 @@ ### Autogenerated by /usr/libexec/vyos/conf_mode/containers.py ### -{% if registry is defined and registry is not none %} +{% if registry is vyos_defined %} unqualified-search-registries = {{ registry }} {% endif %} diff --git a/data/templates/dhcp-client/daemon-options.tmpl b/data/templates/dhcp-client/daemon-options.tmpl index 40629dca1..5b3bff73f 100644 --- a/data/templates/dhcp-client/daemon-options.tmpl +++ b/data/templates/dhcp-client/daemon-options.tmpl @@ -1,4 +1,4 @@ ### Autogenerated by interface.py ### -DHCLIENT_OPTS="-nw -cf /var/lib/dhcp/dhclient_{{ifname}}.conf -pf /var/lib/dhcp/dhclient_{{ifname}}.pid -lf /var/lib/dhcp/dhclient_{{ifname}}.leases{{" -e IF_METRIC=" ~ dhcp_options.default_route_distance if dhcp_options.default_route_distance is defined and dhcp_options.default_route_distance is not none}} {{ifname}}" +DHCLIENT_OPTS="-nw -cf /var/lib/dhcp/dhclient_{{ ifname }}.conf -pf /var/lib/dhcp/dhclient_{{ ifname }}.pid -lf /var/lib/dhcp/dhclient_{{ ifname }}.leases{{" -e IF_METRIC=" ~ dhcp_options.default_route_distance if dhcp_options.default_route_distance is vyos_defined }} {{ ifname }}" diff --git a/data/templates/dhcp-client/ipv4.tmpl b/data/templates/dhcp-client/ipv4.tmpl index b3e74c22b..83fb93dc1 100644 --- a/data/templates/dhcp-client/ipv4.tmpl +++ b/data/templates/dhcp-client/ipv4.tmpl @@ -7,7 +7,7 @@ initial-interval 2; interface "{{ ifname }}" { send host-name "{{ dhcp_options.host_name }}"; -{% if dhcp_options.client_id is defined and dhcp_options.client_id is not none %} +{% if dhcp_options.client_id is vyos_defined %} {% set client_id = dhcp_options.client_id %} {# Use HEX representation of client-id as it is send in MAC-address style using hex characters. If not HEX, use double quotes ASCII format #} {% if not dhcp_options.client_id.split(':') | length >= 5 %} @@ -15,18 +15,18 @@ interface "{{ ifname }}" { {% endif %} send dhcp-client-identifier {{ client_id }}; {% endif %} -{% if dhcp_options.vendor_class_id is defined and dhcp_options.vendor_class_id is not none %} +{% if dhcp_options.vendor_class_id is vyos_defined %} send vendor-class-identifier "{{ dhcp_options.vendor_class_id }}"; {% endif %} # The request statement causes the client to request that any server responding to the # client send the client its values for the specified options. - request subnet-mask, broadcast-address,{{ " routers," if dhcp_options.no_default_route is not defined }} domain-name-servers, + request subnet-mask, broadcast-address,{{ " routers," if dhcp_options.no_default_route is not vyos_defined }} domain-name-servers, rfc3442-classless-static-routes, domain-name, interface-mtu; # The require statement lists options that must be sent in order for an offer to be # accepted. Offers that do not contain all the listed options will be ignored! require subnet-mask; -{% if dhcp_options.reject is defined and dhcp_options.reject is not none %} +{% if dhcp_options.reject is vyos_defined %} # Block addresses coming from theses dhcp servers if configured. reject {{ dhcp_options.reject | join(', ') }}; {% endif %} diff --git a/data/templates/dhcp-client/ipv6.tmpl b/data/templates/dhcp-client/ipv6.tmpl index c292664e9..085cfe5a9 100644 --- a/data/templates/dhcp-client/ipv6.tmpl +++ b/data/templates/dhcp-client/ipv6.tmpl @@ -2,54 +2,54 @@ # man https://www.unix.com/man-page/debian/5/dhcp6c.conf/ interface {{ ifname }} { -{% if dhcpv6_options is defined and dhcpv6_options.duid is defined and dhcpv6_options.duid is not none %} +{% if dhcpv6_options.duid is vyos_defined %} send client-id {{ dhcpv6_options.duid }}; {% endif %} -{% if address is defined and 'dhcpv6' in address %} +{% if address is vyos_defined and 'dhcpv6' in address %} request domain-name-servers; request domain-name; -{% if dhcpv6_options is defined and dhcpv6_options.parameters_only is defined %} +{% if dhcpv6_options.parameters_only is vyos_defined %} information-only; {% endif %} -{% if dhcpv6_options is not defined or dhcpv6_options.temporary is not defined %} +{% if dhcpv6_options.temporary is not vyos_defined %} send ia-na 0; # non-temporary address {% endif %} -{% if dhcpv6_options is defined and dhcpv6_options.rapid_commit is defined %} +{% if dhcpv6_options.rapid_commit is vyos_defined %} send rapid-commit; # wait for immediate reply instead of advertisements {% endif %} {% endif %} -{% if dhcpv6_options is defined and dhcpv6_options.pd is defined %} +{% if dhcpv6_options.pd is vyos_defined %} {% for pd in dhcpv6_options.pd %} send ia-pd {{ pd }}; # prefix delegation #{{ pd }} {% endfor %} {% endif %} }; -{% if address is defined and 'dhcpv6' in address %} -{% if dhcpv6_options is not defined or dhcpv6_options.temporary is not defined %} +{% if address is vyos_defined and 'dhcpv6' in address %} +{% if dhcpv6_options.temporary is not vyos_defined %} id-assoc na 0 { # Identity association for non temporary address }; {% endif %} {% endif %} -{% if dhcpv6_options is defined and dhcpv6_options.pd is defined %} -{% for pd in dhcpv6_options.pd %} +{% if dhcpv6_options.pd is vyos_defined %} +{% for pd, pd_config in dhcpv6_options.pd.items() %} id-assoc pd {{ pd }} { {# length got a default value #} - prefix ::/{{ dhcpv6_options.pd[pd].length }} infinity; -{% set sla_len = 64 - dhcpv6_options.pd[pd].length|int %} + prefix ::/{{ pd_config.length }} infinity; +{% set sla_len = 64 - pd_config.length|int %} {% set count = namespace(value=0) %} -{% for interface in dhcpv6_options.pd[pd].interface if dhcpv6_options.pd[pd].interface is defined %} +{% for interface, interface_config in pd_config.interface.items() if pd_config.interface is vyos_defined %} prefix-interface {{ interface }} { sla-len {{ sla_len }}; -{% if dhcpv6_options.pd[pd].interface[interface].sla_id is defined and dhcpv6_options.pd[pd].interface[interface].sla_id is not none %} - sla-id {{ dhcpv6_options.pd[pd].interface[interface].sla_id }}; +{% if interface_config.sla_id is vyos_defined %} + sla-id {{ interface_config.sla_id }}; {% else %} sla-id {{ count.value }}; {% endif %} -{% if dhcpv6_options.pd[pd].interface[interface].address is defined and dhcpv6_options.pd[pd].interface[interface].address is not none %} - ifid {{ dhcpv6_options.pd[pd].interface[interface].address }}; +{% if interface_config.address is vyos_defined %} + ifid {{ interface_config.address }}; {% endif %} }; {% set count.value = count.value + 1 %} diff --git a/data/templates/dhcp-relay/dhcrelay.conf.tmpl b/data/templates/dhcp-relay/dhcrelay.conf.tmpl index a9d17ed9a..11710bd8e 100644 --- a/data/templates/dhcp-relay/dhcrelay.conf.tmpl +++ b/data/templates/dhcp-relay/dhcrelay.conf.tmpl @@ -1,6 +1,6 @@ ### Autogenerated by dhcp_relay.py ### -{% set max_size = '-A ' + relay_options.max_size if relay_options.max_size is defined and relay_options.max_size is not none %} +{% set max_size = '-A ' ~ relay_options.max_size if relay_options.max_size is vyos_defined %} {# hop_count and relay_agents_packets is a default option, thus it is always present #} OPTIONS="-c {{ relay_options.hop_count }} -a -m {{ relay_options.relay_agents_packets }} {{ max_size }} -i {{ interface | join(' -i ') }} {{ server | join(' ') }}" diff --git a/data/templates/dhcp-relay/dhcrelay6.conf.tmpl b/data/templates/dhcp-relay/dhcrelay6.conf.tmpl index 58c216b7c..1fd5de18c 100644 --- a/data/templates/dhcp-relay/dhcrelay6.conf.tmpl +++ b/data/templates/dhcp-relay/dhcrelay6.conf.tmpl @@ -4,18 +4,18 @@ {% set upstream = namespace(value='') %} {% for interface, config in upstream_interface.items() %} {% for address in config.address %} -{% set upstream.value = upstream.value + '-u ' + address + '%' + interface + ' ' %} +{% set upstream.value = upstream.value ~ '-u ' ~ address ~ '%' ~ interface ~ ' ' %} {% endfor %} {% endfor %} {# listen_interface is mandatory so it's always present #} {% set listen = namespace(value='') %} {% for interface, config in listen_interface.items() %} -{% if config.address is defined and config.address is not none %} -{% set listen.value = listen.value + '-l ' + config.address + '%' + interface + ' ' %} +{% if config.address is vyos_defined %} +{% set listen.value = listen.value ~ '-l ' ~ config.address ~ '%' ~ interface ~ ' ' %} {% else %} -{% set listen.value = listen.value + '-l ' + interface + ' ' %} +{% set listen.value = listen.value ~ '-l ' ~ interface ~ ' ' %} {% endif %} {% endfor %} -OPTIONS="{{ listen.value }} {{ upstream.value }} -c {{ max_hop_count }} {{ '-I' if use_interface_id_option is defined }}" +OPTIONS="{{ listen.value }} {{ upstream.value }} -c {{ max_hop_count }} {{ '-I' if use_interface_id_option is vyos_defined }}" diff --git a/data/templates/dhcp-server/dhcpd.conf.tmpl b/data/templates/dhcp-server/dhcpd.conf.tmpl index dbd864b5e..00f6eba8e 100644 --- a/data/templates/dhcp-server/dhcpd.conf.tmpl +++ b/data/templates/dhcp-server/dhcpd.conf.tmpl @@ -4,7 +4,7 @@ # https://www.isc.org/wp-content/uploads/2017/08/dhcp43options.html # # log-facility local7; -{% if hostfile_update is defined %} +{% if hostfile_update is vyos_defined %} on release { set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name); set ClientIp = binary-to-ascii(10, 8, ".",leased-address); @@ -17,13 +17,13 @@ on expiry { } {% endif %} -{{ 'use-host-decl-names on;' if host_decl_name is defined }} -ddns-update-style {{ 'interim' if dynamic_dns_update is defined else 'none' }}; +{{ 'use-host-decl-names on;' if host_decl_name is vyos_defined }} +ddns-update-style {{ 'interim' if dynamic_dns_update is vyos_defined else 'none' }}; option rfc3442-static-route code 121 = array of integer 8; option windows-static-route code 249 = array of integer 8; option wpad-url code 252 = text; -{% if global_parameters is defined and global_parameters is not none %} +{% if global_parameters is vyos_defined %} # The following {{ global_parameters | length }} line(s) have been added as # global-parameters in the CLI and have not been validated !!! {% for parameter in global_parameters %} @@ -31,7 +31,7 @@ option wpad-url code 252 = text; {% endfor %} {% endif %} -{% if failover is defined and failover is not none %} +{% if failover is vyos_defined %} # DHCP failover configuration failover peer "{{ failover.name }}" { {% if failover.status == 'primary' %} @@ -50,7 +50,7 @@ failover peer "{{ failover.name }}" { load balance max seconds 3; } {% endif %} -{% if listen_address is defined and listen_address is not none %} +{% if listen_address is vyos_defined %} # DHCP server serving relay subnet, we need a connector to the real world {% for address in listen_address %} @@ -60,70 +60,70 @@ subnet {{ address | network_from_ipv4 }} netmask {{ address | netmask_from_ipv4 {% endif %} # Shared network configration(s) -{% if shared_network_name is defined and shared_network_name is not none %} -{% for network, network_config in shared_network_name.items() if network_config.disable is not defined %} -shared-network {{ network | replace('_','-') }} { -{% if network_config.authoritative is defined %} +{% if shared_network_name is vyos_defined %} +{% for network, network_config in shared_network_name.items() if network_config.disable is not vyos_defined %} +shared-network {{ network }} { +{% if network_config.authoritative is vyos_defined %} authoritative; {% endif %} -{% if network_config.name_server is defined and network_config.name_server is not none %} +{% if network_config.name_server is vyos_defined %} option domain-name-servers {{ network_config.name_server | join(', ') }}; {% endif %} -{% if network_config.domain_name is defined and network_config.domain_name is not none %} +{% if network_config.domain_name is vyos_defined %} option domain-name "{{ network_config.domain_name }}"; {% endif %} -{% if network_config.domain_search is defined and network_config.domain_search is not none %} +{% if network_config.domain_search is vyos_defined %} option domain-search "{{ network_config.domain_search | join('", "') }}"; {% endif %} -{% if network_config.ntp_server is defined and network_config.ntp_server is not none %} +{% if network_config.ntp_server is vyos_defined %} option ntp-servers {{ network_config.ntp_server | join(', ') }}; {% endif %} -{% if network_config.ping_check is defined %} +{% if network_config.ping_check is vyos_defined %} ping-check true; {% endif %} -{% if network_config.shared_network_parameters is defined and network_config.shared_network_parameters is not none %} +{% if network_config.shared_network_parameters is vyos_defined %} # The following {{ network_config.shared_network_parameters | length }} line(s) # were added as shared-network-parameters in the CLI and have not been validated {% for parameter in network_config.shared_network_parameters %} {{ parameter }} {% endfor %} {% endif %} -{% if network_config.subnet is defined and network_config.subnet is not none %} +{% if network_config.subnet is vyos_defined %} {% for subnet, subnet_config in network_config.subnet.items() %} -{% if subnet_config.description is defined and subnet_config.description is not none %} +{% if subnet_config.description is vyos_defined %} # {{ subnet_config.description }} {% endif %} subnet {{ subnet | address_from_cidr }} netmask {{ subnet | netmask_from_cidr }} { -{% if subnet_config.name_server is defined and subnet_config.name_server is not none %} +{% if subnet_config.name_server is vyos_defined %} option domain-name-servers {{ subnet_config.name_server | join(', ') }}; {% endif %} -{% if subnet_config.domain_name is defined and subnet_config.domain_name is not none %} +{% if subnet_config.domain_name is vyos_defined %} option domain-name "{{ subnet_config.domain_name }}"; {% endif %} -{% if subnet_config.domain_search is defined and subnet_config.domain_search is not none %} +{% if subnet_config.domain_search is vyos_defined %} option domain-search "{{ subnet_config.domain_search | join('", "') }}"; {% endif %} -{% if subnet_config.ntp_server is defined and subnet_config.ntp_server is not none %} +{% if subnet_config.ntp_server is vyos_defined %} option ntp-servers {{ subnet_config.ntp_server | join(', ') }}; {% endif %} -{% if subnet_config.pop_server is defined and subnet_config.pop_server is not none %} +{% if subnet_config.pop_server is vyos_defined %} option pop-server {{ subnet_config.pop_server | join(', ') }}; {% endif %} -{% if subnet_config.smtp_server is defined and subnet_config.smtp_server is not none %} +{% if subnet_config.smtp_server is vyos_defined %} option smtp-server {{ subnet_config.smtp_server | join(', ') }}; {% endif %} -{% if subnet_config.time_server is defined and subnet_config.time_server is not none %} +{% if subnet_config.time_server is vyos_defined %} option time-servers {{ subnet_config.time_server | join(', ') }}; {% endif %} -{% if subnet_config.wins_server is defined and subnet_config.wins_server is not none %} +{% if subnet_config.wins_server is vyos_defined %} option netbios-name-servers {{ subnet_config.wins_server | join(', ') }}; {% endif %} -{% if subnet_config.static_route is defined and subnet_config.static_route is not none %} +{% if subnet_config.static_route is vyos_defined %} {% set static_default_route = '' %} -{% if subnet_config.default_router and subnet_config.default_router is not none %} -{% set static_default_route = ', ' + '0.0.0.0/0' | isc_static_route(subnet_config.default_router) %} +{% if subnet_config.default_router is vyos_defined %} +{% set static_default_route = ', ' ~ '0.0.0.0/0' | isc_static_route(subnet_config.default_router) %} {% endif %} -{% if subnet_config.static_route is defined and subnet_config.static_route is not none %} +{% if subnet_config.static_route is vyos_defined %} {% set rfc3442_routes = [] %} {% for route, route_options in subnet_config.static_route.items() %} {% set rfc3442_routes = rfc3442_routes.append(route | isc_static_route(route_options.next_hop)) %} @@ -132,56 +132,59 @@ shared-network {{ network | replace('_','-') }} { option windows-static-route {{ rfc3442_routes | join(', ') }}; {% endif %} {% endif %} -{% if subnet_config.ip_forwarding is defined %} +{% if subnet_config.ip_forwarding is vyos_defined %} option ip-forwarding true; {% endif %} -{% if subnet_config.default_router and subnet_config.default_router is not none %} +{% if subnet_config.default_router is vyos_defined %} option routers {{ subnet_config.default_router }}; {% endif %} -{% if subnet_config.server_identifier is defined and subnet_config.server_identifier is not none %} +{% if subnet_config.server_identifier is vyos_defined %} option dhcp-server-identifier {{ subnet_config.server_identifier }}; {% endif %} -{% if subnet_config.subnet_parameters is defined and subnet_config.subnet_parameters is not none %} +{% if subnet_config.subnet_parameters is vyos_defined %} # The following {{ subnet_config.subnet_parameters | length }} line(s) were added as # subnet-parameters in the CLI and have not been validated!!! {% for parameter in subnet_config.subnet_parameters %} {{ parameter }} {% endfor %} {% endif %} -{% if subnet_config.tftp_server_name is defined and subnet_config.tftp_server_name is not none %} +{% if subnet_config.tftp_server_name is vyos_defined %} option tftp-server-name "{{ subnet_config.tftp_server_name }}"; {% endif %} -{% if subnet_config.bootfile_name is defined and subnet_config.bootfile_name is not none %} +{% if subnet_config.bootfile_name is vyos_defined %} option bootfile-name "{{ subnet_config.bootfile_name }}"; filename "{{ subnet_config.bootfile_name }}"; {% endif %} -{% if subnet_config.bootfile_server is defined and subnet_config.bootfile_server is not none %} +{% if subnet_config.bootfile_server is vyos_defined %} next-server {{ subnet_config.bootfile_server }}; {% endif %} -{% if subnet_config.time_offset is defined and subnet_config.time_offset is not none %} +{% if subnet_config.bootfile_size is defined and subnet_config.bootfile_size is not none %} + option boot-size {{ subnet_config.bootfile_size }}; +{% endif %} +{% if subnet_config.time_offset is vyos_defined %} option time-offset {{ subnet_config.time_offset }}; {% endif %} -{% if subnet_config.wpad_url is defined and subnet_config.wpad_url is not none %} +{% if subnet_config.wpad_url is vyos_defined %} option wpad-url "{{ subnet_config.wpad_url }}"; {% endif %} -{% if subnet_config.client_prefix_length is defined and subnet_config.client_prefix_length is not none %} +{% if subnet_config.client_prefix_length is vyos_defined %} option subnet-mask {{ ('0.0.0.0/' ~ subnet_config.client_prefix_length) | netmask_from_cidr }}; {% endif %} -{% if subnet_config.lease is defined and subnet_config.lease is not none %} +{% if subnet_config.lease is vyos_defined %} default-lease-time {{ subnet_config.lease }}; max-lease-time {{ subnet_config.lease }}; {% endif %} -{% if network_config.ping_check is not defined and subnet_config.ping_check is defined %} +{% if network_config.ping_check is not vyos_defined and subnet_config.ping_check is vyos_defined %} ping-check true; {% endif %} -{% if subnet_config.static_mapping is defined and subnet_config.static_mapping is not none %} -{% for host, host_config in subnet_config.static_mapping.items() if host_config.disable is not defined %} - host {{ host | replace('_','-') if host_decl_name is defined else network | replace('_','-') + '_' + host | replace('_','-') }} { -{% if host_config.ip_address is defined and host_config.ip_address is not none %} +{% if subnet_config.static_mapping is vyos_defined %} +{% for host, host_config in subnet_config.static_mapping.items() if host_config.disable is not vyos_defined %} + host {{ host | replace('_','-') if host_decl_name is vyos_defined else network | replace('_','-') ~ '_' ~ host | replace('_','-') }} { +{% if host_config.ip_address is vyos_defined %} fixed-address {{ host_config.ip_address }}; {% endif %} hardware ethernet {{ host_config.mac_address }}; -{% if host_config.static_mapping_parameters is defined and host_config.static_mapping_parameters is not none %} +{% if host_config.static_mapping_parameters is vyos_defined %} # The following {{ host_config.static_mapping_parameters | length }} line(s) were added # as static-mapping-parameters in the CLI and have not been validated {% for parameter in host_config.static_mapping_parameters %} @@ -191,20 +194,20 @@ shared-network {{ network | replace('_','-') }} { } {% endfor %} {% endif %} -{% if subnet_config.range is defined and subnet_config.range is not none %} +{% if subnet_config.range is vyos_defined %} {# pool configuration can only be used if there follows a range option #} pool { {% endif %} -{% if subnet_config.enable_failover is defined %} +{% if subnet_config.enable_failover is vyos_defined %} failover peer "{{ failover.name }}"; deny dynamic bootp clients; {% endif %} -{% if subnet_config.range is defined and subnet_config.range is not none %} +{% if subnet_config.range is vyos_defined %} {% for range, range_options in subnet_config.range.items() %} range {{ range_options.start }} {{ range_options.stop }}; {% endfor %} {% endif %} -{% if subnet_config.range is defined and subnet_config.range is not none %} +{% if subnet_config.range is vyos_defined %} {# pool configuration can only be used if there follows a range option #} } {% endif %} @@ -212,8 +215,8 @@ shared-network {{ network | replace('_','-') }} { {% endfor %} {% endif %} on commit { - set shared-networkname = "{{ network | replace('_','-') }}"; -{% if hostfile_update is defined %} + set shared-networkname = "{{ network }}"; +{% if hostfile_update is vyos_defined %} set ClientIp = binary-to-ascii(10, 8, ".", leased-address); set ClientMac = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6)); set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name, "empty_hostname"); diff --git a/data/templates/dhcp-server/dhcpdv6.conf.tmpl b/data/templates/dhcp-server/dhcpdv6.conf.tmpl index 45d629928..1a55668e1 100644 --- a/data/templates/dhcp-server/dhcpdv6.conf.tmpl +++ b/data/templates/dhcp-server/dhcpdv6.conf.tmpl @@ -4,74 +4,74 @@ # https://www.isc.org/wp-content/uploads/2017/08/dhcp43options.html log-facility local7; -{% if preference is defined and preference is not none %} +{% if preference is vyos_defined %} option dhcp6.preference {{ preference }}; {% endif %} -{% if global_parameters is defined and global_parameters.name_server is defined and global_parameters.name_server is not none %} +{% if global_parameters.name_server is vyos_defined %} option dhcp6.name-servers {{ global_parameters.name_server | join(', ') }}; {% endif %} # Shared network configration(s) -{% if shared_network_name is defined and shared_network_name is not none %} -{% for network, network_config in shared_network_name.items() if network_config.disable is not defined %} -shared-network {{ network | replace('_','-') }} { -{% if network_config.common_options is defined and network_config.common_options is not none %} -{% if network_config.common_options.info_refresh_time is defined and network_config.common_options.info_refresh_time is not none %} +{% if shared_network_name is vyos_defined %} +{% for network, network_config in shared_network_name.items() if network_config.disable is not vyos_defined %} +shared-network {{ network }} { +{% if network_config.common_options is vyos_defined %} +{% if network_config.common_options.info_refresh_time is vyos_defined %} option dhcp6.info-refresh-time {{ network_config.common_options.info_refresh_time }}; {% endif %} -{% if network_config.common_options.domain_search is defined and network_config.common_options.domain_search is not none %} +{% if network_config.common_options.domain_search is vyos_defined %} option dhcp6.domain-search "{{ network_config.common_options.domain_search | join('", "') }}"; {% endif %} -{% if network_config.common_options.name_server is defined and network_config.common_options.name_server is not none %} +{% if network_config.common_options.name_server is vyos_defined %} option dhcp6.name-servers {{ network_config.common_options.name_server | join(', ') }}; {% endif %} {% endif %} -{% if network_config.subnet is defined and network_config.subnet is not none %} +{% if network_config.subnet is vyos_defined %} {% for subnet, subnet_config in network_config.subnet.items() %} subnet6 {{ subnet }} { -{% if subnet_config.address_range is defined and subnet_config.address_range is not none %} -{% if subnet_config.address_range.prefix is defined and subnet_config.address_range.prefix is not none %} +{% if subnet_config.address_range is vyos_defined %} +{% if subnet_config.address_range.prefix is vyos_defined %} {% for prefix, prefix_config in subnet_config.address_range.prefix.items() %} - range6 {{ prefix }} {{ "temporary" if prefix_config.temporary is defined }}; + range6 {{ prefix }} {{ "temporary" if prefix_config.temporary is vyos_defined }}; {% endfor %} {% endif %} -{% if subnet_config.address_range.start is defined and subnet_config.address_range.start is not none %} +{% if subnet_config.address_range.start is vyos_defined %} {% for address, address_config in subnet_config.address_range.start.items() %} range6 {{ address }} {{ address_config.stop }}; {% endfor %} {% endif %} {% endif %} -{% if subnet_config.domain_search is defined and subnet_config.domain_search is not none %} +{% if subnet_config.domain_search is vyos_defined %} option dhcp6.domain-search "{{ subnet_config.domain_search | join('", "') }}"; {% endif %} -{% if subnet_config.lease_time is defined and subnet_config.lease_time is not none %} -{% if subnet_config.lease_time.default is defined and subnet_config.lease_time.default is not none %} +{% if subnet_config.lease_time is vyos_defined %} +{% if subnet_config.lease_time.default is vyos_defined %} default-lease-time {{ subnet_config.lease_time.default }}; {% endif %} -{% if subnet_config.lease_time.maximum is defined and subnet_config.lease_time.maximum is not none %} +{% if subnet_config.lease_time.maximum is vyos_defined %} max-lease-time {{ subnet_config.lease_time.maximum }}; {% endif %} -{% if subnet_config.lease_time.minimum is defined and subnet_config.lease_time.minimum is not none %} +{% if subnet_config.lease_time.minimum is vyos_defined %} min-lease-time {{ subnet_config.lease_time.minimum }}; {% endif %} {% endif %} -{% if subnet_config.name_server is defined and subnet_config.name_server is not none %} +{% if subnet_config.name_server is vyos_defined %} option dhcp6.name-servers {{ subnet_config.name_server | join(', ') }}; {% endif %} -{% if subnet_config.nis_domain is defined and subnet_config.nis_domain is not none %} +{% if subnet_config.nis_domain is vyos_defined %} option dhcp6.nis-domain-name "{{ subnet_config.nis_domain }}"; {% endif %} -{% if subnet_config.nis_server is defined and subnet_config.nis_server is not none %} +{% if subnet_config.nis_server is vyos_defined %} option dhcp6.nis-servers {{ subnet_config.nis_server | join(', ') }}; {% endif %} -{% if subnet_config.nisplus_domain is defined and subnet_config.nisplus_domain is not none %} +{% if subnet_config.nisplus_domain is vyos_defined %} option dhcp6.nisp-domain-name "{{ subnet_config.nisplus_domain }}"; {% endif %} -{% if subnet_config.nisplus_server is defined and subnet_config.nisplus_server is not none %} +{% if subnet_config.nisplus_server is vyos_defined %} option dhcp6.nisp-servers {{ subnet_config.nisplus_server | join(', ') }}; {% endif %} -{% if subnet_config.sip_server is defined and subnet_config.sip_server is not none %} +{% if subnet_config.sip_server is vyos_defined %} {% set server_ip = [] %} {% set server_fqdn = [] %} {% for address in subnet_config.sip_server %} @@ -81,33 +81,33 @@ shared-network {{ network | replace('_','-') }} { {% set server_fqdn = server_fqdn.append(address) %} {% endif %} {% endfor %} -{% if server_ip is defined and server_ip | length > 0 %} +{% if server_ip is vyos_defined and server_ip | length > 0 %} option dhcp6.sip-servers-addresses {{ server_ip | join(', ') }}; {% endif %} -{% if server_fqdn is defined and server_fqdn | length > 0 %} +{% if server_fqdn is vyos_defined and server_fqdn | length > 0 %} option dhcp6.sip-servers-names "{{ server_fqdn | join('", "') }}"; {% endif %} {% endif %} -{% if subnet_config.sntp_server is defined and subnet_config.sntp_server is not none %} +{% if subnet_config.sntp_server is vyos_defined %} option dhcp6.sntp-servers {{ subnet_config.sntp_server | join(', ') }}; {% endif %} -{% if subnet_config.prefix_delegation is defined and subnet_config.prefix_delegation.start is defined and subnet_config.prefix_delegation.start is not none %} +{% if subnet_config.prefix_delegation.start is vyos_defined %} {% for prefix, prefix_config in subnet_config.prefix_delegation.start.items() %} prefix6 {{ prefix }} {{ prefix_config.stop }} /{{ prefix_config.prefix_length }}; {% endfor %} {% endif %} -{% if subnet_config.static_mapping is defined and subnet_config.static_mapping is not none %} +{% if subnet_config.static_mapping is vyos_defined %} # begin configuration of static client mappings -{% for host, host_config in subnet_config.static_mapping.items() if host_config.disable is not defined %} +{% for host, host_config in subnet_config.static_mapping.items() if host_config.disable is not vyos_defined %} host {{ network | replace('_','-') }}_{{ host | replace('_','-') }} { -{% if host_config.identifier is defined and host_config.identifier is not none %} +{% if host_config.identifier is vyos_defined %} host-identifier option dhcp6.client-id {{ host_config.identifier }}; {% endif %} -{% if host_config.ipv6_address is defined and host_config.ipv6_address is not none %} +{% if host_config.ipv6_address is vyos_defined %} fixed-address6 {{ host_config.ipv6_address }}; {% endif %} -{% if host_config.ipv6_prefix is defined and host_config.ipv6_prefix is not none %} +{% if host_config.ipv6_prefix is vyos_defined %} fixed-prefix6 {{ host_config.ipv6_prefix }}; {% endif %} } @@ -117,7 +117,7 @@ shared-network {{ network | replace('_','-') }} { {% endfor %} {% endif %} on commit { - set shared-networkname = "{{ network | replace('_','-') }}"; + set shared-networkname = "{{ network }}"; } } {% endfor %} diff --git a/data/templates/dns-forwarding/recursor.conf.tmpl b/data/templates/dns-forwarding/recursor.conf.tmpl index 02efe903b..d4ec80a3a 100644 --- a/data/templates/dns-forwarding/recursor.conf.tmpl +++ b/data/templates/dns-forwarding/recursor.conf.tmpl @@ -19,6 +19,9 @@ max-cache-entries={{ cache_size }} # negative TTL for NXDOMAIN max-negative-ttl={{ negative_ttl }} +# timeout +network-timeout={{ timeout }} + # ignore-hosts-file export-etc-hosts={{ 'no' if ignore_hosts_file is defined else 'yes' }} diff --git a/data/templates/frr/bfdd.frr.tmpl b/data/templates/frr/bfdd.frr.tmpl index 439f79d67..ac55d4634 100644 --- a/data/templates/frr/bfdd.frr.tmpl +++ b/data/templates/frr/bfdd.frr.tmpl @@ -1,22 +1,22 @@ -{% if profile is defined or peer is defined %} +{% if profile is vyos_defined or peer is vyos_defined %} bfd -{% if profile is defined and profile is not none %} +{% if profile is vyos_defined %} {% for profile_name, profile_config in profile.items() %} profile {{ profile_name }} detect-multiplier {{ profile_config.interval.multiplier }} receive-interval {{ profile_config.interval.receive }} transmit-interval {{ profile_config.interval.transmit }} -{% if profile_config.interval.echo_interval is defined and profile_config.interval.echo_interval is not none %} +{% if profile_config.interval.echo_interval is vyos_defined %} echo transmit-interval {{ profile_config.interval.echo_interval }} echo receive-interval {{ profile_config.interval.echo_interval }} {% endif %} -{% if profile_config.echo_mode is defined %} +{% if profile_config.echo_mode is vyos_defined %} echo-mode {% endif %} -{% if profile_config.passive is defined %} +{% if profile_config.passive is vyos_defined %} passive-mode {% endif %} -{% if profile_config.shutdown is defined %} +{% if profile_config.shutdown is vyos_defined %} shutdown {% else %} no shutdown @@ -25,26 +25,26 @@ bfd ! {% endfor %} {% endif %} -{% if peer is defined and peer is not none %} +{% if peer is vyos_defined %} {% for peer_name, peer_config in peer.items() %} - peer {{ peer_name }}{{ ' multihop' if peer_config.multihop is defined }}{{ ' local-address ' + peer_config.source.address if peer_config.source is defined and peer_config.source.address is defined }}{{ ' interface ' + peer_config.source.interface if peer_config.source is defined and peer_config.source.interface is defined }} {{ ' vrf ' + peer_config.vrf if peer_config.vrf is defined and peer_config.vrf is not none }} + peer {{ peer_name }}{{ ' multihop' if peer_config.multihop is vyos_defined }}{{ ' local-address ' + peer_config.source.address if peer_config.source.address is vyos_defined }}{{ ' interface ' + peer_config.source.interface if peer_config.source.interface is vyos_defined }} {{ ' vrf ' + peer_config.vrf if peer_config.vrf is vyos_defined }} detect-multiplier {{ peer_config.interval.multiplier }} receive-interval {{ peer_config.interval.receive }} transmit-interval {{ peer_config.interval.transmit }} -{% if peer_config.interval.echo_interval is defined and peer_config.interval.echo_interval is not none %} +{% if peer_config.interval.echo_interval is vyos_defined %} echo transmit-interval {{ peer_config.interval.echo_interval }} echo receive-interval {{ peer_config.interval.echo_interval }} {% endif %} -{% if peer_config.echo_mode is defined %} +{% if peer_config.echo_mode is vyos_defined %} echo-mode {% endif %} -{% if peer_config.passive is defined %} +{% if peer_config.passive is vyos_defined %} passive-mode {% endif %} -{% if peer_config.profile is defined and peer_config.profile is not none %} +{% if peer_config.profile is vyos_defined %} profile {{ peer_config.profile }} {% endif %} -{% if peer_config.shutdown is defined %} +{% if peer_config.shutdown is vyos_defined %} shutdown {% else %} no shutdown diff --git a/data/templates/frr/bgpd.frr.tmpl b/data/templates/frr/bgpd.frr.tmpl index 0bc0fd36e..8baa128a7 100644 --- a/data/templates/frr/bgpd.frr.tmpl +++ b/data/templates/frr/bgpd.frr.tmpl @@ -3,113 +3,113 @@ {% macro bgp_neighbor(neighbor, config, peer_group=false) %} {% if peer_group == true %} neighbor {{ neighbor }} peer-group -{% elif config.peer_group is defined and config.peer_group is not none %} +{% elif config.peer_group is vyos_defined %} neighbor {{ neighbor }} peer-group {{ config.peer_group }} {% endif %} -{% if config.remote_as is defined and config.remote_as is not none %} +{% if config.remote_as is vyos_defined %} neighbor {{ neighbor }} remote-as {{ config.remote_as }} {% endif %} -{% if config.interface is defined and config.interface.remote_as is defined and config.interface.remote_as is not none %} +{% if config.interface.remote_as is vyos_defined %} neighbor {{ neighbor }} interface remote-as {{ config.interface.remote_as }} {% endif %} -{% if config.advertisement_interval is defined and config.advertisement_interval is not none %} +{% if config.advertisement_interval is vyos_defined %} neighbor {{ neighbor }} advertisement-interval {{ config.advertisement_interval }} {% endif %} -{% if config.bfd is defined %} +{% if config.bfd is vyos_defined %} neighbor {{ neighbor }} bfd -{% if config.bfd.check_control_plane_failure is defined %} +{% if config.bfd.check_control_plane_failure is vyos_defined %} neighbor {{ neighbor }} bfd check-control-plane-failure {% endif %} -{% if config.bfd.profile is defined and config.bfd.profile is not none %} +{% if config.bfd.profile is vyos_defined %} neighbor {{ neighbor }} bfd profile {{ config.bfd.profile }} {% endif %} {% endif %} -{% if config.capability is defined and config.capability is not none %} -{% if config.capability.dynamic is defined %} +{% if config.capability is vyos_defined %} +{% if config.capability.dynamic is vyos_defined %} neighbor {{ neighbor }} capability dynamic {% endif %} -{% if config.capability.extended_nexthop is defined %} +{% if config.capability.extended_nexthop is vyos_defined %} neighbor {{ neighbor }} capability extended-nexthop {% endif %} {% endif %} -{% if config.description is defined and config.description is not none %} +{% if config.description is vyos_defined %} neighbor {{ neighbor }} description {{ config.description }} {% endif %} -{% if config.disable_capability_negotiation is defined %} +{% if config.disable_capability_negotiation is vyos_defined %} neighbor {{ neighbor }} dont-capability-negotiate {% endif %} -{% if config.ebgp_multihop is defined and config.ebgp_multihop is not none %} +{% if config.ebgp_multihop is vyos_defined %} neighbor {{ neighbor }} ebgp-multihop {{ config.ebgp_multihop }} {% endif %} -{% if config.graceful_restart is defined and config.graceful_restart is not none %} -{% if config.graceful_restart == 'enable' %} +{% if config.graceful_restart is vyos_defined %} +{% if config.graceful_restart is vyos_defined('enable') %} {% set graceful_restart = 'graceful-restart' %} -{% elif config.graceful_restart == 'disable' %} +{% elif config.graceful_restart is vyos_defined('disable') %} {% set graceful_restart = 'graceful-restart-disable' %} -{% elif config.graceful_restart == 'restart-helper' %} +{% elif config.graceful_restart is vyos_defined('restart-helper') %} {% set graceful_restart = 'graceful-restart-helper' %} {% endif %} neighbor {{ neighbor }} {{ graceful_restart }} {% endif %} -{% if config.local_as is defined and config.local_as is not none %} +{% if config.local_as is vyos_defined %} {% for local_as, local_as_config in config.local_as.items() %} {# There can be only one local-as value, this is checked in the Python code #} - neighbor {{ neighbor }} local-as {{ local_as }} {{ 'no-prepend' if local_as_config.no_prepend is defined }} {{ 'replace-as' if local_as_config.no_prepend is defined and local_as_config.no_prepend.replace_as is defined }} + neighbor {{ neighbor }} local-as {{ local_as }} {{ 'no-prepend' if local_as_config.no_prepend is vyos_defined }} {{ 'replace-as' if local_as_config.no_prepend is vyos_defined and local_as_config.no_prepend.replace_as is vyos_defined }} {% endfor %} {% endif %} -{% if config.override_capability is defined %} +{% if config.override_capability is vyos_defined %} neighbor {{ neighbor }} override-capability {% endif %} -{% if config.passive is defined %} +{% if config.passive is vyos_defined %} neighbor {{ neighbor }} passive {% endif %} -{% if config.password is defined and config.password is not none %} +{% if config.password is vyos_defined %} neighbor {{ neighbor }} password {{ config.password }} {% endif %} -{% if config.port is defined and config.port is not none %} +{% if config.port is vyos_defined %} neighbor {{ neighbor }} port {{ config.port }} {% endif %} -{% if config.shutdown is defined %} +{% if config.shutdown is vyos_defined %} neighbor {{ neighbor }} shutdown {% endif %} -{% if config.solo is defined %} +{% if config.solo is vyos_defined %} neighbor {{ neighbor }} solo {% endif %} -{% if config.strict_capability_match is defined %} +{% if config.strict_capability_match is vyos_defined %} neighbor {{ neighbor }} strict-capability-match {% endif %} -{% if config.ttl_security is defined and config.ttl_security.hops is defined and config.ttl_security.hops is not none %} +{% if config.ttl_security.hops is vyos_defined %} neighbor {{ neighbor }} ttl-security hops {{ config.ttl_security.hops }} {% endif %} -{% if config.timers is defined %} -{% if config.timers.connect is defined and config.timers.connect is not none %} +{% if config.timers is vyos_defined %} +{% if config.timers.connect is vyos_defined %} neighbor {{ neighbor }} timers connect {{ config.timers.connect }} {% endif %} -{% if config.timers.holdtime is defined and config.timers.keepalive is defined and config.timers.holdtime is not none and config.timers.keepalive is not none %} +{% if config.timers.keepalive is vyos_defined and config.timers.holdtime is vyos_defined %} neighbor {{ neighbor }} timers {{ config.timers.keepalive }} {{ config.timers.holdtime }} {% endif %} {% endif %} -{% if config.update_source is defined and config.update_source is not none %} +{% if config.update_source is vyos_defined %} neighbor {{ neighbor }} update-source {{ config.update_source }} {% endif %} -{% if config.interface is defined and config.interface is not none %} -{% if config.interface.peer_group is defined and config.interface.peer_group is not none %} +{% if config.interface is vyos_defined %} +{% if config.interface.peer_group is vyos_defined %} neighbor {{ neighbor }} interface peer-group {{ config.interface.peer_group }} {% endif %} -{% if config.interface.source_interface is defined and config.interface.source_interface is not none %} +{% if config.interface.source_interface is vyos_defined %} neighbor {{ neighbor }} interface {{ config.interface.source_interface }} {% endif %} -{% if config.interface.v6only is defined and config.interface.v6only is not none %} -{% if config.interface.v6only.peer_group is defined and config.interface.v6only.peer_group is not none %} +{% if config.interface.v6only is vyos_defined %} +{% if config.interface.v6only.peer_group is vyos_defined %} neighbor {{ neighbor }} interface v6only peer-group {{ config.interface.v6only.peer_group }} {% endif %} -{% if config.interface.v6only.remote_as is defined and config.interface.v6only.remote_as is not none %} +{% if config.interface.v6only.remote_as is vyos_defined %} neighbor {{ neighbor }} interface v6only remote-as {{ config.interface.v6only.remote_as }} {% endif %} {% endif %} {% endif %} ! -{% if config.address_family is defined and config.address_family is not none %} +{% if config.address_family is vyos_defined %} {% for afi, afi_config in config.address_family.items() %} {% if afi == 'ipv4_unicast' %} address-family ipv4 unicast @@ -134,104 +134,96 @@ {% elif afi == 'l2vpn_evpn' %} address-family l2vpn evpn {% endif %} -{% if afi_config.addpath_tx_all is defined %} +{% if afi_config.addpath_tx_all is vyos_defined %} neighbor {{ neighbor }} addpath-tx-all-paths {% endif %} -{% if afi_config.addpath_tx_per_as is defined %} +{% if afi_config.addpath_tx_per_as is vyos_defined %} neighbor {{ neighbor }} addpath-tx-bestpath-per-AS {% endif %} -{% if afi_config.allowas_in is defined and afi_config.allowas_in is not none %} - neighbor {{ neighbor }} allowas-in {{ afi_config.allowas_in.number if afi_config.allowas_in.number is defined }} +{% if afi_config.allowas_in is vyos_defined %} + neighbor {{ neighbor }} allowas-in {{ afi_config.allowas_in.number if afi_config.allowas_in.number is vyos_defined }} {% endif %} -{% if afi_config.as_override is defined %} +{% if afi_config.as_override is vyos_defined %} neighbor {{ neighbor }} as-override {% endif %} -{% if afi_config.conditionally_advertise is defined and afi_config.conditionally_advertise is not none %} -{% if afi_config.conditionally_advertise.advertise_map is defined and afi_config.conditionally_advertise.advertise_map is not none %} +{% if afi_config.conditionally_advertise is vyos_defined %} +{% if afi_config.conditionally_advertise.advertise_map is vyos_defined %} {% set exist_non_exist_map = 'exist-map' %} -{% if afi_config.conditionally_advertise.exist_map is defined and afi_config.conditionally_advertise.exist_map is not none %} +{% if afi_config.conditionally_advertise.exist_map is vyos_defined %} {% set exist_non_exist_map = 'exist-map ' ~ afi_config.conditionally_advertise.exist_map %} -{% elif afi_config.conditionally_advertise.non_exist_map is defined and afi_config.conditionally_advertise.non_exist_map is not none %} +{% elif afi_config.conditionally_advertise.non_exist_map is vyos_defined %} {% set exist_non_exist_map = 'non-exist-map ' ~ afi_config.conditionally_advertise.non_exist_map %} {% endif %} neighbor {{ neighbor }} advertise-map {{ afi_config.conditionally_advertise.advertise_map }} {{ exist_non_exist_map }} {% endif %} {% endif %} -{% if afi_config.remove_private_as is defined %} +{% if afi_config.remove_private_as is vyos_defined %} neighbor {{ neighbor }} remove-private-AS {% endif %} -{% if afi_config.route_reflector_client is defined %} +{% if afi_config.route_reflector_client is vyos_defined %} neighbor {{ neighbor }} route-reflector-client {% endif %} -{% if afi_config.weight is defined and afi_config.weight is not none %} +{% if afi_config.weight is vyos_defined %} neighbor {{ neighbor }} weight {{ afi_config.weight }} {% endif %} -{% if afi_config.attribute_unchanged is defined and afi_config.attribute_unchanged is not none %} - neighbor {{ neighbor }} attribute-unchanged {{ 'as-path ' if afi_config.attribute_unchanged.as_path is defined }}{{ 'med ' if afi_config.attribute_unchanged.med is defined }}{{ 'next-hop ' if afi_config.attribute_unchanged.next_hop is defined }} +{% if afi_config.attribute_unchanged is vyos_defined %} + neighbor {{ neighbor }} attribute-unchanged {{ 'as-path ' if afi_config.attribute_unchanged.as_path is vyos_defined }}{{ 'med ' if afi_config.attribute_unchanged.med is vyos_defined }}{{ 'next-hop ' if afi_config.attribute_unchanged.next_hop is vyos_defined }} {% endif %} -{% if afi_config.capability is defined and afi_config.capability.orf is defined and afi_config.capability.orf.prefix_list is defined and afi_config.capability.orf.prefix_list.send is defined %} +{% if afi_config.capability.orf.prefix_list.send is vyos_defined %} neighbor {{ neighbor }} capability orf prefix-list send {% endif %} -{% if afi_config.capability is defined and afi_config.capability.orf is defined and afi_config.capability.orf.prefix_list is defined and afi_config.capability.orf.prefix_list.receive is defined %} +{% if afi_config.capability.orf.prefix_list.receive is vyos_defined %} neighbor {{ neighbor }} capability orf prefix-list receive {% endif %} -{% if afi_config.default_originate is defined %} - neighbor {{ neighbor }} default-originate {{ 'route-map ' ~ afi_config.default_originate.route_map if afi_config.default_originate.route_map is defined }} +{% if afi_config.default_originate is vyos_defined %} + neighbor {{ neighbor }} default-originate {{ 'route-map ' ~ afi_config.default_originate.route_map if afi_config.default_originate.route_map is vyos_defined }} {% endif %} -{% if afi_config.distribute_list is defined and afi_config.distribute_list is not none %} -{% if afi_config.distribute_list.export is defined and afi_config.distribute_list.export is not none %} +{% if afi_config.distribute_list.export is vyos_defined %} neighbor {{ neighbor }} distribute-list {{ afi_config.distribute_list.export }} out -{% endif %} -{% if afi_config.distribute_list.import is defined and afi_config.distribute_list.import is not none %} +{% endif %} +{% if afi_config.distribute_list.import is vyos_defined %} neighbor {{ neighbor }} distribute-list {{ afi_config.distribute_list.import }} in -{% endif %} {% endif %} -{% if afi_config.filter_list is defined and afi_config.filter_list is not none %} -{% if afi_config.filter_list.export is defined and afi_config.filter_list.export is not none %} +{% if afi_config.filter_list.export is vyos_defined %} neighbor {{ neighbor }} filter-list {{ afi_config.filter_list.export }} out -{% endif %} -{% if afi_config.filter_list.import is defined and afi_config.filter_list.import is not none %} +{% endif %} +{% if afi_config.filter_list.import is vyos_defined %} neighbor {{ neighbor }} filter-list {{ afi_config.filter_list.import }} in -{% endif %} {% endif %} -{% if afi_config.maximum_prefix is defined and afi_config.maximum_prefix is not none %} +{% if afi_config.maximum_prefix is vyos_defined %} neighbor {{ neighbor }} maximum-prefix {{ afi_config.maximum_prefix }} {% endif %} -{% if afi_config.maximum_prefix_out is defined and afi_config.maximum_prefix_out is not none %} +{% if afi_config.maximum_prefix_out is vyos_defined %} neighbor {{ neighbor }} maximum-prefix-out {{ afi_config.maximum_prefix_out }} {% endif %} -{% if afi_config.nexthop_self is defined %} - neighbor {{ neighbor }} next-hop-self {{ 'force' if afi_config.nexthop_self.force is defined }} +{% if afi_config.nexthop_self is vyos_defined %} + neighbor {{ neighbor }} next-hop-self {{ 'force' if afi_config.nexthop_self.force is vyos_defined }} {% endif %} -{% if afi_config.route_server_client is defined %} +{% if afi_config.route_server_client is vyos_defined %} neighbor {{ neighbor }} route-server-client {% endif %} -{% if afi_config.route_map is defined and afi_config.route_map is not none %} -{% if afi_config.route_map.export is defined and afi_config.route_map.export is not none %} +{% if afi_config.route_map.export is vyos_defined %} neighbor {{ neighbor }} route-map {{ afi_config.route_map.export }} out -{% endif %} -{% if afi_config.route_map.import is defined and afi_config.route_map.import is not none %} +{% endif %} +{% if afi_config.route_map.import is vyos_defined %} neighbor {{ neighbor }} route-map {{ afi_config.route_map.import }} in -{% endif %} {% endif %} -{% if afi_config.prefix_list is defined and afi_config.prefix_list is not none %} -{% if afi_config.prefix_list.export is defined and afi_config.prefix_list.export is not none %} +{% if afi_config.prefix_list.export is vyos_defined %} neighbor {{ neighbor }} prefix-list {{ afi_config.prefix_list.export }} out -{% endif %} -{% if afi_config.prefix_list.import is defined and afi_config.prefix_list.import is not none %} +{% endif %} +{% if afi_config.prefix_list.import is vyos_defined %} neighbor {{ neighbor }} prefix-list {{ afi_config.prefix_list.import }} in -{% endif %} {% endif %} -{% if afi_config.soft_reconfiguration is defined and afi_config.soft_reconfiguration.inbound is defined %} +{% if afi_config.soft_reconfiguration.inbound is vyos_defined %} neighbor {{ neighbor }} soft-reconfiguration inbound {% endif %} -{% if afi_config.unsuppress_map is defined and afi_config.unsuppress_map is not none %} +{% if afi_config.unsuppress_map is vyos_defined %} neighbor {{ neighbor }} unsuppress-map {{ afi_config.unsuppress_map }} {% endif %} -{% if afi_config.disable_send_community is defined and afi_config.disable_send_community.extended is defined %} +{% if afi_config.disable_send_community.extended is vyos_defined %} no neighbor {{ neighbor }} send-community extended {% endif %} -{% if afi_config.disable_send_community is defined and afi_config.disable_send_community.standard is defined %} +{% if afi_config.disable_send_community.standard is vyos_defined %} no neighbor {{ neighbor }} send-community standard {% endif %} neighbor {{ neighbor }} activate @@ -241,8 +233,8 @@ {% endif %} {% endmacro %} ! -router bgp {{ local_as }} {{ 'vrf ' ~ vrf if vrf is defined and vrf is not none }} -{% if parameters is defined and parameters.ebgp_requires_policy is defined %} +router bgp {{ local_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }} +{% if parameters.ebgp_requires_policy is vyos_defined %} bgp ebgp-requires-policy {% else %} no bgp ebgp-requires-policy @@ -251,7 +243,7 @@ router bgp {{ local_as }} {{ 'vrf ' ~ vrf if vrf is defined and vrf is not none no bgp default ipv4-unicast {# Workaround for T2100 until we have decided about a migration script #} no bgp network import-check -{% if address_family is defined and address_family is not none %} +{% if address_family is vyos_defined %} {% for afi, afi_config in address_family.items() %} ! {% if afi == 'ipv4_unicast' %} @@ -276,25 +268,25 @@ router bgp {{ local_as }} {{ 'vrf ' ~ vrf if vrf is defined and vrf is not none address-family ipv6 flowspec {% elif afi == 'l2vpn_evpn' %} address-family l2vpn evpn -{% if afi_config.rd is defined and afi_config.rd is not none %} +{% if afi_config.rd is vyos_defined %} rd {{ afi_config.rd }} {% endif %} {% endif %} -{% if afi_config.aggregate_address is defined and afi_config.aggregate_address is not none %} +{% if afi_config.aggregate_address is vyos_defined %} {% for aggregate, aggregate_config in afi_config.aggregate_address.items() %} - aggregate-address {{ aggregate }}{{ ' as-set' if aggregate_config.as_set is defined }}{{ ' summary-only' if aggregate_config.summary_only is defined }} -{% if aggregate_config.route_map is defined and aggregate_config.route_map is not none %} + aggregate-address {{ aggregate }}{{ ' as-set' if aggregate_config.as_set is vyos_defined }}{{ ' summary-only' if aggregate_config.summary_only is vyos_defined }} +{% if aggregate_config.route_map is vyos_defined %} aggregate-address {{ aggregate }} route-map {{ aggregate_config.route_map }} {% endif %} {% endfor %} {% endif %} -{% if afi_config.maximum_paths is defined and afi_config.maximum_paths.ebgp is defined and afi_config.maximum_paths.ebgp is not none %} +{% if afi_config.maximum_paths.ebgp is vyos_defined %} maximum-paths {{ afi_config.maximum_paths.ebgp }} {% endif %} -{% if afi_config.maximum_paths is defined and afi_config.maximum_paths.ibgp is defined and afi_config.maximum_paths.ibgp is not none %} +{% if afi_config.maximum_paths.ibgp is vyos_defined %} maximum-paths ibgp {{ afi_config.maximum_paths.ibgp }} {% endif %} -{% if afi_config.redistribute is defined and afi_config.redistribute is not none %} +{% if afi_config.redistribute is vyos_defined %} {% for protocol in afi_config.redistribute %} {% if protocol == 'table' %} redistribute table {{ afi_config.redistribute[protocol].table }} @@ -303,135 +295,123 @@ router bgp {{ local_as }} {{ 'vrf ' ~ vrf if vrf is defined and vrf is not none {% if protocol == 'ospfv3' %} {% set redistribution_protocol = 'ospf6' %} {% endif %} - redistribute {{ redistribution_protocol }}{% if afi_config.redistribute[protocol].metric is defined %} metric {{ afi_config.redistribute[protocol].metric }}{% endif %}{% if afi_config.redistribute[protocol].route_map is defined %} route-map {{ afi_config.redistribute[protocol].route_map }}{% endif %} + redistribute {{ redistribution_protocol }}{% if afi_config.redistribute[protocol].metric is vyos_defined %} metric {{ afi_config.redistribute[protocol].metric }}{% endif %}{% if afi_config.redistribute[protocol].route_map is vyos_defined %} route-map {{ afi_config.redistribute[protocol].route_map }}{% endif %} {####### we need this blank line!! #######} {% endif %} {% endfor %} {% endif %} -{% if afi_config.network is defined and afi_config.network is not none %} +{% if afi_config.network is vyos_defined %} {% for network in afi_config.network %} - network {{ network }}{% if afi_config.network[network].route_map is defined %} route-map {{ afi_config.network[network].route_map }}{% endif %}{% if afi_config.network[network].backdoor is defined %} backdoor{% endif %}{% if afi_config.network[network].rd is defined and afi_config.network[network].label is defined%} rd {{ afi_config.network[network].rd }} label {{ afi_config.network[network].label }}{% endif %} + network {{ network }}{% if afi_config.network[network].route_map is vyos_defined %} route-map {{ afi_config.network[network].route_map }}{% endif %}{% if afi_config.network[network].backdoor is vyos_defined %} backdoor{% endif %}{% if afi_config.network[network].rd is vyos_defined and afi_config.network[network].label is vyos_defined %} rd {{ afi_config.network[network].rd }} label {{ afi_config.network[network].label }}{% endif %} {####### we need this blank line!! #######} {% endfor %} {% endif %} -{% if afi_config.advertise is defined and afi_config.advertise is not none %} +{% if afi_config.advertise is vyos_defined %} {% for adv_afi, adv_afi_config in afi_config.advertise.items() %} -{% if adv_afi_config.unicast is defined and adv_afi_config.unicast is not none %} - advertise {{ adv_afi }} unicast {{ 'route-map ' ~ adv_afi_config.unicast.route_map if adv_afi_config.unicast.route_map is defined }} +{% if adv_afi_config.unicast is vyos_defined %} + advertise {{ adv_afi }} unicast {{ 'route-map ' ~ adv_afi_config.unicast.route_map if adv_afi_config.unicast.route_map is vyos_defined }} {% endif %} {% endfor %} {% endif %} -{% if afi_config.distance is defined and afi_config.distance is not none %} -{% if afi_config.distance is defined and afi_config.distance.external is defined and afi_config.distance.internal is defined and afi_config.distance.local is defined %} +{% if afi_config.distance.external is vyos_defined and afi_config.distance.internal is vyos_defined and afi_config.distance.local is vyos_defined %} distance bgp {{ afi_config.distance.external }} {{ afi_config.distance.internal }} {{ afi_config.distance.local }} -{% endif %} -{% if afi_config.distance.prefix is defined and afi_config.distance.prefix is not none %} -{% for prefix in afi_config.distance.prefix %} +{% endif %} +{% if afi_config.distance.prefix is vyos_defined %} +{% for prefix in afi_config.distance.prefix %} distance {{ afi_config.distance.prefix[prefix].distance }} {{ prefix }} -{% endfor %} -{% endif %} +{% endfor %} {% endif %} -{% if afi_config.export is defined and afi_config.export.vpn is defined %} +{% if afi_config.export.vpn is vyos_defined %} export vpn {% endif %} -{% if afi_config.import is defined and afi_config.import is not none %} -{% if afi_config.import.vpn is defined %} +{% if afi_config.import.vpn is vyos_defined %} import vpn -{% endif %} -{% if afi_config.import.vrf is defined and afi_config.import.vrf is not none %} -{% for vrf in afi_config.import.vrf %} +{% endif %} +{% if afi_config.import.vrf is vyos_defined %} +{% for vrf in afi_config.import.vrf %} import vrf {{ vrf }} -{% endfor %} -{% endif %} +{% endfor %} {% endif %} -{% if afi_config.label is defined and afi_config.label.vpn is defined and afi_config.label.vpn.export is defined and afi_config.label.vpn.export is not none %} +{% if afi_config.label.vpn.export is vyos_defined %} label vpn export {{ afi_config.label.vpn.export }} {% endif %} -{% if afi_config.local_install is defined and afi_config.local_install is not none %} +{% if afi_config.local_install is vyos_defined %} {% for interface in afi_config.local_install.interface %} local-install {{ interface }} {% endfor %} {% endif %} -{% if afi_config.advertise_all_vni is defined %} +{% if afi_config.advertise_all_vni is vyos_defined %} advertise-all-vni {% endif %} -{% if afi_config.advertise_default_gw is defined %} +{% if afi_config.advertise_default_gw is vyos_defined %} advertise-default-gw {% endif %} -{% if afi_config.advertise_pip is defined and afi_config.advertise_pip is not none %} +{% if afi_config.advertise_pip is vyos_defined %} advertise-pip ip {{ afi_config.advertise_pip }} {% endif %} -{% if afi_config.advertise_svi_ip is defined %} +{% if afi_config.advertise_svi_ip is vyos_defined %} advertise-svi-ip {% endif %} -{% if afi_config.rt_auto_derive is defined %} +{% if afi_config.rt_auto_derive is vyos_defined %} autort rfc8365-compatible {% endif %} -{% if afi_config.flooding is defined and afi_config.flooding.disable is defined %} +{% if afi_config.flooding.disable is vyos_defined %} flooding disable {% endif %} -{% if afi_config.flooding is defined and afi_config.flooding.head_end_replication is defined %} +{% if afi_config.flooding.head_end_replication is vyos_defined %} flooding head-end-replication {% endif %} -{% if afi_config.rd is defined and afi_config.rd.vpn is defined and afi_config.rd.vpn.export is defined %} +{% if afi_config.rd.vpn.export is vyos_defined %} rd vpn export {{ afi_config.rd.vpn.export }} {% endif %} -{% if afi_config.route_target is defined and afi_config.route_target is not none %} -{% if afi_config.route_target.vpn is defined and afi_config.route_target.vpn is not none %} -{% if afi_config.route_target.vpn.both is defined and afi_config.route_target.vpn.both is not none %} +{% if afi_config.route_target.vpn.both is vyos_defined %} route-target vpn both {{ afi_config.route_target.vpn.both }} -{% else %} -{% if afi_config.route_target.vpn.export is defined and afi_config.route_target.vpn.export is not none %} +{% else %} +{% if afi_config.route_target.vpn.export is vyos_defined %} route-target vpn export {{ afi_config.route_target.vpn.export }} -{% endif %} -{% if afi_config.route_target.vpn.import is defined and afi_config.route_target.vpn.import is not none %} +{% endif %} +{% if afi_config.route_target.vpn.import is vyos_defined %} route-target vpn import {{ afi_config.route_target.vpn.import }} -{% endif %} -{% endif %} {% endif %} -{% if afi_config.route_target.both is defined and afi_config.route_target.both is not none %} +{% endif %} +{% if afi_config.route_target.both is vyos_defined %} route-target both {{ afi_config.route_target.both }} -{% else %} -{% if afi_config.route_target.export is defined and afi_config.route_target.export is not none %} +{% else %} +{% if afi_config.route_target.export is vyos_defined %} route-target export {{ afi_config.route_target.export }} -{% endif %} -{% if afi_config.route_target.import is defined and afi_config.route_target.import is not none %} +{% endif %} +{% if afi_config.route_target.import is vyos_defined %} route-target import {{ afi_config.route_target.import }} -{% endif %} {% endif %} {% endif %} -{% if afi_config.route_map is defined and afi_config.route_map.vpn is defined and afi_config.route_map.vpn is not none %} -{% if afi_config.route_map.vpn.export is defined and afi_config.route_map.vpn.export is not none %} +{% if afi_config.route_map.vpn.export is vyos_defined %} route-map vpn export {{ afi_config.route_map.vpn.export }} -{% endif %} -{% if afi_config.route_map.vpn.import is defined and afi_config.route_map.vpn.import is not none %} +{% endif %} +{% if afi_config.route_map.vpn.import is vyos_defined %} route-map vpn import {{ afi_config.route_map.vpn.import }} -{% endif %} {% endif %} -{% if afi_config.vni is defined and afi_config.vni is not none %} +{% if afi_config.vni is vyos_defined %} {% for vni, vni_config in afi_config.vni.items() %} vni {{ vni }} -{% if vni_config.advertise_default_gw is defined %} +{% if vni_config.advertise_default_gw is vyos_defined %} advertise-default-gw {% endif %} -{% if vni_config.advertise_svi_ip is defined %} +{% if vni_config.advertise_svi_ip is vyos_defined %} advertise-svi-ip {% endif %} -{% if vni_config.rd is defined and vni_config.rd is not none %} +{% if vni_config.rd is vyos_defined %} rd {{ vni_config.rd }} {% endif %} -{% if vni_config.route_target is defined and vni_config.route_target is not none %} -{% if vni_config.route_target.both is defined and vni_config.route_target.both is not none %} +{% if vni_config.route_target.both is vyos_defined %} route-target both {{ vni_config.route_target.both }} -{% endif %} -{% if vni_config.route_target.export is defined and vni_config.route_target.export is not none %} +{% endif %} +{% if vni_config.route_target.export is vyos_defined %} route-target export {{ vni_config.route_target.export }} -{% endif %} -{% if vni_config.route_target.import is defined and vni_config.route_target.import is not none %} +{% endif %} +{% if vni_config.route_target.import is vyos_defined %} route-target import {{ vni_config.route_target.import }} -{% endif %} {% endif %} exit-vni {% endfor %} @@ -440,128 +420,116 @@ router bgp {{ local_as }} {{ 'vrf ' ~ vrf if vrf is defined and vrf is not none {% endfor %} {% endif %} ! -{% if peer_group is defined and peer_group is not none %} +{% if peer_group is vyos_defined %} {% for peer, config in peer_group.items() %} {{ bgp_neighbor(peer, config, true) }} {% endfor %} {% endif %} ! -{% if neighbor is defined and neighbor is not none %} +{% if neighbor is vyos_defined %} {% for peer, config in neighbor.items() %} {{ bgp_neighbor(peer, config) }} {% endfor %} {% endif %} ! -{% if listen is defined %} -{% if listen.limit is defined and listen.limit is not none %} +{% if listen.limit is vyos_defined %} bgp listen limit {{ listen.limit }} -{% endif %} +{% endif %} +{% if listen.range is vyos_defined %} {% for prefix, options in listen.range.items() %} -{% if options.peer_group is defined and options.peer_group is not none %} +{% if options.peer_group is vyos_defined %} bgp listen range {{ prefix }} peer-group {{ options.peer_group }} {% endif %} {% endfor %} {% endif %} -{% if parameters is defined %} -{% if parameters.always_compare_med is defined %} +{% if parameters.always_compare_med is vyos_defined %} bgp always-compare-med -{% endif %} -{% if parameters.bestpath is defined and parameters.bestpath is not none %} -{% if parameters.bestpath.as_path is defined and parameters.bestpath.as_path is not none %} -{% for option in parameters.bestpath.as_path %} +{% endif %} +{% if parameters.bestpath.as_path is vyos_defined %} +{% for option in parameters.bestpath.as_path %} {# replace is required for multipath-relax option #} bgp bestpath as-path {{ option|replace('_', '-') }} -{% endfor %} -{% endif %} -{% if parameters.bestpath.bandwidth is defined and parameters.bestpath.bandwidth is not none %} +{% endfor %} +{% endif %} +{% if parameters.bestpath.bandwidth is vyos_defined %} bgp bestpath bandwidth {{ parameters.bestpath.bandwidth }} -{% endif %} -{% if parameters.bestpath.compare_routerid is defined %} +{% endif %} +{% if parameters.bestpath.compare_routerid is vyos_defined %} bgp bestpath compare-routerid -{% endif %} -{% if parameters.bestpath.med is defined and parameters.bestpath.med is not none %} - bgp bestpath med {{ 'confed' if parameters.bestpath.med.confed is defined }} {{ 'missing-as-worst' if parameters.bestpath.med.missing_as_worst is defined }} -{% endif %} -{% endif %} -{% if parameters.cluster_id is defined and parameters.cluster_id is not none %} +{% endif %} +{% if parameters.bestpath.med is vyos_defined %} + bgp bestpath med {{ 'confed' if parameters.bestpath.med.confed is vyos_defined }} {{ 'missing-as-worst' if parameters.bestpath.med.missing_as_worst is vyos_defined }} +{% endif %} +{% if parameters.cluster_id is vyos_defined %} bgp cluster-id {{ parameters.cluster_id }} -{% endif %} -{% if parameters.conditional_advertisement is defined and parameters.conditional_advertisement is not none %} -{% if parameters.conditional_advertisement.timer is defined and parameters.conditional_advertisement.timer is not none %} +{% endif %} +{% if parameters.conditional_advertisement.timer is vyos_defined %} bgp conditional-advertisement timer {{ parameters.conditional_advertisement.timer }} -{% endif %} -{% endif %} -{% if parameters.confederation is defined and parameters.confederation is not none %} -{% if parameters.confederation.identifier is defined and parameters.confederation.identifier is not none %} +{% endif %} +{% if parameters.confederation.identifier is vyos_defined %} bgp confederation identifier {{ parameters.confederation.identifier }} -{% endif %} -{% if parameters.confederation.peers is defined and parameters.confederation.peers is not none %} +{% endif %} +{% if parameters.confederation.peers is vyos_defined %} bgp confederation peers {{ parameters.confederation.peers | join(' ') }} -{% endif %} -{% endif %} -{% if parameters.dampening is defined and parameters.dampening is defined and parameters.dampening.half_life is defined and parameters.dampening.half_life is not none %} +{% endif %} +{% if parameters.dampening.half_life is vyos_defined %} {# Doesn't work in current FRR configuration; vtysh (bgp dampening 16 751 2001 61) #} - bgp dampening {{ parameters.dampening.half_life }} {{ parameters.dampening.re_use if parameters.dampening.re_use is defined }} {{ parameters.dampening.start_suppress_time if parameters.dampening.start_suppress_time is defined }} {{ parameters.dampening.max_suppress_time if parameters.dampening.max_suppress_time is defined }} -{% endif %} -{% if parameters.default is defined and parameters.default is not none %} -{% if parameters.default.local_pref is defined and parameters.default.local_pref is not none %} + bgp dampening {{ parameters.dampening.half_life }} {{ parameters.dampening.re_use if parameters.dampening.re_use is vyos_defined }} {{ parameters.dampening.start_suppress_time if parameters.dampening.start_suppress_time is vyos_defined }} {{ parameters.dampening.max_suppress_time if parameters.dampening.max_suppress_time is vyos_defined }} +{% endif %} +{% if parameters.default.local_pref is vyos_defined %} bgp default local-preference {{ parameters.default.local_pref }} -{% endif %} -{% endif %} -{% if parameters.deterministic_med is defined %} +{% endif %} +{% if parameters.deterministic_med is vyos_defined %} bgp deterministic-med -{% endif %} -{% if parameters.distance is defined and parameters.distance is not none %} -{% if parameters.distance.global is defined and parameters.distance.global.external is defined and parameters.distance.global.internal is defined and parameters.distance.global.local is defined %} +{% endif %} +{% if parameters.distance.global.external is vyos_defined and parameters.distance.global.internal is vyos_defined and parameters.distance.global.local is vyos_defined %} distance bgp {{ parameters.distance.global.external }} {{ parameters.distance.global.internal }} {{ parameters.distance.global.local }} -{% endif %} -{% if parameters.distance.prefix is defined and parameters.distance.prefix is not none %} -{% for prefix in parameters.distance.prefix %} +{% endif %} +{% if parameters.distance.prefix is vyos_defined %} +{% for prefix in parameters.distance.prefix %} distance {{ parameters.distance.prefix[prefix].distance }} {{ prefix }} -{% endfor %} -{% endif %} -{% endif %} -{% if parameters.fast_convergence is defined %} +{% endfor %} +{% endif %} +{% if parameters.fast_convergence is vyos_defined %} bgp fast-convergence -{% endif %} -{% if parameters.graceful_restart is defined %} - bgp graceful-restart {{ 'stalepath-time ' ~ parameters.graceful_restart.stalepath_time if parameters.graceful_restart.stalepath_time is defined }} -{% endif %} -{% if parameters.graceful_shutdown is defined %} +{% endif %} +{% if parameters.graceful_restart is vyos_defined %} + bgp graceful-restart {{ 'stalepath-time ' ~ parameters.graceful_restart.stalepath_time if parameters.graceful_restart.stalepath_time is vyos_defined }} +{% endif %} +{% if parameters.graceful_shutdown is vyos_defined %} bgp graceful-shutdown -{% endif %} -{% if parameters.log_neighbor_changes is defined %} +{% endif %} +{% if parameters.log_neighbor_changes is vyos_defined %} bgp log-neighbor-changes -{% endif %} -{% if parameters.minimum_holdtime is defined and parameters.minimum_holdtime is not none %} +{% endif %} +{% if parameters.minimum_holdtime is vyos_defined %} bgp minimum-holdtime {{ parameters.minimum_holdtime }} -{% endif %} -{% if parameters.network_import_check is defined %} +{% endif %} +{% if parameters.network_import_check is vyos_defined %} bgp network import-check -{% endif %} -{% if parameters.no_client_to_client_reflection is defined %} +{% endif %} +{% if parameters.no_client_to_client_reflection is vyos_defined %} no bgp client-to-client reflection -{% endif %} -{% if parameters.no_fast_external_failover is defined %} +{% endif %} +{% if parameters.no_fast_external_failover is vyos_defined %} no bgp fast-external-failover -{% endif %} -{% if parameters.no_suppress_duplicates is defined %} +{% endif %} +{% if parameters.no_suppress_duplicates is vyos_defined %} no bgp suppress-duplicates -{% endif %} -{% if parameters.reject_as_sets is defined %} +{% endif %} +{% if parameters.reject_as_sets is vyos_defined %} bgp reject-as-sets -{% endif %} -{% if parameters.router_id is defined and parameters.router_id is not none %} +{% endif %} +{% if parameters.router_id is vyos_defined and parameters.router_id is not none %} bgp router-id {{ parameters.router_id }} -{% endif %} -{% if parameters.shutdown is defined %} +{% endif %} +{% if parameters.shutdown is vyos_defined %} bgp shutdown -{% endif %} -{% if parameters.suppress_fib_pending is defined %} +{% endif %} +{% if parameters.suppress_fib_pending is vyos_defined %} bgp suppress-fib-pending -{% endif %} {% endif %} -{% if timers is defined and timers.keepalive is defined and timers.holdtime is defined %} +{% if timers.keepalive is vyos_defined and timers.holdtime is vyos_defined %} timers bgp {{ timers.keepalive }} {{ timers.holdtime }} {% endif %} exit diff --git a/data/templates/frr/isisd.frr.tmpl b/data/templates/frr/isisd.frr.tmpl index c68dda443..238541903 100644 --- a/data/templates/frr/isisd.frr.tmpl +++ b/data/templates/frr/isisd.frr.tmpl @@ -1,46 +1,48 @@ ! -{% if interface is defined and interface is not none %} +{% if interface is vyos_defined %} {% for iface, iface_config in interface.items() %} interface {{ iface }} ip router isis VyOS ipv6 router isis VyOS -{% if iface_config.bfd is defined %} +{% if iface_config.bfd is vyos_defined %} isis bfd -{% if iface_config.bfd.profile is defined and iface_config.bfd.profile is not none %} +{% if iface_config.bfd.profile is vyos_defined %} isis bfd profile {{ iface_config.bfd.profile }} {% endif %} {% endif %} -{% if iface_config.network is defined and iface_config.network.point_to_point is defined %} +{% if iface_config.network.point_to_point is vyos_defined %} isis network point-to-point {% endif %} -{% if iface_config.circuit_type is defined %} +{% if iface_config.circuit_type is vyos_defined %} isis circuit-type {{ iface_config.circuit_type }} {% endif %} -{% if iface_config.hello_interval is defined and iface_config.hello_interval is not none %} +{% if iface_config.hello_interval is vyos_defined %} isis hello-interval {{ iface_config.hello_interval }} {% endif %} -{% if iface_config.hello_multiplier is defined and iface_config.hello_multiplier is not none %} +{% if iface_config.hello_multiplier is vyos_defined %} isis hello-multiplier {{ iface_config.hello_multiplier }} {% endif %} -{% if iface_config.hello_padding is defined %} +{% if iface_config.hello_padding is vyos_defined %} isis hello padding {% endif %} -{% if iface_config.metric is defined and iface_config.metric is not none %} +{% if iface_config.metric is vyos_defined %} isis metric {{ iface_config.metric }} {% endif %} -{% if iface_config.passive is defined %} +{% if iface_config.passive is vyos_defined %} isis passive {% endif %} -{% if iface_config.password is defined and iface_config.password.plaintext_password is defined and iface_config.password.plaintext_password is not none %} +{% if iface_config.password.md5 is vyos_defined %} + isis password md5 {{ iface_config.password.md5 }} +{% elif iface_config.password.plaintext_password is vyos_defined %} isis password clear {{ iface_config.password.plaintext_password }} {% endif %} -{% if iface_config.priority is defined and iface_config.priority is not none %} +{% if iface_config.priority is vyos_defined %} isis priority {{ iface_config.priority }} {% endif %} -{% if iface_config.psnp_interval is defined and iface_config.psnp_interval is not none %} +{% if iface_config.psnp_interval is vyos_defined %} isis psnp-interval {{ iface_config.psnp_interval }} {% endif %} -{% if iface_config.no_three_way_handshake is defined %} +{% if iface_config.no_three_way_handshake is vyos_defined %} no isis three-way-handshake {% endif %} exit @@ -48,98 +50,95 @@ exit {% endfor %} {% endif %} ! -router isis VyOS {{ 'vrf ' + vrf if vrf is defined and vrf is not none }} +router isis VyOS {{ 'vrf ' + vrf if vrf is vyos_defined }} net {{ net }} -{% if dynamic_hostname is defined %} +{% if dynamic_hostname is vyos_defined %} hostname dynamic {% endif %} -{% if purge_originator is defined %} +{% if purge_originator is vyos_defined %} purge-originator {% endif %} -{% if set_attached_bit is defined %} +{% if set_attached_bit is vyos_defined %} set-attached-bit {% endif %} -{% if set_overload_bit is defined %} +{% if set_overload_bit is vyos_defined %} set-overload-bit {% endif %} -{% if domain_password is defined and domain_password is not none %} -{% if domain_password.md5 is defined and domain_password.md5 is not none %} +{% if domain_password.md5 is vyos_defined %} domain-password md5 {{ domain_password.plaintext_password }} -{% elif domain_password.plaintext_password is defined and domain_password.plaintext_password is not none %} +{% elif domain_password.plaintext_password is vyos_defined %} domain-password clear {{ domain_password.plaintext_password }} -{% endif %} {% endif %} -{% if log_adjacency_changes is defined %} +{% if log_adjacency_changes is vyos_defined %} log-adjacency-changes {% endif %} -{% if lsp_gen_interval is defined and lsp_gen_interval is not none %} +{% if lsp_gen_interval is vyos_defined %} lsp-gen-interval {{ lsp_gen_interval }} {% endif %} -{% if lsp_mtu is defined and lsp_mtu is not none %} +{% if lsp_mtu is vyos_defined %} lsp-mtu {{ lsp_mtu }} {% endif %} -{% if lsp_refresh_interval is defined and lsp_refresh_interval is not none %} +{% if lsp_refresh_interval is vyos_defined %} lsp-refresh-interval {{ lsp_refresh_interval }} {% endif %} -{% if max_lsp_lifetime is defined and max_lsp_lifetime is not none %} +{% if max_lsp_lifetime is vyos_defined %} max-lsp-lifetime {{ max_lsp_lifetime }} {% endif %} -{% if spf_interval is defined and spf_interval is not none %} +{% if spf_interval is vyos_defined %} spf-interval {{ spf_interval }} {% endif %} -{% if traffic_engineering is defined and traffic_engineering is not none %} -{% if traffic_engineering.enable is defined %} +{% if traffic_engineering.enable is vyos_defined %} mpls-te on -{% endif %} -{% if traffic_engineering.address is defined %} +{% endif %} +{% if traffic_engineering.address is vyos_defined %} mpls-te router-address {{ traffic_engineering.address }} +{% endif %} +{% if traffic_engineering.inter_as is vyos_defined %} +{% set level = '' %} +{% if traffic_engineering.inter_as.level_1 is vyos_defined %} +{% set level = ' level-1' %} {% endif %} -{% if traffic_engineering.inter_as is defined %} -{% if traffic_engineering.inter_as.level_1 is defined %} - mpls-te inter-as level-1 -{% endif %} -{% if traffic_engineering.inter_as.level_1_2 is defined %} - mpls-te inter-as level-1-2 -{% endif %} -{% if traffic_engineering.inter_as.level_2 is defined %} - mpls-te inter-as level-2-only -{% endif %} -{% else %} - mpls-te inter-as +{% if traffic_engineering.inter_as.level_1_2 is vyos_defined %} +{% set level = ' level-1-2' %} +{% endif %} +{% if traffic_engineering.inter_as.level_2 is vyos_defined %} +{% set level = ' level-2-only' %} {% endif %} + mpls-te inter-as{{ level }} {% endif %} -{% if segment_routing is defined %} -{% if segment_routing.enable is defined %} +{% if segment_routing is vyos_defined %} +{% if segment_routing.enable is vyos_defined %} segment-routing on {% endif %} -{% if segment_routing.maximum_label_depth is defined %} +{% if segment_routing.maximum_label_depth is vyos_defined %} segment-routing node-msd {{ segment_routing.maximum_label_depth }} {% endif %} -{% if segment_routing.global_block is defined %} +{% if segment_routing.global_block is vyos_defined %} +{% if segment_routing.local_block is vyos_defined %} + segment-routing global-block {{ segment_routing.global_block.low_label_value }} {{ segment_routing.global_block.high_label_value }} local-block {{ segment_routing.local_block.low_label_value }} {{ segment_routing.local_block.high_label_value }} +{% else %} segment-routing global-block {{ segment_routing.global_block.low_label_value }} {{ segment_routing.global_block.high_label_value }} +{% endif %} {% endif %} -{% if segment_routing.local_block is defined %} - segment-routing local-block {{ segment_routing.global_block.low_label_value }} {{ segment_routing.local_block.high_label_value }} -{% endif %} -{% if segment_routing.prefix is defined %} +{% if segment_routing.prefix is vyos_defined %} {% for prefixes in segment_routing.prefix %} -{% if segment_routing.prefix[prefixes].absolute is defined %} -{% if segment_routing.prefix[prefixes].absolute.value is defined %} +{% if segment_routing.prefix[prefixes].absolute is vyos_defined %} +{% if segment_routing.prefix[prefixes].absolute.value is vyos_defined %} segment-routing prefix {{ prefixes }} absolute {{ segment_routing.prefix[prefixes].absolute.value }} -{% if segment_routing.prefix[prefixes].absolute.explicit_null is defined %} +{% if segment_routing.prefix[prefixes].absolute.explicit_null is vyos_defined %} segment-routing prefix {{ prefixes }} absolute {{ segment_routing.prefix[prefixes].absolute.value }} explicit-null {% endif %} -{% if segment_routing.prefix[prefixes].absolute.no_php_flag is defined %} +{% if segment_routing.prefix[prefixes].absolute.no_php_flag is vyos_defined %} segment-routing prefix {{ prefixes }} absolute {{ segment_routing.prefix[prefixes].absolute.value }} no-php-flag {% endif %} {% endif %} -{% if segment_routing.prefix[prefixes].index is defined %} -{% if segment_routing.prefix[prefixes].index.value is defined %} +{% if segment_routing.prefix[prefixes].index is vyos_defined %} +{% if segment_routing.prefix[prefixes].index.value is vyos_defined %} segment-routing prefix {{ prefixes }} index {{ segment_routing.prefix[prefixes].index.value }} -{% if segment_routing.prefix[prefixes].index.explicit_null is defined %} +{% if segment_routing.prefix[prefixes].index.explicit_null is vyos_defined %} segment-routing prefix {{ prefixes }} index {{ segment_routing.prefix[prefixes].index.value }} explicit-null {% endif %} -{% if segment_routing.prefix[prefixes].index.no_php_flag is defined %} +{% if segment_routing.prefix[prefixes].index.no_php_flag is vyos_defined %} segment-routing prefix {{ prefixes }} index {{ segment_routing.prefix[prefixes].index.value }} no-php-flag {% endif %} {% endif %} @@ -148,57 +147,51 @@ router isis VyOS {{ 'vrf ' + vrf if vrf is defined and vrf is not none }} {% endfor %} {% endif %} {% endif %} -{% if spf_delay_ietf is defined and spf_delay_ietf.init_delay is defined and spf_delay_ietf.init_delay is not none %} +{% if spf_delay_ietf.init_delay is vyos_defined %} spf-delay-ietf init-delay {{ spf_delay_ietf.init_delay }} short-delay {{ spf_delay_ietf.short_delay }} long-delay {{ spf_delay_ietf.long_delay }} holddown {{ spf_delay_ietf.holddown }} time-to-learn {{ spf_delay_ietf.time_to_learn }} {% endif %} -{% if area_password is defined and area_password is not none %} -{% if area_password.md5 is defined and area_password.md5 is not none %} +{% if area_password.md5 is vyos_defined %} area-password md5 {{ area_password.md5 }} -{% elif area_password.plaintext_password is defined and area_password.plaintext_password is not none %} +{% elif area_password.plaintext_password is vyos_defined %} area-password clear {{ area_password.plaintext_password }} -{% endif %} {% endif %} -{% if default_information is defined and default_information.originate is defined and default_information.originate is not none %} +{% if default_information.originate is vyos_defined %} {% for afi, afi_config in default_information.originate.items() %} {% for level, level_config in afi_config.items() %} - default-information originate {{ afi }} {{ level | replace('_', '-') }} {{ 'always' if level_config.always is defined }} {{ 'route-map ' ~ level_config.route_map if level_config.route_map is defined }} {{ 'metric ' ~ level_config.metric if level_config.metric is defined }} + default-information originate {{ afi }} {{ level | replace('_', '-') }} {{ 'always' if level_config.always is vyos_defined }} {{ 'route-map ' ~ level_config.route_map if level_config.route_map is vyos_defined }} {{ 'metric ' ~ level_config.metric if level_config.metric is vyos_defined }} {% endfor %} {% endfor %} {% endif %} -{% if redistribute is defined %} -{% if redistribute.ipv4 is defined and redistribute.ipv4 is not none %} -{% for protocol, protocol_options in redistribute.ipv4.items() %} -{% for level, level_config in protocol_options.items() %} -{% if level_config.metric is defined and level_config.metric is not none %} +{% if redistribute.ipv4 is vyos_defined %} +{% for protocol, protocol_options in redistribute.ipv4.items() %} +{% for level, level_config in protocol_options.items() %} +{% if level_config.metric is vyos_defined %} redistribute ipv4 {{ protocol }} {{ level | replace('_', '-') }} metric {{ level_config.metric }} -{% elif level_config.route_map is defined and level_config.route_map is not none %} +{% elif level_config.route_map is vyos_defined %} redistribute ipv4 {{ protocol }} {{ level | replace('_', '-') }} route-map {{ level_config.route_map }} -{% else %} +{% else %} redistribute ipv4 {{ protocol }} {{ level | replace('_', '-') }} -{% endif %} -{% endfor %} +{% endif %} {% endfor %} -{% endif %} -{% if redistribute.ipv6 is defined and redistribute.ipv6 is not none %} -{% for protocol, protocol_options in redistribute.ipv6.items() %} -{% for level, level_config in protocol_options.items() %} -{% if level_config.metric is defined and level_config.metric is not none %} +{% endfor %} +{% endif %} +{% if redistribute.ipv6 is vyos_defined %} +{% for protocol, protocol_options in redistribute.ipv6.items() %} +{% for level, level_config in protocol_options.items() %} +{% if level_config.metric is vyos_defined %} redistribute ipv6 {{ protocol }} {{ level | replace('_', '-') }} metric {{ level_config.metric }} -{% elif level_config.route_map is defined and level_config.route_map is not none %} +{% elif level_config.route_map is vyos_defined %} redistribute ipv6 {{ protocol }} {{ level | replace('_', '-') }} route-map {{ level_config.route_map }} -{% else %} +{% else %} redistribute ipv6 {{ protocol }} {{ level | replace('_', '-') }} -{% endif %} -{% endfor %} +{% endif %} {% endfor %} -{% endif %} +{% endfor %} {% endif %} -{% if level is defined and level is not none %} -{% if level == 'level-2' %} +{% if level is vyos_defined('level-2') %} is-type level-2-only -{% else %} +{% elif level is vyos_defined %} is-type {{ level }} -{% endif %} {% endif %} exit !
\ No newline at end of file diff --git a/data/templates/frr/ldpd.frr.tmpl b/data/templates/frr/ldpd.frr.tmpl index 537ea4025..5a67b5cdf 100644 --- a/data/templates/frr/ldpd.frr.tmpl +++ b/data/templates/frr/ldpd.frr.tmpl @@ -1,190 +1,157 @@ ! -{% if ldp is defined %} +{% if ldp is vyos_defined %} mpls ldp -{% if ldp.router_id is defined %} +{% if ldp.router_id is vyos_defined %} router-id {{ ldp.router_id }} -{% endif %} -{% if ldp.parameters is defined %} -{% if ldp.parameters.cisco_interop_tlv is defined %} +{% endif %} +{% if ldp.parameters.cisco_interop_tlv is vyos_defined %} dual-stack cisco-interop -{% endif %} -{% if ldp.parameters.transport_prefer_ipv4 is defined%} +{% endif %} +{% if ldp.parameters.transport_prefer_ipv4 is vyos_defined %} dual-stack transport-connection prefer ipv4 -{% endif %} -{% if ldp.parameters.ordered_control is defined%} +{% endif %} +{% if ldp.parameters.ordered_control is vyos_defined %} ordered-control -{% endif %} -{% endif %} -{% if ldp.neighbor is defined %} -{% for neighbors in ldp.neighbor %} -{% if ldp.neighbor[neighbors].password is defined %} - neighbor {{ neighbors }} password {{ ldp.neighbor[neighbors].password }} -{% endif %} -{% if ldp.neighbor[neighbors].ttl_security is defined %} -{% if 'disable' in ldp.neighbor[neighbors].ttl_security %} +{% endif %} +{% if ldp.neighbor is vyos_defined %} +{% for neighbor, neighbor_config in ldp.neighbor %} +{% if neighbor_config.password is vyos_defined %} + neighbor {{ neighbors }} password {{ neighbor_config.password }} +{% endif %} +{% if neighbor_config.ttl_security is vyos_defined %} +{% if neighbor_config.ttl_security.disable is vyos_defined%} neighbor {{ neighbors }} ttl-security disable -{% else %} - neighbor {{ neighbors }} ttl-security hops {{ ldp.neighbor[neighbors].ttl_security }} -{% endif %} -{% endif %} -{% if ldp.neighbor[neighbors].session_holdtime is defined %} - neighbor {{ neighbors }} session holdtime {{ ldp.neighbor[neighbors].session_holdtime }} -{% endif %} -{% endfor %} -{% endif %} +{% else %} + neighbor {{ neighbors }} ttl-security hops {{ neighbor_config.ttl_security }} +{% endif %} +{% endif %} +{% if neighbor_config.session_holdtime is vyos_defined %} + neighbor {{ neighbors }} session holdtime {{ neighbor_config.session_holdtime }} +{% endif %} +{% endfor %} +{% endif %} ! -{% if ldp.discovery is defined %} -{% if ldp.discovery.transport_ipv4_address is defined %} +{% if ldp.discovery.transport_ipv4_address is vyos_defined %} address-family ipv4 -{% if ldp.allocation is defined %} -{% if ldp.allocation.ipv4 is defined %} -{% if ldp.allocation.ipv4.access_list is defined %} +{% if ldp.allocation.ipv4.access_list is vyos_defined %} label local allocate for {{ ldp.allocation.ipv4.access_list }} -{% endif %} -{% endif %} -{% else %} +{% else %} label local allocate host-routes -{% endif %} -{% if ldp.discovery.transport_ipv4_address is defined %} +{% endif %} +{% if ldp.discovery.transport_ipv4_address is vyos_defined %} discovery transport-address {{ ldp.discovery.transport_ipv4_address }} -{% endif %} -{% if ldp.discovery.hello_ipv4_holdtime is defined %} +{% endif %} +{% if ldp.discovery.hello_ipv4_holdtime is vyos_defined %} discovery hello holdtime {{ ldp.discovery.hello_ipv4_holdtime }} -{% endif %} -{% if ldp.discovery.hello_ipv4_interval is defined %} +{% endif %} +{% if ldp.discovery.hello_ipv4_interval is vyos_defined %} discovery hello interval {{ ldp.discovery.hello_ipv4_interval }} -{% endif %} -{% if ldp.discovery.session_ipv4_holdtime is defined %} +{% endif %} +{% if ldp.discovery.session_ipv4_holdtime is vyos_defined %} session holdtime {{ ldp.discovery.session_ipv4_holdtime }} -{% endif %} -{% if ldp.import is defined %} -{% if ldp.import.ipv4 is defined %} -{% if ldp.import.ipv4.import_filter is defined %} -{% if ldp.import.ipv4.import_filter.filter_access_list is defined %} -{% if ldp.import.ipv4.import_filter.neighbor_access_list is defined %} +{% endif %} +{% if ldp.import.ipv4.import_filter.filter_access_list is vyos_defined %} +{% if ldp.import.ipv4.import_filter.neighbor_access_list is vyos_defined %} label remote accept for {{ ldp.import.ipv4.import_filter.filter_access_list }} from {{ ldp.import.ipv4.import_filter.neighbor_access_list }} -{% else %} +{% else %} label remote accept for {{ ldp.import.ipv4.import_filter.filter_access_list }} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% if ldp.export is defined %} -{% if ldp.export.ipv4 is defined %} -{% if ldp.export.ipv4.explicit_null is defined %} +{% endif %} +{% endif %} +{% if ldp.export.ipv4.explicit_null is vyos_defined %} label local advertise explicit-null -{% endif %} -{% if ldp.export.ipv4.export_filter is defined %} -{% if ldp.export.ipv4.export_filter.filter_access_list is defined %} -{% if ldp.export.ipv4.export_filter.neighbor_access_list is defined %} +{% endif %} +{% if ldp.export.ipv4.export_filter.filter_access_list is vyos_defined %} +{% if ldp.export.ipv4.export_filter.neighbor_access_list is vyos_defined %} label local advertise for {{ ldp.export.ipv4.export_filter.filter_access_list }} to {{ ldp.export.ipv4.export_filter.neighbor_access_list }} -{% else %} +{% else %} label local advertise for {{ ldp.export.ipv4.export_filter.filter_access_list }} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% if ldp.targeted_neighbor is defined %} -{% if ldp.targeted_neighbor.ipv4.enable is defined %} +{% endif %} +{% endif %} +{% if ldp.targeted_neighbor is vyos_defined %} +{% if ldp.targeted_neighbor.ipv4.enable is vyos_defined %} discovery targeted-hello accept -{% endif %} -{% if ldp.targeted_neighbor.ipv4.hello_holdtime is defined %} +{% endif %} +{% if ldp.targeted_neighbor.ipv4.hello_holdtime is vyos_defined %} discovery targeted-hello holdtime {{ ldp.targeted_neighbor.ipv4.hello_holdtime }} -{% endif %} -{% if ldp.targeted_neighbor.ipv4.hello_interval is defined %} +{% endif %} +{% if ldp.targeted_neighbor.ipv4.hello_interval is vyos_defined %} discovery targeted-hello interval {{ ldp.targeted_neighbor.ipv4.hello_interval }} -{% endif %} -{% for addresses in ldp.targeted_neighbor.ipv4.address %} - neighbor {{addresses}} targeted -{% endfor %} -{% endif %} -{% for interfaces in ldp.interface %} - interface {{interfaces}} -{% endfor %} +{% endif %} +{% for addresses in ldp.targeted_neighbor.ipv4.address %} + neighbor {{ addresses }} targeted +{% endfor %} +{% endif %} +{% if ldp.interface is vyos_defined %} +{% for interface in ldp.interface %} + interface {{ interface }} + exit +{% endfor %} +{% endif %} exit-address-family -{% else %} +{% else %} no address-family ipv4 -{% endif %} -{% endif %} +{% endif %} ! -{% if ldp.discovery is defined %} -{% if ldp.discovery.transport_ipv6_address is defined %} +{% if ldp.discovery.transport_ipv6_address is vyos_defined %} address-family ipv6 -{% if ldp.allocation is defined %} -{% if ldp.allocation.ipv6 is defined %} -{% if ldp.allocation.ipv6.access_list6 is defined %} +{% if ldp.allocation.ipv6.access_list6 is vyos_defined %} label local allocate for {{ ldp.allocation.ipv6.access_list6 }} -{% endif %} -{% endif %} -{% else %} +{% else %} label local allocate host-routes -{% endif %} -{% if ldp.discovery.transport_ipv6_address is defined %} +{% endif %} +{% if ldp.discovery.transport_ipv6_address is vyos_defined %} discovery transport-address {{ ldp.discovery.transport_ipv6_address }} -{% endif %} -{% if ldp.discovery.hello_ipv6_holdtime is defined %} +{% endif %} +{% if ldp.discovery.hello_ipv6_holdtime is vyos_defined %} discovery hello holdtime {{ ldp.discovery.hello_ipv6_holdtime }} -{% endif %} -{% if ldp.discovery.hello_ipv6_interval is defined %} +{% endif %} +{% if ldp.discovery.hello_ipv6_interval is vyos_defined %} discovery hello interval {{ ldp.discovery.hello_ipv6_interval }} -{% endif %} -{% if ldp.discovery.session_ipv6_holdtime is defined %} +{% endif %} +{% if ldp.discovery.session_ipv6_holdtime is vyos_defined %} session holdtime {{ ldp.discovery.session_ipv6_holdtime }} -{% endif %} -{% if ldp.import is defined %} -{% if ldp.import.ipv6 is defined %} -{% if ldp.import.ipv6.import_filter is defined %} -{% if ldp.import.ipv6.import_filter.filter_access_list6 is defined %} -{% if ldp.import.ipv6.import_filter.neighbor_access_list6 is defined %} +{% endif %} +{% if ldp.import.ipv6.import_filter.filter_access_list6 is vyos_defined %} +{% if ldp.import.ipv6.import_filter.neighbor_access_list6 is vyos_defined %} label remote accept for {{ ldp.import.ipv6.import_filter.filter_access_list6 }} from {{ ldp.import.ipv6.import_filter.neighbor_access_list6 }} -{% else %} +{% else %} label remote accept for {{ ldp.import.ipv6.import_filter.filter_access_list6 }} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% if ldp.export is defined %} -{% if ldp.export.ipv6 is defined %} -{% if ldp.export.ipv6.explicit_null is defined %} +{% endif %} +{% endif %} +{% if ldp.export.ipv6.explicit_null is vyos_defined %} label local advertise explicit-null -{% endif %} -{% if ldp.export.ipv6.export_filter is defined %} -{% if ldp.export.ipv6.export_filter.filter_access_list6 is defined %} -{% if ldp.export.ipv6.export_filter.neighbor_access_list6 is defined %} +{% endif %} +{% if ldp.export.ipv6.export_filter.filter_access_list6 is vyos_defined %} +{% if ldp.export.ipv6.export_filter.neighbor_access_list6 is vyos_defined %} label local advertise for {{ ldp.export.ipv6.export_filter.filter_access_list6 }} to {{ ldp.export.ipv6.export_filter.neighbor_access_list6 }} -{% else %} +{% else %} label local advertise for {{ ldp.export.ipv6.export_filter.filter_access_list6 }} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% if ldp.targeted_neighbor is defined %} -{% if ldp.targeted_neighbor.ipv6.enable is defined %} +{% endif %} +{% endif %} +{% if ldp.targeted_neighbor is vyos_defined %} +{% if ldp.targeted_neighbor.ipv6.enable is vyos_defined %} discovery targeted-hello accept -{% endif %} -{% if ldp.targeted_neighbor.ipv6.hello_holdtime is defined %} +{% endif %} +{% if ldp.targeted_neighbor.ipv6.hello_holdtime is vyos_defined %} discovery targeted-hello holdtime {{ ldp.targeted_neighbor.ipv6.hello_holdtime }} -{% endif %} -{% if ldp.targeted_neighbor.ipv6.hello_interval is defined %} +{% endif %} +{% if ldp.targeted_neighbor.ipv6.hello_interval is vyos_defined %} discovery targeted-hello interval {{ ldp.targeted_neighbor.ipv6.hello_interval }} -{% endif %} -{% for addresses in ldp.targeted_neighbor.ipv6.address %} - neighbor {{addresses}} targeted -{% endfor %} -{% endif %} -{% for interfaces in ldp.interface %} - interface {{interfaces}} -{% endfor %} +{% endif %} +{% for addresses in ldp.targeted_neighbor.ipv6.address %} + neighbor {{ addresses }} targeted +{% endfor %} +{% endif %} +{% if ldp.interface is vyos_defined %} +{% for interface in ldp.interface %} + interface {{ interface }} +{% endfor %} +{% endif %} exit-address-family -{% else %} +{% else %} no address-family ipv6 -{% endif %} +{% endif %} ! -{% endif %} exit {% endif %} ! diff --git a/data/templates/frr/ospf6d.frr.tmpl b/data/templates/frr/ospf6d.frr.tmpl index a73c6cac3..325f05213 100644 --- a/data/templates/frr/ospf6d.frr.tmpl +++ b/data/templates/frr/ospf6d.frr.tmpl @@ -1,47 +1,47 @@ ! -{% if interface is defined and interface is not none %} +{% if interface is vyos_defined %} {% for iface, iface_config in interface.items() %} interface {{ iface }} -{% if iface_config.area is defined and iface_config.area is not none %} +{% if iface_config.area is vyos_defined %} ipv6 ospf6 area {{ iface_config.area }} {% endif %} -{% if iface_config.cost is defined and iface_config.cost is not none %} +{% if iface_config.cost is vyos_defined %} ipv6 ospf6 cost {{ iface_config.cost }} {% endif %} -{% if iface_config.priority is defined and iface_config.priority is not none %} +{% if iface_config.priority is vyos_defined %} ipv6 ospf6 priority {{ iface_config.priority }} {% endif %} -{% if iface_config.hello_interval is defined and iface_config.hello_interval is not none %} +{% if iface_config.hello_interval is vyos_defined %} ipv6 ospf6 hello-interval {{ iface_config.hello_interval }} {% endif %} -{% if iface_config.retransmit_interval is defined and iface_config.retransmit_interval is not none %} +{% if iface_config.retransmit_interval is vyos_defined %} ipv6 ospf6 retransmit-interval {{ iface_config.retransmit_interval }} {% endif %} -{% if iface_config.transmit_delay is defined and iface_config.transmit_delay is not none %} +{% if iface_config.transmit_delay is vyos_defined %} ipv6 ospf6 transmit-delay {{ iface_config.transmit_delay }} {% endif %} -{% if iface_config.dead_interval is defined and iface_config.dead_interval is not none %} +{% if iface_config.dead_interval is vyos_defined %} ipv6 ospf6 dead-interval {{ iface_config.dead_interval }} {% endif %} -{% if iface_config.bfd is defined %} +{% if iface_config.bfd is vyos_defined %} ipv6 ospf6 bfd -{% if iface_config.bfd.profile is defined and iface_config.bfd.profile is not none %} +{% endif %} +{% if iface_config.bfd.profile is vyos_defined %} ipv6 ospf6 bfd profile {{ iface_config.bfd.profile }} -{% endif %} {% endif %} -{% if iface_config.mtu_ignore is defined %} +{% if iface_config.mtu_ignore is vyos_defined %} ipv6 ospf6 mtu-ignore {% endif %} -{% if iface_config.ifmtu is defined and iface_config.ifmtu is not none %} +{% if iface_config.ifmtu is vyos_defined %} ipv6 ospf6 ifmtu {{ iface_config.ifmtu }} {% endif %} -{% if iface_config.network is defined and iface_config.network is not none %} +{% if iface_config.network is vyos_defined %} ipv6 ospf6 network {{ iface_config.network }} {% endif %} -{% if iface_config.instance_id is defined and iface_config.instance_id is not none %} +{% if iface_config.instance_id is vyos_defined %} ipv6 ospf6 instance-id {{ iface_config.instance_id }} {% endif %} -{% if iface_config.passive is defined %} +{% if iface_config.passive is vyos_defined %} ipv6 ospf6 passive {% endif %} exit @@ -49,50 +49,46 @@ exit {% endfor %} {% endif %} ! -router ospf6 {{ 'vrf ' + vrf if vrf is defined and vrf is not none }} -{% if area is defined and area is not none %} +router ospf6 {{ 'vrf ' ~ vrf if vrf is vyos_defined }} +{% if area is vyos_defined %} {% for area_id, area_config in area.items() %} -{% if area_config.area_type is defined and area_config.area_type is not none %} +{% if area_config.area_type is vyos_defined %} {% for type, type_config in area_config.area_type.items() %} - area {{ area_id }} {{ type }} {{ 'default-information-originate' if type_config.default_information_originate is defined }} {{ 'no-summary' if type_config.no_summary is defined }} + area {{ area_id }} {{ type }} {{ 'default-information-originate' if type_config.default_information_originate is vyos_defined }} {{ 'no-summary' if type_config.no_summary is vyos_defined }} {% endfor %} {% endif %} -{% if area_config.range is defined and area_config.range is not none %} +{% if area_config.range is vyos_defined %} {% for prefix, prefix_config in area_config.range.items() %} - area {{ area_id }} range {{ prefix }} {{ 'advertise' if prefix_config.advertise is defined }} {{ 'not-advertise' if prefix_config.not_advertise is defined }} + area {{ area_id }} range {{ prefix }} {{ 'advertise' if prefix_config.advertise is vyos_defined }} {{ 'not-advertise' if prefix_config.not_advertise is vyos_defined }} {% endfor %} {% endif %} -{% if area_config.export_list is defined and area_config.export_list is not none %} +{% if area_config.export_list is vyos_defined %} area {{ area_id }} export-list {{ area_config.export_list }} {% endif %} -{% if area_config.import_list is defined and area_config.import_list is not none %} +{% if area_config.import_list is vyos_defined %} area {{ area_id }} import-list {{ area_config.import_list }} {% endif %} {% endfor %} {% endif %} auto-cost reference-bandwidth {{ auto_cost.reference_bandwidth }} -{% if default_information is defined and default_information.originate is defined and default_information.originate is not none %} - default-information originate {{ 'always' if default_information.originate.always is defined }} {{ 'metric ' + default_information.originate.metric if default_information.originate.metric is defined }} {{ 'metric-type ' + default_information.originate.metric_type if default_information.originate.metric_type is defined }} {{ 'route-map ' + default_information.originate.route_map if default_information.originate.route_map is defined }} +{% if default_information.originate is vyos_defined %} + default-information originate {{ 'always' if default_information.originate.always is vyos_defined }} {{ 'metric ' + default_information.originate.metric if default_information.originate.metric is vyos_defined }} {{ 'metric-type ' + default_information.originate.metric_type if default_information.originate.metric_type is vyos_defined }} {{ 'route-map ' + default_information.originate.route_map if default_information.originate.route_map is vyos_defined }} {% endif %} -{% if distance is defined and distance is not none %} -{% if distance.global is defined and distance.global is not none %} +{% if distance.global is vyos_defined %} distance {{ distance.global }} -{% endif %} -{% if distance.ospfv3 is defined and distance.ospfv3 is not none %} - distance ospf6 {{ 'intra-area ' + distance.ospfv3.intra_area if distance.ospfv3.intra_area is defined }} {{ 'inter-area ' + distance.ospfv3.inter_area if distance.ospfv3.inter_area is defined }} {{ 'external ' + distance.ospfv3.external if distance.ospfv3.external is defined }} -{% endif %} {% endif %} -{% if log_adjacency_changes is defined %} - log-adjacency-changes {{ "detail" if log_adjacency_changes.detail is defined }} +{% if distance.ospfv3 is vyos_defined %} + distance ospf6 {{ 'intra-area ' + distance.ospfv3.intra_area if distance.ospfv3.intra_area is vyos_defined }} {{ 'inter-area ' + distance.ospfv3.inter_area if distance.ospfv3.inter_area is vyos_defined }} {{ 'external ' + distance.ospfv3.external if distance.ospfv3.external is vyos_defined }} +{% endif %} +{% if log_adjacency_changes is vyos_defined %} + log-adjacency-changes {{ "detail" if log_adjacency_changes.detail is vyos_defined }} {% endif %} -{% if parameters is defined and parameters is not none %} -{% if parameters.router_id is defined and parameters.router_id is not none %} +{% if parameters.router_id is vyos_defined %} ospf6 router-id {{ parameters.router_id }} -{% endif %} {% endif %} -{% if redistribute is defined and redistribute is not none %} +{% if redistribute is vyos_defined %} {% for protocol, options in redistribute.items() %} - redistribute {{ protocol }} {{ 'route-map ' + options.route_map if options.route_map is defined }} + redistribute {{ protocol }} {{ 'route-map ' + options.route_map if options.route_map is vyos_defined }} {% endfor %} {% endif %} exit diff --git a/data/templates/frr/ospfd.frr.tmpl b/data/templates/frr/ospfd.frr.tmpl index 59d936b55..7c6738181 100644 --- a/data/templates/frr/ospfd.frr.tmpl +++ b/data/templates/frr/ospfd.frr.tmpl @@ -1,121 +1,117 @@ ! -{% if interface is defined and interface is not none %} +{% if interface is vyos_defined %} {% for iface, iface_config in interface.items() %} interface {{ iface }} -{% if iface_config.authentication is defined and iface_config.authentication is not none %} -{% if iface_config.authentication.plaintext_password is defined and iface_config.authentication.plaintext_password is not none %} +{% if iface_config.authentication.plaintext_password is vyos_defined %} ip ospf authentication-key {{ iface_config.authentication.plaintext_password }} -{% elif iface_config.authentication.md5 is defined %} +{% elif iface_config.authentication.md5 is vyos_defined %} ip ospf authentication message-digest -{% if iface_config.authentication.md5.key_id is defined and iface_config.authentication.md5.key_id is not none %} -{% for key, key_config in iface_config.authentication.md5.key_id.items() %} +{% if iface_config.authentication.md5.key_id is vyos_defined %} +{% for key, key_config in iface_config.authentication.md5.key_id.items() %} ip ospf message-digest-key {{ key }} md5 {{ key_config.md5_key }} -{% endfor %} -{% endif %} +{% endfor %} {% endif %} {% endif %} -{% if iface_config.area is defined and iface_config.area is not none %} +{% if iface_config.area is vyos_defined %} ip ospf area {{ iface_config.area }} {% endif %} -{% if iface_config.bandwidth is defined and iface_config.bandwidth is not none %} +{% if iface_config.bandwidth is vyos_defined %} bandwidth {{ iface_config.bandwidth }} {% endif %} -{% if iface_config.cost is defined and iface_config.cost is not none %} +{% if iface_config.cost is vyos_defined %} ip ospf cost {{ iface_config.cost }} {% endif %} -{% if iface_config.priority is defined and iface_config.priority is not none %} +{% if iface_config.priority is vyos_defined %} ip ospf priority {{ iface_config.priority }} {% endif %} -{% if iface_config.hello_interval is defined and iface_config.hello_interval is not none %} +{% if iface_config.hello_interval is vyos_defined %} ip ospf hello-interval {{ iface_config.hello_interval }} {% endif %} -{% if iface_config.retransmit_interval is defined and iface_config.retransmit_interval is not none %} +{% if iface_config.retransmit_interval is vyos_defined %} ip ospf retransmit-interval {{ iface_config.retransmit_interval }} {% endif %} -{% if iface_config.transmit_delay is defined and iface_config.transmit_delay is not none %} +{% if iface_config.transmit_delay is vyos_defined %} ip ospf transmit-delay {{ iface_config.transmit_delay }} {% endif %} -{% if iface_config.dead_interval is defined and iface_config.dead_interval is not none %} +{% if iface_config.dead_interval is vyos_defined %} ip ospf dead-interval {{ iface_config.dead_interval }} -{% elif iface_config.hello_multiplier is defined and iface_config.hello_multiplier is not none %} +{% elif iface_config.hello_multiplier is vyos_defined %} ip ospf dead-interval minimal hello-multiplier {{ iface_config.hello_multiplier }} {% endif %} -{% if iface_config.bfd is defined %} +{% if iface_config.bfd is vyos_defined %} ip ospf bfd -{% if iface_config.bfd.profile is defined and iface_config.bfd.profile is not none %} +{% endif %} +{% if iface_config.bfd.profile is vyos_defined %} ip ospf bfd profile {{ iface_config.bfd.profile }} -{% endif %} {% endif %} -{% if iface_config.mtu_ignore is defined %} +{% if iface_config.mtu_ignore is vyos_defined %} ip ospf mtu-ignore {% endif %} -{% if iface_config.network is defined and iface_config.network is not none %} +{% if iface_config.network is vyos_defined %} ip ospf network {{ iface_config.network }} {% endif %} -{% if iface_config.passive is defined %} - {{ 'no ' if iface_config.passive.disable is defined }}ip ospf passive +{% if iface_config.passive is vyos_defined %} + {{ 'no ' if iface_config.passive.disable is vyos_defined }}ip ospf passive {% endif %} exit ! {% endfor %} {% endif %} ! -router ospf {{ 'vrf ' + vrf if vrf is defined and vrf is not none }} -{% if access_list is defined and access_list is not none %} +router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }} +{% if access_list is vyos_defined %} {% for acl, acl_config in access_list.items() %} -{% for protocol in acl_config.export if acl_config.export is defined %} +{% for protocol in acl_config.export if acl_config.export is vyos_defined %} distribute-list {{ acl }} out {{ protocol }} {% endfor %} {% endfor %} {% endif %} -{% if area is defined and area is not none %} +{% if area is vyos_defined %} {% for area_id, area_config in area.items() %} -{% if area_config.area_type is defined and area_config.area_type is not none %} +{% if area_config.area_type is vyos_defined %} {% for type, type_config in area_config.area_type.items() if type != 'normal' %} - area {{ area_id }} {{ type }} {{ 'no-summary' if type_config.no_summary is defined }} -{% if type_config.default_cost is defined and type_config.default_cost is not none %} + area {{ area_id }} {{ type }} {{ 'no-summary' if type_config.no_summary is vyos_defined }} +{% if type_config.default_cost is vyos_defined %} area {{ area_id }} default-cost {{ type_config.default_cost }} {% endif %} {% endfor %} {% endif %} -{% if area_config.authentication is defined and area_config.authentication is not none %} - area {{ area_id }} authentication {{ 'message-digest' if area_config.authentication == 'md5' }} +{% if area_config.authentication is vyos_defined %} + area {{ area_id }} authentication {{ 'message-digest' if area_config.authentication is vyos_defined('md5') }} {% endif %} -{% for network in area_config.network if area_config.network is defined %} +{% for network in area_config.network if area_config.network is vyos_defined %} network {{ network }} area {{ area_id }} {% endfor %} -{% if area_config.range is defined and area_config.range is not none %} +{% if area_config.range is vyos_defined %} {% for range, range_config in area_config.range.items() %} -{% if range_config.cost is defined and range_config.cost is not none %} +{% if range_config.cost is vyos_defined %} area {{ area_id }} range {{ range }} cost {{ range_config.cost }} {% endif %} -{% if range_config.not_advertise is defined %} +{% if range_config.not_advertise is vyos_defined %} area {{ area_id }} range {{ range }} not-advertise {% endif %} -{% if range_config.substitute is defined and range_config.substitute is not none %} +{% if range_config.substitute is vyos_defined %} area {{ area_id }} range {{ range }} substitute {{ range_config.substitute }} {% endif %} {% endfor %} {% endif %} -{% if area_config.export_list is defined and area_config.export_list is not none %} +{% if area_config.export_list is vyos_defined %} area {{ area_id }} export-list {{ area_config.export_list }} {% endif %} -{% if area_config.import_list is defined and area_config.import_list is not none %} +{% if area_config.import_list is vyos_defined %} area {{ area_id }} import-list {{ area_config.import_list }} {% endif %} -{% if area_config.shortcut is defined and area_config.shortcut is not none %} +{% if area_config.shortcut is vyos_defined %} area {{ area_id }} shortcut {{ area_config.shortcut }} {% endif %} -{% if area_config.virtual_link is defined and area_config.virtual_link is not none %} +{% if area_config.virtual_link is vyos_defined %} {% for link, link_config in area_config.virtual_link.items() %} -{% if link_config.authentication is defined and link_config.authentication is not none %} -{% if link_config.authentication.plaintext_password is defined and link_config.authentication.plaintext_password is not none %} +{% if link_config.authentication.plaintext_password is vyos_defined %} area {{ area_id }} virtual-link {{ link }} authentication-key {{ link_config.authentication.plaintext_password }} -{% elif link_config.authentication.md5 is defined and link_config.authentication.md5.key_id is defined and link_config.authentication.md5.key_id is not none %} -{% for key, key_config in link_config.authentication.md5.key_id.items() %} +{% elif link_config.authentication.md5.key_id is vyos_defined %} +{% for key, key_config in link_config.authentication.md5.key_id.items() %} area {{ area_id }} virtual-link {{ link }} message-digest-key {{ key }} md5 {{ key_config.md5_key }} -{% endfor %} -{% endif %} +{% endfor %} {% endif %} {# The following values are default values #} area {{ area_id }} virtual-link {{ link }} hello-interval {{ link_config.hello_interval }} retransmit-interval {{ link_config.retransmit_interval }} transmit-delay {{ link_config.transmit_delay }} dead-interval {{ link_config.dead_interval }} @@ -123,75 +119,69 @@ router ospf {{ 'vrf ' + vrf if vrf is defined and vrf is not none }} {% endif %} {% endfor %} {% endif %} -{% if auto_cost is defined and auto_cost.reference_bandwidth is defined and auto_cost.reference_bandwidth is not none %} +{% if auto_cost.reference_bandwidth is vyos_defined %} auto-cost reference-bandwidth {{ auto_cost.reference_bandwidth }} {% endif %} -{% if default_information is defined and default_information.originate is defined and default_information.originate is not none %} - default-information originate {{ 'always' if default_information.originate.always is defined }} {{ 'metric ' + default_information.originate.metric if default_information.originate.metric is defined }} {{ 'metric-type ' + default_information.originate.metric_type if default_information.originate.metric_type is defined }} {{ 'route-map ' + default_information.originate.route_map if default_information.originate.route_map is defined }} +{% if default_information.originate is vyos_defined %} + default-information originate {{ 'always' if default_information.originate.always is vyos_defined }} {{ 'metric ' + default_information.originate.metric if default_information.originate.metric is vyos_defined }} {{ 'metric-type ' + default_information.originate.metric_type if default_information.originate.metric_type is vyos_defined }} {{ 'route-map ' + default_information.originate.route_map if default_information.originate.route_map is vyos_defined }} {% endif %} -{% if default_metric is defined and default_metric is not none %} +{% if default_metric is vyos_defined %} default-metric {{ default_metric }} {% endif %} -{% if maximum_paths is defined and maximum_paths is not none %} +{% if maximum_paths is vyos_defined %} maximum-paths {{ maximum_paths }} {% endif %} -{% if distance is defined and distance is not none %} -{% if distance.global is defined and distance.global is not none %} +{% if distance.global is vyos_defined %} distance {{ distance.global }} -{% endif %} -{% if distance.ospf is defined and distance.ospf is not none %} - distance ospf {{ 'intra-area ' + distance.ospf.intra_area if distance.ospf.intra_area is defined }} {{ 'inter-area ' + distance.ospf.inter_area if distance.ospf.inter_area is defined }} {{ 'external ' + distance.ospf.external if distance.ospf.external is defined }} -{% endif %} {% endif %} -{% if log_adjacency_changes is defined %} - log-adjacency-changes {{ "detail" if log_adjacency_changes.detail is defined }} +{% if distance.ospf is vyos_defined %} + distance ospf {{ 'intra-area ' + distance.ospf.intra_area if distance.ospf.intra_area is vyos_defined }} {{ 'inter-area ' + distance.ospf.inter_area if distance.ospf.inter_area is vyos_defined }} {{ 'external ' + distance.ospf.external if distance.ospf.external is vyos_defined }} {% endif %} -{% if max_metric is defined and max_metric.router_lsa is defined and max_metric.router_lsa is not none %} -{% if max_metric.router_lsa.administrative is defined %} +{% if log_adjacency_changes is vyos_defined %} + log-adjacency-changes {{ "detail" if log_adjacency_changes.detail is vyos_defined }} +{% endif %} +{% if max_metric.router_lsa.administrative is vyos_defined %} max-metric router-lsa administrative -{% endif %} -{% if max_metric.router_lsa.on_shutdown is defined and max_metric.router_lsa.on_shutdown is not none %} +{% endif %} +{% if max_metric.router_lsa.on_shutdown is vyos_defined %} max-metric router-lsa on-shutdown {{ max_metric.router_lsa.on_shutdown }} -{% endif %} -{% if max_metric.router_lsa.on_startup is defined and max_metric.router_lsa.on_startup is not none %} +{% endif %} +{% if max_metric.router_lsa.on_startup is vyos_defined %} max-metric router-lsa on-startup {{ max_metric.router_lsa.on_startup }} -{% endif %} {% endif %} -{% if mpls_te is defined and mpls_te.enable is defined %} +{% if mpls_te.enable is vyos_defined %} mpls-te on mpls-te router-address {{ mpls_te.router_address }} {% endif %} -{% if neighbor is defined and neighbor is not none%} +{% if neighbor is vyos_defined %} {% for address, address_config in neighbor.items() %} - neighbor {{ address }} {{ 'priority ' + address_config.priority if address_config.priority is defined }} {{ 'poll-interval ' + address_config.poll_interval if address_config.poll_interval is defined }} + neighbor {{ address }} {{ 'priority ' + address_config.priority if address_config.priority is vyos_defined }} {{ 'poll-interval ' + address_config.poll_interval if address_config.poll_interval is vyos_defined }} {% endfor %} {% endif %} -{% if parameters is defined and parameters is not none %} -{% if parameters.abr_type is defined and parameters.abr_type is not none %} +{% if parameters.abr_type is vyos_defined %} ospf abr-type {{ parameters.abr_type }} -{% endif %} -{% if parameters.router_id is defined and parameters.router_id is not none %} +{% endif %} +{% if parameters.router_id is vyos_defined %} ospf router-id {{ parameters.router_id }} -{% endif %} {% endif %} -{% if passive_interface is defined and passive_interface.default is defined %} +{% if passive_interface.default is vyos_defined %} passive-interface default {% endif %} -{% if redistribute is defined and redistribute is not none %} +{% if redistribute is vyos_defined %} {% for protocol, protocols_options in redistribute.items() %} {% if protocol == 'table' %} {% for table, table_options in protocols_options.items() %} - redistribute {{ protocol }} {{ table }} {{ 'metric ' + table_options.metric if table_options.metric is defined }} {{ 'metric-type ' + table_options.metric_type if table_options.metric_type is defined }} {{ 'route-map ' + table_options.route_map if table_options.route_map is defined }} + redistribute {{ protocol }} {{ table }} {{ 'metric ' + table_options.metric if table_options.metric is vyos_defined }} {{ 'metric-type ' + table_options.metric_type if table_options.metric_type is vyos_defined }} {{ 'route-map ' + table_options.route_map if table_options.route_map is vyos_defined }} {% endfor %} {% else %} - redistribute {{ protocol }} {{ 'metric ' + protocols_options.metric if protocols_options.metric is defined }} {{ 'metric-type ' + protocols_options.metric_type if protocols_options.metric_type is defined }} {{ 'route-map ' + protocols_options.route_map if protocols_options.route_map is defined }} + redistribute {{ protocol }} {{ 'metric ' + protocols_options.metric if protocols_options.metric is vyos_defined }} {{ 'metric-type ' + protocols_options.metric_type if protocols_options.metric_type is vyos_defined }} {{ 'route-map ' + protocols_options.route_map if protocols_options.route_map is vyos_defined }} {% endif %} {% endfor %} {% endif %} -{% if refresh is defined and refresh.timers is defined and refresh.timers is not none %} +{% if refresh.timers is vyos_defined %} refresh timer {{ refresh.timers }} {% endif %} -{% if timers is defined and timers.throttle is defined and timers.throttle.spf is defined and timers.throttle.spf is not none %} +{% if timers.throttle.spf.delay is vyos_defined and timers.throttle.spf.initial_holdtime is vyos_defined and timers.throttle.spf.max_holdtime is vyos_defined %} {# Timer values have default values #} timers throttle spf {{ timers.throttle.spf.delay }} {{ timers.throttle.spf.initial_holdtime }} {{ timers.throttle.spf.max_holdtime }} {% endif %} diff --git a/data/templates/frr/policy.frr.tmpl b/data/templates/frr/policy.frr.tmpl index 60e15f4fd..814dbf761 100644 --- a/data/templates/frr/policy.frr.tmpl +++ b/data/templates/frr/policy.frr.tmpl @@ -1,18 +1,18 @@ -{% if access_list is defined and access_list is not none %} +{% if access_list is vyos_defined %} {% for acl, acl_config in access_list.items() | natural_sort %} -{% if acl_config.description is defined and acl_config.description is not none %} +{% if acl_config.description is vyos_defined %} access-list {{ acl }} remark {{ acl_config.description }} {% endif %} -{% if acl_config.rule is defined and acl_config.rule is not none %} +{% if acl_config.rule is vyos_defined %} {% for rule, rule_config in acl_config.rule.items() | natural_sort %} {% set ip = '' %} {% set src = '' %} {% set src_mask = '' %} -{% if rule_config.source is defined and rule_config.source.any is defined %} +{% if rule_config.source.any is vyos_defined %} {% set src = 'any' %} -{% elif rule_config.source is defined and rule_config.source.host is defined and rule_config.source.host is not none %} -{% set src = 'host ' + rule_config.source.host %} -{% elif rule_config.source is defined and rule_config.source.network is defined and rule_config.source.network is not none %} +{% elif rule_config.source.host is vyos_defined %} +{% set src = 'host ' ~ rule_config.source.host %} +{% elif rule_config.source.network is vyos_defined %} {% set src = rule_config.source.network %} {% set src_mask = rule_config.source.inverse_mask %} {% endif %} @@ -21,11 +21,11 @@ access-list {{ acl }} remark {{ acl_config.description }} {% if (acl|int >= 100 and acl|int <= 199) or (acl|int >= 2000 and acl|int <= 2699) %} {% set ip = 'ip' %} {% set dst = 'any' %} -{% if rule_config.destination is defined and rule_config.destination.any is defined %} +{% if rule_config.destination.any is vyos_defined %} {% set dst = 'any' %} -{% elif rule_config.destination is defined and rule_config.destination.host is defined and rule_config.destination.host is not none %} -{% set dst = 'host ' + rule_config.destination.host %} -{% elif rule_config.destination is defined and rule_config.destination.network is defined and rule_config.destination.network is not none %} +{% elif rule_config.destination.host is vyos_defined %} +{% set dst = 'host ' ~ rule_config.destination.host %} +{% elif rule_config.destination.network is vyos_defined %} {% set dst = rule_config.destination.network %} {% set dst_mask = rule_config.destination.inverse_mask %} {% endif %} @@ -36,28 +36,28 @@ access-list {{ acl }} seq {{ rule }} {{ rule_config.action }} {{ ip }} {{ src }} {% endfor %} {% endif %} ! -{% if access_list6 is defined and access_list6 is not none %} +{% if access_list6 is vyos_defined %} {% for acl, acl_config in access_list6.items() | natural_sort %} -{% if acl_config.description is defined and acl_config.description is not none %} +{% if acl_config.description is vyos_defined %} ipv6 access-list {{ acl }} remark {{ acl_config.description }} {% endif %} -{% if acl_config.rule is defined and acl_config.rule is not none %} +{% if acl_config.rule is vyos_defined %} {% for rule, rule_config in acl_config.rule.items() | natural_sort %} {% set src = '' %} -{% if rule_config.source is defined and rule_config.source.any is defined %} +{% if rule_config.source.any is vyos_defined %} {% set src = 'any' %} -{% elif rule_config.source is defined and rule_config.source.network is defined and rule_config.source.network is not none %} +{% elif rule_config.source.network is vyos_defined %} {% set src = rule_config.source.network %} {% endif %} -ipv6 access-list {{ acl }} seq {{ rule }} {{ rule_config.action }} {{ src }} {{ 'exact-match' if rule_config.source.exact_match is defined }} +ipv6 access-list {{ acl }} seq {{ rule }} {{ rule_config.action }} {{ src }} {{ 'exact-match' if rule_config.source.exact_match is vyos_defined }} {% endfor %} {% endif %} {% endfor %} {% endif %} ! -{% if as_path_list is defined and as_path_list is not none %} +{% if as_path_list is vyos_defined %} {% for acl, acl_config in as_path_list.items() | natural_sort %} -{% if acl_config.rule is defined and acl_config.rule is not none %} +{% if acl_config.rule is vyos_defined %} {% for rule, rule_config in acl_config.rule.items() | natural_sort %} bgp as-path access-list {{ acl }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.regex }} {% endfor %} @@ -65,9 +65,9 @@ bgp as-path access-list {{ acl }} seq {{ rule }} {{ rule_config.action }} {{ rul {% endfor %} {% endif %} ! -{% if community_list is defined and community_list is not none %} +{% if community_list is vyos_defined %} {% for list, list_config in community_list.items() | natural_sort %} -{% if list_config.rule is defined and list_config.rule is not none %} +{% if list_config.rule is vyos_defined %} {% for rule, rule_config in list_config.rule.items() | natural_sort %} {# by default, if casting to int fails it returns 0 #} {% if list|int != 0 %} @@ -80,9 +80,9 @@ bgp community-list expanded {{ list }} seq {{ rule }} {{ rule_config.action }} { {% endfor %} {% endif %} ! -{% if extcommunity_list is defined and extcommunity_list is not none %} +{% if extcommunity_list is vyos_defined %} {% for list, list_config in extcommunity_list.items() | natural_sort %} -{% if list_config.rule is defined and list_config.rule is not none %} +{% if list_config.rule is vyos_defined %} {% for rule, rule_config in list_config.rule.items() | natural_sort %} {# by default, if casting to int fails it returns 0 #} {% if list|int != 0 %} @@ -95,9 +95,9 @@ bgp extcommunity-list expanded {{ list }} seq {{ rule }} {{ rule_config.action } {% endfor %} {% endif %} ! -{% if large_community_list is defined and large_community_list is not none %} +{% if large_community_list is vyos_defined %} {% for list, list_config in large_community_list.items() | natural_sort %} -{% if list_config.rule is defined and list_config.rule is not none %} +{% if list_config.rule is vyos_defined %} {% for rule, rule_config in list_config.rule.items() | natural_sort %} {# by default, if casting to int fails it returns 0 #} {% if list|int != 0 %} @@ -110,209 +110,207 @@ bgp large-community-list expanded {{ list }} seq {{ rule }} {{ rule_config.actio {% endfor %} {% endif %} ! -{% if prefix_list is defined and prefix_list is not none %} +{% if prefix_list is vyos_defined %} {% for prefix_list, prefix_list_config in prefix_list.items() | natural_sort %} -{% if prefix_list_config.description is defined and prefix_list_config.description is not none %} +{% if prefix_list_config.description is vyos_defined %} ip prefix-list {{ prefix_list }} description {{ prefix_list_config.description }} {% endif %} -{% if prefix_list_config.rule is defined and prefix_list_config.rule is not none %} +{% if prefix_list_config.rule is vyos_defined %} {% for rule, rule_config in prefix_list_config.rule.items() | natural_sort %} -{% if rule_config.prefix is defined and rule_config.prefix is not none %} -ip prefix-list {{ prefix_list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.prefix }} {{ 'ge ' + rule_config.ge if rule_config.ge is defined }} {{ 'le ' + rule_config.le if rule_config.le is defined }} +{% if rule_config.prefix is vyos_defined %} +ip prefix-list {{ prefix_list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.prefix }} {{ 'ge ' ~ rule_config.ge if rule_config.ge is vyos_defined }} {{ 'le ' ~ rule_config.le if rule_config.le is vyos_defined }} {% endif %} {% endfor %} {% endif %} {% endfor %} {% endif %} ! -{% if prefix_list6 is defined and prefix_list6 is not none %} +{% if prefix_list6 is vyos_defined %} {% for prefix_list, prefix_list_config in prefix_list6.items() | natural_sort %} -{% if prefix_list_config.description is defined and prefix_list_config.description is not none %} +{% if prefix_list_config.description is vyos_defined %} ipv6 prefix-list {{ prefix_list }} description {{ prefix_list_config.description }} {% endif %} -{% if prefix_list_config.rule is defined and prefix_list_config.rule is not none %} +{% if prefix_list_config.rule is vyos_defined %} {% for rule, rule_config in prefix_list_config.rule.items() | natural_sort %} -{% if rule_config.prefix is defined and rule_config.prefix is not none %} -ipv6 prefix-list {{ prefix_list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.prefix }} {{ 'ge ' + rule_config.ge if rule_config.ge is defined }} {{ 'le ' + rule_config.le if rule_config.le is defined }} +{% if rule_config.prefix is vyos_defined %} +ipv6 prefix-list {{ prefix_list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.prefix }} {{ 'ge ' ~ rule_config.ge if rule_config.ge is vyos_defined }} {{ 'le ' ~ rule_config.le if rule_config.le is vyos_defined }} {% endif %} {% endfor %} {% endif %} {% endfor %} {% endif %} ! -{% if route_map is defined and route_map is not none %} +{% if route_map is vyos_defined %} {% for route_map, route_map_config in route_map.items() | natural_sort %} -{% if route_map_config.rule is defined and route_map_config.rule is not none %} +{% if route_map_config.rule is vyos_defined %} {% for rule, rule_config in route_map_config.rule.items() | natural_sort %} route-map {{ route_map }} {{ rule_config.action }} {{ rule }} -{% if rule_config.call is defined and rule_config.call is not none %} +{% if rule_config.call is vyos_defined %} call {{ rule_config.call }} {% endif %} -{% if rule_config.continue is defined and rule_config.continue is not none %} +{% if rule_config.continue is vyos_defined %} on-match goto {{ rule_config.continue }} {% endif %} -{% if rule_config.description is defined and rule_config.description is not none %} +{% if rule_config.description is vyos_defined %} description {{ rule_config.description }} {% endif %} -{% if rule_config.match is defined and rule_config.match is not none %} -{% if rule_config.match.as_path is defined and rule_config.match.as_path is not none %} +{% if rule_config.match is vyos_defined %} +{% if rule_config.match.as_path is vyos_defined %} match as-path {{ rule_config.match.as_path }} {% endif %} -{% if rule_config.match.community is defined and rule_config.match.community.community_list is defined and rule_config.match.community.community_list is not none %} - match community {{ rule_config.match.community.community_list }} {{ 'exact-match' if rule_config.match.community.exact_match is defined }} +{% if rule_config.match.community.community_list is vyos_defined %} + match community {{ rule_config.match.community.community_list }} {{ 'exact-match' if rule_config.match.community.exact_match is vyos_defined }} {% endif %} -{% if rule_config.match.extcommunity is defined and rule_config.match.extcommunity is not none %} +{% if rule_config.match.extcommunity is vyos_defined %} match extcommunity {{ rule_config.match.extcommunity }} {% endif %} -{% if rule_config.match.evpn is defined and rule_config.match.evpn.default_route is defined %} +{% if rule_config.match.evpn.default_route is vyos_defined %} match evpn default-route {% endif %} -{% if rule_config.match.evpn is defined and rule_config.match.evpn.rd is defined and rule_config.match.evpn.rd is not none %} +{% if rule_config.match.evpn.rd is vyos_defined %} match evpn rd {{ rule_config.match.evpn.rd }} {% endif %} -{% if rule_config.match.evpn is defined and rule_config.match.evpn.route_type is defined and rule_config.match.evpn.route_type is not none %} +{% if rule_config.match.evpn.route_type is vyos_defined %} match evpn route-type {{ rule_config.match.evpn.route_type }} {% endif %} -{% if rule_config.match.evpn is defined and rule_config.match.evpn.vni is defined and rule_config.match.evpn.vni is not none %} +{% if rule_config.match.evpn.vni is vyos_defined %} match evpn vni {{ rule_config.match.evpn.vni }} {% endif %} -{% if rule_config.match.interface is defined and rule_config.match.interface is not none %} +{% if rule_config.match.interface is vyos_defined %} match interface {{ rule_config.match.interface }} {% endif %} -{% if rule_config.match.ip is defined and rule_config.match.ip.address is defined and rule_config.match.ip.address.access_list is defined and rule_config.match.ip.address.access_list is not none %} +{% if rule_config.match.ip.address.access_list is vyos_defined %} match ip address {{ rule_config.match.ip.address.access_list }} {% endif %} -{% if rule_config.match.ip is defined and rule_config.match.ip.address is defined and rule_config.match.ip.address.prefix_list is defined and rule_config.match.ip.address.prefix_list is not none %} +{% if rule_config.match.ip.address.prefix_list is vyos_defined %} match ip address prefix-list {{ rule_config.match.ip.address.prefix_list }} {% endif %} -{% if rule_config.match.ip is defined and rule_config.match.ip.nexthop is defined and rule_config.match.ip.nexthop.access_list is defined and rule_config.match.ip.nexthop.access_list is not none %} +{% if rule_config.match.ip.nexthop.access_list is vyos_defined %} match ip next-hop {{ rule_config.match.ip.nexthop.access_list }} {% endif %} -{% if rule_config.match.ip is defined and rule_config.match.ip.nexthop is defined and rule_config.match.ip.nexthop.prefix_list is defined and rule_config.match.ip.nexthop.prefix_list is not none %} +{% if rule_config.match.ip.nexthop.prefix_list is vyos_defined %} match ip next-hop prefix-list {{ rule_config.match.ip.nexthop.prefix_list }} {% endif %} -{% if rule_config.match.ip is defined and rule_config.match.ip.route_source is defined and rule_config.match.ip.route_source.access_list is defined and rule_config.match.ip.route_source.access_list is not none %} +{% if rule_config.match.ip.route_source.access_list is vyos_defined %} match ip route-source {{ rule_config.match.ip.route_source.access_list }} {% endif %} -{% if rule_config.match.ip is defined and rule_config.match.ip.route_source is defined and rule_config.match.ip.route_source.prefix_list is defined and rule_config.match.ip.route_source.prefix_list is not none %} +{% if rule_config.match.ip.route_source.prefix_list is vyos_defined %} match ip route-source prefix-list {{ rule_config.match.ip.route_source.prefix_list }} {% endif %} -{% if rule_config.match.ipv6 is defined and rule_config.match.ipv6.address is defined and rule_config.match.ipv6.address.access_list is defined and rule_config.match.ipv6.address.access_list is not none %} +{% if rule_config.match.ipv6.address.access_list is vyos_defined %} match ipv6 address {{ rule_config.match.ipv6.address.access_list }} {% endif %} -{% if rule_config.match.ipv6 is defined and rule_config.match.ipv6.address is defined and rule_config.match.ipv6.address.prefix_list is defined and rule_config.match.ipv6.address.prefix_list is not none %} +{% if rule_config.match.ipv6.address.prefix_list is vyos_defined %} match ipv6 address prefix-list {{ rule_config.match.ipv6.address.prefix_list }} {% endif %} -{% if rule_config.match.ipv6 is defined and rule_config.match.ipv6.nexthop is defined and rule_config.match.ipv6.nexthop is not none %} +{% if rule_config.match.ipv6.nexthop is vyos_defined %} match ipv6 next-hop address {{ rule_config.match.ipv6.nexthop }} {% endif %} -{% if rule_config.match.large_community is defined and rule_config.match.large_community.large_community_list is defined and rule_config.match.large_community.large_community_list is not none %} +{% if rule_config.match.large_community.large_community_list is vyos_defined %} match large-community {{ rule_config.match.large_community.large_community_list }} {% endif %} -{% if rule_config.match.local_preference is defined and rule_config.match.local_preference is not none %} +{% if rule_config.match.local_preference is vyos_defined %} match local-preference {{ rule_config.match.local_preference }} {% endif %} -{% if rule_config.match.metric is defined and rule_config.match.metric is not none %} +{% if rule_config.match.metric is vyos_defined %} match metric {{ rule_config.match.metric }} {% endif %} -{% if rule_config.match.origin is defined and rule_config.match.origin is not none %} +{% if rule_config.match.origin is vyos_defined %} match origin {{ rule_config.match.origin }} {% endif %} -{% if rule_config.match.peer is defined and rule_config.match.peer is not none %} +{% if rule_config.match.peer is vyos_defined %} match peer {{ rule_config.match.peer }} {% endif %} -{% if rule_config.match.rpki is defined and rule_config.match.rpki is not none %} +{% if rule_config.match.rpki is vyos_defined %} match rpki {{ rule_config.match.rpki }} {% endif %} -{% if rule_config.match.tag is defined and rule_config.match.tag is not none %} +{% if rule_config.match.tag is vyos_defined %} match tag {{ rule_config.match.tag }} {% endif %} {% endif %} -{% if rule_config.on_match is defined and rule_config.on_match is not none %} -{% if rule_config.on_match.next is defined %} +{% if rule_config.on_match.next is vyos_defined %} on-match next -{% endif %} -{% if rule_config.on_match.goto is defined and rule_config.on_match.goto is not none %} +{% endif %} +{% if rule_config.on_match.goto is vyos_defined %} on-match goto {{ rule_config.on_match.goto }} -{% endif %} {% endif %} -{% if rule_config.set is defined and rule_config.set is not none %} -{% if rule_config.set.aggregator is defined and rule_config.set.aggregator.as is defined and rule_config.set.aggregator.ip is defined %} +{% if rule_config.set is vyos_defined %} +{% if rule_config.set.aggregator.as is vyos_defined and rule_config.set.aggregator.ip is vyos_defined %} set aggregator as {{ rule_config.set.aggregator.as }} {{ rule_config.set.aggregator.ip }} {% endif %} -{% if rule_config.set.as_path_exclude is defined and rule_config.set.as_path_exclude is not none %} +{% if rule_config.set.as_path_exclude is vyos_defined %} set as-path exclude {{ rule_config.set.as_path_exclude }} {% endif %} -{% if rule_config.set.as_path_prepend is defined and rule_config.set.as_path_prepend is not none %} +{% if rule_config.set.as_path_prepend is vyos_defined %} set as-path prepend {{ rule_config.set.as_path_prepend }} {% endif %} -{% if rule_config.set.atomic_aggregate is defined %} +{% if rule_config.set.atomic_aggregate is vyos_defined %} set atomic-aggregate {% endif %} -{% if rule_config.set.comm_list is defined and rule_config.set.comm_list.comm_list is defined and rule_config.set.comm_list.comm_list is not none %} - set comm-list {{ rule_config.set.comm_list.comm_list }} {{ 'delete' if rule_config.set.comm_list.delete is defined }} +{% if rule_config.set.comm_list.comm_list is vyos_defined %} + set comm-list {{ rule_config.set.comm_list.comm_list }} {{ 'delete' if rule_config.set.comm_list.delete is vyos_defined }} {% endif %} -{% if rule_config.set.community is defined and rule_config.set.community is not none %} +{% if rule_config.set.community is vyos_defined %} set community {{ rule_config.set.community }} {% endif %} -{% if rule_config.set.distance is defined and rule_config.set.distance is not none %} +{% if rule_config.set.distance is vyos_defined %} set distance {{ rule_config.set.distance }} {% endif %} -{% if rule_config.set.extcommunity is defined and rule_config.set.extcommunity.bandwidth is defined and rule_config.set.extcommunity.bandwidth is not none %} +{% if rule_config.set.extcommunity.bandwidth is vyos_defined %} set extcommunity bandwidth {{ rule_config.set.extcommunity.bandwidth }} {% endif %} -{% if rule_config.set.extcommunity is defined and rule_config.set.extcommunity.rt is defined and rule_config.set.extcommunity.rt is not none %} +{% if rule_config.set.extcommunity.rt is vyos_defined %} set extcommunity rt {{ rule_config.set.extcommunity.rt }} {% endif %} -{% if rule_config.set.extcommunity is defined and rule_config.set.extcommunity.soo is defined and rule_config.set.extcommunity.soo is not none %} +{% if rule_config.set.extcommunity.soo is vyos_defined %} set extcommunity soo {{ rule_config.set.extcommunity.soo }} {% endif %} -{% if rule_config.set.ip_next_hop is defined and rule_config.set.ip_next_hop is not none %} +{% if rule_config.set.ip_next_hop is vyos_defined %} set ip next-hop {{ rule_config.set.ip_next_hop }} {% endif %} -{% if rule_config.set.ipv6_next_hop is defined and rule_config.set.ipv6_next_hop.global is defined and rule_config.set.ipv6_next_hop.global is not none %} +{% if rule_config.set.ipv6_next_hop.global is vyos_defined %} set ipv6 next-hop global {{ rule_config.set.ipv6_next_hop.global }} {% endif %} -{% if rule_config.set.ipv6_next_hop is defined and rule_config.set.ipv6_next_hop.local is defined and rule_config.set.ipv6_next_hop.local is not none %} +{% if rule_config.set.ipv6_next_hop.local is vyos_defined %} set ipv6 next-hop local {{ rule_config.set.ipv6_next_hop.local }} {% endif %} -{% if rule_config.set.ipv6_next_hop is defined and rule_config.set.ipv6_next_hop.peer_address is defined %} +{% if rule_config.set.ipv6_next_hop.peer_address is vyos_defined %} set ipv6 next-hop peer-address {% endif %} -{% if rule_config.set.ipv6_next_hop is defined and rule_config.set.ipv6_next_hop.prefer_global is defined %} +{% if rule_config.set.ipv6_next_hop.prefer_global is vyos_defined %} set ipv6 next-hop prefer-global {% endif %} -{% if rule_config.set.large_community is defined and rule_config.set.large_community is not none %} +{% if rule_config.set.large_community is vyos_defined %} set large-community {{ rule_config.set.large_community }} {% endif %} -{% if rule_config.set.large_comm_list_delete is defined and rule_config.set.large_comm_list_delete is not none %} +{% if rule_config.set.large_comm_list_delete is vyos_defined %} set large-comm-list {{ rule_config.set.large_comm_list_delete }} delete {% endif %} -{% if rule_config.set.local_preference is defined and rule_config.set.local_preference is not none %} +{% if rule_config.set.local_preference is vyos_defined %} set local-preference {{ rule_config.set.local_preference }} {% endif %} -{% if rule_config.set.metric is defined and rule_config.set.metric is not none %} +{% if rule_config.set.metric is vyos_defined %} set metric {{ rule_config.set.metric }} {% endif %} -{% if rule_config.set.metric_type is defined and rule_config.set.metric_type is not none %} +{% if rule_config.set.metric_type is vyos_defined %} set metric-type {{ rule_config.set.metric_type }} {% endif %} -{% if rule_config.set.origin is defined and rule_config.set.origin is not none %} +{% if rule_config.set.origin is vyos_defined %} set origin {{ rule_config.set.origin }} {% endif %} -{% if rule_config.set.originator_id is defined and rule_config.set.originator_id is not none %} +{% if rule_config.set.originator_id is vyos_defined %} set originator-id {{ rule_config.set.originator_id }} {% endif %} -{% if rule_config.set.src is defined and rule_config.set.src is not none %} +{% if rule_config.set.src is vyos_defined %} set src {{ rule_config.set.src }} {% endif %} -{% if rule_config.set.table is defined and rule_config.set.table is not none %} +{% if rule_config.set.table is vyos_defined %} set table {{ rule_config.set.table }} {% endif %} -{% if rule_config.set.tag is defined and rule_config.set.tag is not none %} +{% if rule_config.set.tag is vyos_defined %} set tag {{ rule_config.set.tag }} {% endif %} -{% if rule_config.set.weight is defined and rule_config.set.weight is not none %} +{% if rule_config.set.weight is vyos_defined %} set weight {{ rule_config.set.weight }} {% endif %} {% endif %} diff --git a/data/templates/frr/rip_ripng.frr.j2 b/data/templates/frr/rip_ripng.frr.j2 index de180ee6b..3732371b2 100644 --- a/data/templates/frr/rip_ripng.frr.j2 +++ b/data/templates/frr/rip_ripng.frr.j2 @@ -1,36 +1,36 @@ -{% if default_information is defined and default_information.originate is defined %} +{% if default_information is vyos_defined %} default-information originate {% endif %} -{% if default_metric is defined and default_metric is not none %} +{% if default_metric is vyos_defined %} default-metric {{ default_metric }} {% endif %} -{% if passive_interface is defined and passive_interface is not none %} +{% if passive_interface is vyos_defined %} {% for interface in passive_interface %} passive-interface {{ interface }} {% endfor %} {% endif %} -{% if network is defined and network is not none %} +{% if network is vyos_defined %} {% for prefix in network %} network {{ prefix }} {% endfor %} {% endif %} -{% if interface is defined and interface is not none %} +{% if interface is vyos_defined %} {% for ifname in interface %} network {{ ifname }} {% endfor %} {% endif %} -{% if route is defined and route is not none %} +{% if route is vyos_defined %} {% for prefix in route %} route {{ prefix }} {% endfor %} {% endif %} {# timers have default values #} timers basic {{ timers['update'] }} {{ timers.timeout }} {{ timers.garbage_collection }} -{% if redistribute is defined and redistribute is not none %} +{% if redistribute is vyos_defined %} {% for protocol, protocol_config in redistribute.items() %} -{% if protocol == 'ospfv3' %} +{% if protocol is vyos_defined('ospfv3') %} {% set protocol = 'ospf6' %} {% endif %} - redistribute {{ protocol }} {{ 'metric ' + protocol_config.metric if protocol_config.metric is defined }} {{ 'route-map ' + protocol_config.route_map if protocol_config.route_map is defined }} + redistribute {{ protocol }} {{ 'metric ' ~ protocol_config.metric if protocol_config.metric is vyos_defined }} {{ 'route-map ' ~ protocol_config.route_map if protocol_config.route_map is vyos_defined }} {% endfor %} {% endif %} diff --git a/data/templates/frr/ripd.frr.tmpl b/data/templates/frr/ripd.frr.tmpl index c44bb6d27..2dbb93052 100644 --- a/data/templates/frr/ripd.frr.tmpl +++ b/data/templates/frr/ripd.frr.tmpl @@ -1,11 +1,11 @@ {# RIP key-chain definition #} -{% if interface is defined and interface is not none %} +{% if interface is vyos_defined %} {% for iface, iface_config in interface.items() %} -{% if iface_config.authentication is defined and iface_config.authentication.md5 is defined and iface_config.authentication.md5 is not none %} +{% if iface_config.authentication.md5 is vyos_defined %} key chain {{ iface }}-rip {% for key_id, key_options in iface_config.authentication.md5.items() %} key {{ key_id }} -{% if key_options.password is defined and key_options.password is not none %} +{% if key_options.password is vyos_defined %} key-string {{ key_options.password }} {% endif %} exit @@ -16,20 +16,20 @@ exit {% endif %} ! {# Interface specific configuration #} -{% if interface is defined and interface is not none %} +{% if interface is vyos_defined %} {% for iface, iface_config in interface.items() %} interface {{ iface }} -{% if iface_config.authentication is defined and iface_config.authentication.plaintext_password is defined and iface_config.authentication.plaintext_password is not none %} +{% if iface_config.authentication.plaintext_password is vyos_defined %} ip rip authentication mode text ip rip authentication string {{ iface_config.authentication.plaintext_password }} -{% elif iface_config.authentication is defined and iface_config.authentication.md5 is defined and iface_config.authentication.md5 is not none %} +{% elif iface_config.authentication.md5 is vyos_defined %} ip rip authentication key-chain {{ iface }}-rip ip rip authentication mode md5 {% endif %} -{% if iface_config.split_horizon is defined and iface_config.split_horizon.disable is defined %} +{% if iface_config.split_horizon.disable is vyos_defined %} no ip rip split-horizon {% endif %} -{% if iface_config.split_horizon is defined and iface_config.split_horizon.poison_reverse is defined %} +{% if iface_config.split_horizon.poison_reverse is vyos_defined %} ip rip split-horizon poisoned-reverse {% endif %} exit @@ -38,63 +38,55 @@ exit {% endif %} ! router rip -{% if default_distance is defined and default_distance is not none %} +{% if default_distance is vyos_defined %} distance {{ default_distance }} {% endif %} -{% if network_distance is defined and network_distance is not none %} +{% if network_distance is vyos_defined %} {% for network, network_config in network_distance.items() %} -{% if network_config.distance is defined and network_config.distance is not none %} +{% if network_config.distance is vyos_defined %} distance {{ network_config.distance }} {{ network }} {% endif %} {% endfor %} {% endif %} -{% if neighbor is defined and neighbor is not none %} +{% if neighbor is vyos_defined %} {% for address in neighbor %} neighbor {{ address }} {% endfor %} {% endif %} -{% if distribute_list is defined and distribute_list is not none %} -{% if distribute_list.access_list is defined and distribute_list.access_list is not none %} -{% if distribute_list.access_list.in is defined and distribute_list.access_list.in is not none %} +{% if distribute_list is vyos_defined %} +{% if distribute_list.access_list.in is vyos_defined %} distribute-list {{ distribute_list.access_list.in }} in -{% endif %} -{% if distribute_list.access_list.out is defined and distribute_list.access_list.out is not none %} +{% endif %} +{% if distribute_list.access_list.out is vyos_defined %} distribute-list {{ distribute_list.access_list.out }} out -{% endif %} {% endif %} -{% if distribute_list.interface is defined and distribute_list.interface is not none %} +{% if distribute_list.interface is vyos_defined %} {% for interface, interface_config in distribute_list.interface.items() %} -{% if interface_config.access_list is defined and interface_config.access_list is not none %} -{% if interface_config.access_list.in is defined and interface_config.access_list.in is not none %} +{% if interface_config.access_list.in is vyos_defined %} distribute-list {{ interface_config.access_list.in }} in {{ interface }} -{% endif %} -{% if interface_config.access_list.out is defined and interface_config.access_list.out is not none %} +{% endif %} +{% if interface_config.access_list.out is vyos_defined %} distribute-list {{ interface_config.access_list.out }} out {{ interface }} -{% endif %} {% endif %} -{% if interface_config.prefix_list is defined and interface_config.prefix_list is not none %} -{% if interface_config.prefix_list.in is defined and interface_config.prefix_list.in is not none %} +{% if interface_config.prefix_list.in is vyos_defined %} distribute-list prefix {{ interface_config.prefix_list.in }} in {{ interface }} -{% endif %} -{% if interface_config.prefix_list.out is defined and interface_config.prefix_list.out is not none %} +{% endif %} +{% if interface_config.prefix_list.out is vyos_defined %} distribute-list prefix {{ interface_config.prefix_list.out }} out {{ interface }} -{% endif %} {% endif %} {% endfor %} {% endif %} -{% if distribute_list.prefix_list is defined and distribute_list.prefix_list is not none %} -{% if distribute_list.prefix_list.in is defined and distribute_list.prefix_list.in is not none %} +{% if distribute_list.prefix_list.in is vyos_defined %} distribute-list prefix {{ distribute_list.prefix_list.in }} in -{% endif %} -{% if distribute_list.prefix_list.out is defined and distribute_list.prefix_list.out is not none %} +{% endif %} +{% if distribute_list.prefix_list.out is vyos_defined %} distribute-list prefix {{ distribute_list.prefix_list.out }} out -{% endif %} {% endif %} {% endif %} {% include 'frr/rip_ripng.frr.j2' %} exit ! -{% if route_map is defined and route_map is not none %} +{% if route_map is vyos_defined %} ip protocol rip route-map {{ route_map }} {% endif %} ! diff --git a/data/templates/frr/ripngd.frr.tmpl b/data/templates/frr/ripngd.frr.tmpl index ca7b9b5fb..06c61dd48 100644 --- a/data/templates/frr/ripngd.frr.tmpl +++ b/data/templates/frr/ripngd.frr.tmpl @@ -1,11 +1,11 @@ {# Interface specific configuration #} -{% if interface is defined and interface is not none %} +{% if interface is vyos_defined %} {% for iface, iface_config in interface.items() %} interface {{ iface }} -{% if iface_config.split_horizon is defined and iface_config.split_horizon.disable is defined %} +{% if iface_config.split_horizon.disable is vyos_defined %} no ipv6 rip split-horizon {% endif %} -{% if iface_config.split_horizon is defined and iface_config.split_horizon.poison_reverse is defined %} +{% if iface_config.split_horizon.poison_reverse is vyos_defined %} ipv6 rip split-horizon poisoned-reverse {% endif %} exit @@ -13,53 +13,45 @@ exit {% endif %} ! router ripng -{% if aggregate_address is defined and aggregate_address is not none %} +{% if aggregate_address is vyos_defined %} {% for prefix in aggregate_address %} aggregate-address {{ prefix }} {% endfor %} {% endif %} -{% if distribute_list is defined and distribute_list is not none %} -{% if distribute_list.access_list is defined and distribute_list.access_list is not none %} -{% if distribute_list.access_list.in is defined and distribute_list.access_list.in is not none %} +{% if distribute_list is vyos_defined %} +{% if distribute_list.access_list.in is vyos_defined %} ipv6 distribute-list {{ distribute_list.access_list.in }} in -{% endif %} -{% if distribute_list.access_list.out is defined and distribute_list.access_list.out is not none %} +{% endif %} +{% if distribute_list.access_list.out is vyos_defined %} ipv6 distribute-list {{ distribute_list.access_list.out }} out -{% endif %} {% endif %} -{% if distribute_list.interface is defined and distribute_list.interface is not none %} +{% if distribute_list.interface is vyos_defined %} {% for interface, interface_config in distribute_list.interface.items() %} -{% if interface_config.access_list is defined and interface_config.access_list is not none %} -{% if interface_config.access_list.in is defined and interface_config.access_list.in is not none %} +{% if interface_config.access_list.in is vyos_defined %} ipv6 distribute-list {{ interface_config.access_list.in }} in {{ interface }} -{% endif %} -{% if interface_config.access_list.out is defined and interface_config.access_list.out is not none %} +{% endif %} +{% if interface_config.access_list.out is vyos_defined %} ipv6 distribute-list {{ interface_config.access_list.out }} out {{ interface }} -{% endif %} {% endif %} -{% if interface_config.prefix_list is defined and interface_config.prefix_list is not none %} -{% if interface_config.prefix_list.in is defined and interface_config.prefix_list.in is not none %} +{% if interface_config.prefix_list.in is vyos_defined %} ipv6 distribute-list prefix {{ interface_config.prefix_list.in }} in {{ interface }} -{% endif %} -{% if interface_config.prefix_list.out is defined and interface_config.prefix_list.out is not none %} +{% endif %} +{% if interface_config.prefix_list.out is vyos_defined %} ipv6 distribute-list prefix {{ interface_config.prefix_list.out }} out {{ interface }} -{% endif %} {% endif %} {% endfor %} {% endif %} -{% if distribute_list.prefix_list is defined and distribute_list.prefix_list is not none %} -{% if distribute_list.prefix_list.in is defined and distribute_list.prefix_list.in is not none %} +{% if distribute_list.prefix_list.in is vyos_defined %} ipv6 distribute-list prefix {{ distribute_list.prefix_list.in }} in -{% endif %} -{% if distribute_list.prefix_list.out is defined and distribute_list.prefix_list.out is not none %} +{% endif %} +{% if distribute_list.prefix_list.out is vyos_defined %} ipv6 distribute-list prefix {{ distribute_list.prefix_list.out }} out -{% endif %} {% endif %} {% endif %} {% include 'frr/rip_ripng.frr.j2' %} exit ! -{% if route_map is defined and route_map is not none %} +{% if route_map is vyos_defined %} ipv6 protocol ripng route-map {{ route_map }} {% endif %} ! diff --git a/data/templates/frr/rpki.frr.tmpl b/data/templates/frr/rpki.frr.tmpl index 7f9823f6b..3f4fd3236 100644 --- a/data/templates/frr/rpki.frr.tmpl +++ b/data/templates/frr/rpki.frr.tmpl @@ -1,17 +1,17 @@ ! {# as FRR does not support deleting the entire rpki section we leave it in place even when it's empty #} rpki -{% if cache is defined and cache is not none %} +{% if cache is vyos_defined %} {% for peer, peer_config in cache.items() %} {# port is mandatory and preference uses a default value #} -{% if peer_config.ssh is defined and peer_config.ssh.username is defined and peer_config.ssh.username is not none %} +{% if peer_config.ssh.username is vyos_defined %} rpki cache {{ peer | replace('_', '-') }} {{ peer_config.port }} {{ peer_config.ssh.username }} {{ peer_config.ssh.private_key_file }} {{ peer_config.ssh.public_key_file }} {{ peer_config.ssh.known_hosts_file }} preference {{ peer_config.preference }} {% else %} rpki cache {{ peer | replace('_', '-') }} {{ peer_config.port }} preference {{ peer_config.preference }} {% endif %} {% endfor %} {% endif %} -{% if polling_period is defined and polling_period is not none %} +{% if polling_period is vyos_defined %} rpki polling_period {{ polling_period }} {% endif %} exit diff --git a/data/templates/frr/static_routes_macro.j2 b/data/templates/frr/static_routes_macro.j2 index 8359357b7..0b242a868 100644 --- a/data/templates/frr/static_routes_macro.j2 +++ b/data/templates/frr/static_routes_macro.j2 @@ -1,24 +1,24 @@ {% macro static_routes(ip_ipv6, prefix, prefix_config, table=None) %} -{% if prefix_config.blackhole is defined %} -{{ ip_ipv6 }} route {{ prefix }} blackhole {{ prefix_config.blackhole.distance if prefix_config.blackhole.distance is defined }} {{ 'tag ' + prefix_config.blackhole.tag if prefix_config.blackhole.tag is defined }} {{ 'table ' + table if table is defined and table is not none }} +{% if prefix_config.blackhole is vyos_defined %} +{{ ip_ipv6 }} route {{ prefix }} blackhole {{ prefix_config.blackhole.distance if prefix_config.blackhole.distance is vyos_defined }} {{ 'tag ' ~ prefix_config.blackhole.tag if prefix_config.blackhole.tag is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined and table is not none }} {% endif %} -{% if prefix_config.reject is defined %} -{{ ip_ipv6 }} route {{ prefix }} reject {{ prefix_config.reject.distance if prefix_config.reject.distance is defined }} {{ 'tag ' + prefix_config.reject.tag if prefix_config.reject.tag is defined }} {{ 'table ' + table if table is defined and table is not none }} +{% if prefix_config.reject is vyos_defined %} +{{ ip_ipv6 }} route {{ prefix }} reject {{ prefix_config.reject.distance if prefix_config.reject.distance is vyos_defined }} {{ 'tag ' ~ prefix_config.reject.tag if prefix_config.reject.tag is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined }} {% endif %} -{% if prefix_config.dhcp_interface is defined and prefix_config.dhcp_interface is not none %} +{% if prefix_config.dhcp_interface is vyos_defined %} {% set next_hop = prefix_config.dhcp_interface | get_dhcp_router %} -{% if next_hop is defined and next_hop is not none %} -{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ prefix_config.dhcp_interface }} {{ 'table ' + table if table is defined and table is not none }} +{% if next_hop is vyos_defined %} +{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ prefix_config.dhcp_interface }} {{ 'table ' ~ table if table is vyos_defined }} {% endif %} {% endif %} -{% if prefix_config.interface is defined and prefix_config.interface is not none %} +{% if prefix_config.interface is vyos_defined %} {% for interface, interface_config in prefix_config.interface.items() if interface_config.disable is not defined %} -{{ ip_ipv6 }} route {{ prefix }} {{ interface }} {{ interface_config.distance if interface_config.distance is defined }} {{ 'nexthop-vrf ' + interface_config.vrf if interface_config.vrf is defined }} {{ 'table ' + table if table is defined and table is not none }} +{{ ip_ipv6 }} route {{ prefix }} {{ interface }} {{ interface_config.distance if interface_config.distance is vyos_defined }} {{ 'nexthop-vrf ' ~ interface_config.vrf if interface_config.vrf is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined }} {% endfor %} {% endif %} -{% if prefix_config.next_hop is defined and prefix_config.next_hop is not none %} +{% if prefix_config.next_hop is vyos_defined and prefix_config.next_hop is not none %} {% for next_hop, next_hop_config in prefix_config.next_hop.items() if next_hop_config.disable is not defined %} -{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ next_hop_config.interface if next_hop_config.interface is defined }} {{ next_hop_config.distance if next_hop_config.distance is defined }} {{ 'nexthop-vrf ' + next_hop_config.vrf if next_hop_config.vrf is defined }} {{ 'table ' + table if table is defined and table is not none }} +{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ next_hop_config.interface if next_hop_config.interface is vyos_defined }} {{ next_hop_config.distance if next_hop_config.distance is vyos_defined }} {{ 'nexthop-vrf ' ~ next_hop_config.vrf if next_hop_config.vrf is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined}} {% endfor %} {% endif %} {% endmacro %} diff --git a/data/templates/frr/staticd.frr.tmpl b/data/templates/frr/staticd.frr.tmpl index 5d833228a..c7138b12b 100644 --- a/data/templates/frr/staticd.frr.tmpl +++ b/data/templates/frr/staticd.frr.tmpl @@ -2,7 +2,7 @@ ! {% set ip_prefix = 'ip' %} {% set ipv6_prefix = 'ipv6' %} -{% if vrf is defined and vrf is not none %} +{% if vrf is vyos_defined %} {# We need to add an additional whitespace in front of the prefix #} {# when VRFs are in use, thus we use a variable for prefix handling #} {% set ip_prefix = ' ip' %} @@ -10,40 +10,40 @@ vrf {{ vrf }} {% endif %} {# IPv4 routing #} -{% if route is defined and route is not none %} +{% if route is vyos_defined %} {% for prefix, prefix_config in route.items() %} {{ static_routes(ip_prefix, prefix, prefix_config) }} {%- endfor -%} {% endif %} {# IPv4 default routes from DHCP interfaces #} -{% if dhcp is defined and dhcp is not none %} +{% if dhcp is vyos_defined %} {% for interface, interface_config in dhcp.items() %} {% set next_hop = interface | get_dhcp_router %} -{% if next_hop is defined and next_hop is not none %} +{% if next_hop is vyos_defined %} {{ ip_prefix }} route 0.0.0.0/0 {{ next_hop }} {{ interface }} tag 210 {{ interface_config.distance }} {% endif %} {% endfor %} {% endif %} {# IPv6 routing #} -{% if route6 is defined and route6 is not none %} +{% if route6 is vyos_defined %} {% for prefix, prefix_config in route6.items() %} {{ static_routes(ipv6_prefix, prefix, prefix_config) }} {%- endfor -%} {% endif %} -{% if vrf is defined and vrf is not none %} +{% if vrf is vyos_defined %} exit-vrf {% endif %} ! {# Policy route tables #} -{% if table is defined and table is not none %} +{% if table is vyos_defined %} {% for table_id, table_config in table.items() %} -{% if table_config.route is defined and table_config.route is not none %} +{% if table_config.route is vyos_defined %} {% for prefix, prefix_config in table_config.route.items() %} {{ static_routes('ip', prefix, prefix_config, table_id) }} {%- endfor -%} {% endif %} ! -{% if table_config.route6 is defined and table_config.route6 is not none %} +{% if table_config.route6 is vyos_defined %} {% for prefix, prefix_config in table_config.route6.items() %} {{ static_routes('ipv6', prefix, prefix_config, table_id) }} {%- endfor -%} @@ -52,7 +52,7 @@ vrf {{ vrf }} {% endfor %} {% endif %} ! -{% if route_map is defined and route_map is not none %} +{% if route_map is vyos_defined %} ip protocol static route-map {{ route_map }} ! {% endif %} diff --git a/data/templates/frr/vrf-vni.frr.tmpl b/data/templates/frr/vrf-vni.frr.tmpl index 299c9719e..916b5d05d 100644 --- a/data/templates/frr/vrf-vni.frr.tmpl +++ b/data/templates/frr/vrf-vni.frr.tmpl @@ -1,7 +1,7 @@ -{% if name is defined and name is not none %} +{% if name is vyos_defined %} {% for vrf, vrf_config in name.items() %} vrf {{ vrf }} -{% if vrf_config.vni is defined and vrf_config.vni is not none %} +{% if vrf_config.vni is vyos_defined %} vni {{ vrf_config.vni }} {% endif %} exit-vrf diff --git a/data/templates/frr/vrf.route-map.frr.tmpl b/data/templates/frr/vrf.route-map.frr.tmpl index cb0e07616..5e0c56a7b 100644 --- a/data/templates/frr/vrf.route-map.frr.tmpl +++ b/data/templates/frr/vrf.route-map.frr.tmpl @@ -1,10 +1,10 @@ ! -{% if vrf is defined and vrf is not none and route_map is defined and route_map is not none %} +{% if vrf is vyos_defined and route_map is vyos_defined %} vrf {{ vrf }} ip protocol {{ protocol }} route-map {{ route_map }} exit-vrf ! -{% elif route_map is defined and route_map is not none %} +{% elif route_map is vyos_defined %} ip protocol {{ protocol }} route-map {{ route_map }} {% endif %} ! diff --git a/data/templates/https/nginx.default.tmpl b/data/templates/https/nginx.default.tmpl index e8511bd62..a51505270 100644 --- a/data/templates/https/nginx.default.tmpl +++ b/data/templates/https/nginx.default.tmpl @@ -53,19 +53,6 @@ server { } error_page 497 =301 https://$host:{{ server.port }}$request_uri; - error_page 501 502 503 =200 @50*_json; - -{% if api_set %} - location @50*_json { - default_type application/json; - return 200 '{"error": "service https api unavailable at this proxy address: set service https api-restrict virtual-host"}'; - } -{% else %} - location @50*_json { - default_type application/json; - return 200 '{"error": "Start service in configuration mode: set service https api"}'; - } -{% endif %} } diff --git a/debian/vyos-1x.install b/debian/vyos-1x.install index 63dff43a5..493c896eb 100644 --- a/debian/vyos-1x.install +++ b/debian/vyos-1x.install @@ -1,4 +1,3 @@ -etc/cron.d etc/cron.hourly etc/dhcp etc/ipsec.d diff --git a/interface-definitions/dhcp-server.xml.in b/interface-definitions/dhcp-server.xml.in index 312dcd2a0..4ea2d471d 100644 --- a/interface-definitions/dhcp-server.xml.in +++ b/interface-definitions/dhcp-server.xml.in @@ -142,6 +142,11 @@ boot file is to be loaded</help> </properties> </leafNode> + <leafNode name="bootfile-size"> + <properties> + <help>Bootstrap file size in 512 byte blocks</help> + </properties> + </leafNode> <leafNode name="client-prefix-length"> <properties> <help>Specifies the clients subnet mask as per RFC 950. If unset, subnet declaration is used.</help> diff --git a/interface-definitions/dns-forwarding.xml.in b/interface-definitions/dns-forwarding.xml.in index a2e809da8..08501a4b5 100644 --- a/interface-definitions/dns-forwarding.xml.in +++ b/interface-definitions/dns-forwarding.xml.in @@ -598,6 +598,19 @@ </properties> <defaultValue>3600</defaultValue> </leafNode> + <leafNode name="timeout"> + <properties> + <help>Number of milliseconds to wait for a remote authoritative server to respond</help> + <valueHelp> + <format>u32:10-60000</format> + <description>Network timeout in milliseconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 10-60000"/> + </constraint> + </properties> + <defaultValue>1500</defaultValue> + </leafNode> #include <include/name-server-ipv4-ipv6.xml.i> <leafNode name="source-address"> <properties> diff --git a/interface-definitions/include/accel-ppp/client-ip-pool-subnet-single.xml.i b/interface-definitions/include/accel-ppp/client-ip-pool-subnet-single.xml.i new file mode 100644 index 000000000..e5918b765 --- /dev/null +++ b/interface-definitions/include/accel-ppp/client-ip-pool-subnet-single.xml.i @@ -0,0 +1,15 @@ +<!-- include start from accel-ppp/client-ip-pool-subnet-single.xml.i --> +<leafNode name="subnet"> + <properties> + <help>Client IP subnet (CIDR notation)</help> + <valueHelp> + <format>ipv4net</format> + <description>IPv4 address and prefix length</description> + </valueHelp> + <constraint> + <validator name="ipv4-prefix"/> + </constraint> + <constraintErrorMessage>Not a valid CIDR formatted prefix</constraintErrorMessage> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/firewall/common-rule.xml.i b/interface-definitions/include/firewall/common-rule.xml.i index 353804990..cd80b7e28 100644 --- a/interface-definitions/include/firewall/common-rule.xml.i +++ b/interface-definitions/include/firewall/common-rule.xml.i @@ -66,11 +66,11 @@ <properties> <help>Maximum average matching rate</help> <valueHelp> - <format>u32:0-4294967295</format> - <description>Maximum average matching rate</description> + <format>txt</format> + <description>integer/unit (Example: 5/minute)</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-4294967295"/> + <regex>^\d+/(second|minute|hour|day)$</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/interface/traffic-policy.xml.i b/interface-definitions/include/interface/traffic-policy.xml.i deleted file mode 100644 index cd60b62a5..000000000 --- a/interface-definitions/include/interface/traffic-policy.xml.i +++ /dev/null @@ -1,43 +0,0 @@ -<!-- include start from interface/traffic-policy.xml.i --> -<node name="traffic-policy"> - <properties> - <help>Traffic-policy for interface</help> - </properties> - <children> - <leafNode name="in"> - <properties> - <help>Ingress traffic policy for interface</help> - <completionHelp> - <path>traffic-policy drop-tail</path> - <path>traffic-policy fair-queue</path> - <path>traffic-policy fq-codel</path> - <path>traffic-policy limiter</path> - <path>traffic-policy network-emulator</path> - <path>traffic-policy priority-queue</path> - <path>traffic-policy random-detect</path> - <path>traffic-policy rate-control</path> - <path>traffic-policy round-robin</path> - <path>traffic-policy shaper</path> - <path>traffic-policy shaper-hfsc</path> - </completionHelp> - <valueHelp> - <format>txt</format> - <description>Policy name</description> - </valueHelp> - </properties> - </leafNode> - <leafNode name="out"> - <properties> - <help>Egress traffic policy for interface</help> - <completionHelp> - <path>traffic-policy</path> - </completionHelp> - <valueHelp> - <format>txt</format> - <description>Policy name</description> - </valueHelp> - </properties> - </leafNode> - </children> -</node> -<!-- include end -->
\ No newline at end of file diff --git a/interface-definitions/include/interface/vif-s.xml.i b/interface-definitions/include/interface/vif-s.xml.i index 59a47b5ff..3b305618e 100644 --- a/interface-definitions/include/interface/vif-s.xml.i +++ b/interface-definitions/include/interface/vif-s.xml.i @@ -44,6 +44,7 @@ #include <include/interface/ipv4-options.xml.i> #include <include/interface/ipv6-options.xml.i> #include <include/interface/mac.xml.i> + #include <include/interface/mirror.xml.i> #include <include/interface/mtu-68-16000.xml.i> <tagNode name="vif-c"> <properties> @@ -63,16 +64,15 @@ #include <include/interface/ipv4-options.xml.i> #include <include/interface/ipv6-options.xml.i> #include <include/interface/mac.xml.i> + #include <include/interface/mirror.xml.i> #include <include/interface/mtu-68-16000.xml.i> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> #include <include/interface/interface-firewall-vif-c.xml.i> #include <include/interface/interface-policy-vif-c.xml.i> </children> </tagNode> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/include/interface/vif.xml.i b/interface-definitions/include/interface/vif.xml.i index 8a1475711..4e7f9b3c2 100644 --- a/interface-definitions/include/interface/vif.xml.i +++ b/interface-definitions/include/interface/vif.xml.i @@ -49,9 +49,9 @@ #include <include/interface/ipv4-options.xml.i> #include <include/interface/ipv6-options.xml.i> #include <include/interface/mac.xml.i> + #include <include/interface/mirror.xml.i> #include <include/interface/mtu-68-16000.xml.i> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/include/isis/high-low-label-value.xml.i b/interface-definitions/include/isis/high-low-label-value.xml.i new file mode 100644 index 000000000..adc28417d --- /dev/null +++ b/interface-definitions/include/isis/high-low-label-value.xml.i @@ -0,0 +1,26 @@ +<!-- include start from isis/high-low-label-value.xml.i --> +<leafNode name="low-label-value"> + <properties> + <help>MPLS label lower bound</help> + <valueHelp> + <format>u32:16-1048575</format> + <description>Label value</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 16-1048575"/> + </constraint> + </properties> +</leafNode> +<leafNode name="high-label-value"> + <properties> + <help>MPLS label upper bound</help> + <valueHelp> + <format>u32:16-1048575</format> + <description>Label value</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 16-1048575"/> + </constraint> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/isis/password.xml.i b/interface-definitions/include/isis/password.xml.i new file mode 100644 index 000000000..27c3b0fa0 --- /dev/null +++ b/interface-definitions/include/isis/password.xml.i @@ -0,0 +1,20 @@ +<!-- include start from isis/password.xml.i --> +<leafNode name="plaintext-password"> + <properties> + <help>Plain-text authentication type</help> + <valueHelp> + <format>txt</format> + <description>Circuit password</description> + </valueHelp> + </properties> +</leafNode> +<leafNode name="md5"> + <properties> + <help>MD5 authentication type</help> + <valueHelp> + <format>txt</format> + <description>Level-wide password</description> + </valueHelp> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/isis/protocol-common-config.xml.i b/interface-definitions/include/isis/protocol-common-config.xml.i index 8ffa14a19..75a0355d4 100644 --- a/interface-definitions/include/isis/protocol-common-config.xml.i +++ b/interface-definitions/include/isis/protocol-common-config.xml.i @@ -4,24 +4,7 @@ <help>Configure the authentication password for an area</help> </properties> <children> - <leafNode name="plaintext-password"> - <properties> - <help>Plain-text authentication type</help> - <valueHelp> - <format>txt</format> - <description>Level-wide password</description> - </valueHelp> - </properties> - </leafNode> - <leafNode name="md5"> - <properties> - <help>MD5 authentication type</help> - <valueHelp> - <format>txt</format> - <description>Level-wide password</description> - </valueHelp> - </properties> - </leafNode> + #include <include/isis/password.xml.i> </children> </node> <node name="default-information"> @@ -59,24 +42,7 @@ <help>Set the authentication password for a routing domain</help> </properties> <children> - <leafNode name="plaintext-password"> - <properties> - <help>Plain-text authentication type</help> - <valueHelp> - <format>txt</format> - <description>Level-wide password</description> - </valueHelp> - </properties> - </leafNode> - <leafNode name="md5"> - <properties> - <help>MD5 authentication type</help> - <valueHelp> - <format>txt</format> - <description>Level-wide password</description> - </valueHelp> - </properties> - </leafNode> + #include <include/isis/password.xml.i> </children> </node> <leafNode name="dynamic-hostname"> @@ -104,7 +70,7 @@ <description>Act as an area router</description> </valueHelp> <constraint> - <regex>^(level-1|level-1-2|level-2)$</regex> + <regex>(level-1|level-1-2|level-2)</regex> </constraint> </properties> </leafNode> @@ -182,7 +148,7 @@ <description>Use new style of TLVs to carry wider metric</description> </valueHelp> <constraint> - <regex>^(narrow|transition|wide)$</regex> + <regex>(narrow|transition|wide)</regex> </constraint> </properties> </leafNode> @@ -275,68 +241,20 @@ </leafNode> <node name="global-block"> <properties> - <help>Global block label range</help> + <help>Segment Routing Global Block label range</help> </properties> <children> - <leafNode name="low-label-value"> - <properties> - <help>The lower bound of the global block</help> - <valueHelp> - <format>u32:16-1048575</format> - <description>MPLS label value</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 16-1048575"/> - </constraint> - </properties> - </leafNode> - <leafNode name="high-label-value"> - <properties> - <help>The upper bound of the global block</help> - <valueHelp> - <format>u32:16-1048575</format> - <description>MPLS label value</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 16-1048575"/> - </constraint> - </properties> - </leafNode> + #include <include/isis/high-low-label-value.xml.i> </children> </node> -<!-- <node name="local-block"> <properties> - <help>Local Block label range</help> + <help>Segment Routing Local Block label range</help> </properties> <children> - <leafNode name="low-label-value"> - <properties> - <help>The lower bound of the local block</help> - <valueHelp> - <format>u32:16-1048575</format> - <description>MPLS label value</description> - </valueHelp> - <constraint> - <validator name="numeric" argument=" range 16-1048575"/> - </constraint> - </properties> - </leafNode> - <leafNode name="high-label-value"> - <properties> - <help>The upper bound of the local block</help> - <valueHelp> - <format>u32:16-1048575</format> - <description>MPLS label value</description> - </valueHelp> - <constraint> - <validator name="numeric" argument=" range 16-1048575"/> - </constraint> - </properties> - </leafNode> + #include <include/isis/high-low-label-value.xml.i> </children> </node> ---> <leafNode name="maximum-label-depth"> <properties> <help>Maximum MPLS labels allowed for this router</help> @@ -668,7 +586,7 @@ <description>Level-2 only adjacencies are formed</description> </valueHelp> <constraint> - <regex>^(level-1|level-1-2|level-2-only)$</regex> + <regex>(level-1|level-1-2|level-2-only)</regex> </constraint> </properties> </leafNode> @@ -722,15 +640,7 @@ <help>Configure the authentication password for a circuit</help> </properties> <children> - <leafNode name="plaintext-password"> - <properties> - <help>Plain-text authentication type</help> - <valueHelp> - <format>txt</format> - <description>Circuit password</description> - </valueHelp> - </properties> - </leafNode> + #include <include/isis/password.xml.i> </children> </node> <leafNode name="priority"> diff --git a/interface-definitions/include/version/system-version.xml.i b/interface-definitions/include/version/system-version.xml.i index fb4629bf1..19591256d 100644 --- a/interface-definitions/include/version/system-version.xml.i +++ b/interface-definitions/include/version/system-version.xml.i @@ -1,3 +1,3 @@ <!-- include start from include/version/system-version.xml.i --> -<syntaxVersion component='system' version='22'></syntaxVersion> +<syntaxVersion component='system' version='23'></syntaxVersion> <!-- include end --> diff --git a/interface-definitions/interfaces-bonding.xml.in b/interface-definitions/interfaces-bonding.xml.in index 20ece5137..5ae67a672 100644 --- a/interface-definitions/interfaces-bonding.xml.in +++ b/interface-definitions/interfaces-bonding.xml.in @@ -208,7 +208,6 @@ </properties> </leafNode> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vif-s.xml.i> #include <include/interface/vif.xml.i> #include <include/interface/xdp.xml.i> diff --git a/interface-definitions/interfaces-bridge.xml.in b/interface-definitions/interfaces-bridge.xml.in index 6957067cd..be4c92583 100644 --- a/interface-definitions/interfaces-bridge.xml.in +++ b/interface-definitions/interfaces-bridge.xml.in @@ -211,7 +211,6 @@ </properties> </leafNode> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vif.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-dummy.xml.in b/interface-definitions/interfaces-dummy.xml.in index 109ed1b50..7f9ae90e5 100644 --- a/interface-definitions/interfaces-dummy.xml.in +++ b/interface-definitions/interfaces-dummy.xml.in @@ -29,9 +29,9 @@ #include <include/interface/source-validation.xml.i> </children> </node> + #include <include/interface/mirror.xml.i> #include <include/interface/netns.xml.i> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-ethernet.xml.in b/interface-definitions/interfaces-ethernet.xml.in index 7d28912c0..7fa07e9ec 100644 --- a/interface-definitions/interfaces-ethernet.xml.in +++ b/interface-definitions/interfaces-ethernet.xml.in @@ -197,7 +197,6 @@ </children> </node> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vif-s.xml.i> #include <include/interface/vif.xml.i> #include <include/interface/vrf.xml.i> diff --git a/interface-definitions/interfaces-geneve.xml.in b/interface-definitions/interfaces-geneve.xml.in index aa5809e60..fa5a78be5 100644 --- a/interface-definitions/interfaces-geneve.xml.in +++ b/interface-definitions/interfaces-geneve.xml.in @@ -50,8 +50,8 @@ </node> </children> </node> + #include <include/interface/mirror.xml.i> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/tunnel-remote.xml.i> #include <include/vni.xml.i> </children> diff --git a/interface-definitions/interfaces-input.xml.in b/interface-definitions/interfaces-input.xml.in index f2eb01c58..2164bfa4e 100644 --- a/interface-definitions/interfaces-input.xml.in +++ b/interface-definitions/interfaces-input.xml.in @@ -22,7 +22,6 @@ #include <include/interface/interface-firewall.xml.i> #include <include/interface/interface-policy.xml.i> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/interfaces-l2tpv3.xml.in b/interface-definitions/interfaces-l2tpv3.xml.in index 680170b0f..1f23a89a5 100644 --- a/interface-definitions/interfaces-l2tpv3.xml.in +++ b/interface-definitions/interfaces-l2tpv3.xml.in @@ -58,6 +58,7 @@ #include <include/interface/ipv4-options.xml.i> #include <include/interface/ipv6-options.xml.i> #include <include/source-address-ipv4-ipv6.xml.i> + #include <include/interface/mirror.xml.i> #include <include/interface/mtu-68-16000.xml.i> <leafNode name="mtu"> <defaultValue>1488</defaultValue> @@ -124,7 +125,6 @@ </constraint> </properties> </leafNode> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-loopback.xml.in b/interface-definitions/interfaces-loopback.xml.in index ffffc0220..7ac0545c6 100644 --- a/interface-definitions/interfaces-loopback.xml.in +++ b/interface-definitions/interfaces-loopback.xml.in @@ -26,8 +26,8 @@ #include <include/interface/source-validation.xml.i> </children> </node> + #include <include/interface/mirror.xml.i> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in index 311e95c2f..cb3c489aa 100644 --- a/interface-definitions/interfaces-macsec.xml.in +++ b/interface-definitions/interfaces-macsec.xml.in @@ -23,6 +23,7 @@ #include <include/interface/ipv6-options.xml.i> #include <include/interface/interface-firewall.xml.i> #include <include/interface/interface-policy.xml.i> + #include <include/interface/mirror.xml.i> <node name="security"> <properties> <help>Security/Encryption Settings</help> @@ -123,7 +124,6 @@ </leafNode> #include <include/source-interface-ethernet.xml.i> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-openvpn.xml.in b/interface-definitions/interfaces-openvpn.xml.in index 73e30e590..c917b9312 100644 --- a/interface-definitions/interfaces-openvpn.xml.in +++ b/interface-definitions/interfaces-openvpn.xml.in @@ -168,6 +168,7 @@ </children> </node> #include <include/interface/ipv6-options.xml.i> + #include <include/interface/mirror.xml.i> <leafNode name="hash"> <properties> <help>Hashing Algorithm</help> @@ -817,7 +818,6 @@ </properties> </leafNode> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-pppoe.xml.in b/interface-definitions/interfaces-pppoe.xml.in index 1d888236e..3a0b7a40c 100644 --- a/interface-definitions/interfaces-pppoe.xml.in +++ b/interface-definitions/interfaces-pppoe.xml.in @@ -102,6 +102,7 @@ </constraint> </properties> </leafNode> + #include <include/interface/mirror.xml.i> #include <include/interface/mtu-68-1500.xml.i> <leafNode name="mtu"> <defaultValue>1492</defaultValue> @@ -134,7 +135,6 @@ </properties> </leafNode> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-pseudo-ethernet.xml.in b/interface-definitions/interfaces-pseudo-ethernet.xml.in index 7baeac537..5f5e9fdef 100644 --- a/interface-definitions/interfaces-pseudo-ethernet.xml.in +++ b/interface-definitions/interfaces-pseudo-ethernet.xml.in @@ -27,6 +27,7 @@ #include <include/interface/ipv6-options.xml.i> #include <include/source-interface-ethernet.xml.i> #include <include/interface/mac.xml.i> + #include <include/interface/mirror.xml.i> #include <include/interface/interface-firewall.xml.i> #include <include/interface/interface-policy.xml.i> <leafNode name="mode"> @@ -60,7 +61,6 @@ </leafNode> #include <include/interface/mtu-68-16000.xml.i> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vif-s.xml.i> #include <include/interface/vif.xml.i> </children> diff --git a/interface-definitions/interfaces-tunnel.xml.in b/interface-definitions/interfaces-tunnel.xml.in index bc9297c86..42ec62775 100644 --- a/interface-definitions/interfaces-tunnel.xml.in +++ b/interface-definitions/interfaces-tunnel.xml.in @@ -107,6 +107,7 @@ <constraintErrorMessage>Invalid encapsulation, must be one of: erspan, gre, gretap, ip6erspan, ip6gre, ip6gretap, ipip, sit, ipip6 or ip6ip6</constraintErrorMessage> </properties> </leafNode> + #include <include/interface/mirror.xml.i> <leafNode name="multicast"> <properties> <help>Multicast operation over tunnel</help> @@ -289,7 +290,6 @@ </node> #include <include/interface/vrf.xml.i> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/interfaces-vti.xml.in b/interface-definitions/interfaces-vti.xml.in index 538194c2b..5893e4c4c 100644 --- a/interface-definitions/interfaces-vti.xml.in +++ b/interface-definitions/interfaces-vti.xml.in @@ -34,8 +34,8 @@ #include <include/interface/ipv4-options.xml.i> #include <include/interface/ipv6-options.xml.i> #include <include/interface/mtu-68-16000.xml.i> + #include <include/interface/mirror.xml.i> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> #include <include/interface/interface-firewall.xml.i> #include <include/interface/interface-policy.xml.i> diff --git a/interface-definitions/interfaces-vxlan.xml.in b/interface-definitions/interfaces-vxlan.xml.in index 18abf9f20..9747b1816 100644 --- a/interface-definitions/interfaces-vxlan.xml.in +++ b/interface-definitions/interfaces-vxlan.xml.in @@ -53,6 +53,7 @@ #include <include/interface/ipv6-options.xml.i> #include <include/interface/mac.xml.i> #include <include/interface/mtu-1200-16000.xml.i> + #include <include/interface/mirror.xml.i> #include <include/interface/interface-firewall.xml.i> #include <include/interface/interface-policy.xml.i> <leafNode name="mtu"> @@ -100,7 +101,6 @@ #include <include/source-interface.xml.i> #include <include/interface/tunnel-remote-multi.xml.i> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> #include <include/vni.xml.i> </children> diff --git a/interface-definitions/interfaces-wireguard.xml.in b/interface-definitions/interfaces-wireguard.xml.in index 2f130c6f2..eb0892f07 100644 --- a/interface-definitions/interfaces-wireguard.xml.in +++ b/interface-definitions/interfaces-wireguard.xml.in @@ -23,6 +23,7 @@ #include <include/interface/mtu-68-16000.xml.i> #include <include/interface/interface-firewall.xml.i> #include <include/interface/interface-policy.xml.i> + #include <include/interface/mirror.xml.i> <leafNode name="mtu"> <defaultValue>1420</defaultValue> </leafNode> @@ -120,7 +121,6 @@ </children> </tagNode> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-wireless.xml.in b/interface-definitions/interfaces-wireless.xml.in index eebe8f841..db01657eb 100644 --- a/interface-definitions/interfaces-wireless.xml.in +++ b/interface-definitions/interfaces-wireless.xml.in @@ -6,6 +6,9 @@ <properties> <help>Wireless (WiFi/WLAN) Network Interface</help> <priority>318</priority> + <completionHelp> + <script>cd /sys/class/net; if compgen -G "wlan*" > /dev/null; then ls -d wlan*; fi</script> + </completionHelp> <constraint> <regex>^wlan[0-9]+$</regex> </constraint> @@ -563,6 +566,7 @@ </properties> <defaultValue>g</defaultValue> </leafNode> + #include <include/interface/mirror.xml.i> <leafNode name="physical-device"> <properties> <help>Wireless physical device</help> @@ -779,7 +783,6 @@ <defaultValue>monitor</defaultValue> </leafNode> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vif.xml.i> #include <include/interface/vif-s.xml.i> </children> diff --git a/interface-definitions/interfaces-wwan.xml.in b/interface-definitions/interfaces-wwan.xml.in index 7007a67ae..3cb1645c4 100644 --- a/interface-definitions/interfaces-wwan.xml.in +++ b/interface-definitions/interfaces-wwan.xml.in @@ -7,7 +7,7 @@ <help>Wireless Modem (WWAN) Interface</help> <priority>350</priority> <completionHelp> - <script>cd /sys/class/net; ls -d wwan*</script> + <script>cd /sys/class/net; if compgen -G "wwan*" > /dev/null; then ls -d wwan*; fi</script> </completionHelp> <constraint> <regex>^wwan[0-9]+$</regex> @@ -31,6 +31,7 @@ #include <include/interface/description.xml.i> #include <include/interface/disable.xml.i> #include <include/interface/disable-link-detect.xml.i> + #include <include/interface/mirror.xml.i> #include <include/interface/mtu-68-1500.xml.i> <leafNode name="mtu"> <defaultValue>1430</defaultValue> @@ -41,7 +42,6 @@ #include <include/interface/interface-firewall.xml.i> #include <include/interface/interface-policy.xml.i> #include <include/interface/redirect.xml.i> - #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/policy.xml.in b/interface-definitions/policy.xml.in index 5e037b558..1a4781397 100644 --- a/interface-definitions/policy.xml.in +++ b/interface-definitions/policy.xml.in @@ -1086,7 +1086,7 @@ <description>Based on a router-id IP address</description> </valueHelp> <constraint> - <regex>^((?:[0-9]{1,3}\.){3}[0-9]{1,3}|\d+):\d+$</regex> + <regex>^(((\b(?:(?:2(?:[0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9])\.){3}(?:(?:2([0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9]))\b)|(\d+)):(\d+) ?)+$</regex> </constraint> <constraintErrorMessage>Should be in form: ASN:NN or IPADDR:NN where ASN is autonomous system number</constraintErrorMessage> </properties> diff --git a/interface-definitions/qos.xml.in b/interface-definitions/qos.xml.in index d4468543c..e8f575a1e 100644 --- a/interface-definitions/qos.xml.in +++ b/interface-definitions/qos.xml.in @@ -1,721 +1,789 @@ <?xml version="1.0"?> <interfaceDefinition> - <node name="traffic-policy" owner="${vyos_conf_scripts_dir}/qos.py"> + <node name="qos" owner="${vyos_conf_scripts_dir}/qos.py"> <properties> - <help>Quality of Service (QOS) policy type</help> - <priority>900</priority> + <help>Quality of Service (QoS)</help> </properties> <children> - <tagNode name="drop-tail"> + <tagNode name="interface"> <properties> - <help>Packet limited First In, First Out queue</help> + <help>Interface to apply QoS policy</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> <valueHelp> <format>txt</format> - <description>Policy name</description> + <description>Interface name</description> </valueHelp> <constraint> - <regex>[[:alnum:]][-_[:alnum:]]*</regex> + <validator name="interface-name"/> </constraint> - <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> </properties> <children> - #include <include/generic-description.xml.i> - #include <include/qos/queue-limit-1-4294967295.xml.i> - </children> - </tagNode> - <tagNode name="fair-queue"> - <properties> - <help>Stochastic Fairness Queueing</help> - <valueHelp> - <format>txt</format> - <description>Policy name</description> - </valueHelp> - <constraint> - <regex>[[:alnum:]][-_[:alnum:]]*</regex> - </constraint> - <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> - </properties> - <children> - #include <include/generic-description.xml.i> - <leafNode name="hash-interval"> + <leafNode name="ingress"> <properties> - <help>Interval in seconds for queue algorithm perturbation</help> - <valueHelp> - <format>u32:0</format> - <description>No perturbation</description> - </valueHelp> + <help>Interface ingress traffic policy</help> + <completionHelp> + <path>traffic-policy drop-tail</path> + <path>traffic-policy fair-queue</path> + <path>traffic-policy fq-codel</path> + <path>traffic-policy limiter</path> + <path>traffic-policy network-emulator</path> + <path>traffic-policy priority-queue</path> + <path>traffic-policy random-detect</path> + <path>traffic-policy rate-control</path> + <path>traffic-policy round-robin</path> + <path>traffic-policy shaper</path> + <path>traffic-policy shaper-hfsc</path> + </completionHelp> <valueHelp> - <format>u32:1-127</format> - <description>Interval in seconds for queue algorithm perturbation (advised: 10)</description> + <format>txt</format> + <description>QoS Policy name</description> </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-127"/> - </constraint> - <constraintErrorMessage>Interval must be in range 0 to 127</constraintErrorMessage> </properties> - <defaultValue>0</defaultValue> </leafNode> - <leafNode name="queue-limit"> + <leafNode name="egress"> <properties> - <help>Upper limit of the SFQ</help> + <help>Interface egress traffic policy</help> + <completionHelp> + <path>traffic-policy drop-tail</path> + <path>traffic-policy fair-queue</path> + <path>traffic-policy fq-codel</path> + <path>traffic-policy limiter</path> + <path>traffic-policy network-emulator</path> + <path>traffic-policy priority-queue</path> + <path>traffic-policy random-detect</path> + <path>traffic-policy rate-control</path> + <path>traffic-policy round-robin</path> + <path>traffic-policy shaper</path> + <path>traffic-policy shaper-hfsc</path> + </completionHelp> <valueHelp> - <format>u32:2-127</format> - <description>Queue size in packets</description> + <format>txt</format> + <description>QoS Policy name</description> </valueHelp> - <constraint> - <validator name="numeric" argument="--range 2-127"/> - </constraint> - <constraintErrorMessage>Queue limit must greater than 1 and less than 128</constraintErrorMessage> </properties> - <defaultValue>127</defaultValue> </leafNode> </children> </tagNode> - <tagNode name="fq-codel"> + <node name="policy" owner="${vyos_conf_scripts_dir}/qos.py"> <properties> - <help>Fair Queuing Controlled Delay</help> - <valueHelp> - <format>txt</format> - <description>Policy name</description> - </valueHelp> - <constraint> - <regex>[[:alnum:]][-_[:alnum:]]*</regex> - </constraint> - <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + <help>Service Policy definitions</help> + <priority>900</priority> </properties> <children> - #include <include/generic-description.xml.i> - #include <include/qos/codel-quantum.xml.i> - #include <include/qos/flows.xml.i> - #include <include/qos/interval.xml.i> - #include <include/qos/queue-limit-2-10999.xml.i> - #include <include/qos/target.xml.i> - </children> - </tagNode> - <tagNode name="limiter"> - <properties> - <help>Traffic input limiting policy</help> - <valueHelp> - <format>txt</format> - <description>Policy name</description> - </valueHelp> - <constraint> - <regex>[[:alnum:]][-_[:alnum:]]*</regex> - </constraint> - <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> - </properties> - <children> - <tagNode name="class"> + <tagNode name="drop-tail"> <properties> - <help>Class ID</help> + <help>Packet limited First In, First Out queue</help> <valueHelp> - <format>u32:1-4090</format> - <description>Class Identifier</description> + <format>txt</format> + <description>Policy name</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 1-4090"/> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> </constraint> - <constraintErrorMessage>Class identifier must be between 1 and 4090</constraintErrorMessage> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + #include <include/qos/queue-limit-1-4294967295.xml.i> + </children> + </tagNode> + <tagNode name="fair-queue"> + <properties> + <help>Stochastic Fairness Queueing</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> </properties> <children> - #include <include/qos/bandwidth.xml.i> - #include <include/qos/burst.xml.i> #include <include/generic-description.xml.i> - #include <include/qos/match.xml.i> - <leafNode name="priority"> + <leafNode name="hash-interval"> + <properties> + <help>Interval in seconds for queue algorithm perturbation</help> + <valueHelp> + <format>u32:0</format> + <description>No perturbation</description> + </valueHelp> + <valueHelp> + <format>u32:1-127</format> + <description>Interval in seconds for queue algorithm perturbation (advised: 10)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-127"/> + </constraint> + <constraintErrorMessage>Interval must be in range 0 to 127</constraintErrorMessage> + </properties> + <defaultValue>0</defaultValue> + </leafNode> + <leafNode name="queue-limit"> <properties> - <help>Priority for rule evaluation</help> + <help>Upper limit of the SFQ</help> <valueHelp> - <format>u32:0-20</format> - <description>Priority for match rule evaluation</description> + <format>u32:2-127</format> + <description>Queue size in packets</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-20"/> + <validator name="numeric" argument="--range 2-127"/> </constraint> - <constraintErrorMessage>Priority must be between 0 and 20</constraintErrorMessage> + <constraintErrorMessage>Queue limit must greater than 1 and less than 128</constraintErrorMessage> </properties> - <defaultValue>20</defaultValue> + <defaultValue>127</defaultValue> </leafNode> </children> </tagNode> - <node name="default"> - <properties> - <help>Default policy</help> - </properties> - <children> - #include <include/qos/bandwidth.xml.i> - #include <include/qos/burst.xml.i> - </children> - </node> - #include <include/generic-description.xml.i> - </children> - </tagNode> - <tagNode name="network-emulator"> - <properties> - <help>Network emulator policy</help> - <valueHelp> - <format>txt</format> - <description>Policy name</description> - </valueHelp> - <constraint> - <regex>[[:alnum:]][-_[:alnum:]]*</regex> - </constraint> - <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> - </properties> - <children> - #include <include/qos/bandwidth.xml.i> - #include <include/qos/burst.xml.i> - #include <include/generic-description.xml.i> - <leafNode name="network-delay"> - <properties> - <help>Adds delay to packets outgoing to chosen network interface</help> - <valueHelp> - <format><number></format> - <description>Time in milliseconds</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-65535"/> - </constraint> - <constraintErrorMessage>Priority must be between 0 and 65535</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="packet-corruption"> - <properties> - <help>Introducing error in a random position for chosen percent of packets</help> - <valueHelp> - <format><number></format> - <description>Percentage of packets affected</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-100"/> - </constraint> - <constraintErrorMessage>Priority must be between 0 and 100</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="packet-loss"> - <properties> - <help>Add independent loss probability to the packets outgoing to chosen network interface</help> - <valueHelp> - <format><number></format> - <description>Percentage of packets affected</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-100"/> - </constraint> - <constraintErrorMessage>Must be between 0 and 100</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="packet-loss"> + <tagNode name="fq-codel"> <properties> - <help>Add independent loss probability to the packets outgoing to chosen network interface</help> + <help>Fair Queuing Controlled Delay</help> <valueHelp> - <format><number></format> - <description>Percentage of packets affected</description> + <format>txt</format> + <description>Policy name</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-100"/> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> </constraint> - <constraintErrorMessage>Must be between 0 and 100</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="packet-loss"> - <properties> - <help>Packet reordering percentage</help> - <valueHelp> - <format><number></format> - <description>Percentage of packets affected</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-100"/> - </constraint> - <constraintErrorMessage>Must be between 0 and 100</constraintErrorMessage> - </properties> - </leafNode> - #include <include/qos/queue-limit-1-4294967295.xml.i> - </children> - </tagNode> - <tagNode name="priority-queue"> - <properties> - <help>Priority queuing based policy</help> - <valueHelp> - <format>txt</format> - <description>Policy name</description> - </valueHelp> - <constraint> - <regex>[[:alnum:]][-_[:alnum:]]*</regex> - </constraint> - <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> - </properties> - <children> - <tagNode name="class"> - <properties> - <help>Class Handle</help> - <valueHelp> - <format>u32:1-7</format> - <description>Priority</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-7"/> - </constraint> - <constraintErrorMessage>Class handle must be between 1 and 7</constraintErrorMessage> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> </properties> <children> #include <include/generic-description.xml.i> #include <include/qos/codel-quantum.xml.i> #include <include/qos/flows.xml.i> #include <include/qos/interval.xml.i> - #include <include/qos/match.xml.i> #include <include/qos/queue-limit-2-10999.xml.i> #include <include/qos/target.xml.i> - #include <include/qos/queue-type.xml.i> </children> </tagNode> - <node name="default"> + <tagNode name="limiter"> <properties> - <help>Default policy</help> + <help>Traffic input limiting policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> </properties> <children> + <tagNode name="class"> + <properties> + <help>Class ID</help> + <valueHelp> + <format>u32:1-4090</format> + <description>Class Identifier</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-4090"/> + </constraint> + <constraintErrorMessage>Class identifier must be between 1 and 4090</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + #include <include/qos/burst.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/match.xml.i> + <leafNode name="priority"> + <properties> + <help>Priority for rule evaluation</help> + <valueHelp> + <format>u32:0-20</format> + <description>Priority for match rule evaluation</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-20"/> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 20</constraintErrorMessage> + </properties> + <defaultValue>20</defaultValue> + </leafNode> + </children> + </tagNode> + <node name="default"> + <properties> + <help>Default policy</help> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + #include <include/qos/burst.xml.i> + </children> + </node> #include <include/generic-description.xml.i> - #include <include/qos/codel-quantum.xml.i> - #include <include/qos/flows.xml.i> - #include <include/qos/interval.xml.i> - #include <include/qos/queue-limit-2-10999.xml.i> - #include <include/qos/target.xml.i> - #include <include/qos/queue-type.xml.i> </children> - </node> - #include <include/generic-description.xml.i> - </children> - </tagNode> - <tagNode name="random-detect"> - <properties> - <help>Priority queuing based policy</help> - <valueHelp> - <format>txt</format> - <description>Policy name</description> - </valueHelp> - <constraint> - <regex>[[:alnum:]][-_[:alnum:]]*</regex> - </constraint> - <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> - </properties> - <children> - #include <include/qos/bandwidth.xml.i> - <leafNode name="bandwidth"> - <defaultValue>auto</defaultValue> - </leafNode> - #include <include/generic-description.xml.i> - <tagNode name="precedence"> + </tagNode> + <tagNode name="network-emulator"> <properties> - <help>IP precedence</help> + <help>Network emulator policy</help> <valueHelp> - <format>u32:0-7</format> - <description>IP precedence value</description> + <format>txt</format> + <description>Policy name</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-7"/> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> </constraint> - <constraintErrorMessage>IP precedence value must be between 0 and 7</constraintErrorMessage> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> </properties> <children> - #include <include/qos/queue-limit-1-4294967295.xml.i> - <leafNode name="average-packet"> + #include <include/qos/bandwidth.xml.i> + #include <include/qos/burst.xml.i> + #include <include/generic-description.xml.i> + <leafNode name="network-delay"> <properties> - <help>Average packet size (bytes)</help> + <help>Adds delay to packets outgoing to chosen network interface</help> <valueHelp> - <format>u32:16-10240</format> - <description>Average packet size in bytes</description> + <format><number></format> + <description>Time in milliseconds</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-100"/> + <validator name="numeric" argument="--range 0-65535"/> </constraint> - <constraintErrorMessage>Average packet size must be between 16 and 10240</constraintErrorMessage> + <constraintErrorMessage>Priority must be between 0 and 65535</constraintErrorMessage> </properties> - <defaultValue>1024</defaultValue> </leafNode> - <leafNode name="mark-probability"> + <leafNode name="packet-corruption"> <properties> - <help>Mark probability for this precedence</help> + <help>Introducing error in a random position for chosen percent of packets</help> <valueHelp> <format><number></format> - <description>Numeric value (1/N)</description> + <description>Percentage of packets affected</description> </valueHelp> <constraint> - <validator name="numeric" argument="--positive"/> + <validator name="numeric" argument="--range 0-100"/> </constraint> - <constraintErrorMessage>Mark probability must be greater than 0</constraintErrorMessage> + <constraintErrorMessage>Priority must be between 0 and 100</constraintErrorMessage> </properties> </leafNode> - <leafNode name="maximum-threshold"> + <leafNode name="packet-loss"> <properties> - <help>Maximum threshold for random detection</help> + <help>Add independent loss probability to the packets outgoing to chosen network interface</help> <valueHelp> - <format>u32:0-4096</format> - <description>Maximum Threshold in packets</description> + <format><number></format> + <description>Percentage of packets affected</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-4096"/> + <validator name="numeric" argument="--range 0-100"/> </constraint> - <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> + <constraintErrorMessage>Must be between 0 and 100</constraintErrorMessage> </properties> </leafNode> - <leafNode name="minimum-threshold"> + <leafNode name="packet-loss"> <properties> - <help>Minimum threshold for random detection</help> + <help>Add independent loss probability to the packets outgoing to chosen network interface</help> <valueHelp> - <format>u32:0-4096</format> - <description>Maximum Threshold in packets</description> + <format><number></format> + <description>Percentage of packets affected</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-4096"/> + <validator name="numeric" argument="--range 0-100"/> </constraint> - <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> + <constraintErrorMessage>Must be between 0 and 100</constraintErrorMessage> </properties> </leafNode> - </children> - </tagNode> - </children> - </tagNode> - <tagNode name="rate-control"> - <properties> - <help>Rate limiting policy (Token Bucket Filter)</help> - <valueHelp> - <format>txt</format> - <description>Policy name</description> - </valueHelp> - <constraint> - <regex>[[:alnum:]][-_[:alnum:]]*</regex> - </constraint> - <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> - </properties> - <children> - #include <include/qos/bandwidth.xml.i> - #include <include/generic-description.xml.i> - #include <include/qos/burst.xml.i> - <leafNode name="latency"> - <properties> - <help>Maximum latency</help> - <valueHelp> - <format><number></format> - <description>Time in milliseconds</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-4096"/> - </constraint> - <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> - </properties> - <defaultValue>50</defaultValue> - </leafNode> - </children> - </tagNode> - <tagNode name="round-robin"> - <properties> - <help>Round-Robin based policy</help> - <valueHelp> - <format>txt</format> - <description>Policy name</description> - </valueHelp> - <constraint> - <regex>[[:alnum:]][-_[:alnum:]]*</regex> - </constraint> - <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> - </properties> - <children> - #include <include/generic-description.xml.i> - <tagNode name="class"> - <properties> - <help>Class ID</help> - <valueHelp> - <format>u32:1-4095</format> - <description>Class Identifier</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-4095"/> - </constraint> - <constraintErrorMessage>Class identifier must be between 1 and 4095</constraintErrorMessage> - </properties> - <children> - #include <include/qos/codel-quantum.xml.i> - #include <include/generic-description.xml.i> - #include <include/qos/flows.xml.i> - #include <include/qos/interval.xml.i> - #include <include/qos/match.xml.i> - <leafNode name="quantum"> + <leafNode name="packet-loss"> <properties> - <help>Packet scheduling quantum</help> + <help>Packet reordering percentage</help> <valueHelp> - <format>u32:1-4294967295</format> - <description>Packet scheduling quantum (bytes)</description> + <format><number></format> + <description>Percentage of packets affected</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 1-4294967295"/> + <validator name="numeric" argument="--range 0-100"/> </constraint> - <constraintErrorMessage>Quantum must be in range 1 to 4294967295</constraintErrorMessage> + <constraintErrorMessage>Must be between 0 and 100</constraintErrorMessage> </properties> </leafNode> #include <include/qos/queue-limit-1-4294967295.xml.i> - #include <include/qos/queue-type.xml.i> - #include <include/qos/target.xml.i> </children> </tagNode> - </children> - </tagNode> - <tagNode name="shaper-hfsc"> - <properties> - <help>Hierarchical Fair Service Curve's policy</help> - <valueHelp> - <format>txt</format> - <description>Policy name</description> - </valueHelp> - <constraint> - <regex>[[:alnum:]][-_[:alnum:]]*</regex> - </constraint> - <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> - </properties> - <children> - #include <include/qos/bandwidth.xml.i> - <leafNode name="bandwidth"> - <defaultValue>auto</defaultValue> - </leafNode> - #include <include/generic-description.xml.i> - <tagNode name="class"> + <tagNode name="priority-queue"> <properties> - <help>Class ID</help> + <help>Priority queuing based policy</help> <valueHelp> - <format>u32:1-4095</format> - <description>Class Identifier</description> + <format>txt</format> + <description>Policy name</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 1-4095"/> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> </constraint> - <constraintErrorMessage>Class identifier must be between 1 and 4095</constraintErrorMessage> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> </properties> <children> - #include <include/generic-description.xml.i> - <node name="linkshare"> + <tagNode name="class"> <properties> - <help>Linkshare class settings</help> - </properties> - <children> - #include <include/qos/hfsc-d.xml.i> - #include <include/qos/hfsc-m1.xml.i> - #include <include/qos/hfsc-m2.xml.i> - </children> - </node> - #include <include/qos/match.xml.i> - <node name="realtime"> - <properties> - <help>Realtime class settings</help> + <help>Class Handle</help> + <valueHelp> + <format>u32:1-7</format> + <description>Priority</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-7"/> + </constraint> + <constraintErrorMessage>Class handle must be between 1 and 7</constraintErrorMessage> </properties> <children> - #include <include/qos/hfsc-d.xml.i> - #include <include/qos/hfsc-m1.xml.i> - #include <include/qos/hfsc-m2.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/codel-quantum.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + #include <include/qos/match.xml.i> + #include <include/qos/queue-limit-2-10999.xml.i> + #include <include/qos/target.xml.i> + #include <include/qos/queue-type.xml.i> </children> - </node> - <node name="upperlimit"> + </tagNode> + <node name="default"> <properties> - <help>Upperlimit class settings</help> + <help>Default policy</help> </properties> <children> - #include <include/qos/hfsc-d.xml.i> - #include <include/qos/hfsc-m1.xml.i> - #include <include/qos/hfsc-m2.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/codel-quantum.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + #include <include/qos/queue-limit-2-10999.xml.i> + #include <include/qos/target.xml.i> + #include <include/qos/queue-type.xml.i> </children> </node> + #include <include/generic-description.xml.i> </children> </tagNode> - <node name="default"> + <tagNode name="random-detect"> <properties> - <help>Default policy</help> + <help>Priority queuing based policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> </properties> <children> - <node name="linkshare"> - <properties> - <help>Linkshare class settings</help> - </properties> - <children> - #include <include/qos/hfsc-d.xml.i> - #include <include/qos/hfsc-m1.xml.i> - #include <include/qos/hfsc-m2.xml.i> - </children> - </node> - <node name="realtime"> - <properties> - <help>Realtime class settings</help> - </properties> - <children> - #include <include/qos/hfsc-d.xml.i> - #include <include/qos/hfsc-m1.xml.i> - #include <include/qos/hfsc-m2.xml.i> - </children> - </node> - <node name="upperlimit"> + #include <include/qos/bandwidth.xml.i> + <leafNode name="bandwidth"> + <defaultValue>auto</defaultValue> + </leafNode> + #include <include/generic-description.xml.i> + <tagNode name="precedence"> <properties> - <help>Upperlimit class settings</help> + <help>IP precedence</help> + <valueHelp> + <format>u32:0-7</format> + <description>IP precedence value</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-7"/> + </constraint> + <constraintErrorMessage>IP precedence value must be between 0 and 7</constraintErrorMessage> </properties> <children> - #include <include/qos/hfsc-d.xml.i> - #include <include/qos/hfsc-m1.xml.i> - #include <include/qos/hfsc-m2.xml.i> + #include <include/qos/queue-limit-1-4294967295.xml.i> + <leafNode name="average-packet"> + <properties> + <help>Average packet size (bytes)</help> + <valueHelp> + <format>u32:16-10240</format> + <description>Average packet size in bytes</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-100"/> + </constraint> + <constraintErrorMessage>Average packet size must be between 16 and 10240</constraintErrorMessage> + </properties> + <defaultValue>1024</defaultValue> + </leafNode> + <leafNode name="mark-probability"> + <properties> + <help>Mark probability for this precedence</help> + <valueHelp> + <format><number></format> + <description>Numeric value (1/N)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--positive"/> + </constraint> + <constraintErrorMessage>Mark probability must be greater than 0</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="maximum-threshold"> + <properties> + <help>Maximum threshold for random detection</help> + <valueHelp> + <format>u32:0-4096</format> + <description>Maximum Threshold in packets</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4096"/> + </constraint> + <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="minimum-threshold"> + <properties> + <help>Minimum threshold for random detection</help> + <valueHelp> + <format>u32:0-4096</format> + <description>Maximum Threshold in packets</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4096"/> + </constraint> + <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> + </properties> + </leafNode> </children> - </node> + </tagNode> </children> - </node> - </children> - </tagNode> - <tagNode name="shaper"> - <properties> - <help>Traffic shaping based policy (Hierarchy Token Bucket)</help> - <valueHelp> - <format>txt</format> - <description>Policy name</description> - </valueHelp> - <constraint> - <regex>[[:alnum:]][-_[:alnum:]]*</regex> - </constraint> - <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> - </properties> - <children> - #include <include/qos/bandwidth.xml.i> - <leafNode name="bandwidth"> - <defaultValue>auto</defaultValue> - </leafNode> - <tagNode name="class"> + </tagNode> + <tagNode name="rate-control"> <properties> - <help>Class ID</help> + <help>Rate limiting policy (Token Bucket Filter)</help> <valueHelp> - <format>u32:2-4095</format> - <description>Class Identifier</description> + <format>txt</format> + <description>Policy name</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 2-4095"/> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> </constraint> - <constraintErrorMessage>Class identifier must be between 2 and 4095</constraintErrorMessage> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> </properties> <children> #include <include/qos/bandwidth.xml.i> - <leafNode name="bandwidth"> - <defaultValue>100%</defaultValue> - </leafNode> + #include <include/generic-description.xml.i> #include <include/qos/burst.xml.i> - <leafNode name="ceiling"> + <leafNode name="latency"> <properties> - <help>Bandwidth limit for this class</help> + <help>Maximum latency</help> <valueHelp> <format><number></format> - <description>Rate in kbit (kilobit per second)</description> - </valueHelp> - <valueHelp> - <format><number>%%</format> - <description>Percentage of overall rate</description> - </valueHelp> - <valueHelp> - <format><number>bit</format> - <description>bit(1), kbit(10^3), mbit(10^6), gbit, tbit</description> - </valueHelp> - <valueHelp> - <format><number>ibit</format> - <description>kibit(1024), mibit(1024^2), gibit(1024^3), tbit(1024^4)</description> - </valueHelp> - <valueHelp> - <format><number>ibps</format> - <description>kibps(1024*8), mibps(1024^2*8), gibps, tibps - Byte/sec</description> - </valueHelp> - <valueHelp> - <format><number>bps</format> - <description>bps(8),kbps(8*10^3),mbps(8*10^6), gbps, tbps - Byte/sec</description> + <description>Time in milliseconds</description> </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4096"/> + </constraint> + <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> </properties> + <defaultValue>50</defaultValue> </leafNode> - #include <include/qos/codel-quantum.xml.i> + </children> + </tagNode> + <tagNode name="round-robin"> + <properties> + <help>Round-Robin based policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> #include <include/generic-description.xml.i> - #include <include/qos/flows.xml.i> - #include <include/qos/interval.xml.i> - #include <include/qos/match.xml.i> - <leafNode name="priority"> + <tagNode name="class"> <properties> - <help>Priority for usage of excess bandwidth</help> + <help>Class ID</help> <valueHelp> - <format>u32:0-7</format> - <description>Priority order for bandwidth pool</description> + <format>u32:1-4095</format> + <description>Class Identifier</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-7"/> + <validator name="numeric" argument="--range 1-4095"/> </constraint> - <constraintErrorMessage>Priority must be between 0 and 7</constraintErrorMessage> + <constraintErrorMessage>Class identifier must be between 1 and 4095</constraintErrorMessage> </properties> - <defaultValue>20</defaultValue> - </leafNode> - #include <include/qos/queue-limit-1-4294967295.xml.i> - #include <include/qos/queue-type.xml.i> - #include <include/qos/set-dscp.xml.i> - #include <include/qos/target.xml.i> + <children> + #include <include/qos/codel-quantum.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + #include <include/qos/match.xml.i> + <leafNode name="quantum"> + <properties> + <help>Packet scheduling quantum</help> + <valueHelp> + <format>u32:1-4294967295</format> + <description>Packet scheduling quantum (bytes)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-4294967295"/> + </constraint> + <constraintErrorMessage>Quantum must be in range 1 to 4294967295</constraintErrorMessage> + </properties> + </leafNode> + #include <include/qos/queue-limit-1-4294967295.xml.i> + #include <include/qos/queue-type.xml.i> + #include <include/qos/target.xml.i> + </children> + </tagNode> </children> </tagNode> - #include <include/generic-description.xml.i> - <node name="default"> + <tagNode name="shaper-hfsc"> <properties> - <help>Default policy</help> + <help>Hierarchical Fair Service Curve's policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> </properties> <children> #include <include/qos/bandwidth.xml.i> - #include <include/qos/burst.xml.i> - <leafNode name="ceiling"> + <leafNode name="bandwidth"> + <defaultValue>auto</defaultValue> + </leafNode> + #include <include/generic-description.xml.i> + <tagNode name="class"> <properties> - <help>Bandwidth limit for this class</help> - <valueHelp> - <format><number></format> - <description>Rate in kbit (kilobit per second)</description> - </valueHelp> - <valueHelp> - <format><number>%%</format> - <description>Percentage of overall rate</description> - </valueHelp> + <help>Class ID</help> <valueHelp> - <format><number>bit</format> - <description>bit(1), kbit(10^3), mbit(10^6), gbit, tbit</description> - </valueHelp> - <valueHelp> - <format><number>ibit</format> - <description>kibit(1024), mibit(1024^2), gibit(1024^3), tbit(1024^4)</description> - </valueHelp> - <valueHelp> - <format><number>ibps</format> - <description>kibps(1024*8), mibps(1024^2*8), gibps, tibps - Byte/sec</description> - </valueHelp> - <valueHelp> - <format><number>bps</format> - <description>bps(8),kbps(8*10^3),mbps(8*10^6), gbps, tbps - Byte/sec</description> + <format>u32:1-4095</format> + <description>Class Identifier</description> </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-4095"/> + </constraint> + <constraintErrorMessage>Class identifier must be between 1 and 4095</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + <node name="linkshare"> + <properties> + <help>Linkshare class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + #include <include/qos/match.xml.i> + <node name="realtime"> + <properties> + <help>Realtime class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + <node name="upperlimit"> + <properties> + <help>Upperlimit class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + </children> + </tagNode> + <node name="default"> + <properties> + <help>Default policy</help> </properties> + <children> + <node name="linkshare"> + <properties> + <help>Linkshare class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + <node name="realtime"> + <properties> + <help>Realtime class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + <node name="upperlimit"> + <properties> + <help>Upperlimit class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + </children> + </node> + </children> + </tagNode> + <tagNode name="shaper"> + <properties> + <help>Traffic shaping based policy (Hierarchy Token Bucket)</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + <leafNode name="bandwidth"> + <defaultValue>auto</defaultValue> </leafNode> - #include <include/qos/codel-quantum.xml.i> - #include <include/generic-description.xml.i> - #include <include/qos/flows.xml.i> - #include <include/qos/interval.xml.i> - <leafNode name="priority"> + <tagNode name="class"> <properties> - <help>Priority for usage of excess bandwidth</help> + <help>Class ID</help> <valueHelp> - <format>u32:0-7</format> - <description>Priority order for bandwidth pool</description> + <format>u32:2-4095</format> + <description>Class Identifier</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-7"/> + <validator name="numeric" argument="--range 2-4095"/> </constraint> - <constraintErrorMessage>Priority must be between 0 and 7</constraintErrorMessage> + <constraintErrorMessage>Class identifier must be between 2 and 4095</constraintErrorMessage> </properties> - <defaultValue>20</defaultValue> - </leafNode> - #include <include/qos/queue-limit-1-4294967295.xml.i> - #include <include/qos/queue-type.xml.i> - #include <include/qos/set-dscp.xml.i> - #include <include/qos/target.xml.i> + <children> + #include <include/qos/bandwidth.xml.i> + <leafNode name="bandwidth"> + <defaultValue>100%</defaultValue> + </leafNode> + #include <include/qos/burst.xml.i> + <leafNode name="ceiling"> + <properties> + <help>Bandwidth limit for this class</help> + <valueHelp> + <format><number></format> + <description>Rate in kbit (kilobit per second)</description> + </valueHelp> + <valueHelp> + <format><number>%%</format> + <description>Percentage of overall rate</description> + </valueHelp> + <valueHelp> + <format><number>bit</format> + <description>bit(1), kbit(10^3), mbit(10^6), gbit, tbit</description> + </valueHelp> + <valueHelp> + <format><number>ibit</format> + <description>kibit(1024), mibit(1024^2), gibit(1024^3), tbit(1024^4)</description> + </valueHelp> + <valueHelp> + <format><number>ibps</format> + <description>kibps(1024*8), mibps(1024^2*8), gibps, tibps - Byte/sec</description> + </valueHelp> + <valueHelp> + <format><number>bps</format> + <description>bps(8),kbps(8*10^3),mbps(8*10^6), gbps, tbps - Byte/sec</description> + </valueHelp> + </properties> + </leafNode> + #include <include/qos/codel-quantum.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + #include <include/qos/match.xml.i> + <leafNode name="priority"> + <properties> + <help>Priority for usage of excess bandwidth</help> + <valueHelp> + <format>u32:0-7</format> + <description>Priority order for bandwidth pool</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-7"/> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 7</constraintErrorMessage> + </properties> + <defaultValue>20</defaultValue> + </leafNode> + #include <include/qos/queue-limit-1-4294967295.xml.i> + #include <include/qos/queue-type.xml.i> + #include <include/qos/set-dscp.xml.i> + #include <include/qos/target.xml.i> + </children> + </tagNode> + #include <include/generic-description.xml.i> + <node name="default"> + <properties> + <help>Default policy</help> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + #include <include/qos/burst.xml.i> + <leafNode name="ceiling"> + <properties> + <help>Bandwidth limit for this class</help> + <valueHelp> + <format><number></format> + <description>Rate in kbit (kilobit per second)</description> + </valueHelp> + <valueHelp> + <format><number>%%</format> + <description>Percentage of overall rate</description> + </valueHelp> + <valueHelp> + <format><number>bit</format> + <description>bit(1), kbit(10^3), mbit(10^6), gbit, tbit</description> + </valueHelp> + <valueHelp> + <format><number>ibit</format> + <description>kibit(1024), mibit(1024^2), gibit(1024^3), tbit(1024^4)</description> + </valueHelp> + <valueHelp> + <format><number>ibps</format> + <description>kibps(1024*8), mibps(1024^2*8), gibps, tibps - Byte/sec</description> + </valueHelp> + <valueHelp> + <format><number>bps</format> + <description>bps(8),kbps(8*10^3),mbps(8*10^6), gbps, tbps - Byte/sec</description> + </valueHelp> + </properties> + </leafNode> + #include <include/qos/codel-quantum.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + <leafNode name="priority"> + <properties> + <help>Priority for usage of excess bandwidth</help> + <valueHelp> + <format>u32:0-7</format> + <description>Priority order for bandwidth pool</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-7"/> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 7</constraintErrorMessage> + </properties> + <defaultValue>20</defaultValue> + </leafNode> + #include <include/qos/queue-limit-1-4294967295.xml.i> + #include <include/qos/queue-type.xml.i> + #include <include/qos/set-dscp.xml.i> + #include <include/qos/target.xml.i> + </children> + </node> </children> - </node> + </tagNode> </children> - </tagNode> + </node> </children> </node> </interfaceDefinition> diff --git a/interface-definitions/service_ipoe-server.xml.in b/interface-definitions/service_ipoe-server.xml.in index b19acab56..1325ba10d 100644 --- a/interface-definitions/service_ipoe-server.xml.in +++ b/interface-definitions/service_ipoe-server.xml.in @@ -112,6 +112,22 @@ </children> </tagNode> #include <include/name-server-ipv4-ipv6.xml.i> + <node name="client-ip-pool"> + <properties> + <help>Client IP pools and gateway setting</help> + </properties> + <children> + <tagNode name="name"> + <properties> + <help>Pool name</help> + </properties> + <children> + #include <include/accel-ppp/gateway-address.xml.i> + #include <include/accel-ppp/client-ip-pool-subnet-single.xml.i> + </children> + </tagNode> + </children> + </node> #include <include/accel-ppp/client-ipv6-pool.xml.i> <node name="authentication"> <properties> diff --git a/interface-definitions/system-ipv6.xml.in b/interface-definitions/system-ipv6.xml.in index af4dcdb0f..63260d00c 100644 --- a/interface-definitions/system-ipv6.xml.in +++ b/interface-definitions/system-ipv6.xml.in @@ -15,12 +15,6 @@ <valueless/> </properties> </leafNode> - <leafNode name="disable"> - <properties> - <help>Disable assignment of IPv6 addresses on all interfaces</help> - <valueless/> - </properties> - </leafNode> <node name="multipath"> <properties> <help>IPv6 multipath settings</help> diff --git a/op-mode-definitions/include/ospf-common.xml.i b/op-mode-definitions/include/ospf-common.xml.i index 0edc3c37f..23769c8ba 100644 --- a/op-mode-definitions/include/ospf-common.xml.i +++ b/op-mode-definitions/include/ospf-common.xml.i @@ -523,15 +523,6 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - <tagNode name="address"> - <properties> - <help>Show IPv4 OSPF neighbor information for specified IP address</help> - <completionHelp> - <list><x.x.x.x></list> - </completionHelp> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - </tagNode> <node name="detail"> <properties> <help>Show detailed IPv4 OSPF neighbor information</help> diff --git a/op-mode-definitions/monitor-log.xml.in b/op-mode-definitions/monitor-log.xml.in index 352c84ff1..cbdf76fc3 100644 --- a/op-mode-definitions/monitor-log.xml.in +++ b/op-mode-definitions/monitor-log.xml.in @@ -14,6 +14,79 @@ </properties> <command>grc tail --follow=name /var/log/messages</command> </node> + <node name="protocol"> + <properties> + <help>Monitor log for Routing Protocols</help> + </properties> + <children> + <leafNode name="ospf"> + <properties> + <help>Monitor log for OSPF</help> + </properties> + <command>journalctl --follow --boot /usr/lib/frr/ospfd</command> + </leafNode> + <leafNode name="ospfv3"> + <properties> + <help>Monitor log for OSPF for IPv6</help> + </properties> + <command>journalctl --follow --boot /usr/lib/frr/ospf6d</command> + </leafNode> + <leafNode name="bgp"> + <properties> + <help>Monitor log for BGP</help> + </properties> + <command>journalctl --follow --boot /usr/lib/frr/bgpd</command> + </leafNode> + <leafNode name="rip"> + <properties> + <help>Monitor log for RIP</help> + </properties> + <command>journalctl --follow --boot /usr/lib/frr/ripd</command> + </leafNode> + <leafNode name="ripng"> + <properties> + <help>Monitor log for RIPng</help> + </properties> + <command>journalctl --follow --boot /usr/lib/frr/ripngd</command> + </leafNode> + <leafNode name="static"> + <properties> + <help>Monitor log for static route</help> + </properties> + <command>journalctl --follow --boot /usr/lib/frr/staticd</command> + </leafNode> + <leafNode name="multicast"> + <properties> + <help>Monitor log for Multicast protocol</help> + </properties> + <command>journalctl --follow --boot /usr/lib/frr/pimd</command> + </leafNode> + <leafNode name="isis"> + <properties> + <help>Monitor log for ISIS</help> + </properties> + <command>journalctl --follow --boot /usr/lib/frr/isisd</command> + </leafNode> + <leafNode name="nhrp"> + <properties> + <help>Monitor log for NHRP</help> + </properties> + <command>journalctl --follow --boot /usr/lib/frr/nhrpd</command> + </leafNode> + <leafNode name="bfd"> + <properties> + <help>Monitor log for BFD</help> + </properties> + <command>journalctl --follow --boot /usr/lib/frr/bfdd</command> + </leafNode> + <leafNode name="mpls"> + <properties> + <help>Monitor log for MPLS</help> + </properties> + <command>journalctl --follow --boot /usr/lib/frr/ldpd</command> + </leafNode> + </children> + </node> </children> </node> </children> diff --git a/op-mode-definitions/show-log.xml.in b/op-mode-definitions/show-log.xml.in index 2d75f119d..15bbc7f42 100644 --- a/op-mode-definitions/show-log.xml.in +++ b/op-mode-definitions/show-log.xml.in @@ -221,67 +221,67 @@ <properties> <help>Show log for OSPF</help> </properties> - <command>journalctl -b /usr/lib/frr/ospfd</command> + <command>journalctl --boot /usr/lib/frr/ospfd</command> </leafNode> <leafNode name="ospfv3"> <properties> <help>Show log for OSPF for IPv6</help> </properties> - <command>journalctl -b /usr/lib/frr/ospf6d</command> + <command>journalctl --boot /usr/lib/frr/ospf6d</command> </leafNode> <leafNode name="bgp"> <properties> <help>Show log for BGP</help> </properties> - <command>journalctl -b /usr/lib/frr/bgpd</command> + <command>journalctl --boot /usr/lib/frr/bgpd</command> </leafNode> <leafNode name="rip"> <properties> <help>Show log for RIP</help> </properties> - <command>journalctl -b /usr/lib/frr/ripd</command> + <command>journalctl --boot /usr/lib/frr/ripd</command> </leafNode> <leafNode name="ripng"> <properties> <help>Show log for RIPng</help> </properties> - <command>journalctl -b /usr/lib/frr/ripngd</command> + <command>journalctl --boot /usr/lib/frr/ripngd</command> </leafNode> <leafNode name="static"> <properties> <help>Show log for static route</help> </properties> - <command>journalctl -b /usr/lib/frr/staticd</command> + <command>journalctl --boot /usr/lib/frr/staticd</command> </leafNode> <leafNode name="multicast"> <properties> <help>Show log for Multicast protocol</help> </properties> - <command>journalctl -b /usr/lib/frr/pimd</command> + <command>journalctl --boot /usr/lib/frr/pimd</command> </leafNode> <leafNode name="isis"> <properties> <help>Show log for ISIS</help> </properties> - <command>journalctl -b /usr/lib/frr/isisd</command> + <command>journalctl --boot /usr/lib/frr/isisd</command> </leafNode> <leafNode name="nhrp"> <properties> <help>Show log for NHRP</help> </properties> - <command>journalctl -b /usr/lib/frr/nhrpd</command> + <command>journalctl --boot /usr/lib/frr/nhrpd</command> </leafNode> <leafNode name="bfd"> <properties> <help>Show log for BFD</help> </properties> - <command>journalctl -b /usr/lib/frr/bfdd</command> + <command>journalctl --boot /usr/lib/frr/bfdd</command> </leafNode> <leafNode name="mpls"> <properties> <help>Show log for MPLS</help> </properties> - <command>journalctl -b /usr/lib/frr/ldpd</command> + <command>journalctl --boot /usr/lib/frr/ldpd</command> </leafNode> </children> </node> diff --git a/python/vyos/base.py b/python/vyos/base.py index c78045548..fd22eaccd 100644 --- a/python/vyos/base.py +++ b/python/vyos/base.py @@ -15,6 +15,12 @@ from textwrap import fill +class DeprecationWarning(): + def __init__(self, message): + # Reformat the message and trim it to 72 characters in length + message = fill(message, width=72) + print(f'\nDEPRECATION WARNING: {message}\n') + class ConfigError(Exception): def __init__(self, message): # Reformat the message and trim it to 72 characters in length diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py index 7f1258575..1062d51ee 100644 --- a/python/vyos/configverify.py +++ b/python/vyos/configverify.py @@ -178,31 +178,37 @@ def verify_eapol(config): if 'certificate' not in ca_cert: raise ConfigError('Invalid CA certificate specified for EAPoL') -def verify_mirror(config): +def verify_mirror_redirect(config): """ Common helper function used by interface implementations to perform - recurring validation of mirror interface configuration. + recurring validation of mirror and redirect interface configuration via tc(8) It makes no sense to mirror traffic back at yourself! """ + import os + if {'mirror', 'redirect'} <= set(config): + raise ConfigError('Mirror and redirect can not be enabled at the same time!') + if 'mirror' in config: for direction, mirror_interface in config['mirror'].items(): + if not os.path.exists(f'/sys/class/net/{mirror_interface}'): + raise ConfigError(f'Requested mirror interface "{mirror_interface}" '\ + 'does not exist!') + if mirror_interface == config['ifname']: - raise ConfigError(f'Can not mirror "{direction}" traffic back ' \ + raise ConfigError(f'Can not mirror "{direction}" traffic back '\ 'the originating interface!') -def verify_redirect(config): - """ - Common helper function used by interface implementations to perform - recurring validation of the redirect interface configuration. - - It makes no sense to mirror and redirect traffic at the same time! - """ - if {'mirror', 'redirect'} <= set(config): - raise ConfigError('Can not do both redirect and mirror') + if 'redirect' in config: + redirect_ifname = config['redirect'] + if not os.path.exists(f'/sys/class/net/{redirect_ifname}'): + raise ConfigError(f'Requested redirect interface "{redirect_ifname}" '\ + 'does not exist!') if dict_search('traffic_policy.in', config) != None: - raise ConfigError('Can not use ingress policy and redirect') + # XXX: support combination of limiting and redirect/mirror - this is an + # artificial limitation + raise ConfigError('Can not use ingress policy tigether with mirror or redirect!') def verify_authentication(config): """ @@ -322,30 +328,37 @@ def verify_vlan_config(config): if duplicate: raise ConfigError(f'Duplicate VLAN id "{duplicate[0]}" used for vif and vif-s interfaces!') + parent_ifname = config['ifname'] # 802.1q VLANs - for vlan in config.get('vif', {}): - vlan = config['vif'][vlan] + for vlan_id in config.get('vif', {}): + vlan = config['vif'][vlan_id] + vlan['ifname'] = f'{parent_ifname}.{vlan_id}' + verify_dhcpv6(vlan) verify_address(vlan) verify_vrf(vlan) - verify_redirect(vlan) + verify_mirror_redirect(vlan) verify_mtu_parent(vlan, config) # 802.1ad (Q-in-Q) VLANs - for s_vlan in config.get('vif_s', {}): - s_vlan = config['vif_s'][s_vlan] + for s_vlan_id in config.get('vif_s', {}): + s_vlan = config['vif_s'][s_vlan_id] + s_vlan['ifname'] = f'{parent_ifname}.{s_vlan_id}' + verify_dhcpv6(s_vlan) verify_address(s_vlan) verify_vrf(s_vlan) - verify_redirect(s_vlan) + verify_mirror_redirect(s_vlan) verify_mtu_parent(s_vlan, config) - for c_vlan in s_vlan.get('vif_c', {}): - c_vlan = s_vlan['vif_c'][c_vlan] + for c_vlan_id in s_vlan.get('vif_c', {}): + c_vlan = s_vlan['vif_c'][c_vlan_id] + c_vlan['ifname'] = f'{parent_ifname}.{s_vlan_id}.{c_vlan_id}' + verify_dhcpv6(c_vlan) verify_address(c_vlan) verify_vrf(c_vlan) - verify_redirect(c_vlan) + verify_mirror_redirect(c_vlan) verify_mtu_parent(c_vlan, config) verify_mtu_parent(c_vlan, s_vlan) diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py index 55ce318e7..ff8623592 100644 --- a/python/vyos/firewall.py +++ b/python/vyos/firewall.py @@ -174,7 +174,7 @@ def parse_rule(rule_conf, fw_name, rule_id, ip_name): if 'limit' in rule_conf: if 'rate' in rule_conf['limit']: - output.append(f'limit rate {rule_conf["limit"]["rate"]}/second') + output.append(f'limit rate {rule_conf["limit"]["rate"]}') if 'burst' in rule_conf['limit']: output.append(f'burst {rule_conf["limit"]["burst"]} packets') diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index f39da90e4..6b0f08fd4 100755 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -13,7 +13,6 @@ # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see <http://www.gnu.org/licenses/>. -from netifaces import interfaces import os import re import json @@ -39,7 +38,6 @@ from vyos.util import read_file from vyos.util import get_interface_config from vyos.util import get_interface_namespace from vyos.util import is_systemd_service_active -from vyos.util import is_ipv6_enabled from vyos.template import is_ipv4 from vyos.template import is_ipv6 from vyos.validate import is_intf_addr_assigned @@ -1081,12 +1079,6 @@ class Interface(Control): if addr in self._addr: return False - addr_is_v4 = is_ipv4(addr) - - # Failsave - do not add IPv6 address if IPv6 is disabled - if is_ipv6(addr) and not is_ipv6_enabled(): - return False - # add to interface if addr == 'dhcp': self.set_dhcp(True) @@ -1294,48 +1286,57 @@ class Interface(Control): if os.path.isfile(config_file): os.remove(config_file) - def set_mirror(self): + def set_mirror_redirect(self): # Please refer to the document for details # - https://man7.org/linux/man-pages/man8/tc.8.html # - https://man7.org/linux/man-pages/man8/tc-mirred.8.html # Depening if we are the source or the target interface of the port # mirror we need to setup some variables. source_if = self._config['ifname'] - config = self._config.get('mirror', None) + mirror_config = None + if 'mirror' in self._config: + mirror_config = self._config['mirror'] if 'is_mirror_intf' in self._config: source_if = next(iter(self._config['is_mirror_intf'])) - config = self._config['is_mirror_intf'][source_if].get('mirror', None) - - # Check configuration stored by old perl code before delete T3782/T4056 - if not 'redirect' in self._config and not 'traffic_policy' in self._config: - # Please do not clear the 'set $? = 0 '. It's meant to force a return of 0 - # Remove existing mirroring rules - delete_tc_cmd = f'tc qdisc del dev {source_if} handle ffff: ingress 2> /dev/null;' - delete_tc_cmd += f'tc qdisc del dev {source_if} handle 1: root prio 2> /dev/null;' - delete_tc_cmd += 'set $?=0' - self._popen(delete_tc_cmd) - - # Bail out early if nothing needs to be configured - if not config: - return - - for direction, mirror_if in config.items(): - if mirror_if not in interfaces(): - continue - - if direction == 'ingress': - handle = 'ffff: ingress' - parent = 'ffff:' - elif direction == 'egress': - handle = '1: root prio' - parent = '1:' - - # Mirror egress traffic - mirror_cmd = f'tc qdisc add dev {source_if} handle {handle}; ' - # Export the mirrored traffic to the interface - mirror_cmd += f'tc filter add dev {source_if} parent {parent} protocol all prio 10 u32 match u32 0 0 flowid 1:1 action mirred egress mirror dev {mirror_if}' - self._popen(mirror_cmd) + mirror_config = self._config['is_mirror_intf'][source_if].get('mirror', None) + + redirect_config = None + + # clear existing ingess - ignore errors (e.g. "Error: Cannot find specified + # qdisc on specified device") - we simply cleanup all stuff here + self._popen(f'tc qdisc del dev {source_if} parent ffff: 2>/dev/null'); + self._popen(f'tc qdisc del dev {source_if} parent 1: 2>/dev/null'); + + # Apply interface mirror policy + if mirror_config: + for direction, target_if in mirror_config.items(): + if direction == 'ingress': + handle = 'ffff: ingress' + parent = 'ffff:' + elif direction == 'egress': + handle = '1: root prio' + parent = '1:' + + # Mirror egress traffic + mirror_cmd = f'tc qdisc add dev {source_if} handle {handle}; ' + # Export the mirrored traffic to the interface + mirror_cmd += f'tc filter add dev {source_if} parent {parent} protocol '\ + f'all prio 10 u32 match u32 0 0 flowid 1:1 action mirred '\ + f'egress mirror dev {target_if}' + _, err = self._popen(mirror_cmd) + if err: print('tc qdisc(filter for mirror port failed') + + # Apply interface traffic redirection policy + elif 'redirect' in self._config: + _, err = self._popen(f'tc qdisc add dev {source_if} handle ffff: ingress') + if err: print(f'tc qdisc add for redirect failed!') + + target_if = self._config['redirect'] + _, err = self._popen(f'tc filter add dev {source_if} parent ffff: protocol '\ + f'all prio 10 u32 match u32 0 0 flowid 1:1 action mirred '\ + f'egress redirect dev {target_if}') + if err: print('tc filter add for redirect failed') def set_xdp(self, state): """ @@ -1434,9 +1435,6 @@ class Interface(Control): else: self.del_addr(addr) - for addr in new_addr: - self.add_addr(addr) - # start DHCPv6 client when only PD was configured if dhcpv6pd: self.set_dhcpv6(True) @@ -1451,6 +1449,10 @@ class Interface(Control): # checked before self.set_vrf(config.get('vrf', '')) + # Add this section after vrf T4331 + for addr in new_addr: + self.add_addr(addr) + # Configure MSS value for IPv4 TCP connections tmp = dict_search('ip.adjust_mss', config) value = tmp if (tmp != None) else '0' @@ -1501,55 +1503,56 @@ class Interface(Control): value = tmp if (tmp != None) else '0' self.set_ipv4_source_validation(value) - # Only change IPv6 parameters if IPv6 was not explicitly disabled - if is_ipv6_enabled(): - # Configure MSS value for IPv6 TCP connections - tmp = dict_search('ipv6.adjust_mss', config) - value = tmp if (tmp != None) else '0' - self.set_tcp_ipv6_mss(value) - - # IPv6 forwarding - tmp = dict_search('ipv6.disable_forwarding', config) - value = '0' if (tmp != None) else '1' - self.set_ipv6_forwarding(value) - - # IPv6 router advertisements - tmp = dict_search('ipv6.address.autoconf', config) - value = '2' if (tmp != None) else '1' - if 'dhcpv6' in new_addr: - value = '2' - self.set_ipv6_accept_ra(value) - - # IPv6 address autoconfiguration - tmp = dict_search('ipv6.address.autoconf', config) - value = '1' if (tmp != None) else '0' - self.set_ipv6_autoconf(value) - - # IPv6 Duplicate Address Detection (DAD) tries - tmp = dict_search('ipv6.dup_addr_detect_transmits', config) - value = tmp if (tmp != None) else '1' - self.set_ipv6_dad_messages(value) - - # Delete old IPv6 EUI64 addresses before changing MAC - for addr in (dict_search('ipv6.address.eui64_old', config) or []): - self.del_ipv6_eui64_address(addr) - - # Manage IPv6 link-local addresses - if dict_search('ipv6.address.no_default_link_local', config) != None: - self.del_ipv6_eui64_address('fe80::/64') - else: - self.add_ipv6_eui64_address('fe80::/64') - - # Add IPv6 EUI-based addresses - tmp = dict_search('ipv6.address.eui64', config) - if tmp: - for addr in tmp: - self.add_ipv6_eui64_address(addr) - - # MTU - Maximum Transfer Unit + # MTU - Maximum Transfer Unit has a default value. It must ALWAYS be set + # before mangling any IPv6 option. If MTU is less then 1280 IPv6 will be + # automatically disabled by the kernel. Also MTU must be increased before + # configuring any IPv6 address on the interface. if 'mtu' in config: self.set_mtu(config.get('mtu')) + # Configure MSS value for IPv6 TCP connections + tmp = dict_search('ipv6.adjust_mss', config) + value = tmp if (tmp != None) else '0' + self.set_tcp_ipv6_mss(value) + + # IPv6 forwarding + tmp = dict_search('ipv6.disable_forwarding', config) + value = '0' if (tmp != None) else '1' + self.set_ipv6_forwarding(value) + + # IPv6 router advertisements + tmp = dict_search('ipv6.address.autoconf', config) + value = '2' if (tmp != None) else '1' + if 'dhcpv6' in new_addr: + value = '2' + self.set_ipv6_accept_ra(value) + + # IPv6 address autoconfiguration + tmp = dict_search('ipv6.address.autoconf', config) + value = '1' if (tmp != None) else '0' + self.set_ipv6_autoconf(value) + + # IPv6 Duplicate Address Detection (DAD) tries + tmp = dict_search('ipv6.dup_addr_detect_transmits', config) + value = tmp if (tmp != None) else '1' + self.set_ipv6_dad_messages(value) + + # Delete old IPv6 EUI64 addresses before changing MAC + for addr in (dict_search('ipv6.address.eui64_old', config) or []): + self.del_ipv6_eui64_address(addr) + + # Manage IPv6 link-local addresses + if dict_search('ipv6.address.no_default_link_local', config) != None: + self.del_ipv6_eui64_address('fe80::/64') + else: + self.add_ipv6_eui64_address('fe80::/64') + + # Add IPv6 EUI-based addresses + tmp = dict_search('ipv6.address.eui64', config) + if tmp: + for addr in tmp: + self.add_ipv6_eui64_address(addr) + # re-add ourselves to any bridge we might have fallen out of if 'is_bridge_member' in config: bridge_dict = config.get('is_bridge_member') @@ -1558,8 +1561,8 @@ class Interface(Control): # eXpress Data Path - highly experimental self.set_xdp('xdp' in config) - # configure port mirror - self.set_mirror() + # configure interface mirror or redirection target + self.set_mirror_redirect() # Enable/Disable of an interface must always be done at the end of the # derived class to make use of the ref-counting set_admin_state() @@ -1718,6 +1721,3 @@ class VLANIf(Interface): return None return super().set_admin_state(state) - - def set_mirror(self): - return diff --git a/python/vyos/ifconfig/loopback.py b/python/vyos/ifconfig/loopback.py index 30c890fdf..b3babfadc 100644 --- a/python/vyos/ifconfig/loopback.py +++ b/python/vyos/ifconfig/loopback.py @@ -14,7 +14,6 @@ # License along with this library. If not, see <http://www.gnu.org/licenses/>. from vyos.ifconfig.interface import Interface -from vyos.util import is_ipv6_enabled @Interface.register class LoopbackIf(Interface): @@ -58,15 +57,14 @@ class LoopbackIf(Interface): interface setup code and provide a single point of entry when workin on any interface. """ - addr = config.get('address', []) - + address = config.get('address', []) # We must ensure that the loopback addresses are never deleted from the system - addr.append('127.0.0.1/8') - if is_ipv6_enabled(): - addr.append('::1/128') + for tmp in self._persistent_addresses: + if tmp not in address: + address.append(tmp) # Update IP address entry in our dictionary - config.update({'address' : addr}) + config.update({'address' : address}) # call base class super().update(config) diff --git a/python/vyos/template.py b/python/vyos/template.py index dabf53692..132f5ddde 100644 --- a/python/vyos/template.py +++ b/python/vyos/template.py @@ -18,7 +18,7 @@ import os from jinja2 import Environment from jinja2 import FileSystemLoader - +from jinja2 import ChainableUndefined from vyos.defaults import directories from vyos.util import chmod from vyos.util import chown @@ -27,6 +27,7 @@ from vyos.util import makedir # Holds template filters registered via register_filter() _FILTERS = {} +_TESTS = {} # reuse Environments with identical settings to improve performance @functools.lru_cache(maxsize=2) @@ -42,8 +43,10 @@ def _get_environment(location=None): cache_size=100, loader=loc_loader, trim_blocks=True, + undefined=ChainableUndefined, ) env.filters.update(_FILTERS) + env.tests.update(_TESTS) return env @@ -67,6 +70,26 @@ def register_filter(name, func=None): _FILTERS[name] = func return func +def register_test(name, func=None): + """Register a function to be available as test in templates under given name. + + It can also be used as a decorator, see below in this module for examples. + + :raise RuntimeError: + when trying to register a test after a template has been rendered already + :raise ValueError: when trying to register a name which was taken already + """ + if func is None: + return functools.partial(register_test, name) + if _get_environment.cache_info().currsize: + raise RuntimeError( + "Tests can only be registered before rendering the first template" + ) + if name in _TESTS: + raise ValueError(f"A test with name {name!r} was registered already") + _TESTS[name] = func + return func + def render_to_string(template, content, formater=None, location=None): """Render a template from the template directory, raise on any errors. @@ -566,3 +589,55 @@ def nft_intra_zone_action(zone_conf, ipv6=False): name = dict_search_args(intra_zone, 'firewall', fw_name) return f'jump {name_prefix}{name}' return 'return' + +@register_test('vyos_defined') +def vyos_defined(value, test_value=None, var_type=None): + """ + Jinja2 plugin to test if a variable is defined and not none - vyos_defined + will test value if defined and is not none and return true or false. + + If test_value is supplied, the value must also pass == test_value to return true. + If var_type is supplied, the value must also be of the specified class/type + + Examples: + 1. Test if var is defined and not none: + {% if foo is vyos_defined %} + ... + {% endif %} + + 2. Test if variable is defined, not none and has value "something" + {% if bar is vyos_defined("something") %} + ... + {% endif %} + + Parameters + ---------- + value : any + Value to test from ansible + test_value : any, optional + Value to test in addition of defined and not none, by default None + var_type : ['float', 'int', 'str', 'list', 'dict', 'tuple', 'bool'], optional + Type or Class to test for + + Returns + ------- + boolean + True if variable matches criteria, False in other cases. + + Implementation inspired and re-used from https://github.com/aristanetworks/ansible-avd/ + """ + + from jinja2 import Undefined + + if isinstance(value, Undefined) or value is None: + # Invalid value - return false + return False + elif test_value is not None and value != test_value: + # Valid value but not matching the optional argument + return False + elif str(var_type).lower() in ['float', 'int', 'str', 'list', 'dict', 'tuple', 'bool'] and str(var_type).lower() != type(value).__name__: + # Invalid class - return false + return False + else: + # Valid value and is matching optional argument if provided - return true + return True diff --git a/python/vyos/util.py b/python/vyos/util.py index f3f323c34..de55e108b 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -989,6 +989,11 @@ def is_wwan_connected(interface): if not interface.startswith('wwan'): raise ValueError(f'Specified interface "{interface}" is not a WWAN interface') + # ModemManager is required for connection(s) - if service is not running, + # there won't be any connection at all! + if not is_systemd_service_active('ModemManager.service'): + return False + modem = interface.lstrip('wwan') tmp = cmd(f'mmcli --modem {modem} --output-json') @@ -1019,7 +1024,3 @@ def sysctl_write(name, value): call(f'sysctl -wq {name}={value}') return True return False - -def is_ipv6_enabled() -> bool: - """ Check if IPv6 support on the system is enabled or not """ - return (sysctl_read('net.ipv6.conf.all.disable_ipv6') == '0') diff --git a/smoketest/configs/dialup-router-complex b/smoketest/configs/dialup-router-complex index 1b62deb5c..ac5ff5e99 100644 --- a/smoketest/configs/dialup-router-complex +++ b/smoketest/configs/dialup-router-complex @@ -498,6 +498,9 @@ firewall { destination { port 110,995 } + limit { + rate "10/minute" + } protocol tcp } rule 123 { diff --git a/smoketest/configs/ipv6-disable b/smoketest/configs/ipv6-disable new file mode 100644 index 000000000..da41e9020 --- /dev/null +++ b/smoketest/configs/ipv6-disable @@ -0,0 +1,83 @@ +interfaces { + ethernet eth0 { + duplex auto + smp-affinity auto + speed auto + vif 201 { + address 172.18.201.10/24 + } + vif 202 { + address 172.18.202.10/24 + } + vif 203 { + address 172.18.203.10/24 + } + vif 204 { + address 172.18.204.10/24 + } + } +} +protocols { + static { + route 0.0.0.0/0 { + next-hop 172.18.201.254 { + distance 10 + } + next-hop 172.18.202.254 { + distance 20 + } + next-hop 172.18.203.254 { + distance 30 + } + next-hop 172.18.204.254 { + distance 40 + } + } + } +} +system { + config-management { + commit-revisions 200 + } + console { + device ttyS0 { + speed 115200 + } + } + domain-name vyos.net + host-name vyos + ipv6 { + disable + } + login { + user vyos { + authentication { + encrypted-password $6$2Ta6TWHd/U$NmrX0x9kexCimeOcYK1MfhMpITF9ELxHcaBU/znBq.X2ukQOj61fVI2UYP/xBzP4QtiTcdkgs7WOQMHWsRymO/ + plaintext-password "" + } + level admin + } + } + name-server 172.16.254.20 + name-server 172.16.254.30 + ntp { + server 172.16.254.20 { + } + server 172.16.254.30 { + } + } + syslog { + global { + facility all { + level info + } + facility protocols { + level debug + } + } + } +} + +/* Warning: Do not remove the following line. */ +/* === vyatta-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack-sync@1:conntrack@1:dhcp-relay@2:dhcp-server@5:dns-forwarding@1:firewall@5:ipsec@5:l2tp@1:mdns@1:nat@4:ntp@1:pptp@1:qos@1:quagga@6:snmp@1:ssh@1:system@9:vrrp@2:wanloadbalance@3:webgui@1:webproxy@1:webproxy@2:zone-policy@1" === */ +/* Release version: 1.2.6 */ diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py index ecc0c29a0..16b020e07 100755 --- a/smoketest/scripts/cli/test_firewall.py +++ b/smoketest/scripts/cli/test_firewall.py @@ -88,6 +88,10 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'destination', 'port', '8888']) self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'tcp', 'flags', 'syn']) self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'tcp', 'flags', 'not', 'ack']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'action', 'accept']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'protocol', 'tcp']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'destination', 'port', '22']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'limit', 'rate', '5/minute']) self.cli_set(['interfaces', 'ethernet', 'eth0', 'firewall', 'in', 'name', 'smoketest']) @@ -97,6 +101,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): ['iifname "eth0"', 'jump NAME_smoketest'], ['saddr 172.16.20.10', 'daddr 172.16.10.10', 'return'], ['tcp flags & (syn | ack) == syn', 'tcp dport { 8888 }', 'reject'], + ['tcp dport { 22 }', 'limit rate 5/minute', 'return'], ['smoketest default-action', 'drop'] ] diff --git a/smoketest/scripts/cli/test_policy.py b/smoketest/scripts/cli/test_policy.py index 0acd41903..b232a2241 100755 --- a/smoketest/scripts/cli/test_policy.py +++ b/smoketest/scripts/cli/test_policy.py @@ -665,6 +665,40 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): self.assertIn(tmp, config) + def test_prefix_list_duplicates(self): + # FRR does not allow to specify the same profix list rule multiple times + # + # vyos(config)# ip prefix-list foo seq 10 permit 192.0.2.0/24 + # vyos(config)# ip prefix-list foo seq 20 permit 192.0.2.0/24 + # % Configuration failed. + # Error type: validation + # Error description: duplicated prefix list value: 192.0.2.0/24 + + # There is also a VyOS verify() function to test this + + prefix = '100.64.0.0/10' + prefix_list = 'duplicates' + test_range = range(20, 25) + path = base_path + ['prefix-list', prefix_list] + + for rule in test_range: + self.cli_set(path + ['rule', str(rule), 'action', 'permit']) + self.cli_set(path + ['rule', str(rule), 'prefix', prefix]) + + # Duplicate prefixes + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + for rule in test_range: + self.cli_set(path + ['rule', str(rule), 'le', str(rule)]) + + self.cli_commit() + + config = self.getFRRconfig('ip prefix-list', end='') + for rule in test_range: + tmp = f'ip prefix-list {prefix_list} seq {rule} permit {prefix} le {rule}' + self.assertIn(tmp, config) + def test_route_map(self): access_list = '50' as_path_list = '100' diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index db1587ba7..f1db5350a 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2022 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 @@ -36,112 +36,118 @@ bfd_profile = 'foo-bar-baz' neighbor_config = { '192.0.2.1' : { - 'bfd' : '', - 'cap_dynamic' : '', - 'cap_ext_next' : '', - 'remote_as' : '100', - 'adv_interv' : '400', - 'passive' : '', - 'password' : 'VyOS-Secure123', - 'shutdown' : '', - 'cap_over' : '', - 'ttl_security' : '5', - 'local_as' : '300', - 'route_map_in' : route_map_in, - 'route_map_out': route_map_out, + 'bfd' : '', + 'cap_dynamic' : '', + 'cap_ext_next' : '', + 'remote_as' : '100', + 'adv_interv' : '400', + 'passive' : '', + 'password' : 'VyOS-Secure123', + 'shutdown' : '', + 'cap_over' : '', + 'ttl_security' : '5', + 'local_as' : '300', + 'route_map_in' : route_map_in, + 'route_map_out' : route_map_out, 'no_send_comm_ext' : '', - 'addpath_all' : '', + 'addpath_all' : '', }, '192.0.2.2' : { - 'bfd_profile' : bfd_profile, - 'remote_as' : '200', - 'shutdown' : '', - 'no_cap_nego' : '', - 'port' : '667', - 'cap_strict' : '', - 'advertise_map': route_map_in, - 'non_exist_map': route_map_out, - 'pfx_list_in' : prefix_list_in, - 'pfx_list_out' : prefix_list_out, + 'bfd_profile' : bfd_profile, + 'remote_as' : '200', + 'shutdown' : '', + 'no_cap_nego' : '', + 'port' : '667', + 'cap_strict' : '', + 'advertise_map' : route_map_in, + 'non_exist_map' : route_map_out, + 'pfx_list_in' : prefix_list_in, + 'pfx_list_out' : prefix_list_out, 'no_send_comm_std' : '', }, '192.0.2.3' : { - 'advertise_map': route_map_in, - 'description' : 'foo bar baz', - 'remote_as' : '200', - 'passive' : '', - 'multi_hop' : '5', - 'update_src' : 'lo', - 'peer_group' : 'foo', + 'advertise_map' : route_map_in, + 'description' : 'foo bar baz', + 'remote_as' : '200', + 'passive' : '', + 'multi_hop' : '5', + 'update_src' : 'lo', + 'peer_group' : 'foo', + 'graceful_rst' : '', }, '2001:db8::1' : { - 'advertise_map': route_map_in, - 'exist_map' : route_map_out, - 'cap_dynamic' : '', - 'cap_ext_next' : '', - 'remote_as' : '123', - 'adv_interv' : '400', - 'passive' : '', - 'password' : 'VyOS-Secure123', - 'shutdown' : '', - 'cap_over' : '', - 'ttl_security' : '5', - 'local_as' : '300', - 'solo' : '', - 'route_map_in' : route_map_in, - 'route_map_out': route_map_out, + 'advertise_map' : route_map_in, + 'exist_map' : route_map_out, + 'cap_dynamic' : '', + 'cap_ext_next' : '', + 'remote_as' : '123', + 'adv_interv' : '400', + 'passive' : '', + 'password' : 'VyOS-Secure123', + 'shutdown' : '', + 'cap_over' : '', + 'ttl_security' : '5', + 'local_as' : '300', + 'solo' : '', + 'route_map_in' : route_map_in, + 'route_map_out' : route_map_out, 'no_send_comm_std' : '', 'addpath_per_as' : '', - 'peer_group' : 'foo-bar', + 'peer_group' : 'foo-bar', }, '2001:db8::2' : { - 'remote_as' : '456', - 'shutdown' : '', - 'no_cap_nego' : '', - 'port' : '667', - 'cap_strict' : '', - 'pfx_list_in' : prefix_list_in6, - 'pfx_list_out' : prefix_list_out6, + 'remote_as' : '456', + 'shutdown' : '', + 'no_cap_nego' : '', + 'port' : '667', + 'cap_strict' : '', + 'pfx_list_in' : prefix_list_in6, + 'pfx_list_out' : prefix_list_out6, 'no_send_comm_ext' : '', - 'peer_group' : 'foo-bar_baz', + 'peer_group' : 'foo-bar_baz', + 'graceful_rst_hlp' : '' }, } peer_group_config = { 'foo' : { - 'advertise_map': route_map_in, - 'exist_map' : route_map_out, - 'bfd' : '', - 'remote_as' : '100', - 'passive' : '', - 'password' : 'VyOS-Secure123', - 'shutdown' : '', - 'cap_over' : '', - 'ttl_security': '5', + 'advertise_map' : route_map_in, + 'exist_map' : route_map_out, + 'bfd' : '', + 'remote_as' : '100', + 'passive' : '', + 'password' : 'VyOS-Secure123', + 'shutdown' : '', + 'cap_over' : '', + 'ttl_security' : '5', + }, + 'bar' : { + 'remote_as' : '111', + 'graceful_rst_no' : '' }, 'foo-bar' : { - 'advertise_map': route_map_in, - 'description' : 'foo peer bar group', - 'remote_as' : '200', - 'shutdown' : '', - 'no_cap_nego' : '', - 'local_as' : '300', - 'pfx_list_in' : prefix_list_in, - 'pfx_list_out' : prefix_list_out, + 'advertise_map' : route_map_in, + 'description' : 'foo peer bar group', + 'remote_as' : '200', + 'shutdown' : '', + 'no_cap_nego' : '', + 'local_as' : '300', + 'pfx_list_in' : prefix_list_in, + 'pfx_list_out' : prefix_list_out, 'no_send_comm_ext' : '', }, 'foo-bar_baz' : { - 'advertise_map': route_map_in, - 'non_exist_map': route_map_out, - 'bfd_profile' : bfd_profile, - 'cap_dynamic' : '', - 'cap_ext_next' : '', - 'remote_as' : '200', - 'passive' : '', - 'multi_hop' : '5', - 'update_src' : 'lo', - 'route_map_in' : route_map_in, - 'route_map_out': route_map_out, + 'advertise_map' : route_map_in, + 'non_exist_map' : route_map_out, + 'bfd_profile' : bfd_profile, + 'cap_dynamic' : '', + 'cap_ext_next' : '', + 'remote_as' : '200', + 'passive' : '', + 'multi_hop' : '5', + 'update_src' : 'lo', + 'route_map_in' : route_map_in, + 'route_map_out' : route_map_out, }, } @@ -239,6 +245,12 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): if 'non_exist_map' in peer_config: base = f'{base} non-exist-map {peer_config["non_exist_map"]}' self.assertIn(base, frrconfig) + if 'graceful_rst' in peer_config: + self.assertIn(f' neighbor {peer} graceful-restart', frrconfig) + if 'graceful_rst_no' in peer_config: + self.assertIn(f' neighbor {peer} graceful-restart-disable', frrconfig) + if 'graceful_rst_hlp' in peer_config: + self.assertIn(f' neighbor {peer} graceful-restart-helper', frrconfig) def test_bgp_01_simple(self): router_id = '127.0.0.1' @@ -320,6 +332,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): def test_bgp_02_neighbors(self): # Test out individual neighbor configuration items, not all of them are # also available to a peer-group! + self.cli_set(base_path + ['parameters', 'deterministic-med']) + for peer, peer_config in neighbor_config.items(): afi = 'ipv4-unicast' if is_ipv6(peer): @@ -380,6 +394,12 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'addpath-tx-all']) if 'addpath_per_as' in peer_config: self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'addpath-tx-per-as']) + if 'graceful_rst' in peer_config: + self.cli_set(base_path + ['neighbor', peer, 'graceful-restart', 'enable']) + if 'graceful_rst_no' in peer_config: + self.cli_set(base_path + ['neighbor', peer, 'graceful-restart', 'disable']) + if 'graceful_rst_hlp' in peer_config: + self.cli_set(base_path + ['neighbor', peer, 'graceful-restart', 'restart-helper']) # Conditional advertisement if 'advertise_map' in peer_config: @@ -462,6 +482,12 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'addpath-tx-all']) if 'addpath_per_as' in config: self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'addpath-tx-per-as']) + if 'graceful_rst' in config: + self.cli_set(base_path + ['peer-group', peer_group, 'graceful-restart', 'enable']) + if 'graceful_rst_no' in config: + self.cli_set(base_path + ['peer-group', peer_group, 'graceful-restart', 'disable']) + if 'graceful_rst_hlp' in config: + self.cli_set(base_path + ['peer-group', peer_group, 'graceful-restart', 'restart-helper']) # Conditional advertisement if 'advertise_map' in config: @@ -481,6 +507,7 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): if 'peer_group' in peer_config: self.cli_set(base_path + ['neighbor', peer, 'peer-group', peer_config['peer_group']]) + # commit changes self.cli_commit() @@ -856,4 +883,4 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f' exit-address-family', afi_config) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2, failfast=True) diff --git a/smoketest/scripts/cli/test_protocols_isis.py b/smoketest/scripts/cli/test_protocols_isis.py index 7f51c7178..11c765793 100755 --- a/smoketest/scripts/cli/test_protocols_isis.py +++ b/smoketest/scripts/cli/test_protocols_isis.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2022 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 @@ -35,6 +35,10 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): # call base-classes classmethod super(cls, cls).setUpClass() + # ensure we can also run this test on a live system - so lets clean + # out the current configuration :) + cls.cli_delete(cls, base_path) + def tearDown(self): self.cli_delete(base_path) self.cli_commit() @@ -71,13 +75,13 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify all changes - tmp = self.getFRRconfig(f'router isis {domain}') + tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') self.assertIn(f' net {net}', tmp) self.assertIn(f' log-adjacency-changes', tmp) self.assertIn(f' redistribute ipv4 connected level-2 route-map {route_map}', tmp) for interface in self._interfaces: - tmp = self.getFRRconfig(f'interface {interface}') + tmp = self.getFRRconfig(f'interface {interface}', daemon='isisd') self.assertIn(f' ip router isis {domain}', tmp) self.assertIn(f' ipv6 router isis {domain}', tmp) @@ -104,11 +108,11 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify FRR isisd configuration - tmp = self.getFRRconfig(f'router isis {domain}') + tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') self.assertIn(f'router isis {domain}', tmp) self.assertIn(f' net {net}', tmp) - tmp = self.getFRRconfig(f'router isis {domain} vrf {vrf}') + tmp = self.getFRRconfig(f'router isis {domain} vrf {vrf}', daemon='isisd') self.assertIn(f'router isis {domain} vrf {vrf}', tmp) self.assertIn(f' net {net}', tmp) @@ -124,22 +128,26 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.isis_base_config() self.cli_set(base_path + ['redistribute', 'ipv4', 'connected', 'level-2', 'route-map', route_map]) self.cli_set(base_path + ['route-map', route_map]) + self.cli_set(base_path + ['level', 'level-2']) # commit changes self.cli_commit() # Verify FRR configuration zebra_route_map = f'ip protocol isis route-map {route_map}' - frrconfig = self.getFRRconfig(zebra_route_map) + frrconfig = self.getFRRconfig(zebra_route_map, daemon='zebra') self.assertIn(zebra_route_map, frrconfig) + tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') + self.assertIn(' is-type level-2-only', tmp) + # Remove the route-map again self.cli_delete(base_path + ['route-map']) # commit changes self.cli_commit() # Verify FRR configuration - frrconfig = self.getFRRconfig(zebra_route_map) + frrconfig = self.getFRRconfig(zebra_route_map, daemon='zebra') self.assertNotIn(zebra_route_map, frrconfig) self.cli_delete(['policy', 'route-map', route_map]) @@ -159,7 +167,7 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify all changes - tmp = self.getFRRconfig(f'router isis {domain}') + tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') self.assertIn(f' net {net}', tmp) for afi in ['ipv4', 'ipv6']: @@ -172,6 +180,8 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): password = 'foo' self.isis_base_config() + for interface in self._interfaces: + self.cli_set(base_path + ['interface', interface, 'password', 'plaintext-password', f'{password}-{interface}']) self.cli_set(base_path + ['area-password', 'plaintext-password', password]) self.cli_set(base_path + ['area-password', 'md5', password]) @@ -192,11 +202,14 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify all changes - tmp = self.getFRRconfig(f'router isis {domain}') + tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') self.assertIn(f' net {net}', tmp) self.assertIn(f' domain-password clear {password}', tmp) self.assertIn(f' area-password clear {password}', tmp) + for interface in self._interfaces: + tmp = self.getFRRconfig(f'interface {interface}', daemon='isisd') + self.assertIn(f' isis password clear {password}-{interface}', tmp) def test_isis_06_spf_delay_bfd(self): network = 'point-to-point' @@ -237,12 +250,12 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify all changes - tmp = self.getFRRconfig(f'router isis {domain}') + tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') self.assertIn(f' net {net}', tmp) self.assertIn(f' spf-delay-ietf init-delay {init_delay} short-delay {short_delay} long-delay {long_delay} holddown {holddown} time-to-learn {time_to_learn}', tmp) for interface in self._interfaces: - tmp = self.getFRRconfig(f'interface {interface}') + tmp = self.getFRRconfig(f'interface {interface}', daemon='isisd') self.assertIn(f' ip router isis {domain}', tmp) self.assertIn(f' ipv6 router isis {domain}', tmp) self.assertIn(f' isis network {network}', tmp) diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py index 5d8e9cff2..e433d06d0 100755 --- a/smoketest/scripts/cli/test_protocols_ospf.py +++ b/smoketest/scripts/cli/test_protocols_ospf.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2022 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 @@ -40,6 +40,10 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): cls.cli_set(cls, ['policy', 'route-map', route_map, 'rule', '10', 'action', 'permit']) cls.cli_set(cls, ['policy', 'route-map', route_map, 'rule', '20', 'action', 'permit']) + # ensure we can also run this test on a live system - so lets clean + # out the current configuration :) + cls.cli_delete(cls, base_path) + @classmethod def tearDownClass(cls): cls.cli_delete(cls, ['policy', 'route-map', route_map]) diff --git a/smoketest/scripts/cli/test_protocols_ospfv3.py b/smoketest/scripts/cli/test_protocols_ospfv3.py index 2fc694fd7..944190089 100755 --- a/smoketest/scripts/cli/test_protocols_ospfv3.py +++ b/smoketest/scripts/cli/test_protocols_ospfv3.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2022 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 @@ -38,6 +38,10 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): cls.cli_set(cls, ['policy', 'route-map', route_map, 'rule', '10', 'action', 'permit']) cls.cli_set(cls, ['policy', 'route-map', route_map, 'rule', '20', 'action', 'permit']) + # ensure we can also run this test on a live system - so lets clean + # out the current configuration :) + cls.cli_delete(cls, base_path) + @classmethod def tearDownClass(cls): cls.cli_delete(cls, ['policy', 'route-map', route_map]) @@ -70,7 +74,7 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf6') + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') self.assertIn(f'router ospf6', frrconfig) self.assertIn(f' area {default_area} range {prefix}', frrconfig) self.assertIn(f' ospf6 router-id {router_id}', frrconfig) @@ -78,7 +82,7 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.assertIn(f' area {default_area} export-list {acl_name}', frrconfig) for interface in interfaces: - if_config = self.getFRRconfig(f'interface {interface}') + if_config = self.getFRRconfig(f'interface {interface}', daemon='ospf6d') self.assertIn(f'ipv6 ospf6 area {default_area}', if_config) self.cli_delete(['policy', 'access-list6', acl_name]) @@ -99,7 +103,7 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf6') + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') self.assertIn(f'router ospf6', frrconfig) self.assertIn(f' distance {dist_global}', frrconfig) self.assertIn(f' distance ospf6 intra-area {dist_intra_area} inter-area {dist_inter_area} external {dist_external}', frrconfig) @@ -119,7 +123,7 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf6') + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') self.assertIn(f'router ospf6', frrconfig) for protocol in redistribute: self.assertIn(f' redistribute {protocol} route-map {route_map}', frrconfig) @@ -150,13 +154,13 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf6') + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') self.assertIn(f'router ospf6', frrconfig) cost = '100' priority = '10' for interface in interfaces: - if_config = self.getFRRconfig(f'interface {interface}') + if_config = self.getFRRconfig(f'interface {interface}', daemon='ospf6d') self.assertIn(f'interface {interface}', if_config) self.assertIn(f' ipv6 ospf6 bfd', if_config) self.assertIn(f' ipv6 ospf6 bfd profile {bfd_profile}', if_config) @@ -180,7 +184,7 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf6') + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') self.assertIn(f'router ospf6', frrconfig) self.assertIn(f' area {area_stub} stub', frrconfig) self.assertIn(f' area {area_stub_nosum} stub no-summary', frrconfig) @@ -206,7 +210,7 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf6') + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') self.assertIn(f'router ospf6', frrconfig) self.assertIn(f' area {area_nssa} nssa', frrconfig) self.assertIn(f' area {area_nssa_nosum} nssa default-information-originate no-summary', frrconfig) @@ -226,7 +230,7 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf6') + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') self.assertIn(f'router ospf6', frrconfig) self.assertIn(f' default-information originate metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig) @@ -235,7 +239,7 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf6') + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') self.assertIn(f' default-information originate always metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig) @@ -261,15 +265,15 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf6') + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') self.assertIn(f'router ospf6', frrconfig) self.assertIn(f' ospf6 router-id {router_id}', frrconfig) - frrconfig = self.getFRRconfig(f'interface {vrf_iface}') + frrconfig = self.getFRRconfig(f'interface {vrf_iface}', daemon='ospf6d') self.assertIn(f'interface {vrf_iface}', frrconfig) self.assertIn(f' ipv6 ospf6 bfd', frrconfig) - frrconfig = self.getFRRconfig(f'router ospf6 vrf {vrf}') + frrconfig = self.getFRRconfig(f'router ospf6 vrf {vrf}', daemon='ospf6d') self.assertIn(f'router ospf6 vrf {vrf}', frrconfig) self.assertIn(f' ospf6 router-id {router_id_vrf}', frrconfig) diff --git a/smoketest/scripts/cli/test_service_https.py b/smoketest/scripts/cli/test_service_https.py index 8e69efd9c..9413d22d1 100755 --- a/smoketest/scripts/cli/test_service_https.py +++ b/smoketest/scripts/cli/test_service_https.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2020 VyOS maintainers and contributors +# Copyright (C) 2019-2022 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 @@ -15,15 +15,39 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import unittest +import urllib3 + +from requests import request from base_vyostest_shim import VyOSUnitTestSHIM +from vyos.util import read_file from vyos.util import run -base_path = ['service', 'https'] +urllib3.disable_warnings() +base_path = ['service', 'https'] pki_base = ['pki'] -cert_data = 'MIICFDCCAbugAwIBAgIUfMbIsB/ozMXijYgUYG80T1ry+mcwCgYIKoZIzj0EAwIwWTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MB4XDTIxMDcyMDEyNDUxMloXDTI2MDcxOTEyNDUxMlowWTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE01HrLcNttqq4/PtoMua8rMWEkOdBu7vP94xzDO7A8C92ls1v86eePy4QllKCzIw3QxBIoCuH2peGRfWgPRdFsKNhMF8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1UdDgQWBBSu+JnU5ZC4mkuEpqg2+Mk4K79oeDAKBggqhkjOPQQDAgNHADBEAiBEFdzQ/Bc3LftzngrY605UhA6UprHhAogKgROv7iR4QgIgEFUxTtW3xXJcnUPWhhUFhyZoqfn8dE93+dm/LDnp7C0=' -key_data = 'MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPLpD0Ohhoq0g4nhx2KMIuze7ucKUt/lBEB2wc03IxXyhRANCAATTUestw222qrj8+2gy5rysxYSQ50G7u8/3jHMM7sDwL3aWzW/zp54/LhCWUoLMjDdDEEigK4fal4ZF9aA9F0Ww' + +cert_data = """ +MIICFDCCAbugAwIBAgIUfMbIsB/ozMXijYgUYG80T1ry+mcwCgYIKoZIzj0EAwIw +WTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNv +bWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MB4XDTIx +MDcyMDEyNDUxMloXDTI2MDcxOTEyNDUxMlowWTELMAkGA1UEBhMCR0IxEzARBgNV +BAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlP +UzESMBAGA1UEAwwJVnlPUyBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +01HrLcNttqq4/PtoMua8rMWEkOdBu7vP94xzDO7A8C92ls1v86eePy4QllKCzIw3 +QxBIoCuH2peGRfWgPRdFsKNhMF8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1UdDgQWBBSu ++JnU5ZC4mkuEpqg2+Mk4K79oeDAKBggqhkjOPQQDAgNHADBEAiBEFdzQ/Bc3Lftz +ngrY605UhA6UprHhAogKgROv7iR4QgIgEFUxTtW3xXJcnUPWhhUFhyZoqfn8dE93 ++dm/LDnp7C0= +""" + +key_data = """ +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPLpD0Ohhoq0g4nhx +2KMIuze7ucKUt/lBEB2wc03IxXyhRANCAATTUestw222qrj8+2gy5rysxYSQ50G7 +u8/3jHMM7sDwL3aWzW/zp54/LhCWUoLMjDdDEEigK4fal4ZF9aA9F0Ww +""" class TestHTTPSService(VyOSUnitTestSHIM.TestCase): def setUp(self): @@ -61,9 +85,13 @@ class TestHTTPSService(VyOSUnitTestSHIM.TestCase): ret = run('sudo /usr/sbin/nginx -t') self.assertEqual(ret, 0) + nginx_config = read_file('/etc/nginx/sites-enabled/default') + self.assertIn(f'listen {address}:{port} ssl;', nginx_config) + self.assertIn(f'ssl_protocols TLSv1.2 TLSv1.3;', nginx_config) + def test_certificate(self): - self.cli_set(pki_base + ['certificate', 'test_https', 'certificate', cert_data]) - self.cli_set(pki_base + ['certificate', 'test_https', 'private', 'key', key_data]) + self.cli_set(pki_base + ['certificate', 'test_https', 'certificate', cert_data.replace('\n','')]) + self.cli_set(pki_base + ['certificate', 'test_https', 'private', 'key', key_data.replace('\n','')]) self.cli_set(base_path + ['certificates', 'certificate', 'test_https']) @@ -72,5 +100,43 @@ class TestHTTPSService(VyOSUnitTestSHIM.TestCase): ret = run('sudo /usr/sbin/nginx -t') self.assertEqual(ret, 0) + def test_api_auth(self): + vhost_id = 'example' + address = '127.0.0.1' + port = '443' + name = 'localhost' + + self.cli_set(base_path + ['api', 'socket']) + key = 'MySuperSecretVyOS' + self.cli_set(base_path + ['api', 'keys', 'id', 'key-01', 'key', key]) + + test_path = base_path + ['virtual-host', vhost_id] + self.cli_set(test_path + ['listen-address', address]) + self.cli_set(test_path + ['listen-port', port]) + self.cli_set(test_path + ['server-name', name]) + + self.cli_commit() + + nginx_config = read_file('/etc/nginx/sites-enabled/default') + self.assertIn(f'listen {address}:{port} ssl;', nginx_config) + self.assertIn(f'ssl_protocols TLSv1.2 TLSv1.3;', nginx_config) + + url = f'https://{address}/retrieve' + payload = {'data': '{"op": "showConfig", "path": []}', 'key': f'{key}'} + headers = {} + r = request('POST', url, verify=False, headers=headers, data=payload) + # Must get HTTP code 200 on success + self.assertEqual(r.status_code, 200) + + payload_invalid = {'data': '{"op": "showConfig", "path": []}', 'key': 'invalid'} + r = request('POST', url, verify=False, headers=headers, data=payload_invalid) + # Must get HTTP code 401 on invalid key (Unauthorized) + self.assertEqual(r.status_code, 401) + + payload_no_key = {'data': '{"op": "showConfig", "path": []}'} + r = request('POST', url, verify=False, headers=headers, data=payload_no_key) + # Must get HTTP code 401 on missing key (Unauthorized) + self.assertEqual(r.status_code, 401) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_ssh.py b/smoketest/scripts/cli/test_service_ssh.py index a54c03919..9ed263655 100755 --- a/smoketest/scripts/cli/test_service_ssh.py +++ b/smoketest/scripts/cli/test_service_ssh.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2020 VyOS maintainers and contributors +# Copyright (C) 2019-2022 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 @@ -15,13 +15,17 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os +import paramiko import re import unittest +from pwd import getpwall + from base_vyostest_shim import VyOSUnitTestSHIM from vyos.configsession import ConfigSessionError from vyos.util import cmd +from vyos.util import is_systemd_service_running from vyos.util import process_named_running from vyos.util import read_file @@ -49,6 +53,9 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase): cls.cli_delete(cls, base_path) def tearDown(self): + # Check for running process + self.assertTrue(process_named_running(PROCESS_NAME)) + # delete testing SSH config self.cli_delete(base_path) self.cli_commit() @@ -57,6 +64,11 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase): self.assertTrue(os.path.isfile(key_dsa)) self.assertTrue(os.path.isfile(key_ed25519)) + # Established SSH connections remains running after service is stopped. + # We can not use process_named_running here - we rather need to check + # that the systemd service is no longer running + self.assertFalse(is_systemd_service_running(PROCESS_NAME)) + def test_ssh_default(self): # Check if SSH service runs with default settings - used for checking # behavior of <defaultValue> in XML definition @@ -69,9 +81,6 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase): port = get_config_value('Port')[0] self.assertEqual('22', port) - # Check for running process - self.assertTrue(process_named_running(PROCESS_NAME)) - def test_ssh_single_listen_address(self): # Check if SSH service can be configured and runs self.cli_set(base_path + ['port', '1234']) @@ -108,9 +117,6 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase): keepalive = get_config_value('ClientAliveInterval')[0] self.assertTrue("100" in keepalive) - # Check for running process - self.assertTrue(process_named_running(PROCESS_NAME)) - def test_ssh_multiple_listen_addresses(self): # Check if SSH service can be configured and runs with multiple # listen ports and listen-addresses @@ -135,9 +141,6 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase): for address in addresses: self.assertIn(address, tmp) - # Check for running process - self.assertTrue(process_named_running(PROCESS_NAME)) - def test_ssh_vrf(self): # Check if SSH service can be bound to given VRF port = '22' @@ -157,9 +160,6 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase): tmp = get_config_value('Port') self.assertIn(port, tmp) - # Check for running process - self.assertTrue(process_named_running(PROCESS_NAME)) - # Check for process in VRF tmp = cmd(f'ip vrf pids {vrf}') self.assertIn(PROCESS_NAME, tmp) @@ -167,5 +167,51 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase): # delete VRF self.cli_delete(['vrf', 'name', vrf]) + def test_ssh_login(self): + # Perform SSH login and command execution with a predefined user. The + # result (output of uname -a) must match the output if the command is + # run natively. + # + # We also try to login as an invalid user - this is not allowed to work. + + def ssh_send_cmd(command, username, password, host='localhost'): + """ SSH command execution helper """ + # Try to login via SSH + ssh_client = paramiko.SSHClient() + ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh_client.connect(hostname='localhost', username=username, password=password) + _, stdout, stderr = ssh_client.exec_command(command) + output = stdout.read().decode().strip() + error = stderr.read().decode().strip() + ssh_client.close() + return output, error + + test_user = 'ssh_test' + test_pass = 'v2i57DZs8idUwMN3VC92' + test_command = 'uname -a' + + self.cli_set(base_path) + self.cli_set(['system', 'login', 'user', test_user, 'authentication', 'plaintext-password', test_pass]) + + # commit changes + self.cli_commit() + + # Login with proper credentials + output, error = ssh_send_cmd(test_command, test_user, test_pass) + # verify login + self.assertFalse(error) + self.assertEqual(output, cmd(test_command)) + + # Login with invalid credentials + with self.assertRaises(paramiko.ssh_exception.AuthenticationException): + output, error = ssh_send_cmd(test_command, 'invalid_user', 'invalid_password') + + self.cli_delete(['system', 'login', 'user', test_user]) + self.cli_commit() + + # After deletion the test user is not allowed to remain in /etc/passwd + usernames = [x[0] for x in getpwall()] + self.assertNotIn(test_user, usernames) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_system_ipv6.py b/smoketest/scripts/cli/test_system_ipv6.py index 837d1dc12..c8aea9100 100755 --- a/smoketest/scripts/cli/test_system_ipv6.py +++ b/smoketest/scripts/cli/test_system_ipv6.py @@ -20,7 +20,6 @@ from base_vyostest_shim import VyOSUnitTestSHIM from vyos.template import is_ipv4 from vyos.util import read_file -from vyos.util import is_ipv6_enabled from vyos.util import get_interface_config from vyos.validate import is_intf_addr_assigned @@ -46,41 +45,6 @@ class TestSystemIPv6(VyOSUnitTestSHIM.TestCase): self.assertEqual(read_file(file_forwarding), '0') - def test_system_ipv6_disable(self): - # Verify previous "enable" state - self.assertEqual(read_file(file_disable), '0') - self.assertTrue(is_ipv6_enabled()) - - loopbacks = ['127.0.0.1', '::1'] - for addr in loopbacks: - self.assertTrue(is_intf_addr_assigned('lo', addr)) - - # Do not assign any IPv6 address on interfaces, this requires a reboot - # which can not be tested, but we can read the config file :) - self.cli_set(base_path + ['disable']) - self.cli_commit() - - # Verify configuration file - self.assertEqual(read_file(file_disable), '1') - self.assertFalse(is_ipv6_enabled()) - - for addr in loopbacks: - if is_ipv4(addr): - self.assertTrue(is_intf_addr_assigned('lo', addr)) - else: - self.assertFalse(is_intf_addr_assigned('lo', addr)) - - # T4330: Verify MTU can be changed with IPv6 disabled - mtu = '1600' - eth_if = 'eth0' - self.cli_set(['interfaces', 'ethernet', eth_if, 'mtu', mtu]) - self.cli_commit() - - tmp = get_interface_config(eth_if) - self.assertEqual(tmp['mtu'], int(mtu)) - - self.cli_delete(['interfaces', 'ethernet', eth_if, 'mtu']) - def test_system_ipv6_strict_dad(self): # This defaults to 1 self.assertEqual(read_file(file_dad), '1') diff --git a/smoketest/scripts/cli/test_system_login.py b/smoketest/scripts/cli/test_system_login.py index 095300de3..1131b6f93 100755 --- a/smoketest/scripts/cli/test_system_login.py +++ b/smoketest/scripts/cli/test_system_login.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2020 VyOS maintainers and contributors +# Copyright (C) 2019-2022 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 @@ -23,6 +23,7 @@ from base_vyostest_shim import VyOSUnitTestSHIM from distutils.version import LooseVersion from platform import release as kernel_version from subprocess import Popen, PIPE +from pwd import getpwall from vyos.configsession import ConfigSessionError from vyos.util import cmd @@ -52,6 +53,11 @@ class TestSystemLogin(VyOSUnitTestSHIM.TestCase): self.cli_commit() + # After deletion, a user is not allowed to remain in /etc/passwd + usernames = [x[0] for x in getpwall()] + for user in users: + self.assertNotIn(user, usernames) + def test_add_linux_system_user(self): # We are not allowed to re-use a username already taken by the Linux # base system diff --git a/smoketest/scripts/cli/test_vrf.py b/smoketest/scripts/cli/test_vrf.py index 5daea589c..c591d6cf5 100755 --- a/smoketest/scripts/cli/test_vrf.py +++ b/smoketest/scripts/cli/test_vrf.py @@ -131,41 +131,6 @@ class VRFTest(VyOSUnitTestSHIM.TestCase): for addr in loopbacks: self.assertTrue(is_intf_addr_assigned(vrf, addr)) - def test_vrf_loopbacks_no_ipv6(self): - table = '2002' - for vrf in vrfs: - base = base_path + ['name', vrf] - self.cli_set(base + ['table', str(table)]) - table = str(int(table) + 1) - - # Globally disable IPv6 - this will remove all IPv6 interface addresses - self.cli_set(['system', 'ipv6', 'disable']) - - # commit changes - self.cli_commit() - - # Verify VRF configuration - table = '2002' - loopbacks = ['127.0.0.1', '::1'] - for vrf in vrfs: - # Ensure VRF was created - self.assertIn(vrf, interfaces()) - - # Verify VRF table ID - tmp = get_interface_config(vrf) - self.assertEqual(int(table), tmp['linkinfo']['info_data']['table']) - - # Test for proper loopback IP assignment - for addr in loopbacks: - if is_ipv4(addr): - self.assertTrue(is_intf_addr_assigned(vrf, addr)) - else: - self.assertFalse(is_intf_addr_assigned(vrf, addr)) - - table = str(int(table) + 1) - - self.cli_delete(['system', 'ipv6']) - def test_vrf_bind_all(self): table = '2000' for vrf in vrfs: @@ -216,11 +181,11 @@ class VRFTest(VyOSUnitTestSHIM.TestCase): # commit changes self.cli_commit() - # Verify & cleanup + # Verify VRF assignmant for interface in self._interfaces: - # os.readlink resolves to: '../../../../../virtual/net/foovrf' - tmp = os.readlink(f'/sys/class/net/{interface}/master').split('/')[-1] - self.assertEqual(tmp, vrf) + tmp = get_interface_config(interface) + self.assertEqual(vrf, tmp['master']) + # cleanup section = Section.section(interface) self.cli_delete(['interfaces', section, interface, 'vrf']) @@ -262,5 +227,45 @@ class VRFTest(VyOSUnitTestSHIM.TestCase): # Increment table ID for the next run table = str(int(table) + 1) + def test_vrf_link_local_ip_addresses(self): + # Testcase for issue T4331 + table = '100' + vrf = 'orange' + interface = 'dum9998' + addresses = ['192.0.2.1/26', '2001:db8:9998::1/64', 'fe80::1/64'] + + for address in addresses: + self.cli_set(['interfaces', 'dummy', interface, 'address', address]) + + # Create dummy interfaces + self.cli_commit() + + # ... and verify IP addresses got assigned + for address in addresses: + self.assertTrue(is_intf_addr_assigned(interface, address)) + + # Move interface to VRF + self.cli_set(base_path + ['name', vrf, 'table', table]) + self.cli_set(['interfaces', 'dummy', interface, 'vrf', vrf]) + + # Apply VRF config + self.cli_commit() + # Ensure VRF got created + self.assertIn(vrf, interfaces()) + # ... and IP addresses are still assigned + for address in addresses: + self.assertTrue(is_intf_addr_assigned(interface, address)) + # Verify VRF table ID + tmp = get_interface_config(vrf) + self.assertEqual(int(table), tmp['linkinfo']['info_data']['table']) + + # Verify interface is assigned to VRF + tmp = get_interface_config(interface) + self.assertEqual(vrf, tmp['master']) + + # Delete Interface + self.cli_delete(['interfaces', 'dummy', interface]) + self.cli_commit() + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/src/conf_mode/dhcp_server.py b/src/conf_mode/dhcp_server.py index a8cef5ebf..d27f8d995 100755 --- a/src/conf_mode/dhcp_server.py +++ b/src/conf_mode/dhcp_server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2021 VyOS maintainers and contributors +# Copyright (C) 2018-2022 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 @@ -109,7 +109,7 @@ def get_config(config=None): if not conf.exists(base): return None - dhcp = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + dhcp = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True) # T2665: defaults include lease time per TAG node which need to be added to # individual subnet definitions default_values = defaults(base + ['shared-network-name', 'subnet']) diff --git a/src/conf_mode/dhcpv6_server.py b/src/conf_mode/dhcpv6_server.py index e6a2e4486..be1e6db1e 100755 --- a/src/conf_mode/dhcpv6_server.py +++ b/src/conf_mode/dhcpv6_server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2020 VyOS maintainers and contributors +# Copyright (C) 2018-2022 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 @@ -41,7 +41,7 @@ def get_config(config=None): if not conf.exists(base): return None - dhcpv6 = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + dhcpv6 = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True) return dhcpv6 def verify(dhcpv6): diff --git a/src/conf_mode/dns_forwarding.py b/src/conf_mode/dns_forwarding.py index 23a16df63..fa9b21f20 100755 --- a/src/conf_mode/dns_forwarding.py +++ b/src/conf_mode/dns_forwarding.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2020 VyOS maintainers and contributors +# Copyright (C) 2018-2022 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 @@ -16,6 +16,7 @@ import os +from netifaces import interfaces from sys import exit from glob import glob @@ -65,10 +66,6 @@ def get_config(config=None): if conf.exists(base_nameservers): dns.update({'system_name_server': conf.return_values(base_nameservers)}) - base_nameservers_dhcp = ['system', 'name-servers-dhcp'] - if conf.exists(base_nameservers_dhcp): - dns.update({'system_name_server_dhcp': conf.return_values(base_nameservers_dhcp)}) - if 'authoritative_domain' in dns: dns['authoritative_zones'] = [] dns['authoritative_zone_errors'] = [] @@ -272,9 +269,8 @@ def verify(dns): raise ConfigError('Invalid authoritative records have been defined') if 'system' in dns: - if not ('system_name_server' in dns or 'system_name_server_dhcp' in dns): - print("Warning: No 'system name-server' or 'system " \ - "name-servers-dhcp' configured") + if not 'system_name_server' in dns: + print('Warning: No "system name-server" configured') return None @@ -339,10 +335,15 @@ def apply(dns): hc.delete_name_server_tags_recursor(['system']) # add dhcp nameserver tags for configured interfaces - if 'system_name_server_dhcp' in dns: - for interface in dns['system_name_server_dhcp']: - hc.add_name_server_tags_recursor(['dhcp-' + interface, - 'dhcpv6-' + interface ]) + if 'system_name_server' in dns: + for interface in dns['system_name_server']: + # system_name_server key contains both IP addresses and interface + # names (DHCP) to use DNS servers. We need to check if the + # value is an interface name - only if this is the case, add the + # interface based DNS forwarder. + if interface in interfaces(): + hc.add_name_server_tags_recursor(['dhcp-' + interface, + 'dhcpv6-' + interface ]) # hostsd will generate the forward-zones file # the list and keys() are required as get returns a dict, not list diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py index 41df1b84a..f33198a49 100755 --- a/src/conf_mode/firewall.py +++ b/src/conf_mode/firewall.py @@ -171,6 +171,12 @@ def verify_rule(firewall, rule_conf, ipv6): if {'match_frag', 'match_non_frag'} <= set(rule_conf['fragment']): raise ConfigError('Cannot specify both "match-frag" and "match-non-frag"') + if 'limit' in rule_conf: + if 'rate' in rule_conf['limit']: + rate_int = re.sub(r'\D', '', rule_conf['limit']['rate']) + if int(rate_int) < 1: + raise ConfigError('Limit rate integer cannot be less than 1') + if 'ipsec' in rule_conf: if {'match_ipsec', 'match_non_ipsec'} <= set(rule_conf['ipsec']): raise ConfigError('Cannot specify both "match-ipsec" and "match-non-ipsec"') diff --git a/src/conf_mode/interfaces-bonding.py b/src/conf_mode/interfaces-bonding.py index 661dc2298..ad5a0f499 100755 --- a/src/conf_mode/interfaces-bonding.py +++ b/src/conf_mode/interfaces-bonding.py @@ -27,9 +27,8 @@ from vyos.configdict import is_source_interface from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_dhcpv6 -from vyos.configverify import verify_mirror +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect from vyos.configverify import verify_source_interface from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf @@ -151,8 +150,7 @@ def verify(bond): verify_address(bond) verify_dhcpv6(bond) verify_vrf(bond) - verify_mirror(bond) - verify_redirect(bond) + verify_mirror_redirect(bond) # use common function to verify VLAN configuration verify_vlan_config(bond) diff --git a/src/conf_mode/interfaces-bridge.py b/src/conf_mode/interfaces-bridge.py index e16c0e9f4..b1f7e6d7c 100755 --- a/src/conf_mode/interfaces-bridge.py +++ b/src/conf_mode/interfaces-bridge.py @@ -27,8 +27,7 @@ from vyos.configdict import is_source_interface from vyos.configdict import has_vlan_subinterface_configured from vyos.configdict import dict_merge from vyos.configverify import verify_dhcpv6 -from vyos.configverify import verify_mirror -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_vrf from vyos.ifconfig import BridgeIf from vyos.validate import has_address_configured @@ -107,8 +106,7 @@ def verify(bridge): verify_dhcpv6(bridge) verify_vrf(bridge) - verify_mirror(bridge) - verify_redirect(bridge) + verify_mirror_redirect(bridge) ifname = bridge['ifname'] diff --git a/src/conf_mode/interfaces-dummy.py b/src/conf_mode/interfaces-dummy.py index 4072c4452..4a1eb7b93 100755 --- a/src/conf_mode/interfaces-dummy.py +++ b/src/conf_mode/interfaces-dummy.py @@ -21,7 +21,7 @@ from vyos.configdict import get_interface_dict from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import DummyIf from vyos import ConfigError from vyos import airbag @@ -47,7 +47,7 @@ def verify(dummy): verify_vrf(dummy) verify_address(dummy) - verify_redirect(dummy) + verify_mirror_redirect(dummy) return None diff --git a/src/conf_mode/interfaces-ethernet.py b/src/conf_mode/interfaces-ethernet.py index 3eeddf190..6aea7a80e 100755 --- a/src/conf_mode/interfaces-ethernet.py +++ b/src/conf_mode/interfaces-ethernet.py @@ -25,10 +25,9 @@ from vyos.configverify import verify_address from vyos.configverify import verify_dhcpv6 from vyos.configverify import verify_eapol from vyos.configverify import verify_interface_exists -from vyos.configverify import verify_mirror +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_mtu from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf from vyos.ethtool import Ethtool @@ -84,8 +83,7 @@ def verify(ethernet): verify_address(ethernet) verify_vrf(ethernet) verify_eapol(ethernet) - verify_mirror(ethernet) - verify_redirect(ethernet) + verify_mirror_redirect(ethernet) ethtool = Ethtool(ifname) # No need to check speed and duplex keys as both have default values. diff --git a/src/conf_mode/interfaces-geneve.py b/src/conf_mode/interfaces-geneve.py index a94b5e1f7..3a668226b 100755 --- a/src/conf_mode/interfaces-geneve.py +++ b/src/conf_mode/interfaces-geneve.py @@ -24,7 +24,7 @@ from vyos.configdict import get_interface_dict from vyos.configverify import verify_address from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_bridge_delete -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import GeneveIf from vyos import ConfigError @@ -51,7 +51,7 @@ def verify(geneve): verify_mtu_ipv6(geneve) verify_address(geneve) - verify_redirect(geneve) + verify_mirror_redirect(geneve) if 'remote' not in geneve: raise ConfigError('Remote side must be configured') diff --git a/src/conf_mode/interfaces-l2tpv3.py b/src/conf_mode/interfaces-l2tpv3.py index 5ea7159dc..22256bf4f 100755 --- a/src/conf_mode/interfaces-l2tpv3.py +++ b/src/conf_mode/interfaces-l2tpv3.py @@ -25,7 +25,7 @@ from vyos.configdict import leaf_node_changed from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import L2TPv3If from vyos.util import check_kmod from vyos.validate import is_addr_assigned @@ -77,7 +77,7 @@ def verify(l2tpv3): verify_mtu_ipv6(l2tpv3) verify_address(l2tpv3) - verify_redirect(l2tpv3) + verify_mirror_redirect(l2tpv3) return None def generate(l2tpv3): diff --git a/src/conf_mode/interfaces-loopback.py b/src/conf_mode/interfaces-loopback.py index e6a851113..e4bc15bb5 100755 --- a/src/conf_mode/interfaces-loopback.py +++ b/src/conf_mode/interfaces-loopback.py @@ -20,7 +20,7 @@ from sys import exit from vyos.config import Config from vyos.configdict import get_interface_dict -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import LoopbackIf from vyos import ConfigError from vyos import airbag @@ -40,7 +40,7 @@ def get_config(config=None): return loopback def verify(loopback): - verify_redirect(loopback) + verify_mirror_redirect(loopback) return None def generate(loopback): diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py index 6a29fdb11..96fc1c41c 100755 --- a/src/conf_mode/interfaces-macsec.py +++ b/src/conf_mode/interfaces-macsec.py @@ -29,7 +29,7 @@ from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_source_interface from vyos import ConfigError from vyos import airbag @@ -67,7 +67,7 @@ def verify(macsec): verify_vrf(macsec) verify_mtu_ipv6(macsec) verify_address(macsec) - verify_redirect(macsec) + verify_mirror_redirect(macsec) if not (('security' in macsec) and ('cipher' in macsec['security'])): diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index 8f9c0b3f1..83d1c6d9b 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -35,6 +35,7 @@ from vyos.configdict import get_interface_dict from vyos.configdict import leaf_node_changed from vyos.configverify import verify_vrf from vyos.configverify import verify_bridge_delete +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import VTunIf from vyos.pki import load_dh_parameters from vyos.pki import load_private_key @@ -495,6 +496,7 @@ def verify(openvpn): raise ConfigError('Username for authentication is missing') verify_vrf(openvpn) + verify_mirror_redirect(openvpn) return None diff --git a/src/conf_mode/interfaces-pppoe.py b/src/conf_mode/interfaces-pppoe.py index 9962e0a08..bfb1fadd5 100755 --- a/src/conf_mode/interfaces-pppoe.py +++ b/src/conf_mode/interfaces-pppoe.py @@ -28,7 +28,7 @@ from vyos.configverify import verify_source_interface from vyos.configverify import verify_interface_exists from vyos.configverify import verify_vrf from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import PPPoEIf from vyos.template import render from vyos.util import call @@ -86,7 +86,7 @@ def verify(pppoe): verify_authentication(pppoe) verify_vrf(pppoe) verify_mtu_ipv6(pppoe) - verify_redirect(pppoe) + verify_mirror_redirect(pppoe) if {'connect_on_demand', 'vrf'} <= set(pppoe): raise ConfigError('On-demand dialing and VRF can not be used at the same time') diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py index f57e41cc4..f2c85554f 100755 --- a/src/conf_mode/interfaces-pseudo-ethernet.py +++ b/src/conf_mode/interfaces-pseudo-ethernet.py @@ -25,7 +25,7 @@ from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_source_interface from vyos.configverify import verify_vlan_config from vyos.configverify import verify_mtu_parent -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import MACVLANIf from vyos import ConfigError @@ -61,7 +61,7 @@ def verify(peth): verify_vrf(peth) verify_address(peth) verify_mtu_parent(peth, peth['parent']) - verify_redirect(peth) + verify_mirror_redirect(peth) # use common function to verify VLAN configuration verify_vlan_config(peth) diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py index 005fae5eb..f4668d976 100755 --- a/src/conf_mode/interfaces-tunnel.py +++ b/src/conf_mode/interfaces-tunnel.py @@ -26,7 +26,7 @@ from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_interface_exists from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_vrf from vyos.configverify import verify_tunnel from vyos.ifconfig import Interface @@ -158,7 +158,7 @@ def verify(tunnel): verify_mtu_ipv6(tunnel) verify_address(tunnel) verify_vrf(tunnel) - verify_redirect(tunnel) + verify_mirror_redirect(tunnel) if 'source_interface' in tunnel: verify_interface_exists(tunnel['source_interface']) diff --git a/src/conf_mode/interfaces-vti.py b/src/conf_mode/interfaces-vti.py index 30e13536f..f06fdff1b 100755 --- a/src/conf_mode/interfaces-vti.py +++ b/src/conf_mode/interfaces-vti.py @@ -19,7 +19,7 @@ from sys import exit from vyos.config import Config from vyos.configdict import get_interface_dict -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import VTIIf from vyos.util import dict_search from vyos import ConfigError @@ -40,7 +40,7 @@ def get_config(config=None): return vti def verify(vti): - verify_redirect(vti) + verify_mirror_redirect(vti) return None def generate(vti): diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py index a29836efd..0a9b51cac 100755 --- a/src/conf_mode/interfaces-vxlan.py +++ b/src/conf_mode/interfaces-vxlan.py @@ -25,7 +25,7 @@ from vyos.configdict import leaf_node_changed from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_source_interface from vyos.ifconfig import Interface from vyos.ifconfig import VXLANIf @@ -141,7 +141,7 @@ def verify(vxlan): verify_mtu_ipv6(vxlan) verify_address(vxlan) - verify_redirect(vxlan) + verify_mirror_redirect(vxlan) return None def generate(vxlan): diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py index dc0fe7b9c..b404375d6 100755 --- a/src/conf_mode/interfaces-wireguard.py +++ b/src/conf_mode/interfaces-wireguard.py @@ -28,7 +28,7 @@ from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import WireGuardIf from vyos.util import check_kmod from vyos.util import check_port_availability @@ -71,7 +71,7 @@ def verify(wireguard): verify_mtu_ipv6(wireguard) verify_address(wireguard) verify_vrf(wireguard) - verify_redirect(wireguard) + verify_mirror_redirect(wireguard) if 'private_key' not in wireguard: raise ConfigError('Wireguard private-key not defined') diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py index fdf9e3988..500952df1 100755 --- a/src/conf_mode/interfaces-wireless.py +++ b/src/conf_mode/interfaces-wireless.py @@ -27,7 +27,7 @@ from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_dhcpv6 from vyos.configverify import verify_source_interface -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf from vyos.ifconfig import WiFiIf @@ -190,7 +190,7 @@ def verify(wifi): verify_address(wifi) verify_vrf(wifi) - verify_redirect(wifi) + verify_mirror_redirect(wifi) # use common function to verify VLAN configuration verify_vlan_config(wifi) diff --git a/src/conf_mode/interfaces-wwan.py b/src/conf_mode/interfaces-wwan.py index 367a50e82..9a33039a3 100755 --- a/src/conf_mode/interfaces-wwan.py +++ b/src/conf_mode/interfaces-wwan.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-2022 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 @@ -21,9 +21,10 @@ from time import sleep from vyos.config import Config from vyos.configdict import get_interface_dict +from vyos.configdict import leaf_node_changed from vyos.configverify import verify_authentication from vyos.configverify import verify_interface_exists -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_vrf from vyos.ifconfig import WWANIf from vyos.util import cmd @@ -37,7 +38,7 @@ from vyos import airbag airbag.enable() service_name = 'ModemManager.service' -cron_script = '/etc/cron.d/wwan' +cron_script = '/etc/cron.d/vyos-wwan' def get_config(config=None): """ @@ -51,6 +52,32 @@ def get_config(config=None): base = ['interfaces', 'wwan'] wwan = get_interface_dict(conf, base) + # We should only terminate the WWAN session if critical parameters change. + # All parameters that can be changed on-the-fly (like interface description) + # should not lead to a reconnect! + tmp = leaf_node_changed(conf, ['address']) + if tmp: wwan.update({'shutdown_required': {}}) + + tmp = leaf_node_changed(conf, ['apn']) + if tmp: wwan.update({'shutdown_required': {}}) + + tmp = leaf_node_changed(conf, ['disable']) + if tmp: wwan.update({'shutdown_required': {}}) + + tmp = leaf_node_changed(conf, ['vrf']) + # leaf_node_changed() returns a list, as VRF is a non-multi node, there + # will be only one list element + if tmp: wwan.update({'vrf_old': tmp[0]}) + + tmp = leaf_node_changed(conf, ['authentication', 'user']) + if tmp: wwan.update({'shutdown_required': {}}) + + tmp = leaf_node_changed(conf, ['authentication', 'password']) + if tmp: wwan.update({'shutdown_required': {}}) + + tmp = leaf_node_changed(conf, ['ipv6', 'address', 'autoconf']) + if tmp: wwan.update({'shutdown_required': {}}) + # We need to know the amount of other WWAN interfaces as ModemManager needs # to be started or stopped. conf.set_level(base) @@ -58,8 +85,8 @@ def get_config(config=None): get_first_key=True, no_tag_node_value_mangle=True) - # This if-clause is just to be sure - it will always evaluate to true ifname = wwan['ifname'] + # This if-clause is just to be sure - it will always evaluate to true if ifname in wwan['other_interfaces']: del wwan['other_interfaces'][ifname] if len(wwan['other_interfaces']) == 0: @@ -78,19 +105,31 @@ def verify(wwan): verify_interface_exists(ifname) verify_authentication(wwan) verify_vrf(wwan) - verify_redirect(wwan) + verify_mirror_redirect(wwan) return None def generate(wwan): if 'deleted' in wwan: + # We are the last WWAN interface - there are no other ones remaining + # thus the cronjob needs to go away, too + if 'other_interfaces' not in wwan: + if os.path.exists(cron_script): + os.unlink(cron_script) return None + # Install cron triggered helper script to re-dial WWAN interfaces on + # disconnect - e.g. happens during RF signal loss. The script watches every + # WWAN interface - so there is only one instance. if not os.path.exists(cron_script): write_file(cron_script, '*/5 * * * * root /usr/libexec/vyos/vyos-check-wwan.py') + return None def apply(wwan): + # ModemManager is required to dial WWAN connections - one instance is + # required to serve all modems. Activate ModemManager on first invocation + # of any WWAN interface. if not is_systemd_service_active(service_name): cmd(f'systemctl start {service_name}') @@ -103,17 +142,19 @@ def apply(wwan): break sleep(0.250) - # we only need the modem number. wwan0 -> 0, wwan1 -> 1 - modem = wwan['ifname'].lstrip('wwan') - base_cmd = f'mmcli --modem {modem}' - # Number of bearers is limited - always disconnect first - cmd(f'{base_cmd} --simple-disconnect') + if 'shutdown_required' in wwan: + # we only need the modem number. wwan0 -> 0, wwan1 -> 1 + modem = wwan['ifname'].lstrip('wwan') + base_cmd = f'mmcli --modem {modem}' + # Number of bearers is limited - always disconnect first + cmd(f'{base_cmd} --simple-disconnect') w = WWANIf(wwan['ifname']) if 'deleted' in wwan or 'disable' in wwan: w.remove() - # There are no other WWAN interfaces - stop the daemon + # We are the last WWAN interface - there are no other WWAN interfaces + # remaining, thus we can stop ModemManager and free resources. if 'other_interfaces' not in wwan: cmd(f'systemctl stop {service_name}') # Clean CRON helper script which is used for to re-connect when @@ -123,27 +164,25 @@ def apply(wwan): return None - ip_type = 'ipv4' - slaac = dict_search('ipv6.address.autoconf', wwan) != None - if 'address' in wwan: - if 'dhcp' in wwan['address'] and ('dhcpv6' in wwan['address'] or slaac): - ip_type = 'ipv4v6' - elif 'dhcpv6' in wwan['address'] or slaac: - ip_type = 'ipv6' - elif 'dhcp' in wwan['address']: - ip_type = 'ipv4' - - options = f'ip-type={ip_type},apn=' + wwan['apn'] - if 'authentication' in wwan: - options += ',user={user},password={password}'.format(**wwan['authentication']) - - command = f'{base_cmd} --simple-connect="{options}"' - call(command, stdout=DEVNULL) - w.update(wwan) + if 'shutdown_required' in wwan: + ip_type = 'ipv4' + slaac = dict_search('ipv6.address.autoconf', wwan) != None + if 'address' in wwan: + if 'dhcp' in wwan['address'] and ('dhcpv6' in wwan['address'] or slaac): + ip_type = 'ipv4v6' + elif 'dhcpv6' in wwan['address'] or slaac: + ip_type = 'ipv6' + elif 'dhcp' in wwan['address']: + ip_type = 'ipv4' - if 'other_interfaces' not in wwan and 'deleted' in wwan: - cmd(f'systemctl start {service_name}') + options = f'ip-type={ip_type},apn=' + wwan['apn'] + if 'authentication' in wwan: + options += ',user={user},password={password}'.format(**wwan['authentication']) + command = f'{base_cmd} --simple-connect="{options}"' + call(command, stdout=DEVNULL) + + w.update(wwan) return None if __name__ == '__main__': diff --git a/src/conf_mode/policy.py b/src/conf_mode/policy.py index 6b1d3bf1a..9d8fcfa36 100755 --- a/src/conf_mode/policy.py +++ b/src/conf_mode/policy.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-2022 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 @@ -114,10 +114,9 @@ def verify(policy): if 'prefix' not in rule_config: raise ConfigError(f'A prefix {mandatory_error}') - # Check prefix duplicates - if rule_config['prefix'] in entries and ('ge' not in rule_config and 'le' not in rule_config): - raise ConfigError(f'Prefix {rule_config["prefix"]} is duplicated!') - entries.append(rule_config['prefix']) + if rule_config in entries: + raise ConfigError(f'Rule "{rule}" contains a duplicate prefix definition!') + entries.append(rule_config) # route-maps tend to be a bit more complex so they get their own verify() section diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py index 64b113873..dace53d37 100755 --- a/src/conf_mode/protocols_bgp.py +++ b/src/conf_mode/protocols_bgp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-2022 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 @@ -213,6 +213,11 @@ def verify(bgp): if 'non_exist_map' in afi_config['conditionally_advertise']: verify_route_map(afi_config['conditionally_advertise']['non_exist_map'], bgp) + # T4332: bgp deterministic-med cannot be disabled while addpath-tx-bestpath-per-AS is in use + if 'addpath_tx_per_as' in afi_config: + if dict_search('parameters.deterministic_med', bgp) == None: + raise ConfigError('addpath-tx-per-as requires BGP deterministic-med paramtere to be set!') + # Validate if configured Prefix list exists if 'prefix_list' in afi_config: for tmp in ['import', 'export']: diff --git a/src/conf_mode/protocols_isis.py b/src/conf_mode/protocols_isis.py index 9b4b215de..f2501e38a 100755 --- a/src/conf_mode/protocols_isis.py +++ b/src/conf_mode/protocols_isis.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-2022 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 @@ -169,28 +169,40 @@ def verify(isis): # Segment routing checks if dict_search('segment_routing.global_block', isis): - high_label_value = dict_search('segment_routing.global_block.high_label_value', isis) - low_label_value = dict_search('segment_routing.global_block.low_label_value', isis) + g_high_label_value = dict_search('segment_routing.global_block.high_label_value', isis) + g_low_label_value = dict_search('segment_routing.global_block.low_label_value', isis) - # If segment routing global block high value is blank, throw error - if (low_label_value and not high_label_value) or (high_label_value and not low_label_value): - raise ConfigError('Segment routing global block requires both low and high value!') + # If segment routing global block high or low value is blank, throw error + if not (g_low_label_value or g_high_label_value): + raise ConfigError('Segment routing global-block requires both low and high value!') # If segment routing global block low value is higher than the high value, throw error - if int(low_label_value) > int(high_label_value): - raise ConfigError('Segment routing global block low value must be lower than high value') + if int(g_low_label_value) > int(g_high_label_value): + raise ConfigError('Segment routing global-block low value must be lower than high value') if dict_search('segment_routing.local_block', isis): - high_label_value = dict_search('segment_routing.local_block.high_label_value', isis) - low_label_value = dict_search('segment_routing.local_block.low_label_value', isis) + if dict_search('segment_routing.global_block', isis) == None: + raise ConfigError('Segment routing local-block requires global-block to be configured!') - # If segment routing local block high value is blank, throw error - if (low_label_value and not high_label_value) or (high_label_value and not low_label_value): - raise ConfigError('Segment routing local block requires both high and low value!') + l_high_label_value = dict_search('segment_routing.local_block.high_label_value', isis) + l_low_label_value = dict_search('segment_routing.local_block.low_label_value', isis) - # If segment routing local block low value is higher than the high value, throw error - if int(low_label_value) > int(high_label_value): - raise ConfigError('Segment routing local block low value must be lower than high value') + # If segment routing local-block high or low value is blank, throw error + if not (l_low_label_value or l_high_label_value): + raise ConfigError('Segment routing local-block requires both high and low value!') + + # If segment routing local-block low value is higher than the high value, throw error + if int(l_low_label_value) > int(l_high_label_value): + raise ConfigError('Segment routing local-block low value must be lower than high value') + + # local-block most live outside global block + global_range = range(int(g_low_label_value), int(g_high_label_value) +1) + local_range = range(int(l_low_label_value), int(l_high_label_value) +1) + + # Check for overlapping ranges + if list(set(global_range) & set(local_range)): + raise ConfigError(f'Segment-Routing Global Block ({g_low_label_value}/{g_high_label_value}) '\ + f'conflicts with Local Block ({l_low_label_value}/{l_high_label_value})!') return None diff --git a/src/conf_mode/qos.py b/src/conf_mode/qos.py index cf447d4b5..dbe3be225 100755 --- a/src/conf_mode/qos.py +++ b/src/conf_mode/qos.py @@ -28,36 +28,33 @@ def get_config(config=None): conf = config else: conf = Config() - base = ['traffic-policy'] + base = ['qos'] if not conf.exists(base): return None qos = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) - for traffic_policy in ['drop-tail', 'fair-queue', 'fq-codel', 'limiter', - 'network-emulator', 'priority-queue', 'random-detect', - 'rate-control', 'round-robin', 'shaper', 'shaper-hfsc']: - traffic_policy_us = traffic_policy.replace('-','_') - # Individual policy type not present on CLI - no need to blend in - # any default values - if traffic_policy_us not in qos: - continue - - default_values = defaults(base + [traffic_policy_us]) - - # class is another tag node which requires individual handling - class_default_values = defaults(base + [traffic_policy_us, 'class']) - if 'class' in default_values: - del default_values['class'] - - for policy, policy_config in qos[traffic_policy_us].items(): - qos[traffic_policy_us][policy] = dict_merge( - default_values, qos[traffic_policy_us][policy]) - - if 'class' in policy_config: - for policy_class in policy_config['class']: - qos[traffic_policy_us][policy]['class'][policy_class] = dict_merge( - class_default_values, qos[traffic_policy_us][policy]['class'][policy_class]) + if 'policy' in qos: + for policy in qos['policy']: + # CLI mangles - to _ for better Jinja2 compatibility - do we need + # Jinja2 here? + policy = policy.replace('-','_') + + default_values = defaults(base + ['policy', policy]) + + # class is another tag node which requires individual handling + class_default_values = defaults(base + ['policy', policy, 'class']) + if 'class' in default_values: + del default_values['class'] + + for p_name, p_config in qos['policy'][policy].items(): + qos['policy'][policy][p_name] = dict_merge( + default_values, qos['policy'][policy][p_name]) + + if 'class' in p_config: + for p_class in p_config['class']: + qos['policy'][policy][p_name]['class'][p_class] = dict_merge( + class_default_values, qos['policy'][policy][p_name]['class'][p_class]) import pprint pprint.pprint(qos) diff --git a/src/conf_mode/service_ipoe-server.py b/src/conf_mode/service_ipoe-server.py index f676fdbbe..2ebee8018 100755 --- a/src/conf_mode/service_ipoe-server.py +++ b/src/conf_mode/service_ipoe-server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2020 VyOS maintainers and contributors +# Copyright (C) 2018-2022 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 @@ -41,6 +41,7 @@ default_config_data = { 'interfaces': [], 'dnsv4': [], 'dnsv6': [], + 'client_named_ip_pool': [], 'client_ipv6_pool': [], 'client_ipv6_delegate_prefix': [], 'radius_server': [], @@ -219,6 +220,22 @@ def get_config(config=None): conf.set_level(base_path) + # Named client-ip-pool + if conf.exists(['client-ip-pool', 'name']): + for name in conf.list_nodes(['client-ip-pool', 'name']): + tmp = { + 'name': name, + 'gateway_address': '', + 'subnet': '' + } + + if conf.exists(['client-ip-pool', 'name', name, 'gateway-address']): + tmp['gateway_address'] += conf.return_value(['client-ip-pool', 'name', name, 'gateway-address']) + if conf.exists(['client-ip-pool', 'name', name, 'subnet']): + tmp['subnet'] += conf.return_value(['client-ip-pool', 'name', name, 'subnet']) + + ipoe['client_named_ip_pool'].append(tmp) + if conf.exists(['client-ipv6-pool', 'prefix']): for prefix in conf.list_nodes(['client-ipv6-pool', 'prefix']): tmp = { @@ -254,10 +271,6 @@ def verify(ipoe): if not ipoe['interfaces']: raise ConfigError('No IPoE interface configured') - for interface in ipoe['interfaces']: - if not interface['range']: - raise ConfigError(f'No IPoE client subnet defined on interface "{ interface }"') - if len(ipoe['dnsv4']) > 2: raise ConfigError('Not more then two IPv4 DNS name-servers can be configured') diff --git a/src/conf_mode/system-ipv6.py b/src/conf_mode/system-ipv6.py index 7fb2dd1cf..26aacf46b 100755 --- a/src/conf_mode/system-ipv6.py +++ b/src/conf_mode/system-ipv6.py @@ -19,8 +19,6 @@ import os from sys import exit from vyos.config import Config from vyos.configdict import dict_merge -from vyos.configdict import leaf_node_changed -from vyos.util import call from vyos.util import dict_search from vyos.util import sysctl_write from vyos.util import write_file @@ -38,9 +36,6 @@ def get_config(config=None): opt = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) - tmp = leaf_node_changed(conf, base + ['disable']) - if tmp: opt['reboot_required'] = {} - # We have gathered the dict representation of the CLI, but there are default # options which we need to update into the dictionary retrived. default_values = defaults(base) @@ -55,15 +50,6 @@ def generate(opt): pass def apply(opt): - # disable IPv6 globally - tmp = dict_search('disable', opt) - value = '1' if (tmp != None) else '0' - sysctl_write('net.ipv6.conf.all.disable_ipv6', value) - - if 'reboot_required' in opt: - print('Changing IPv6 disable parameter will only take affect\n' \ - 'when the system is rebooted.') - # configure multipath tmp = dict_search('multipath.layer4_hashing', opt) value = '1' if (tmp != None) else '0' diff --git a/src/conf_mode/system-login.py b/src/conf_mode/system-login.py index 4dd7f936d..c9c6aa187 100755 --- a/src/conf_mode/system-login.py +++ b/src/conf_mode/system-login.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-2022 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 @@ -23,6 +23,7 @@ from pwd import getpwall from pwd import getpwnam from spwd import getspnam from sys import exit +from time import sleep from vyos.config import Config from vyos.configdict import dict_merge @@ -31,6 +32,7 @@ from vyos.template import render from vyos.template import is_ipv4 from vyos.util import cmd from vyos.util import call +from vyos.util import run from vyos.util import DEVNULL from vyos.util import dict_search from vyos.xml import defaults @@ -250,13 +252,22 @@ def apply(login): if 'rm_users' in login: for user in login['rm_users']: try: + # Disable user to prevent re-login + call(f'usermod -s /sbin/nologin {user}') + # Logout user if he is still logged in if user in list(set([tmp[0] for tmp in users()])): print(f'{user} is logged in, forcing logout!') - call(f'pkill -HUP -u {user}') - - # Remove user account but leave home directory to be safe - call(f'userdel --remove {user}', stderr=DEVNULL) + # re-run command until user is logged out + while run(f'pkill -HUP -u {user}'): + sleep(0.250) + + # Remove user account but leave home directory in place. Re-run + # command until user is removed - userdel might return 8 as + # SSH sessions are not all yet properly cleaned away, thus we + # simply re-run the command until the account wen't away + while run(f'userdel --remove {user}', stderr=DEVNULL): + sleep(0.250) except Exception as e: raise ConfigError(f'Deleting user "{user}" raised exception: {e}') diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py index c3e2d8efd..f79c8a21e 100755 --- a/src/conf_mode/vrf.py +++ b/src/conf_mode/vrf.py @@ -30,7 +30,6 @@ from vyos.util import get_interface_config from vyos.util import popen from vyos.util import run from vyos.util import sysctl_write -from vyos.util import is_ipv6_enabled from vyos import ConfigError from vyos import frr from vyos import airbag @@ -219,8 +218,7 @@ def apply(vrf): # We also should add proper loopback IP addresses to the newly added # VRF for services bound to the loopback address (SNMP, NTP) vrf_if.add_addr('127.0.0.1/8') - if is_ipv6_enabled(): - vrf_if.add_addr('::1/128') + vrf_if.add_addr('::1/128') # add VRF description if available vrf_if.set_alias(config.get('description', '')) diff --git a/src/etc/cron.d/check-wwan b/src/etc/cron.d/check-wwan deleted file mode 100644 index 28190776f..000000000 --- a/src/etc/cron.d/check-wwan +++ /dev/null @@ -1 +0,0 @@ -*/5 * * * * root /usr/libexec/vyos/vyos-check-wwan.py diff --git a/src/migration-scripts/system/22-to-23 b/src/migration-scripts/system/22-to-23 new file mode 100755 index 000000000..7f832e48a --- /dev/null +++ b/src/migration-scripts/system/22-to-23 @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2022 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 +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os + +from sys import exit, argv +from vyos.configtree import ConfigTree + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] +with open(file_name, 'r') as f: + config_file = f.read() + +base = ['system', 'ipv6'] +config = ConfigTree(config_file) + +if not config.exists(base): + # Nothing to do + exit(0) + +# T4346: drop support to disbale IPv6 address family within the OS Kernel +if config.exists(base + ['disable']): + config.delete(base + ['disable']) + # IPv6 address family disable was the only CLI option set - we can cleanup + # the entire tree + if len(config.list_nodes(base)) == 0: + config.delete(base) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/services/vyos-http-api-server b/src/services/vyos-http-api-server index 1000d8b72..c1b595412 100755 --- a/src/services/vyos-http-api-server +++ b/src/services/vyos-http-api-server @@ -352,7 +352,7 @@ class MultipartRoute(APIRoute): return error(e.status_code, e.detail) except Exception as e: if request.ERR_MISSING_KEY: - return error(422, "Valid API key is required") + return error(401, "Valid API key is required") if request.ERR_MISSING_DATA: return error(422, "Non-empty data field is required") if request.ERR_NOT_JSON: diff --git a/src/tests/test_util.py b/src/tests/test_util.py index 91890262c..8ac9a500a 100644 --- a/src/tests/test_util.py +++ b/src/tests/test_util.py @@ -26,13 +26,3 @@ class TestVyOSUtil(TestCase): def test_sysctl_read(self): self.assertEqual(sysctl_read('net.ipv4.conf.lo.forwarding'), '1') - - def test_ipv6_enabled(self): - tmp = sysctl_read('net.ipv6.conf.all.disable_ipv6') - # We need to test for both variants as this depends on how the - # Docker container is started (with or without IPv6 support) - so we - # will simply check both cases to not make the users life miserable. - if tmp == '0': - self.assertTrue(is_ipv6_enabled()) - else: - self.assertFalse(is_ipv6_enabled()) |