Page MenuHomeVyOS Platform

No OneTemporary

Size
215 KB
Referenced Files
None
Subscribers
None
diff --git a/data/templates/firewall/nftables-policy.j2 b/data/templates/firewall/nftables-policy.j2
index 40118930b..6cb3b2f95 100644
--- a/data/templates/firewall/nftables-policy.j2
+++ b/data/templates/firewall/nftables-policy.j2
@@ -1,56 +1,65 @@
#!/usr/sbin/nft -f
{% import 'firewall/nftables-defines.j2' as group_tmpl %}
-{% if cleanup_commands is vyos_defined %}
-{% for command in cleanup_commands %}
-{{ command }}
-{% endfor %}
+{% if first_install is not vyos_defined %}
+delete table ip vyos_mangle
+delete table ip6 vyos_mangle
{% endif %}
-
-table ip mangle {
-{% if first_install is vyos_defined %}
+table ip vyos_mangle {
chain VYOS_PBR_PREROUTING {
type filter hook prerouting priority -150; policy accept;
+{% if route is vyos_defined %}
+{% for route_text, conf in route.items() if conf.interface is vyos_defined %}
+ iifname { {{ ",".join(conf.interface) }} } counter jump VYOS_PBR_{{ route_text }}
+{% endfor %}
+{% endif %}
}
+
chain VYOS_PBR_POSTROUTING {
type filter hook postrouting priority -150; policy accept;
}
-{% endif %}
+
{% if route is vyos_defined %}
{% for route_text, conf in route.items() %}
chain VYOS_PBR_{{ route_text }} {
{% if conf.rule is vyos_defined %}
{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
{{ rule_conf | nft_rule(route_text, rule_id, 'ip') }}
{% endfor %}
{% endif %}
}
{% endfor %}
{% endif %}
{{ group_tmpl.groups(firewall_group, False) }}
}
-table ip6 mangle {
-{% if first_install is vyos_defined %}
+table ip6 vyos_mangle {
chain VYOS_PBR6_PREROUTING {
type filter hook prerouting priority -150; policy accept;
+{% if route6 is vyos_defined %}
+{% for route_text, conf in route6.items() if conf.interface is vyos_defined %}
+ iifname { {{ ",".join(conf.interface) }} } counter jump VYOS_PBR6_{{ route_text }}
+{% endfor %}
+{% endif %}
}
+
chain VYOS_PBR6_POSTROUTING {
type filter hook postrouting priority -150; policy accept;
}
-{% endif %}
+
{% if route6 is vyos_defined %}
{% for route_text, conf in route6.items() %}
chain VYOS_PBR6_{{ route_text }} {
{% if conf.rule is vyos_defined %}
{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
{{ rule_conf | nft_rule(route_text, rule_id, 'ip6') }}
{% endfor %}
{% endif %}
}
{% endfor %}
{% endif %}
+
{{ group_tmpl.groups(firewall_group, True) }}
}
diff --git a/interface-definitions/include/interface/interface-policy-vif-c.xml.i b/interface-definitions/include/interface/interface-policy-vif-c.xml.i
deleted file mode 100644
index 866fcd5c0..000000000
--- a/interface-definitions/include/interface/interface-policy-vif-c.xml.i
+++ /dev/null
@@ -1,26 +0,0 @@
-<!-- include start from interface/interface-policy-vif-c.xml.i -->
-<node name="policy" owner="${vyos_conf_scripts_dir}/policy-route-interface.py $VAR(../../../@).$VAR(../../@).$VAR(../@)">
- <properties>
- <priority>620</priority>
- <help>Policy route options</help>
- </properties>
- <children>
- <leafNode name="route">
- <properties>
- <help>IPv4 policy route ruleset for interface</help>
- <completionHelp>
- <path>policy route</path>
- </completionHelp>
- </properties>
- </leafNode>
- <leafNode name="route6">
- <properties>
- <help>IPv6 policy route ruleset for interface</help>
- <completionHelp>
- <path>policy route6</path>
- </completionHelp>
- </properties>
- </leafNode>
- </children>
-</node>
-<!-- include end -->
diff --git a/interface-definitions/include/interface/interface-policy-vif.xml.i b/interface-definitions/include/interface/interface-policy-vif.xml.i
deleted file mode 100644
index 83510fe59..000000000
--- a/interface-definitions/include/interface/interface-policy-vif.xml.i
+++ /dev/null
@@ -1,26 +0,0 @@
-<!-- include start from interface/interface-policy-vif.xml.i -->
-<node name="policy" owner="${vyos_conf_scripts_dir}/policy-route-interface.py $VAR(../../@).$VAR(../@)">
- <properties>
- <priority>620</priority>
- <help>Policy route options</help>
- </properties>
- <children>
- <leafNode name="route">
- <properties>
- <help>IPv4 policy route ruleset for interface</help>
- <completionHelp>
- <path>policy route</path>
- </completionHelp>
- </properties>
- </leafNode>
- <leafNode name="route6">
- <properties>
- <help>IPv6 policy route ruleset for interface</help>
- <completionHelp>
- <path>policy route6</path>
- </completionHelp>
- </properties>
- </leafNode>
- </children>
-</node>
-<!-- include end -->
diff --git a/interface-definitions/include/interface/interface-policy.xml.i b/interface-definitions/include/interface/interface-policy.xml.i
deleted file mode 100644
index 42a8fd009..000000000
--- a/interface-definitions/include/interface/interface-policy.xml.i
+++ /dev/null
@@ -1,26 +0,0 @@
-<!-- include start from interface/interface-policy.xml.i -->
-<node name="policy" owner="${vyos_conf_scripts_dir}/policy-route-interface.py $VAR(../@)">
- <properties>
- <priority>620</priority>
- <help>Policy route options</help>
- </properties>
- <children>
- <leafNode name="route">
- <properties>
- <help>IPv4 policy route ruleset for interface</help>
- <completionHelp>
- <path>policy route</path>
- </completionHelp>
- </properties>
- </leafNode>
- <leafNode name="route6">
- <properties>
- <help>IPv6 policy route ruleset for interface</help>
- <completionHelp>
- <path>policy route6</path>
- </completionHelp>
- </properties>
- </leafNode>
- </children>
-</node>
-<!-- include end -->
diff --git a/interface-definitions/include/interface/vif-s.xml.i b/interface-definitions/include/interface/vif-s.xml.i
index 916349ade..6d50d7238 100644
--- a/interface-definitions/include/interface/vif-s.xml.i
+++ b/interface-definitions/include/interface/vif-s.xml.i
@@ -1,77 +1,75 @@
<!-- include start from interface/vif-s.xml.i -->
<tagNode name="vif-s">
<properties>
<help>QinQ TAG-S Virtual Local Area Network (VLAN) ID</help>
<valueHelp>
<format>u32:0-4094</format>
<description>QinQ Virtual Local Area Network (VLAN) ID</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4094"/>
</constraint>
<constraintErrorMessage>VLAN ID must be between 0 and 4094</constraintErrorMessage>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
#include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
#include <include/interface/disable-link-detect.xml.i>
#include <include/interface/disable.xml.i>
- #include <include/interface/interface-policy-vif.xml.i>
<leafNode name="protocol">
<properties>
<help>Protocol used for service VLAN (default: 802.1ad)</help>
<completionHelp>
<list>802.1ad 802.1q</list>
</completionHelp>
<valueHelp>
<format>802.1ad</format>
<description>Provider Bridging (IEEE 802.1ad, Q-inQ), ethertype 0x88a8</description>
</valueHelp>
<valueHelp>
<format>802.1q</format>
<description>VLAN-tagged frame (IEEE 802.1q), ethertype 0x8100</description>
</valueHelp>
<constraint>
<regex>(802.1q|802.1ad)</regex>
</constraint>
<constraintErrorMessage>Ethertype must be 802.1ad or 802.1q</constraintErrorMessage>
</properties>
<defaultValue>802.1ad</defaultValue>
</leafNode>
#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>
<help>QinQ TAG-C Virtual Local Area Network (VLAN) ID</help>
<constraint>
<validator name="numeric" argument="--range 0-4094"/>
</constraint>
<constraintErrorMessage>VLAN ID must be between 0 and 4094</constraintErrorMessage>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
#include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
#include <include/interface/disable-link-detect.xml.i>
#include <include/interface/disable.xml.i>
#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/vrf.xml.i>
- #include <include/interface/interface-policy-vif-c.xml.i>
</children>
</tagNode>
#include <include/interface/redirect.xml.i>
#include <include/interface/vrf.xml.i>
</children>
</tagNode>
<!-- include end -->
diff --git a/interface-definitions/include/interface/vif.xml.i b/interface-definitions/include/interface/vif.xml.i
index 73a8c98ff..3f8f113ea 100644
--- a/interface-definitions/include/interface/vif.xml.i
+++ b/interface-definitions/include/interface/vif.xml.i
@@ -1,57 +1,56 @@
<!-- include start from interface/vif.xml.i -->
<tagNode name="vif">
<properties>
<help>Virtual Local Area Network (VLAN) ID</help>
<valueHelp>
<format>u32:0-4094</format>
<description>Virtual Local Area Network (VLAN) ID</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4094"/>
</constraint>
<constraintErrorMessage>VLAN ID must be between 0 and 4094</constraintErrorMessage>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
#include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
#include <include/interface/disable-link-detect.xml.i>
#include <include/interface/disable.xml.i>
- #include <include/interface/interface-policy-vif.xml.i>
<leafNode name="egress-qos">
<properties>
<help>VLAN egress QoS</help>
<valueHelp>
<format>txt</format>
<description>Format for qos mapping, e.g.: '0:1 1:6 7:6'</description>
</valueHelp>
<constraint>
<regex>[:0-7 ]+</regex>
</constraint>
<constraintErrorMessage>QoS mapping should be in the format of '0:7 2:3' with numbers 0-9</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="ingress-qos">
<properties>
<help>VLAN ingress QoS</help>
<valueHelp>
<format>txt</format>
<description>Format for qos mapping, e.g.: '0:1 1:6 7:6'</description>
</valueHelp>
<constraint>
<regex>[:0-7 ]+</regex>
</constraint>
<constraintErrorMessage>QoS mapping should be in the format of '0:7 2:3' with numbers 0-9</constraintErrorMessage>
</properties>
</leafNode>
#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/vrf.xml.i>
</children>
</tagNode>
<!-- include end -->
diff --git a/interface-definitions/include/version/policy-version.xml.i b/interface-definitions/include/version/policy-version.xml.i
index 89bde20c7..f1494eaa3 100644
--- a/interface-definitions/include/version/policy-version.xml.i
+++ b/interface-definitions/include/version/policy-version.xml.i
@@ -1,3 +1,3 @@
<!-- include start from include/version/policy-version.xml.i -->
-<syntaxVersion component='policy' version='4'></syntaxVersion>
+<syntaxVersion component='policy' version='5'></syntaxVersion>
<!-- include end -->
diff --git a/interface-definitions/interfaces-bonding.xml.in b/interface-definitions/interfaces-bonding.xml.in
index 41e4a68a8..96e0e5d89 100644
--- a/interface-definitions/interfaces-bonding.xml.in
+++ b/interface-definitions/interfaces-bonding.xml.in
@@ -1,234 +1,233 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="bonding" owner="${vyos_conf_scripts_dir}/interfaces-bonding.py">
<properties>
<help>Bonding Interface/Link Aggregation</help>
<priority>320</priority>
<constraint>
<regex>bond[0-9]+</regex>
</constraint>
<constraintErrorMessage>Bonding interface must be named bondN</constraintErrorMessage>
<valueHelp>
<format>bondN</format>
<description>Bonding interface name</description>
</valueHelp>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
<node name="arp-monitor">
<properties>
<help>ARP link monitoring parameters</help>
</properties>
<children>
<leafNode name="interval">
<properties>
<help>ARP link monitoring interval</help>
<valueHelp>
<format>u32</format>
<description>Specifies the ARP link monitoring frequency in milliseconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4294967295"/>
</constraint>
</properties>
</leafNode>
<leafNode name="target">
<properties>
<help>IP address used for ARP monitoring</help>
<valueHelp>
<format>ipv4</format>
<description>Specify IPv4 address of ARP requests when interval is enabled</description>
</valueHelp>
<constraint>
<validator name="ipv4-address"/>
</constraint>
<multi/>
</properties>
</leafNode>
</children>
</node>
#include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
#include <include/interface/disable-link-detect.xml.i>
#include <include/interface/disable.xml.i>
#include <include/interface/vrf.xml.i>
#include <include/interface/mirror.xml.i>
- #include <include/interface/interface-policy.xml.i>
<leafNode name="hash-policy">
<properties>
<help>Bonding transmit hash policy</help>
<completionHelp>
<list>layer2 layer2+3 layer3+4 encap2+3 encap3+4</list>
</completionHelp>
<valueHelp>
<format>layer2</format>
<description>use MAC addresses to generate the hash</description>
</valueHelp>
<valueHelp>
<format>layer2+3</format>
<description>combine MAC address and IP address to make hash</description>
</valueHelp>
<valueHelp>
<format>layer3+4</format>
<description>combine IP address and port to make hash</description>
</valueHelp>
<valueHelp>
<format>encap2+3</format>
<description>combine encapsulated MAC address and IP address to make hash</description>
</valueHelp>
<valueHelp>
<format>encap3+4</format>
<description>combine encapsulated IP address and port to make hash</description>
</valueHelp>
<constraint>
<regex>(layer2\+3|layer3\+4|layer2|encap2\+3|encap3\+4)</regex>
</constraint>
<constraintErrorMessage>hash-policy must be layer2 layer2+3 layer3+4 encap2+3 or encap3+4</constraintErrorMessage>
</properties>
<defaultValue>layer2</defaultValue>
</leafNode>
#include <include/interface/ipv4-options.xml.i>
#include <include/interface/ipv6-options.xml.i>
#include <include/interface/mac.xml.i>
<leafNode name="mii-mon-interval">
<properties>
<help>Specifies the MII link monitoring frequency in milliseconds</help>
<valueHelp>
<format>u32:0</format>
<description>Disable MII link monitoring</description>
</valueHelp>
<valueHelp>
<format>u32:50-1000</format>
<description>MII link monitoring frequency in milliseconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-0 --range 50-1000"/>
</constraint>
</properties>
<defaultValue>100</defaultValue>
</leafNode>
<leafNode name="min-links">
<properties>
<help>Minimum number of member interfaces required up before enabling bond</help>
<valueHelp>
<format>u32:0-16</format>
<description>Minimum number of member interfaces required up before enabling bond</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-16"/>
</constraint>
</properties>
<defaultValue>0</defaultValue>
</leafNode>
<leafNode name="lacp-rate">
<properties>
<help>Rate in which we will ask our link partner to transmit LACPDU packets</help>
<completionHelp>
<list>slow fast</list>
</completionHelp>
<valueHelp>
<format>slow</format>
<description>Request partner to transmit LACPDUs every 30 seconds</description>
</valueHelp>
<valueHelp>
<format>fast</format>
<description>Request partner to transmit LACPDUs every 1 second</description>
</valueHelp>
<constraint>
<regex>(slow|fast)</regex>
</constraint>
</properties>
<defaultValue>slow</defaultValue>
</leafNode>
<leafNode name="mode">
<properties>
<help>Bonding mode</help>
<completionHelp>
<list>802.3ad active-backup broadcast round-robin transmit-load-balance adaptive-load-balance xor-hash</list>
</completionHelp>
<valueHelp>
<format>802.3ad</format>
<description>IEEE 802.3ad Dynamic link aggregation</description>
</valueHelp>
<valueHelp>
<format>active-backup</format>
<description>Fault tolerant: only one slave in the bond is active</description>
</valueHelp>
<valueHelp>
<format>broadcast</format>
<description>Fault tolerant: transmits everything on all slave interfaces</description>
</valueHelp>
<valueHelp>
<format>round-robin</format>
<description>Load balance: transmit packets in sequential order</description>
</valueHelp>
<valueHelp>
<format>transmit-load-balance</format>
<description>Load balance: adapts based on transmit load and speed</description>
</valueHelp>
<valueHelp>
<format>adaptive-load-balance</format>
<description>Load balance: adapts based on transmit and receive plus ARP</description>
</valueHelp>
<valueHelp>
<format>xor-hash</format>
<description>Distribute based on MAC address</description>
</valueHelp>
<constraint>
<regex>(802.3ad|active-backup|broadcast|round-robin|transmit-load-balance|adaptive-load-balance|xor-hash)</regex>
</constraint>
<constraintErrorMessage>mode must be 802.3ad, active-backup, broadcast, round-robin, transmit-load-balance, adaptive-load-balance, or xor</constraintErrorMessage>
</properties>
<defaultValue>802.3ad</defaultValue>
</leafNode>
<node name="member">
<properties>
<help>Bridge member interfaces</help>
</properties>
<children>
<leafNode name="interface">
<properties>
<help>Member interface name</help>
<completionHelp>
<script>${vyos_completion_dir}/list_interfaces.py --bondable</script>
</completionHelp>
<valueHelp>
<format>txt</format>
<description>Interface name</description>
</valueHelp>
<constraint>
<validator name="interface-name"/>
</constraint>
<multi/>
</properties>
</leafNode>
</children>
</node>
#include <include/interface/mtu-68-16000.xml.i>
<leafNode name="primary">
<properties>
<help>Primary device interface</help>
<completionHelp>
<script>${vyos_completion_dir}/list_interfaces.py --bondable</script>
</completionHelp>
<valueHelp>
<format>txt</format>
<description>Interface name</description>
</valueHelp>
<constraint>
<validator name="interface-name"/>
</constraint>
</properties>
</leafNode>
#include <include/interface/redirect.xml.i>
#include <include/interface/vif-s.xml.i>
#include <include/interface/vif.xml.i>
#include <include/interface/xdp.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-bridge.xml.in b/interface-definitions/interfaces-bridge.xml.in
index d633077d9..d52e213b6 100644
--- a/interface-definitions/interfaces-bridge.xml.in
+++ b/interface-definitions/interfaces-bridge.xml.in
@@ -1,224 +1,223 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="bridge" owner="${vyos_conf_scripts_dir}/interfaces-bridge.py">
<properties>
<help>Bridge Interface</help>
<priority>310</priority>
<constraint>
<regex>br[0-9]+</regex>
</constraint>
<constraintErrorMessage>Bridge interface must be named brN</constraintErrorMessage>
<valueHelp>
<format>brN</format>
<description>Bridge interface name</description>
</valueHelp>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
<leafNode name="aging">
<properties>
<help>MAC address aging interval</help>
<valueHelp>
<format>u32:0</format>
<description>Disable MAC address learning (always flood)</description>
</valueHelp>
<valueHelp>
<format>u32:10-1000000</format>
<description>MAC address aging time in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-0 --range 10-1000000"/>
</constraint>
</properties>
<defaultValue>300</defaultValue>
</leafNode>
#include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
#include <include/interface/disable-link-detect.xml.i>
#include <include/interface/disable.xml.i>
#include <include/interface/vrf.xml.i>
#include <include/interface/mtu-68-16000.xml.i>
- #include <include/interface/interface-policy.xml.i>
<leafNode name="forwarding-delay">
<properties>
<help>Forwarding delay</help>
<valueHelp>
<format>u32:0-200</format>
<description>Spanning Tree Protocol forwarding delay in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-200"/>
</constraint>
<constraintErrorMessage>Forwarding delay must be between 0 and 200 seconds</constraintErrorMessage>
</properties>
<defaultValue>14</defaultValue>
</leafNode>
<leafNode name="hello-time">
<properties>
<help>Hello packet advertisement interval</help>
<valueHelp>
<format>u32:1-10</format>
<description>Spanning Tree Protocol hello advertisement interval in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-10"/>
</constraint>
<constraintErrorMessage>Bridge Hello interval must be between 1 and 10 seconds</constraintErrorMessage>
</properties>
<defaultValue>2</defaultValue>
</leafNode>
<node name="igmp">
<properties>
<help>Internet Group Management Protocol (IGMP) and Multicast Listener Discovery (MLD) settings</help>
</properties>
<children>
<leafNode name="querier">
<properties>
<help>Enable IGMP/MLD querier</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="snooping">
<properties>
<help>Enable IGMP/MLD snooping</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
#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>
<leafNode name="enable-vlan">
<properties>
<help>Enable VLAN aware bridge</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="max-age">
<properties>
<help>Interval at which neighbor bridges are removed</help>
<valueHelp>
<format>u32:1-40</format>
<description>Bridge maximum aging time in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-40"/>
</constraint>
<constraintErrorMessage>Bridge max aging value must be between 1 and 40 seconds</constraintErrorMessage>
</properties>
<defaultValue>20</defaultValue>
</leafNode>
<node name="member">
<properties>
<help>Bridge member interfaces</help>
</properties>
<children>
<tagNode name="interface">
<properties>
<help>Member interface name</help>
<completionHelp>
<script>${vyos_completion_dir}/list_interfaces.py --bridgeable</script>
</completionHelp>
</properties>
<children>
<leafNode name="native-vlan">
<properties>
<help>Specify VLAN id which should natively be present on the link</help>
<valueHelp>
<format>u32:1-4094</format>
<description>Virtual Local Area Network (VLAN) ID</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-4094"/>
</constraint>
<constraintErrorMessage>VLAN ID must be between 1 and 4094</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="allowed-vlan">
<properties>
<help>Specify VLAN id which is allowed in this trunk interface</help>
<valueHelp>
<format>&lt;id&gt;</format>
<description>VLAN id allowed to pass this interface</description>
</valueHelp>
<valueHelp>
<format>&lt;idN&gt;-&lt;idM&gt;</format>
<description>VLAN id range allowed on this interface (use '-' as delimiter)</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--allow-range --range 1-4094"/>
</constraint>
<constraintErrorMessage>not a valid VLAN ID value or range</constraintErrorMessage>
<multi/>
</properties>
</leafNode>
<leafNode name="cost">
<properties>
<help>Bridge port cost</help>
<valueHelp>
<format>u32:1-65535</format>
<description>Path cost value for Spanning Tree Protocol</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
<constraintErrorMessage>Path cost value must be between 1 and 65535</constraintErrorMessage>
</properties>
<defaultValue>100</defaultValue>
</leafNode>
<leafNode name="priority">
<properties>
<help>Bridge port priority</help>
<valueHelp>
<format>u32:0-63</format>
<description>Bridge port priority</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-63"/>
</constraint>
<constraintErrorMessage>Port priority value must be between 0 and 63</constraintErrorMessage>
</properties>
<defaultValue>32</defaultValue>
</leafNode>
<leafNode name="isolated">
<properties>
<help>Port is isolated (also known as Private-VLAN)</help>
<valueless/>
</properties>
</leafNode>
</children>
</tagNode>
</children>
</node>
<leafNode name="priority">
<properties>
<help>Priority for this bridge</help>
<valueHelp>
<format>u32:0-65535</format>
<description>Bridge priority</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-65535"/>
</constraint>
<constraintErrorMessage>Bridge priority must be between 0 and 65535 (multiples of 4096)</constraintErrorMessage>
</properties>
<defaultValue>32768</defaultValue>
</leafNode>
<leafNode name="stp">
<properties>
<help>Enable spanning tree protocol</help>
<valueless/>
</properties>
</leafNode>
#include <include/interface/redirect.xml.i>
#include <include/interface/vif.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-dummy.xml.in b/interface-definitions/interfaces-dummy.xml.in
index fb36741f7..eb525b547 100644
--- a/interface-definitions/interfaces-dummy.xml.in
+++ b/interface-definitions/interfaces-dummy.xml.in
@@ -1,39 +1,38 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="dummy" owner="${vyos_conf_scripts_dir}/interfaces-dummy.py">
<properties>
<help>Dummy Interface</help>
<priority>300</priority>
<constraint>
<regex>dum[0-9]+</regex>
</constraint>
<constraintErrorMessage>Dummy interface must be named dumN</constraintErrorMessage>
<valueHelp>
<format>dumN</format>
<description>Dummy interface name</description>
</valueHelp>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6.xml.i>
#include <include/interface/description.xml.i>
#include <include/interface/disable.xml.i>
- #include <include/interface/interface-policy.xml.i>
<node name="ip">
<properties>
<help>IPv4 routing parameters</help>
</properties>
<children>
#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/vrf.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-ethernet.xml.in b/interface-definitions/interfaces-ethernet.xml.in
index 77f130e1c..e9ae0acfe 100644
--- a/interface-definitions/interfaces-ethernet.xml.in
+++ b/interface-definitions/interfaces-ethernet.xml.in
@@ -1,213 +1,212 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<properties>
<help>Network interfaces</help>
</properties>
<children>
<tagNode name="ethernet" owner="${vyos_conf_scripts_dir}/interfaces-ethernet.py">
<properties>
<help>Ethernet Interface</help>
<priority>318</priority>
<valueHelp>
<format>ethN</format>
<description>Ethernet interface name</description>
</valueHelp>
<constraint>
<regex>((eth|lan)[0-9]+|(eno|ens|enp|enx).+)</regex>
</constraint>
<constraintErrorMessage>Invalid Ethernet interface name</constraintErrorMessage>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
#include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
<leafNode name="disable-flow-control">
<properties>
<help>Disable Ethernet flow control (pause frames)</help>
<valueless/>
</properties>
</leafNode>
#include <include/interface/disable-link-detect.xml.i>
#include <include/interface/disable.xml.i>
- #include <include/interface/interface-policy.xml.i>
<leafNode name="duplex">
<properties>
<help>Duplex mode</help>
<completionHelp>
<list>auto half full</list>
</completionHelp>
<valueHelp>
<format>auto</format>
<description>Auto negotiation</description>
</valueHelp>
<valueHelp>
<format>half</format>
<description>Half duplex</description>
</valueHelp>
<valueHelp>
<format>full</format>
<description>Full duplex</description>
</valueHelp>
<constraint>
<regex>(auto|half|full)</regex>
</constraint>
<constraintErrorMessage>duplex must be auto, half or full</constraintErrorMessage>
</properties>
<defaultValue>auto</defaultValue>
</leafNode>
#include <include/interface/eapol.xml.i>
#include <include/interface/hw-id.xml.i>
#include <include/interface/ipv4-options.xml.i>
#include <include/interface/ipv6-options.xml.i>
#include <include/interface/mac.xml.i>
#include <include/interface/mtu-68-16000.xml.i>
#include <include/interface/mirror.xml.i>
<node name="offload">
<properties>
<help>Configurable offload options</help>
</properties>
<children>
<leafNode name="gro">
<properties>
<help>Enable Generic Receive Offload</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="gso">
<properties>
<help>Enable Generic Segmentation Offload</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="lro">
<properties>
<help>Enable Large Receive Offload</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="rps">
<properties>
<help>Enable Receive Packet Steering</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="rfs">
<properties>
<help>Enable Receive Flow Steering</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="sg">
<properties>
<help>Enable Scatter-Gather</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="tso">
<properties>
<help>Enable TCP Segmentation Offloading</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
<leafNode name="speed">
<properties>
<help>Link speed</help>
<completionHelp>
<list>auto 10 100 1000 2500 5000 10000 25000 40000 50000 100000</list>
</completionHelp>
<valueHelp>
<format>auto</format>
<description>Auto negotiation</description>
</valueHelp>
<valueHelp>
<format>10</format>
<description>10 Mbit/sec</description>
</valueHelp>
<valueHelp>
<format>100</format>
<description>100 Mbit/sec</description>
</valueHelp>
<valueHelp>
<format>1000</format>
<description>1 Gbit/sec</description>
</valueHelp>
<valueHelp>
<format>2500</format>
<description>2.5 Gbit/sec</description>
</valueHelp>
<valueHelp>
<format>5000</format>
<description>5 Gbit/sec</description>
</valueHelp>
<valueHelp>
<format>10000</format>
<description>10 Gbit/sec</description>
</valueHelp>
<valueHelp>
<format>25000</format>
<description>25 Gbit/sec</description>
</valueHelp>
<valueHelp>
<format>40000</format>
<description>40 Gbit/sec</description>
</valueHelp>
<valueHelp>
<format>50000</format>
<description>50 Gbit/sec</description>
</valueHelp>
<valueHelp>
<format>100000</format>
<description>100 Gbit/sec</description>
</valueHelp>
<constraint>
<regex>(auto|10|100|1000|2500|5000|10000|25000|40000|50000|100000)</regex>
</constraint>
<constraintErrorMessage>Speed must be auto, 10, 100, 1000, 2500, 5000, 10000, 25000, 40000, 50000 or 100000</constraintErrorMessage>
</properties>
<defaultValue>auto</defaultValue>
</leafNode>
<node name="ring-buffer">
<properties>
<help>Shared buffer between the device driver and NIC</help>
</properties>
<children>
<leafNode name="rx">
<properties>
<help>RX ring buffer</help>
<valueHelp>
<format>u32:80-16384</format>
<description>ring buffer size</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 80-16384"/>
</constraint>
</properties>
</leafNode>
<leafNode name="tx">
<properties>
<help>TX ring buffer</help>
<valueHelp>
<format>u32:80-16384</format>
<description>ring buffer size</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 80-16384"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
#include <include/interface/redirect.xml.i>
#include <include/interface/vif-s.xml.i>
#include <include/interface/vif.xml.i>
#include <include/interface/vrf.xml.i>
#include <include/interface/xdp.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-geneve.xml.in b/interface-definitions/interfaces-geneve.xml.in
index b959c787d..f8e9909f8 100644
--- a/interface-definitions/interfaces-geneve.xml.in
+++ b/interface-definitions/interfaces-geneve.xml.in
@@ -1,60 +1,59 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="geneve" owner="${vyos_conf_scripts_dir}/interfaces-geneve.py">
<properties>
<help>Generic Network Virtualization Encapsulation (GENEVE) Interface</help>
<priority>460</priority>
<constraint>
<regex>gnv[0-9]+</regex>
</constraint>
<constraintErrorMessage>GENEVE interface must be named gnvN</constraintErrorMessage>
<valueHelp>
<format>gnvN</format>
<description>GENEVE interface name</description>
</valueHelp>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6.xml.i>
#include <include/interface/description.xml.i>
#include <include/interface/disable.xml.i>
#include <include/interface/ipv4-options.xml.i>
#include <include/interface/ipv6-options.xml.i>
#include <include/interface/mac.xml.i>
#include <include/interface/mtu-1450-16000.xml.i>
- #include <include/interface/interface-policy.xml.i>
<node name="parameters">
<properties>
<help>GENEVE tunnel parameters</help>
</properties>
<children>
<node name="ip">
<properties>
<help>IPv4 specific tunnel parameters</help>
</properties>
<children>
#include <include/interface/parameters-df.xml.i>
#include <include/interface/parameters-tos.xml.i>
#include <include/interface/parameters-ttl.xml.i>
</children>
</node>
<node name="ipv6">
<properties>
<help>IPv6 specific tunnel parameters</help>
</properties>
<children>
#include <include/interface/parameters-flowlabel.xml.i>
</children>
</node>
</children>
</node>
#include <include/interface/mirror.xml.i>
#include <include/interface/redirect.xml.i>
#include <include/interface/tunnel-remote.xml.i>
#include <include/vni.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-input.xml.in b/interface-definitions/interfaces-input.xml.in
index d01c760f8..97502d954 100644
--- a/interface-definitions/interfaces-input.xml.in
+++ b/interface-definitions/interfaces-input.xml.in
@@ -1,28 +1,27 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="input" owner="${vyos_conf_scripts_dir}/interfaces-input.py">
<properties>
<help>Input Functional Block (IFB) interface name</help>
<!-- before real devices that redirect -->
<priority>310</priority>
<constraint>
<regex>ifb[0-9]+</regex>
</constraint>
<constraintErrorMessage>Input interface must be named ifbN</constraintErrorMessage>
<valueHelp>
<format>ifbN</format>
<description>Input interface name</description>
</valueHelp>
</properties>
<children>
#include <include/interface/description.xml.i>
#include <include/interface/disable.xml.i>
- #include <include/interface/interface-policy.xml.i>
#include <include/interface/redirect.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-l2tpv3.xml.in b/interface-definitions/interfaces-l2tpv3.xml.in
index bde68dd5a..0ebc3253d 100644
--- a/interface-definitions/interfaces-l2tpv3.xml.in
+++ b/interface-definitions/interfaces-l2tpv3.xml.in
@@ -1,132 +1,131 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="l2tpv3" owner="${vyos_conf_scripts_dir}/interfaces-l2tpv3.py">
<properties>
<help>Layer 2 Tunnel Protocol Version 3 (L2TPv3) Interface</help>
<priority>485</priority>
<constraint>
<regex>l2tpeth[0-9]+</regex>
</constraint>
<constraintErrorMessage>L2TPv3 interface must be named l2tpethN</constraintErrorMessage>
<valueHelp>
<format>l2tpethN</format>
<description>L2TPv3 interface name</description>
</valueHelp>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6.xml.i>
#include <include/interface/description.xml.i>
<leafNode name="destination-port">
<properties>
<help>UDP destination port for L2TPv3 tunnel</help>
<valueHelp>
<format>u32:1-65535</format>
<description>Numeric IP port</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
<defaultValue>5000</defaultValue>
</leafNode>
#include <include/interface/disable.xml.i>
- #include <include/interface/interface-policy.xml.i>
<leafNode name="encapsulation">
<properties>
<help>Encapsulation type</help>
<completionHelp>
<list>udp ip</list>
</completionHelp>
<valueHelp>
<format>udp</format>
<description>UDP encapsulation</description>
</valueHelp>
<valueHelp>
<format>ip</format>
<description>IP encapsulation</description>
</valueHelp>
<constraint>
<regex>(udp|ip)</regex>
</constraint>
<constraintErrorMessage>Encapsulation must be UDP or IP</constraintErrorMessage>
</properties>
<defaultValue>udp</defaultValue>
</leafNode>
#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>
</leafNode>
<leafNode name="peer-session-id">
<properties>
<help>Peer session identifier</help>
<valueHelp>
<format>u32:1-429496729</format>
<description>L2TPv3 peer session identifier</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-429496729"/>
</constraint>
</properties>
</leafNode>
<leafNode name="peer-tunnel-id">
<properties>
<help>Peer tunnel identifier</help>
<valueHelp>
<format>u32:1-429496729</format>
<description>L2TPv3 peer tunnel identifier</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-429496729"/>
</constraint>
</properties>
</leafNode>
#include <include/interface/tunnel-remote.xml.i>
<leafNode name="session-id">
<properties>
<help>Session identifier</help>
<valueHelp>
<format>u32:1-429496729</format>
<description>L2TPv3 session identifier</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-429496729"/>
</constraint>
</properties>
</leafNode>
<leafNode name="source-port">
<properties>
<help>UDP source port for L2TPv3 tunnel</help>
<valueHelp>
<format>u32:1-65535</format>
<description>Numeric IP port</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
<defaultValue>5000</defaultValue>
</leafNode>
<leafNode name="tunnel-id">
<properties>
<help>Local tunnel identifier</help>
<valueHelp>
<format>u32:1-429496729</format>
<description>L2TPv3 local tunnel identifier</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-429496729"/>
</constraint>
</properties>
</leafNode>
#include <include/interface/vrf.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in
index 5c9f4cd76..441236ec2 100644
--- a/interface-definitions/interfaces-macsec.xml.in
+++ b/interface-definitions/interfaces-macsec.xml.in
@@ -1,132 +1,131 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="macsec" owner="${vyos_conf_scripts_dir}/interfaces-macsec.py">
<properties>
<help>MACsec Interface (802.1ae)</help>
<priority>461</priority>
<constraint>
<regex>macsec[0-9]+</regex>
</constraint>
<constraintErrorMessage>MACsec interface must be named macsecN</constraintErrorMessage>
<valueHelp>
<format>macsecN</format>
<description>MACsec interface name</description>
</valueHelp>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
#include <include/interface/ipv4-options.xml.i>
#include <include/interface/ipv6-options.xml.i>
- #include <include/interface/interface-policy.xml.i>
#include <include/interface/mirror.xml.i>
<node name="security">
<properties>
<help>Security/Encryption Settings</help>
</properties>
<children>
<leafNode name="cipher">
<properties>
<help>Cipher suite used</help>
<completionHelp>
<list>gcm-aes-128 gcm-aes-256</list>
</completionHelp>
<valueHelp>
<format>gcm-aes-128</format>
<description>Galois/Counter Mode of AES cipher with 128-bit key</description>
</valueHelp>
<valueHelp>
<format>gcm-aes-256</format>
<description>Galois/Counter Mode of AES cipher with 256-bit key</description>
</valueHelp>
<constraint>
<regex>(gcm-aes-128|gcm-aes-256)</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="encrypt">
<properties>
<help>Enable optional MACsec encryption</help>
<valueless/>
</properties>
</leafNode>
<node name="mka">
<properties>
<help>MACsec Key Agreement protocol (MKA)</help>
</properties>
<children>
<leafNode name="cak">
<properties>
<help>Secure Connectivity Association Key</help>
<valueHelp>
<format>txt</format>
<description>16-byte (128-bit) hex-string (32 hex-digits) for gcm-aes-128 or 32-byte (256-bit) hex-string (64 hex-digits) for gcm-aes-256</description>
</valueHelp>
<constraint>
<regex>[A-Fa-f0-9]{32}</regex>
<regex>[A-Fa-f0-9]{64}</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="ckn">
<properties>
<help>Secure Connectivity Association Key Name</help>
<valueHelp>
<format>txt</format>
<description>32-byte (256-bit) hex-string (64 hex-digits)</description>
</valueHelp>
<constraint>
<regex>[A-Fa-f0-9]{64}</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="priority">
<properties>
<help>Priority of MACsec Key Agreement protocol (MKA) actor</help>
<valueHelp>
<format>u32:0-255</format>
<description>MACsec Key Agreement protocol (MKA) priority</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-255" />
</constraint>
</properties>
<defaultValue>255</defaultValue>
</leafNode>
</children>
</node>
<leafNode name="replay-window">
<properties>
<help>IEEE 802.1X/MACsec replay protection window</help>
<valueHelp>
<format>u32:0</format>
<description>No replay window, strict check</description>
</valueHelp>
<valueHelp>
<format>u32:1-4294967295</format>
<description>Number of packets that could be misordered</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4294967295" />
</constraint>
</properties>
</leafNode>
</children>
</node>
#include <include/interface/description.xml.i>
#include <include/interface/disable.xml.i>
#include <include/interface/mtu-68-16000.xml.i>
<leafNode name="mtu">
<defaultValue>1460</defaultValue>
</leafNode>
#include <include/source-interface-ethernet.xml.i>
#include <include/interface/redirect.xml.i>
#include <include/interface/vrf.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-openvpn.xml.in b/interface-definitions/interfaces-openvpn.xml.in
index 3876e31da..7cfb9ee7a 100644
--- a/interface-definitions/interfaces-openvpn.xml.in
+++ b/interface-definitions/interfaces-openvpn.xml.in
@@ -1,820 +1,819 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="openvpn" owner="${vyos_conf_scripts_dir}/interfaces-openvpn.py">
<properties>
<help>OpenVPN Tunnel Interface</help>
<priority>460</priority>
<constraint>
<regex>vtun[0-9]+</regex>
</constraint>
<constraintErrorMessage>OpenVPN tunnel interface must be named vtunN</constraintErrorMessage>
<valueHelp>
<format>vtunN</format>
<description>OpenVPN interface name</description>
</valueHelp>
</properties>
<children>
<node name="authentication">
<properties>
<help>Authentication options</help>
</properties>
<children>
<leafNode name="password">
<properties>
<help>OpenVPN password used for authentication</help>
</properties>
</leafNode>
<leafNode name="username">
<properties>
<help>OpenVPN username used for authentication</help>
</properties>
</leafNode>
</children>
</node>
#include <include/interface/description.xml.i>
- #include <include/interface/interface-policy.xml.i>
<leafNode name="device-type">
<properties>
<help>OpenVPN interface device-type</help>
<completionHelp>
<list>tun tap</list>
</completionHelp>
<valueHelp>
<format>tun</format>
<description>TUN device, required for OSI layer 3</description>
</valueHelp>
<valueHelp>
<format>tap</format>
<description>TAP device, required for OSI layer 2</description>
</valueHelp>
<constraint>
<regex>(tun|tap)</regex>
</constraint>
</properties>
<defaultValue>tun</defaultValue>
</leafNode>
#include <include/interface/disable.xml.i>
<node name="encryption">
<properties>
<help>Data Encryption settings</help>
</properties>
<children>
<leafNode name="cipher">
<properties>
<help>Standard Data Encryption Algorithm</help>
<completionHelp>
<list>none des 3des bf128 bf256 aes128 aes128gcm aes192 aes192gcm aes256 aes256gcm</list>
</completionHelp>
<valueHelp>
<format>none</format>
<description>Disable encryption</description>
</valueHelp>
<valueHelp>
<format>des</format>
<description>DES algorithm</description>
</valueHelp>
<valueHelp>
<format>3des</format>
<description>DES algorithm with triple encryption</description>
</valueHelp>
<valueHelp>
<format>bf128</format>
<description>Blowfish algorithm with 128-bit key</description>
</valueHelp>
<valueHelp>
<format>bf256</format>
<description>Blowfish algorithm with 256-bit key</description>
</valueHelp>
<valueHelp>
<format>aes128</format>
<description>AES algorithm with 128-bit key CBC</description>
</valueHelp>
<valueHelp>
<format>aes128gcm</format>
<description>AES algorithm with 128-bit key GCM</description>
</valueHelp>
<valueHelp>
<format>aes192</format>
<description>AES algorithm with 192-bit key CBC</description>
</valueHelp>
<valueHelp>
<format>aes192gcm</format>
<description>AES algorithm with 192-bit key GCM</description>
</valueHelp>
<valueHelp>
<format>aes256</format>
<description>AES algorithm with 256-bit key CBC</description>
</valueHelp>
<valueHelp>
<format>aes256gcm</format>
<description>AES algorithm with 256-bit key GCM</description>
</valueHelp>
<constraint>
<regex>(none|des|3des|bf128|bf256|aes128|aes128gcm|aes192|aes192gcm|aes256|aes256gcm)</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="ncp-ciphers">
<properties>
<help>Cipher negotiation list for use in server or client mode</help>
<completionHelp>
<list>none des 3des aes128 aes128gcm aes192 aes192gcm aes256 aes256gcm</list>
</completionHelp>
<valueHelp>
<format>none</format>
<description>Disable encryption</description>
</valueHelp>
<valueHelp>
<format>des</format>
<description>DES algorithm</description>
</valueHelp>
<valueHelp>
<format>3des</format>
<description>DES algorithm with triple encryption</description>
</valueHelp>
<valueHelp>
<format>aes128</format>
<description>AES algorithm with 128-bit key CBC</description>
</valueHelp>
<valueHelp>
<format>aes128gcm</format>
<description>AES algorithm with 128-bit key GCM</description>
</valueHelp>
<valueHelp>
<format>aes192</format>
<description>AES algorithm with 192-bit key CBC</description>
</valueHelp>
<valueHelp>
<format>aes192gcm</format>
<description>AES algorithm with 192-bit key GCM</description>
</valueHelp>
<valueHelp>
<format>aes256</format>
<description>AES algorithm with 256-bit key CBC</description>
</valueHelp>
<valueHelp>
<format>aes256gcm</format>
<description>AES algorithm with 256-bit key GCM</description>
</valueHelp>
<constraint>
<regex>(none|des|3des|aes128|aes128gcm|aes192|aes192gcm|aes256|aes256gcm)</regex>
</constraint>
<multi/>
</properties>
</leafNode>
</children>
</node>
#include <include/interface/ipv4-options.xml.i>
#include <include/interface/ipv6-options.xml.i>
#include <include/interface/mirror.xml.i>
<leafNode name="hash">
<properties>
<help>Hashing Algorithm</help>
<completionHelp>
<list>md5 sha1 sha256 sha384 sha512</list>
</completionHelp>
<valueHelp>
<format>md5</format>
<description>MD5 algorithm</description>
</valueHelp>
<valueHelp>
<format>sha1</format>
<description>SHA-1 algorithm</description>
</valueHelp>
<valueHelp>
<format>sha256</format>
<description>SHA-256 algorithm</description>
</valueHelp>
<valueHelp>
<format>sha384</format>
<description>SHA-384 algorithm</description>
</valueHelp>
<valueHelp>
<format>sha512</format>
<description>SHA-512 algorithm</description>
</valueHelp>
<constraint>
<regex>(md5|sha1|sha256|sha384|sha512)</regex>
</constraint>
</properties>
</leafNode>
<node name="keep-alive">
<properties>
<help>Keepalive helper options</help>
</properties>
<children>
<leafNode name="failure-count">
<properties>
<help>Maximum number of keepalive packet failures</help>
<valueHelp>
<format>u32:0-1000</format>
<description>Maximum number of keepalive packet failures</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-1000"/>
</constraint>
</properties>
<defaultValue>60</defaultValue>
</leafNode>
<leafNode name="interval">
<properties>
<help>Keepalive packet interval in seconds</help>
<valueHelp>
<format>u32:0-600</format>
<description>Keepalive packet interval (seconds)</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-600"/>
</constraint>
</properties>
<defaultValue>10</defaultValue>
</leafNode>
</children>
</node>
<tagNode name="local-address">
<properties>
<help>Local IP address of tunnel (IPv4 or IPv6)</help>
<constraint>
<validator name="ip-address"/>
</constraint>
</properties>
<children>
<leafNode name="subnet-mask">
<properties>
<help>Subnet-mask for local IP address of tunnel (IPv4 only)</help>
<constraint>
<validator name="ipv4-address"/>
</constraint>
</properties>
</leafNode>
</children>
</tagNode>
<leafNode name="local-host">
<properties>
<help>Local IP address to accept connections (all if not set)</help>
<valueHelp>
<format>ipv4</format>
<description>Local IPv4 address</description>
</valueHelp>
<valueHelp>
<format>ipv6</format>
<description>Local IPv6 address</description>
</valueHelp>
<constraint>
<validator name="ip-address"/>
</constraint>
</properties>
</leafNode>
<leafNode name="local-port">
<properties>
<help>Local port number to accept connections</help>
<valueHelp>
<format>u32:1-65535</format>
<description>Numeric IP port</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
</leafNode>
<leafNode name="mode">
<properties>
<help>OpenVPN mode of operation</help>
<completionHelp>
<list>site-to-site client server</list>
</completionHelp>
<valueHelp>
<format>site-to-site</format>
<description>Site-to-site mode</description>
</valueHelp>
<valueHelp>
<format>client</format>
<description>Client in client-server mode</description>
</valueHelp>
<valueHelp>
<format>server</format>
<description>Server in client-server mode</description>
</valueHelp>
<constraint>
<regex>(site-to-site|client|server)</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="openvpn-option">
<properties>
<help>Additional OpenVPN options. You must use the syntax of openvpn.conf in this text-field. Using this without proper knowledge may result in a crashed OpenVPN server. Check system log to look for errors.</help>
<multi/>
</properties>
</leafNode>
<leafNode name="persistent-tunnel">
<properties>
<help>Do not close and reopen interface (TUN/TAP device) on client restarts</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="protocol">
<properties>
<help>OpenVPN communication protocol</help>
<completionHelp>
<list>udp tcp-passive tcp-active</list>
</completionHelp>
<valueHelp>
<format>udp</format>
<description>UDP</description>
</valueHelp>
<valueHelp>
<format>tcp-passive</format>
<description>TCP and accepts connections passively</description>
</valueHelp>
<valueHelp>
<format>tcp-active</format>
<description>TCP and initiates connections actively</description>
</valueHelp>
<constraint>
<regex>(udp|tcp-passive|tcp-active)</regex>
</constraint>
</properties>
<defaultValue>udp</defaultValue>
</leafNode>
<leafNode name="remote-address">
<properties>
<help>IP address of remote end of tunnel</help>
<valueHelp>
<format>ipv4</format>
<description>Remote end IPv4 address</description>
</valueHelp>
<valueHelp>
<format>ipv6</format>
<description>Remote end IPv6 address</description>
</valueHelp>
<constraint>
<validator name="ipv4-address"/>
<validator name="ipv6-address"/>
</constraint>
<multi/>
</properties>
</leafNode>
<leafNode name="remote-host">
<properties>
<help>Remote host to connect to (dynamic if not set)</help>
<valueHelp>
<format>ipv4</format>
<description>IPv4 address of remote host</description>
</valueHelp>
<valueHelp>
<format>ipv6</format>
<description>IPv6 address of remote host</description>
</valueHelp>
<valueHelp>
<format>txt</format>
<description>Hostname of remote host</description>
</valueHelp>
<multi/>
</properties>
</leafNode>
<leafNode name="remote-port">
<properties>
<help>Remote port number to connect to</help>
<valueHelp>
<format>u32:1-65535</format>
<description>Numeric IP port</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
</leafNode>
<node name="replace-default-route">
<properties>
<help>OpenVPN tunnel to be used as the default route</help>
</properties>
<children>
<leafNode name="local">
<properties>
<help>Tunnel endpoints are on the same subnet</help>
</properties>
</leafNode>
</children>
</node>
<node name="server">
<properties>
<help>Server-mode options</help>
</properties>
<children>
<tagNode name="client">
<properties>
<help>Client-specific settings</help>
<valueHelp>
<format>name</format>
<description>Client common-name in the certificate</description>
</valueHelp>
</properties>
<children>
#include <include/generic-disable-node.xml.i>
<leafNode name="ip">
<properties>
<help>IP address of the client</help>
<valueHelp>
<format>ipv4</format>
<description>Client IPv4 address</description>
</valueHelp>
<valueHelp>
<format>ipv6</format>
<description>Client IPv6 address</description>
</valueHelp>
<constraint>
<validator name="ip-address"/>
</constraint>
<multi/>
</properties>
</leafNode>
<leafNode name="push-route">
<properties>
<help>Route to be pushed to the client</help>
<valueHelp>
<format>ipv4net</format>
<description>IPv4 network and prefix length</description>
</valueHelp>
<valueHelp>
<format>ipv6net</format>
<description>IPv6 network and prefix length</description>
</valueHelp>
<constraint>
<validator name="ip-prefix"/>
</constraint>
<multi/>
</properties>
</leafNode>
<leafNode name="subnet">
<properties>
<help>Subnet belonging to the client (iroute)</help>
<valueHelp>
<format>ipv4net</format>
<description>IPv4 network and prefix length belonging to the client</description>
</valueHelp>
<valueHelp>
<format>ipv6net</format>
<description>IPv6 network and prefix length belonging to the client</description>
</valueHelp>
<constraint>
<validator name="ip-prefix"/>
</constraint>
<multi/>
</properties>
</leafNode>
</children>
</tagNode>
<node name="client-ip-pool">
<properties>
<help>Pool of client IPv4 addresses</help>
</properties>
<children>
#include <include/generic-disable-node.xml.i>
<leafNode name="start">
<properties>
<help>First IP address in the pool</help>
<constraint>
<validator name="ipv4-address"/>
</constraint>
<valueHelp>
<format>ipv4</format>
<description>IPv4 address</description>
</valueHelp>
</properties>
</leafNode>
<leafNode name="stop">
<properties>
<help>Last IP address in the pool</help>
<constraint>
<validator name="ipv4-address"/>
</constraint>
<valueHelp>
<format>ipv4</format>
<description>IPv4 address</description>
</valueHelp>
</properties>
</leafNode>
<leafNode name="subnet-mask">
<properties>
<help>Subnet mask pushed to dynamic clients. If not set the server subnet mask will be used. Only used with topology subnet or device type tap. Not used with bridged interfaces.</help>
<constraint>
<validator name="ipv4-address"/>
</constraint>
<valueHelp>
<format>ipv4</format>
<description>IPv4 subnet mask</description>
</valueHelp>
</properties>
</leafNode>
</children>
</node>
<node name="client-ipv6-pool">
<properties>
<help>Pool of client IPv6 addresses</help>
</properties>
<children>
<leafNode name="base">
<properties>
<help>Client IPv6 pool base address with optional prefix length</help>
<valueHelp>
<format>ipv6net</format>
<description>Client IPv6 pool base address with optional prefix length (defaults: base = server subnet + 0x1000, prefix length = server prefix length)</description>
</valueHelp>
<constraint>
<validator name="ipv6"/>
</constraint>
</properties>
</leafNode>
#include <include/generic-disable-node.xml.i>
</children>
</node>
<leafNode name="domain-name">
<properties>
<help>DNS suffix to be pushed to all clients</help>
<valueHelp>
<format>txt</format>
<description>Domain Name Server suffix</description>
</valueHelp>
</properties>
</leafNode>
<leafNode name="max-connections">
<properties>
<help>Number of maximum client connections</help>
<valueHelp>
<format>u32:1-4096</format>
<description>Number of concurrent clients</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-4096"/>
</constraint>
</properties>
</leafNode>
#include <include/name-server-ipv4-ipv6.xml.i>
<tagNode name="push-route">
<properties>
<help>Route to be pushed to all clients</help>
<valueHelp>
<format>ipv4net</format>
<description>IPv4 network and prefix length</description>
</valueHelp>
<valueHelp>
<format>ipv6net</format>
<description>IPv6 network and prefix length</description>
</valueHelp>
<constraint>
<validator name="ip-prefix"/>
</constraint>
</properties>
<children>
<leafNode name="metric">
<properties>
<help>Set metric for this route</help>
<valueHelp>
<format>u32:0-4294967295</format>
<description>Metric for this route</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4294967295"/>
</constraint>
</properties>
<defaultValue>0</defaultValue>
</leafNode>
</children>
</tagNode>
<leafNode name="reject-unconfigured-clients">
<properties>
<help>Reject connections from clients that are not explicitly configured</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="subnet">
<properties>
<help>Server-mode subnet (from which client IPs are allocated)</help>
<valueHelp>
<format>ipv4net</format>
<description>IPv4 network and prefix length</description>
</valueHelp>
<valueHelp>
<format>ipv6net</format>
<description>IPv6 network and prefix length</description>
</valueHelp>
<constraint>
<validator name="ip-prefix"/>
</constraint>
<multi/>
</properties>
</leafNode>
<leafNode name="topology">
<properties>
<help>Topology for clients</help>
<completionHelp>
<list>net30 point-to-point subnet</list>
</completionHelp>
<valueHelp>
<format>net30</format>
<description>net30 topology</description>
</valueHelp>
<valueHelp>
<format>point-to-point</format>
<description>Point-to-point topology</description>
</valueHelp>
<valueHelp>
<format>subnet</format>
<description>Subnet topology</description>
</valueHelp>
<constraint>
<regex>(subnet|point-to-point|net30)</regex>
</constraint>
</properties>
<defaultValue>net30</defaultValue>
</leafNode>
<node name="mfa">
<properties>
<help>multi-factor authentication</help>
</properties>
<children>
<node name="totp">
<properties>
<help>Time-based one-time passwords</help>
</properties>
<children>
<leafNode name="slop">
<properties>
<help>Maximum allowed clock slop in seconds</help>
<valueHelp>
<format>1-65535</format>
<description>Seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
<defaultValue>180</defaultValue>
</leafNode>
<leafNode name="drift">
<properties>
<help>Time drift in seconds</help>
<valueHelp>
<format>1-65535</format>
<description>Seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
<defaultValue>0</defaultValue>
</leafNode>
<leafNode name="step">
<properties>
<help>Step value for totp in seconds</help>
<valueHelp>
<format>1-65535</format>
<description>Seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
<defaultValue>30</defaultValue>
</leafNode>
<leafNode name="digits">
<properties>
<help>Number of digits to use for totp hash</help>
<valueHelp>
<format>1-65535</format>
<description>Seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
<defaultValue>6</defaultValue>
</leafNode>
<leafNode name="challenge">
<properties>
<help>Expect password as result of a challenge response protocol</help>
<completionHelp>
<list>disable enable</list>
</completionHelp>
<valueHelp>
<format>disable</format>
<description>Disable challenge-response</description>
</valueHelp>
<valueHelp>
<format>enable</format>
<description>Enable chalenge-response</description>
</valueHelp>
<constraint>
<regex>(disable|enable)</regex>
</constraint>
</properties>
<defaultValue>enable</defaultValue>
</leafNode>
</children>
</node>
</children>
</node>
</children>
</node>
<leafNode name="shared-secret-key">
<properties>
<help>Secret key shared with remote end of tunnel</help>
<completionHelp>
<path>pki openvpn shared-secret</path>
</completionHelp>
</properties>
</leafNode>
<node name="tls">
<properties>
<help>Transport Layer Security (TLS) options</help>
</properties>
<children>
<leafNode name="auth-key">
<properties>
<help>TLS shared secret key for tls-auth</help>
<completionHelp>
<path>pki openvpn shared-secret</path>
</completionHelp>
</properties>
</leafNode>
#include <include/pki/certificate.xml.i>
#include <include/pki/ca-certificate-multi.xml.i>
<leafNode name="dh-params">
<properties>
<help>Diffie Hellman parameters (server only)</help>
<completionHelp>
<path>pki dh</path>
</completionHelp>
</properties>
</leafNode>
<leafNode name="crypt-key">
<properties>
<help>Static key to use to authenticate control channel</help>
<completionHelp>
<path>pki openvpn shared-secret</path>
</completionHelp>
</properties>
</leafNode>
<leafNode name="tls-version-min">
<properties>
<help>Specify the minimum required TLS version</help>
<completionHelp>
<list>1.0 1.1 1.2 1.3</list>
</completionHelp>
<valueHelp>
<format>1.0</format>
<description>TLS v1.0</description>
</valueHelp>
<valueHelp>
<format>1.1</format>
<description>TLS v1.1</description>
</valueHelp>
<valueHelp>
<format>1.2</format>
<description>TLS v1.2</description>
</valueHelp>
<valueHelp>
<format>1.3</format>
<description>TLS v1.3</description>
</valueHelp>
<constraint>
<regex>(1.0|1.1|1.2|1.3)</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="role">
<properties>
<help>TLS negotiation role</help>
<completionHelp>
<list>active passive</list>
</completionHelp>
<valueHelp>
<format>active</format>
<description>Initiate TLS negotiation actively</description>
</valueHelp>
<valueHelp>
<format>passive</format>
<description>Wait for incoming TLS connection</description>
</valueHelp>
<constraint>
<regex>(active|passive)</regex>
</constraint>
</properties>
</leafNode>
</children>
</node>
<leafNode name="use-lzo-compression">
<properties>
<help>Use fast LZO compression on this TUN/TAP interface</help>
<valueless/>
</properties>
</leafNode>
#include <include/interface/redirect.xml.i>
#include <include/interface/vrf.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-pppoe.xml.in b/interface-definitions/interfaces-pppoe.xml.in
index 84f76a7ee..719060fa9 100644
--- a/interface-definitions/interfaces-pppoe.xml.in
+++ b/interface-definitions/interfaces-pppoe.xml.in
@@ -1,119 +1,118 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="pppoe" owner="${vyos_conf_scripts_dir}/interfaces-pppoe.py">
<properties>
<help>Point-to-Point Protocol over Ethernet (PPPoE) Interface</help>
<priority>322</priority>
<constraint>
<regex>pppoe[0-9]+</regex>
</constraint>
<constraintErrorMessage>PPPoE interface must be named pppoeN</constraintErrorMessage>
<valueHelp>
<format>pppoeN</format>
<description>PPPoE dialer interface name</description>
</valueHelp>
</properties>
<children>
#include <include/pppoe-access-concentrator.xml.i>
#include <include/interface/authentication.xml.i>
#include <include/interface/dial-on-demand.xml.i>
- #include <include/interface/interface-policy.xml.i>
#include <include/interface/no-default-route.xml.i>
#include <include/interface/default-route-distance.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
#include <include/interface/description.xml.i>
#include <include/interface/disable.xml.i>
<leafNode name="idle-timeout">
<properties>
<help>Delay before disconnecting idle session (in seconds)</help>
<valueHelp>
<format>u32:0-86400</format>
<description>Idle timeout in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-86400"/>
</constraint>
<constraintErrorMessage>Timeout must be in range 0 to 86400</constraintErrorMessage>
</properties>
</leafNode>
<node name="ip">
<properties>
<help>IPv4 routing parameters</help>
</properties>
<children>
#include <include/interface/adjust-mss.xml.i>
#include <include/interface/disable-forwarding.xml.i>
#include <include/interface/source-validation.xml.i>
</children>
</node>
<node name="ipv6">
<properties>
<help>IPv6 routing parameters</help>
</properties>
<children>
<node name="address">
<properties>
<help>IPv6 address configuration modes</help>
</properties>
<children>
#include <include/interface/ipv6-address-autoconf.xml.i>
</children>
</node>
#include <include/interface/adjust-mss.xml.i>
#include <include/interface/disable-forwarding.xml.i>
</children>
</node>
#include <include/source-interface.xml.i>
<leafNode name="local-address">
<properties>
<help>IPv4 address of local end of the PPPoE link</help>
<valueHelp>
<format>ipv4</format>
<description>Address of local end of the PPPoE link</description>
</valueHelp>
<constraint>
<validator name="ipv4-address"/>
</constraint>
</properties>
</leafNode>
#include <include/interface/mirror.xml.i>
#include <include/interface/mtu-68-1500.xml.i>
<leafNode name="mtu">
<defaultValue>1492</defaultValue>
</leafNode>
<leafNode name="no-peer-dns">
<properties>
<help>Do not use DNS servers provided by the peer</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="remote-address">
<properties>
<help>IPv4 address of remote end of the PPPoE link</help>
<valueHelp>
<format>ipv4</format>
<description>Address of remote end of the PPPoE link</description>
</valueHelp>
<constraint>
<validator name="ipv4-address"/>
</constraint>
</properties>
</leafNode>
<leafNode name="service-name">
<properties>
<help>Service name, only connect to access concentrators advertising this</help>
<constraint>
<regex>[a-zA-Z0-9]+</regex>
</constraint>
<constraintErrorMessage>Service name must be alphanumeric only</constraintErrorMessage>
</properties>
</leafNode>
#include <include/interface/redirect.xml.i>
#include <include/interface/vrf.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-pseudo-ethernet.xml.in b/interface-definitions/interfaces-pseudo-ethernet.xml.in
index 4eb9bf111..2fe07ffd5 100644
--- a/interface-definitions/interfaces-pseudo-ethernet.xml.in
+++ b/interface-definitions/interfaces-pseudo-ethernet.xml.in
@@ -1,69 +1,68 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="pseudo-ethernet" owner="${vyos_conf_scripts_dir}/interfaces-pseudo-ethernet.py">
<properties>
<help>Pseudo Ethernet Interface (Macvlan)</help>
<priority>321</priority>
<constraint>
<regex>peth[0-9]+</regex>
</constraint>
<constraintErrorMessage>Pseudo Ethernet interface must be named pethN</constraintErrorMessage>
<valueHelp>
<format>pethN</format>
<description>Pseudo Ethernet interface name</description>
</valueHelp>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
#include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
#include <include/interface/disable-link-detect.xml.i>
#include <include/interface/disable.xml.i>
#include <include/interface/vrf.xml.i>
#include <include/interface/ipv4-options.xml.i>
#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-policy.xml.i>
<leafNode name="mode">
<properties>
<help>Receive mode (default: private)</help>
<completionHelp>
<list>private vepa bridge passthru</list>
</completionHelp>
<valueHelp>
<format>private</format>
<description>No communication with other pseudo-devices</description>
</valueHelp>
<valueHelp>
<format>vepa</format>
<description>Virtual Ethernet Port Aggregator reflective relay</description>
</valueHelp>
<valueHelp>
<format>bridge</format>
<description>Simple bridge between pseudo-devices</description>
</valueHelp>
<valueHelp>
<format>passthru</format>
<description>Promicious mode passthrough of underlying device</description>
</valueHelp>
<constraint>
<regex>(private|vepa|bridge|passthru)</regex>
</constraint>
<constraintErrorMessage>mode must be private, vepa, bridge or passthru</constraintErrorMessage>
</properties>
<defaultValue>private</defaultValue>
</leafNode>
#include <include/interface/mtu-68-16000.xml.i>
#include <include/interface/redirect.xml.i>
#include <include/interface/vif-s.xml.i>
#include <include/interface/vif.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-tunnel.xml.in b/interface-definitions/interfaces-tunnel.xml.in
index fe49d337a..333a5b178 100644
--- a/interface-definitions/interfaces-tunnel.xml.in
+++ b/interface-definitions/interfaces-tunnel.xml.in
@@ -1,296 +1,295 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="tunnel" owner="${vyos_conf_scripts_dir}/interfaces-tunnel.py">
<properties>
<help>Tunnel interface</help>
<priority>380</priority>
<constraint>
<regex>tun[0-9]+</regex>
</constraint>
<constraintErrorMessage>tunnel interface must be named tunN</constraintErrorMessage>
<valueHelp>
<format>tunN</format>
<description>Tunnel interface name</description>
</valueHelp>
</properties>
<children>
#include <include/interface/description.xml.i>
#include <include/interface/address-ipv4-ipv6.xml.i>
#include <include/interface/disable.xml.i>
#include <include/interface/disable-link-detect.xml.i>
#include <include/interface/mtu-64-8024.xml.i>
<leafNode name="mtu">
<defaultValue>1476</defaultValue>
</leafNode>
#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/tunnel-remote.xml.i>
#include <include/source-interface.xml.i>
- #include <include/interface/interface-policy.xml.i>
<leafNode name="6rd-prefix">
<properties>
<help>6rd network prefix</help>
<valueHelp>
<format>ipv6</format>
<description>IPv6 address and prefix length</description>
</valueHelp>
<constraint>
<validator name="ipv6-prefix"/>
</constraint>
</properties>
</leafNode>
<leafNode name="6rd-relay-prefix">
<properties>
<help>6rd relay prefix</help>
<valueHelp>
<format>ipv4net</format>
<description>IPv4 prefix of interface for 6rd</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
</properties>
</leafNode>
<leafNode name="encapsulation">
<properties>
<help>Encapsulation of this tunnel interface</help>
<completionHelp>
<list>erspan gre gretap ip6erspan ip6gre ip6gretap ip6ip6 ipip ipip6 sit</list>
</completionHelp>
<valueHelp>
<format>erspan</format>
<description>Encapsulated Remote Switched Port Analyzer</description>
</valueHelp>
<valueHelp>
<format>gre</format>
<description>Generic Routing Encapsulation (network layer)</description>
</valueHelp>
<valueHelp>
<format>gretap</format>
<description>Generic Routing Encapsulation (datalink layer)</description>
</valueHelp>
<valueHelp>
<format>ip6erspan</format>
<description>Encapsulated Remote Switched Port Analyzer over IPv6</description>
</valueHelp>
<valueHelp>
<format>ip6gre</format>
<description>GRE over IPv6 (network layer)</description>
</valueHelp>
<valueHelp>
<format>ip6gretap</format>
<description>GRE over IPv6 (datalink layer)</description>
</valueHelp>
<valueHelp>
<format>ip6ip6</format>
<description>IPv6 in IPv6 encapsulation</description>
</valueHelp>
<valueHelp>
<format>ipip</format>
<description>IPv4 in IPv4 encapsulation</description>
</valueHelp>
<valueHelp>
<format>ipip6</format>
<description>IPv4 in IP6 encapsulation</description>
</valueHelp>
<valueHelp>
<format>sit</format>
<description>Simple Internet Transition (IPv6 in IPv4)</description>
</valueHelp>
<constraint>
<regex>(erspan|gre|gretap|ip6erspan|ip6gre|ip6gretap|ip6ip6|ipip|ipip6|sit)</regex>
</constraint>
<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>
<completionHelp>
<list>enable disable</list>
</completionHelp>
<valueHelp>
<format>enable</format>
<description>Enable multicast</description>
</valueHelp>
<valueHelp>
<format>disable</format>
<description>Disable multicast (default)</description>
</valueHelp>
<constraint>
<regex>(enable|disable)</regex>
</constraint>
<constraintErrorMessage>Must be 'disable' or 'enable'</constraintErrorMessage>
</properties>
</leafNode>
<node name="parameters">
<properties>
<help>Tunnel parameters</help>
</properties>
<children>
<node name="erspan">
<properties>
<help>ERSPAN tunnel parameters</help>
</properties>
<children>
<leafNode name="direction">
<properties>
<help>Mirrored traffic direction</help>
<completionHelp>
<list>ingress egress</list>
</completionHelp>
<valueHelp>
<format>ingress</format>
<description>Mirror ingress traffic</description>
</valueHelp>
<valueHelp>
<format>egress</format>
<description>Mirror egress traffic</description>
</valueHelp>
<constraint>
<regex>(ingress|egress)</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="hw-id">
<properties>
<help>Unique identifier of an ERSPAN engine within a system</help>
<valueHelp>
<format>u32:0-1048575</format>
<description>Unique identifier of an ERSPAN engine</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-1048575"/>
</constraint>
</properties>
</leafNode>
<leafNode name="index">
<properties>
<help>ERSPAN version 1 index field</help>
<valueHelp>
<format>u32:0-63</format>
<description>Platform-depedent field for specifying port number and direction</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-63"/>
</constraint>
</properties>
</leafNode>
<leafNode name="version">
<properties>
<help>Protocol version</help>
<completionHelp>
<list>1 2</list>
</completionHelp>
<valueHelp>
<format>1</format>
<description>ERSPAN Type II</description>
</valueHelp>
<valueHelp>
<format>2</format>
<description>ERSPAN Type III</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-2"/>
</constraint>
</properties>
<defaultValue>1</defaultValue>
</leafNode>
</children>
</node>
<node name="ip">
<properties>
<help>IPv4-specific tunnel parameters</help>
</properties>
<children>
<leafNode name="no-pmtu-discovery">
<properties>
<help>Disable path MTU discovery</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="ignore-df">
<properties>
<help>Ignore the DF (don't fragment) bit</help>
<valueless/>
</properties>
</leafNode>
#include <include/interface/parameters-key.xml.i>
#include <include/interface/parameters-tos.xml.i>
#include <include/interface/parameters-ttl.xml.i>
<leafNode name="ttl">
<defaultValue>64</defaultValue>
</leafNode>
</children>
</node>
<node name="ipv6">
<properties>
<help>IPv6-specific tunnel parameters</help>
</properties>
<children>
<leafNode name="encaplimit">
<properties>
<help>Set fixed encapsulation limit</help>
<completionHelp>
<list>none</list>
</completionHelp>
<valueHelp>
<format>u32:0-255</format>
<description>Encapsulation limit</description>
</valueHelp>
<valueHelp>
<format>none</format>
<description>Disable encapsulation limit</description>
</valueHelp>
<constraint>
<regex>(none)</regex>
<validator name="numeric" argument="--range 0-255"/>
</constraint>
<constraintErrorMessage>Tunnel encaplimit must be 0-255 or none</constraintErrorMessage>
</properties>
<defaultValue>4</defaultValue>
</leafNode>
#include <include/interface/parameters-flowlabel.xml.i>
<leafNode name="hoplimit">
<properties>
<help>Hoplimit</help>
<valueHelp>
<format>u32:0-255</format>
<description>Hop limit</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-255"/>
</constraint>
<constraintErrorMessage>hop limit must be between 0-255</constraintErrorMessage>
</properties>
<defaultValue>64</defaultValue>
</leafNode>
<leafNode name="tclass">
<properties>
<help>Traffic class (Tclass)</help>
<valueHelp>
<format>0x0-0x0fffff</format>
<description>Traffic class, 'inherit' or hex value</description>
</valueHelp>
<constraint>
<regex>(0x){0,1}(0?[0-9A-Fa-f]{1,2})</regex>
</constraint>
<constraintErrorMessage>Must be 'inherit' or a number</constraintErrorMessage>
</properties>
<defaultValue>inherit</defaultValue>
</leafNode>
</children>
</node>
</children>
</node>
#include <include/interface/vrf.xml.i>
#include <include/interface/redirect.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-vti.xml.in b/interface-definitions/interfaces-vti.xml.in
index eeaea0dc3..11f001dc0 100644
--- a/interface-definitions/interfaces-vti.xml.in
+++ b/interface-definitions/interfaces-vti.xml.in
@@ -1,33 +1,32 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="vti" owner="${vyos_conf_scripts_dir}/interfaces-vti.py">
<properties>
<help>Virtual Tunnel Interface (XFRM)</help>
<priority>381</priority>
<constraint>
<regex>vti[0-9]+</regex>
</constraint>
<constraintErrorMessage>VTI interface must be named vtiN</constraintErrorMessage>
<valueHelp>
<format>vtiN</format>
<description>VTI interface name</description>
</valueHelp>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6.xml.i>
#include <include/interface/description.xml.i>
#include <include/interface/disable.xml.i>
#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/vrf.xml.i>
- #include <include/interface/interface-policy.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-vxlan.xml.in b/interface-definitions/interfaces-vxlan.xml.in
index 4902ff36d..331f930d3 100644
--- a/interface-definitions/interfaces-vxlan.xml.in
+++ b/interface-definitions/interfaces-vxlan.xml.in
@@ -1,109 +1,108 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="vxlan" owner="${vyos_conf_scripts_dir}/interfaces-vxlan.py">
<properties>
<help>Virtual Extensible LAN (VXLAN) Interface</help>
<priority>460</priority>
<constraint>
<regex>vxlan[0-9]+</regex>
</constraint>
<constraintErrorMessage>VXLAN interface must be named vxlanN</constraintErrorMessage>
<valueHelp>
<format>vxlanN</format>
<description>VXLAN interface name</description>
</valueHelp>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6.xml.i>
#include <include/interface/description.xml.i>
#include <include/interface/disable.xml.i>
<leafNode name="external">
<properties>
<help>Use external control plane</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="gpe">
<properties>
<help>Enable Generic Protocol extension (VXLAN-GPE)</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="group">
<properties>
<help>Multicast group address for VXLAN interface</help>
<valueHelp>
<format>ipv4</format>
<description>Multicast IPv4 group address</description>
</valueHelp>
<valueHelp>
<format>ipv6</format>
<description>Multicast IPv6 group address</description>
</valueHelp>
<constraint>
<validator name="ipv4-multicast"/>
<validator name="ipv6-multicast"/>
</constraint>
<constraintErrorMessage>Multicast IPv4/IPv6 address required</constraintErrorMessage>
</properties>
</leafNode>
#include <include/interface/ipv4-options.xml.i>
#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-policy.xml.i>
<leafNode name="mtu">
<defaultValue>1450</defaultValue>
</leafNode>
<node name="parameters">
<properties>
<help>VXLAN tunnel parameters</help>
</properties>
<children>
<node name="ip">
<properties>
<help>IPv4 specific tunnel parameters</help>
</properties>
<children>
#include <include/interface/parameters-df.xml.i>
#include <include/interface/parameters-tos.xml.i>
#include <include/interface/parameters-ttl.xml.i>
<leafNode name="ttl">
<defaultValue>16</defaultValue>
</leafNode>
</children>
</node>
<node name="ipv6">
<properties>
<help>IPv6 specific tunnel parameters</help>
</properties>
<children>
#include <include/interface/parameters-flowlabel.xml.i>
</children>
</node>
<leafNode name="nolearning">
<properties>
<help>Do not add unknown addresses into forwarding database</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
#include <include/port-number.xml.i>
<leafNode name="port">
<defaultValue>8472</defaultValue>
</leafNode>
#include <include/source-address-ipv4-ipv6.xml.i>
#include <include/source-interface.xml.i>
#include <include/interface/tunnel-remote-multi.xml.i>
#include <include/interface/redirect.xml.i>
#include <include/interface/vrf.xml.i>
#include <include/vni.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-wireguard.xml.in b/interface-definitions/interfaces-wireguard.xml.in
index 23f50d146..35e223588 100644
--- a/interface-definitions/interfaces-wireguard.xml.in
+++ b/interface-definitions/interfaces-wireguard.xml.in
@@ -1,128 +1,127 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="wireguard" owner="${vyos_conf_scripts_dir}/interfaces-wireguard.py">
<properties>
<help>WireGuard Interface</help>
<priority>459</priority>
<constraint>
<regex>wg[0-9]+</regex>
</constraint>
<constraintErrorMessage>WireGuard interface must be named wgN</constraintErrorMessage>
<valueHelp>
<format>wgN</format>
<description>WireGuard interface name</description>
</valueHelp>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6.xml.i>
#include <include/interface/description.xml.i>
#include <include/interface/disable.xml.i>
#include <include/port-number.xml.i>
#include <include/interface/mtu-68-16000.xml.i>
- #include <include/interface/interface-policy.xml.i>
#include <include/interface/mirror.xml.i>
<leafNode name="mtu">
<defaultValue>1420</defaultValue>
</leafNode>
#include <include/interface/ipv4-options.xml.i>
#include <include/interface/ipv6-options.xml.i>
<leafNode name="fwmark">
<properties>
<help>A 32-bit fwmark value set on all outgoing packets</help>
<valueHelp>
<format>number</format>
<description>value which marks the packet for QoS/shaper</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4294967295"/>
</constraint>
</properties>
<defaultValue>0</defaultValue>
</leafNode>
<leafNode name="private-key">
<properties>
<help>Base64 encoded private key</help>
<constraint>
<regex>[0-9a-zA-Z\+/]{43}=</regex>
</constraint>
<constraintErrorMessage>Key is not valid 44-character (32-bytes) base64</constraintErrorMessage>
</properties>
</leafNode>
<tagNode name="peer">
<properties>
<help>peer alias</help>
<constraint>
<regex>[^ ]{1,100}</regex>
</constraint>
<constraintErrorMessage>peer alias too long (limit 100 characters)</constraintErrorMessage>
</properties>
<children>
#include <include/generic-disable-node.xml.i>
<leafNode name="public-key">
<properties>
<help>base64 encoded public key</help>
<constraint>
<regex>[0-9a-zA-Z\+/]{43}=</regex>
</constraint>
<constraintErrorMessage>Key is not valid 44-character (32-bytes) base64</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="preshared-key">
<properties>
<help>base64 encoded preshared key</help>
<constraint>
<regex>[0-9a-zA-Z\+/]{43}=</regex>
</constraint>
<constraintErrorMessage>Key is not valid 44-character (32-bytes) base64</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="allowed-ips">
<properties>
<help>IP addresses allowed to traverse the peer</help>
<constraint>
<validator name="ip-prefix"/>
</constraint>
<multi/>
</properties>
</leafNode>
<leafNode name="address">
<properties>
<help>IP address of tunnel endpoint</help>
<valueHelp>
<format>ipv4</format>
<description>IPv4 address of remote tunnel endpoint</description>
</valueHelp>
<valueHelp>
<format>ipv6</format>
<description>IPv6 address of remote tunnel endpoint</description>
</valueHelp>
<constraint>
<validator name="ip-address"/>
<validator name="ipv6-link-local"/>
</constraint>
</properties>
</leafNode>
#include <include/port-number.xml.i>
<leafNode name="persistent-keepalive">
<properties>
<help>Interval to send keepalive messages</help>
<valueHelp>
<format>u32:1-65535</format>
<description>Interval in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
</leafNode>
</children>
</tagNode>
#include <include/interface/redirect.xml.i>
#include <include/interface/vrf.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-wireless.xml.in b/interface-definitions/interfaces-wireless.xml.in
index 9e7fc29bc..5271df624 100644
--- a/interface-definitions/interfaces-wireless.xml.in
+++ b/interface-definitions/interfaces-wireless.xml.in
@@ -1,789 +1,788 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="wireless" owner="${vyos_conf_scripts_dir}/interfaces-wireless.py">
<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>
<constraintErrorMessage>Wireless interface must be named wlanN</constraintErrorMessage>
<valueHelp>
<format>wlanN</format>
<description>Wireless (WiFi/WLAN) interface name</description>
</valueHelp>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
- #include <include/interface/interface-policy.xml.i>
<node name="capabilities">
<properties>
<help>HT and VHT capabilities for your card</help>
</properties>
<children>
<node name="ht">
<properties>
<help>HT (High Throughput) settings</help>
</properties>
<children>
<leafNode name="40mhz-incapable">
<properties>
<help>40MHz intolerance, use 20MHz only!</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="auto-powersave">
<properties>
<help>Enable WMM-PS unscheduled automatic power aave delivery [U-APSD]</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="channel-set-width">
<properties>
<help>Supported channel set width</help>
<completionHelp>
<list>ht20 ht40+ ht40-</list>
</completionHelp>
<valueHelp>
<format>ht20</format>
<description>Supported channel set width both 20 MHz only</description>
</valueHelp>
<valueHelp>
<format>ht40+</format>
<description>Supported channel set width both 20 MHz and 40 MHz with secondary channel above primary channel</description>
</valueHelp>
<valueHelp>
<format>ht40-</format>
<description>Supported channel set width both 20 MHz and 40 MHz with secondary channel below primary channel</description>
</valueHelp>
<constraint>
<regex>(ht20|ht40\+|ht40-)</regex>
</constraint>
<multi/>
</properties>
</leafNode>
<leafNode name="delayed-block-ack">
<properties>
<help>Enable HT-delayed block ack</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="dsss-cck-40">
<properties>
<help>Enable DSSS_CCK-40</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="greenfield">
<properties>
<help>Enable HT-greenfield</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="ldpc">
<properties>
<help>Enable LDPC coding capability</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="lsig-protection">
<properties>
<help>Enable L-SIG TXOP protection capability</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="max-amsdu">
<properties>
<help>Set maximum A-MSDU length</help>
<completionHelp>
<list>3839 7935</list>
</completionHelp>
<valueHelp>
<format>3839</format>
<description>Set maximum A-MSDU length to 3839 octets</description>
</valueHelp>
<valueHelp>
<format>7935</format>
<description>Set maximum A-MSDU length to 7935 octets</description>
</valueHelp>
<constraint>
<regex>(3839|7935)</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="short-gi">
<properties>
<help>Short GI capabilities</help>
<completionHelp>
<list>20 40</list>
</completionHelp>
<valueHelp>
<format>20</format>
<description>Short GI for 20 MHz</description>
</valueHelp>
<valueHelp>
<format>40</format>
<description>Short GI for 40 MHz</description>
</valueHelp>
<constraint>
<regex>(20|40)</regex>
</constraint>
<multi/>
</properties>
</leafNode>
<leafNode name="smps">
<properties>
<help>Spatial Multiplexing Power Save (SMPS) settings</help>
<completionHelp>
<list>static dynamic</list>
</completionHelp>
<valueHelp>
<format>static</format>
<description>STATIC Spatial Multiplexing (SM) Power Save</description>
</valueHelp>
<valueHelp>
<format>dynamic</format>
<description>DYNAMIC Spatial Multiplexing (SM) Power Save</description>
</valueHelp>
<constraint>
<regex>(static|dynamic)</regex>
</constraint>
</properties>
</leafNode>
<node name="stbc">
<properties>
<help>Support for sending and receiving PPDU using STBC (Space Time Block Coding)</help>
</properties>
<children>
<leafNode name="rx">
<properties>
<help>Enable receiving PPDU using STBC (Space Time Block Coding)</help>
<valueHelp>
<format>[1-3]+</format>
<description>Number of spacial streams that can use RX STBC</description>
</valueHelp>
<constraint>
<regex>[1-3]+</regex>
</constraint>
<constraintErrorMessage>Invalid capability item</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="tx">
<properties>
<help>Enable sending PPDU using STBC (Space Time Block Coding)</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
</children>
</node>
<leafNode name="require-ht">
<properties>
<help>Require stations to support HT PHY (reject association if they do not)</help>
<completionHelp>
<script>echo If you reject non-HT, you also disable 802.11g</script>
</completionHelp>
<valueless/>
</properties>
</leafNode>
<leafNode name="require-vht">
<properties>
<help>Require stations to support VHT PHY (reject association if they do not)</help>
<completionHelp>
<script>echo If you reject non-VHT, you also disable 802.11n</script>
</completionHelp>
<valueless/>
</properties>
</leafNode>
<node name="vht">
<properties>
<help>VHT (Very High Throughput) settings</help>
</properties>
<children>
<leafNode name="antenna-count">
<properties>
<help>Number of antennas on this card</help>
<valueHelp>
<format>u32:1-8</format>
<description>Number of antennas for this card</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-8"/>
</constraint>
</properties>
</leafNode>
<leafNode name="antenna-pattern-fixed">
<properties>
<help>Set if antenna pattern does not change during the lifetime of an association</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="beamform">
<properties>
<help>Beamforming capabilities</help>
<completionHelp>
<list>single-user-beamformer single-user-beamformee multi-user-beamformer multi-user-beamformee</list>
</completionHelp>
<valueHelp>
<format>single-user-beamformer</format>
<description>Support for operation as single user beamformer</description>
</valueHelp>
<valueHelp>
<format>single-user-beamformee</format>
<description>Support for operation as single user beamformee</description>
</valueHelp>
<valueHelp>
<format>multi-user-beamformer</format>
<description>Support for operation as multi user beamformer</description>
</valueHelp>
<valueHelp>
<format>multi-user-beamformee</format>
<description>Support for operation as multi user beamformee</description>
</valueHelp>
<constraint>
<regex>(single-user-beamformer|single-user-beamformee|multi-user-beamformer|multi-user-beamformee)</regex>
</constraint>
<multi/>
</properties>
</leafNode>
<node name="center-channel-freq">
<properties>
<help>VHT operating channel center frequency</help>
</properties>
<children>
<leafNode name="freq-1">
<properties>
<help>VHT operating channel center frequency - center freq 1 (for use with 80, 80+80 and 160 modes)</help>
<valueHelp>
<format>u32:34-173</format>
<description>5Ghz (802.11 a/h/j/n/ac) center channel index (use 42 for primary 80MHz channel 36)</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 34-173"/>
</constraint>
<constraintErrorMessage>Channel center value must be between 34 and 173</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="freq-2">
<properties>
<help>VHT operating channel center frequency - center freq 2 (for use with the 80+80 mode)</help>
<valueHelp>
<format>u32:34-173</format>
<description>5Ghz (802.11 a/h/j/n/ac) center channel index (use 58 for primary 80MHz channel 52)</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 34-173"/>
</constraint>
<constraintErrorMessage>Channel center value must be between 34 and 173</constraintErrorMessage>
</properties>
</leafNode>
</children>
</node>
<leafNode name="channel-set-width">
<properties>
<help>VHT operating Channel width</help>
<completionHelp>
<list>0 1 2 3</list>
</completionHelp>
<valueHelp>
<format>0</format>
<description>20 or 40 MHz channel width</description>
</valueHelp>
<valueHelp>
<format>1</format>
<description>80 MHz channel width</description>
</valueHelp>
<valueHelp>
<format>2</format>
<description>160 MHz channel width</description>
</valueHelp>
<valueHelp>
<format>3</format>
<description>80+80 MHz channel width</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-3"/>
</constraint>
</properties>
</leafNode>
<leafNode name="ldpc">
<properties>
<help>Enable LDPC (Low Density Parity Check) coding capability</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="link-adaptation">
<properties>
<help>VHT link adaptation capabilities</help>
<completionHelp>
<list>unsolicited both</list>
</completionHelp>
<valueHelp>
<format>unsolicited</format>
<description>Station provides only unsolicited VHT MFB</description>
</valueHelp>
<valueHelp>
<format>both</format>
<description>Station can provide VHT MFB in response to VHT MRQ and unsolicited VHT MFB</description>
</valueHelp>
<constraint>
<regex>(unsolicited|both)</regex>
</constraint>
<constraintErrorMessage>Invalid capability item</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="max-mpdu-exp">
<properties>
<help>Set the maximum length of A-MPDU pre-EOF padding that the station can receive</help>
<valueHelp>
<format>u32:0-7</format>
<description>Maximum length of A-MPDU pre-EOF padding = 2 pow(13 + x) -1 octets</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-7"/>
</constraint>
</properties>
</leafNode>
<leafNode name="max-mpdu">
<properties>
<help>Increase Maximum MPDU length to 7991 or 11454 octets (otherwise: 3895 octets)</help>
<completionHelp>
<list>7991 11454</list>
</completionHelp>
<valueHelp>
<format>7991</format>
<description>ncrease Maximum MPDU length to 7991 octets</description>
</valueHelp>
<valueHelp>
<format>11454</format>
<description>ncrease Maximum MPDU length to 11454 octets</description>
</valueHelp>
<constraint>
<regex>(7991|11454)</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="short-gi">
<properties>
<help>Short GI capabilities</help>
<completionHelp>
<list>80 160</list>
</completionHelp>
<valueHelp>
<format>80</format>
<description>Short GI for 80 MHz</description>
</valueHelp>
<valueHelp>
<format>160</format>
<description>Short GI for 160 MHz</description>
</valueHelp>
<constraint>
<regex>(80|160)</regex>
</constraint>
<multi/>
</properties>
</leafNode>
<node name="stbc">
<properties>
<help>Support for sending and receiving PPDU using STBC (Space Time Block Coding)</help>
</properties>
<children>
<leafNode name="rx">
<properties>
<help>Enable receiving PPDU using STBC (Space Time Block Coding)</help>
<valueHelp>
<format>[1-4]+</format>
<description>Number of spacial streams that can use RX STBC</description>
</valueHelp>
<constraint>
<regex>[1-4]+</regex>
</constraint>
<constraintErrorMessage>Invalid capability item</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="tx">
<properties>
<help>Enable sending PPDU using STBC (Space Time Block Coding)</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
<leafNode name="tx-powersave">
<properties>
<help>Enable VHT TXOP Power Save Mode</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="vht-cf">
<properties>
<help>Station supports receiving VHT variant HT Control field</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
</children>
</node>
<leafNode name="channel">
<properties>
<help>Wireless radio channel</help>
<valueHelp>
<format>0</format>
<description>Automatic Channel Selection (ACS)</description>
</valueHelp>
<valueHelp>
<format>u32:1-14</format>
<description>2.4Ghz (802.11 b/g/n) Channel</description>
</valueHelp>
<valueHelp>
<format>u32:34-173</format>
<description>5Ghz (802.11 a/h/j/n/ac) Channel</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-0 --range 1-14 --range 34-173"/>
</constraint>
</properties>
<defaultValue>0</defaultValue>
</leafNode>
<leafNode name="country-code">
<properties>
<help>Indicate country in which device is operating</help>
<completionHelp>
<list>us eu jp de uk cn es fr ru</list>
</completionHelp>
<valueHelp>
<format>txt</format>
<description>ISO/IEC 3166-1 Country Code</description>
</valueHelp>
<constraint>
<regex>[a-z][a-z]</regex>
</constraint>
<constraintErrorMessage>Invalid ISO/IEC 3166-1 Country Code</constraintErrorMessage>
</properties>
</leafNode>
#include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
<leafNode name="disable-broadcast-ssid">
<properties>
<help>Disable broadcast of SSID from access-point</help>
<valueless/>
</properties>
</leafNode>
#include <include/interface/disable-link-detect.xml.i>
#include <include/interface/disable.xml.i>
#include <include/interface/vrf.xml.i>
<leafNode name="expunge-failing-stations">
<properties>
<help>Disassociate stations based on excessive transmission failures</help>
<valueless/>
</properties>
</leafNode>
#include <include/interface/ipv4-options.xml.i>
#include <include/interface/ipv6-options.xml.i>
#include <include/interface/hw-id.xml.i>
<leafNode name="isolate-stations">
<properties>
<help>Isolate stations on the AP so they cannot see each other</help>
<valueless/>
</properties>
</leafNode>
#include <include/interface/mac.xml.i>
<leafNode name="max-stations">
<properties>
<help>Maximum number of wireless radio stations. Excess stations will be rejected upon authentication request.</help>
<valueHelp>
<format>u32:1-2007</format>
<description>Number of allowed stations</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-2007"/>
</constraint>
<constraintErrorMessage>Number of stations must be between 1 and 2007</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="mgmt-frame-protection">
<properties>
<help>Management Frame Protection (MFP) according to IEEE 802.11w</help>
<completionHelp>
<list>disabled optional required</list>
</completionHelp>
<valueHelp>
<format>disabled</format>
<description>no MFP</description>
</valueHelp>
<valueHelp>
<format>optional</format>
<description>MFP optional</description>
</valueHelp>
<valueHelp>
<format>required</format>
<description>MFP enforced</description>
</valueHelp>
<constraint>
<regex>(disabled|optional|required)</regex>
</constraint>
</properties>
<defaultValue>disabled</defaultValue>
</leafNode>
<leafNode name="mode">
<properties>
<help>Wireless radio mode</help>
<completionHelp>
<list>a b g n ac</list>
</completionHelp>
<valueHelp>
<format>a</format>
<description>802.11a - 54 Mbits/sec</description>
</valueHelp>
<valueHelp>
<format>b</format>
<description>802.11b - 11 Mbits/sec</description>
</valueHelp>
<valueHelp>
<format>g</format>
<description>802.11g - 54 Mbits/sec</description>
</valueHelp>
<valueHelp>
<format>n</format>
<description>802.11n - 600 Mbits/sec</description>
</valueHelp>
<valueHelp>
<format>ac</format>
<description>802.11ac - 1300 Mbits/sec</description>
</valueHelp>
<constraint>
<regex>(a|b|g|n|ac)</regex>
</constraint>
</properties>
<defaultValue>g</defaultValue>
</leafNode>
#include <include/interface/mirror.xml.i>
<leafNode name="physical-device">
<properties>
<help>Wireless physical device</help>
<completionHelp>
<script>${vyos_completion_dir}/list_wireless_phys.sh</script>
</completionHelp>
<constraint>
<validator name="wireless-phy"/>
</constraint>
</properties>
<defaultValue>phy0</defaultValue>
</leafNode>
<leafNode name="reduce-transmit-power">
<properties>
<help>Transmission power reduction in dBm</help>
<valueHelp>
<format>u32:0-255</format>
<description>TX power reduction in dBm</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-255"/>
</constraint>
<constraintErrorMessage>dBm value must be between 0 and 255</constraintErrorMessage>
</properties>
</leafNode>
<node name="security">
<properties>
<help>Wireless security settings</help>
</properties>
<children>
<node name="wep">
<properties>
<help>Wired Equivalent Privacy (WEP) parameters</help>
</properties>
<children>
<leafNode name="key">
<properties>
<help>WEP encryption key</help>
<valueHelp>
<format>txt</format>
<description>Wired Equivalent Privacy key</description>
</valueHelp>
<constraint>
<regex>([a-fA-F0-9]{10}|[a-fA-F0-9]{26}|[a-fA-F0-9]{32})</regex>
</constraint>
<constraintErrorMessage>Invalid WEP key</constraintErrorMessage>
<multi/>
</properties>
</leafNode>
</children>
</node>
<node name="wpa">
<properties>
<help>Wifi Protected Access (WPA) parameters</help>
</properties>
<children>
<leafNode name="cipher">
<properties>
<help>Cipher suite for WPA unicast packets</help>
<completionHelp>
<list>GCMP-256 GCMP CCMP-256 CCMP TKIP</list>
</completionHelp>
<valueHelp>
<format>GCMP-256</format>
<description>AES in Galois/counter mode with 256-bit key</description>
</valueHelp>
<valueHelp>
<format>GCMP</format>
<description>AES in Galois/counter mode with 128-bit key</description>
</valueHelp>
<valueHelp>
<format>CCMP-256</format>
<description>AES in Counter mode with CBC-MAC with 256-bit key</description>
</valueHelp>
<valueHelp>
<format>CCMP</format>
<description>AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] (supported on all WPA2 APs)</description>
</valueHelp>
<valueHelp>
<format>TKIP</format>
<description>Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]</description>
</valueHelp>
<constraint>
<regex>(GCMP-256|GCMP|CCMP-256|CCMP|TKIP)</regex>
</constraint>
<constraintErrorMessage>Invalid cipher selection</constraintErrorMessage>
<multi/>
</properties>
</leafNode>
<leafNode name="group-cipher">
<properties>
<help>Cipher suite for WPA multicast and broadcast packets</help>
<completionHelp>
<list>GCMP-256 GCMP CCMP-256 CCMP TKIP</list>
</completionHelp>
<valueHelp>
<format>GCMP-256</format>
<description>AES in Galois/counter mode with 256-bit key</description>
</valueHelp>
<valueHelp>
<format>GCMP</format>
<description>AES in Galois/counter mode with 128-bit key</description>
</valueHelp>
<valueHelp>
<format>CCMP-256</format>
<description>AES in Counter mode with CBC-MAC with 256-bit key</description>
</valueHelp>
<valueHelp>
<format>CCMP</format>
<description>AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] (supported on all WPA2 APs)</description>
</valueHelp>
<valueHelp>
<format>TKIP</format>
<description>Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]</description>
</valueHelp>
<constraint>
<regex>(GCMP-256|GCMP|CCMP-256|CCMP|TKIP)</regex>
</constraint>
<constraintErrorMessage>Invalid group cipher selection</constraintErrorMessage>
<multi/>
</properties>
</leafNode>
<leafNode name="mode">
<properties>
<help>WPA mode</help>
<completionHelp>
<list>wpa wpa2 wpa+wpa2 wpa3</list>
</completionHelp>
<valueHelp>
<format>wpa</format>
<description>WPA (IEEE 802.11i/D3.0)</description>
</valueHelp>
<valueHelp>
<format>wpa2</format>
<description>WPA2 (full IEEE 802.11i/RSN)</description>
</valueHelp>
<valueHelp>
<format>wpa+wpa2</format>
<description>Allow both WPA and WPA2</description>
</valueHelp>
<constraint>
<regex>(wpa|wpa2|wpa\+wpa2|wpa3)</regex>
</constraint>
<constraintErrorMessage>Unknown WPA mode</constraintErrorMessage>
</properties>
<defaultValue>wpa+wpa2</defaultValue>
</leafNode>
<leafNode name="passphrase">
<properties>
<help>WPA personal shared pass phrase. If you are using special characters in the WPA passphrase then single quotes are required.</help>
<valueHelp>
<format>txt</format>
<description>Passphrase of at least 8 but not more than 63 printable characters</description>
</valueHelp>
<constraint>
<regex>.{8,63}</regex>
</constraint>
<constraintErrorMessage>Invalid WPA pass phrase, must be 8 to 63 printable characters!</constraintErrorMessage>
</properties>
</leafNode>
#include <include/radius-server-ipv4.xml.i>
<node name="radius">
<children>
<tagNode name="server">
<children>
<leafNode name="accounting">
<properties>
<help>Enable RADIUS server to receive accounting info</help>
<valueless/>
</properties>
</leafNode>
</children>
</tagNode>
</children>
</node>
</children>
</node>
</children>
</node>
<leafNode name="ssid">
<properties>
<help>Wireless access-point service set identifier (SSID)</help>
<constraint>
<regex>.{1,32}</regex>
</constraint>
<constraintErrorMessage>Invalid SSID</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="type">
<properties>
<help>Wireless device type for this interface</help>
<completionHelp>
<list>access-point station monitor</list>
</completionHelp>
<valueHelp>
<format>access-point</format>
<description>Access-point forwards packets between other nodes</description>
</valueHelp>
<valueHelp>
<format>station</format>
<description>Connects to another access point</description>
</valueHelp>
<valueHelp>
<format>monitor</format>
<description>Passively monitor all packets on the frequency/channel</description>
</valueHelp>
<constraint>
<regex>(access-point|station|monitor)</regex>
</constraint>
<constraintErrorMessage>Type must be access-point, station or monitor</constraintErrorMessage>
</properties>
<defaultValue>monitor</defaultValue>
</leafNode>
#include <include/interface/redirect.xml.i>
#include <include/interface/vif.xml.i>
#include <include/interface/vif-s.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/interfaces-wwan.xml.in b/interface-definitions/interfaces-wwan.xml.in
index b0b8367dc..758784540 100644
--- a/interface-definitions/interfaces-wwan.xml.in
+++ b/interface-definitions/interfaces-wwan.xml.in
@@ -1,49 +1,48 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="wwan" owner="${vyos_conf_scripts_dir}/interfaces-wwan.py">
<properties>
<help>Wireless Modem (WWAN) Interface</help>
<priority>350</priority>
<completionHelp>
<script>cd /sys/class/net; if compgen -G "wwan*" > /dev/null; then ls -d wwan*; fi</script>
</completionHelp>
<constraint>
<regex>wwan[0-9]+</regex>
</constraint>
<constraintErrorMessage>Wireless Modem interface must be named wwanN</constraintErrorMessage>
<valueHelp>
<format>wwanN</format>
<description>Wireless Wide Area Network interface name</description>
</valueHelp>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
<leafNode name="apn">
<properties>
<help>Access Point Name (APN)</help>
</properties>
</leafNode>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
#include <include/interface/authentication.xml.i>
#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>
</leafNode>
#include <include/interface/ipv4-options.xml.i>
#include <include/interface/ipv6-options.xml.i>
#include <include/interface/dial-on-demand.xml.i>
- #include <include/interface/interface-policy.xml.i>
#include <include/interface/redirect.xml.i>
#include <include/interface/vrf.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/policy-route.xml.in b/interface-definitions/policy-route.xml.in
index 44b96c2e6..48a5bf7d1 100644
--- a/interface-definitions/policy-route.xml.in
+++ b/interface-definitions/policy-route.xml.in
@@ -1,113 +1,115 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="policy">
<children>
<tagNode name="route6" owner="${vyos_conf_scripts_dir}/policy-route.py">
<properties>
<help>Policy route rule set name for IPv6</help>
<constraint>
<regex>[a-zA-Z0-9][\w\-\.]*</regex>
</constraint>
<priority>201</priority>
</properties>
<children>
#include <include/generic-description.xml.i>
+ #include <include/generic-interface-multi.xml.i>
#include <include/firewall/enable-default-log.xml.i>
<tagNode name="rule">
<properties>
<help>Policy rule number</help>
<valueHelp>
<format>u32:1-999999</format>
<description>Number of policy rule</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-999999"/>
</constraint>
<constraintErrorMessage>Policy rule number must be between 1 and 999999</constraintErrorMessage>
</properties>
<children>
<node name="destination">
<properties>
<help>Destination parameters</help>
</properties>
<children>
#include <include/firewall/address-ipv6.xml.i>
#include <include/firewall/source-destination-group-ipv6.xml.i>
#include <include/firewall/port.xml.i>
</children>
</node>
<node name="source">
<properties>
<help>Source parameters</help>
</properties>
<children>
#include <include/firewall/address-ipv6.xml.i>
#include <include/firewall/source-destination-group-ipv6.xml.i>
#include <include/firewall/port.xml.i>
</children>
</node>
#include <include/policy/route-common.xml.i>
#include <include/policy/route-ipv6.xml.i>
#include <include/firewall/dscp.xml.i>
#include <include/firewall/packet-length.xml.i>
#include <include/firewall/hop-limit.xml.i>
</children>
</tagNode>
</children>
</tagNode>
<tagNode name="route" owner="${vyos_conf_scripts_dir}/policy-route.py">
<properties>
<help>Policy route rule set name for IPv4</help>
<constraint>
<regex>[a-zA-Z0-9][\w\-\.]*</regex>
</constraint>
<priority>201</priority>
</properties>
<children>
#include <include/generic-description.xml.i>
+ #include <include/generic-interface-multi.xml.i>
#include <include/firewall/enable-default-log.xml.i>
<tagNode name="rule">
<properties>
<help>Policy rule number</help>
<valueHelp>
<format>u32:1-999999</format>
<description>Number of policy rule</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-999999"/>
</constraint>
<constraintErrorMessage>Policy rule number must be between 1 and 999999</constraintErrorMessage>
</properties>
<children>
<node name="destination">
<properties>
<help>Destination parameters</help>
</properties>
<children>
#include <include/firewall/address.xml.i>
#include <include/firewall/source-destination-group.xml.i>
#include <include/firewall/port.xml.i>
</children>
</node>
<node name="source">
<properties>
<help>Source parameters</help>
</properties>
<children>
#include <include/firewall/address.xml.i>
#include <include/firewall/source-destination-group.xml.i>
#include <include/firewall/port.xml.i>
</children>
</node>
#include <include/policy/route-common.xml.i>
#include <include/policy/route-ipv4.xml.i>
#include <include/firewall/dscp.xml.i>
#include <include/firewall/packet-length.xml.i>
#include <include/firewall/ttl.xml.i>
</children>
</tagNode>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/smoketest/scripts/cli/test_policy_route.py b/smoketest/scripts/cli/test_policy_route.py
index 046e385bb..11b3c678e 100755
--- a/smoketest/scripts/cli/test_policy_route.py
+++ b/smoketest/scripts/cli/test_policy_route.py
@@ -1,238 +1,246 @@
#!/usr/bin/env python3
#
# 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
# 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 unittest
from base_vyostest_shim import VyOSUnitTestSHIM
from vyos.util import cmd
mark = '100'
table_mark_offset = 0x7fffffff
table_id = '101'
interface = 'eth0'
interface_ip = '172.16.10.1/24'
class TestPolicyRoute(VyOSUnitTestSHIM.TestCase):
@classmethod
def setUpClass(cls):
super(TestPolicyRoute, cls).setUpClass()
cls.cli_set(cls, ['interfaces', 'ethernet', interface, 'address', interface_ip])
cls.cli_set(cls, ['protocols', 'static', 'table', table_id, 'route', '0.0.0.0/0', 'interface', interface])
@classmethod
def tearDownClass(cls):
cls.cli_delete(cls, ['interfaces', 'ethernet', interface, 'address', interface_ip])
cls.cli_delete(cls, ['protocols', 'static', 'table', table_id])
super(TestPolicyRoute, cls).tearDownClass()
def tearDown(self):
- self.cli_delete(['interfaces', 'ethernet', interface, 'policy'])
self.cli_delete(['policy', 'route'])
self.cli_delete(['policy', 'route6'])
self.cli_commit()
+ # Verify nftables cleanup
nftables_search = [
['set N_smoketest_network'],
['set N_smoketest_network1'],
['chain VYOS_PBR_smoketest']
]
- self.verify_nftables(nftables_search, 'ip mangle', inverse=True)
+ self.verify_nftables(nftables_search, 'ip vyos_mangle', inverse=True)
+
+ # Verify ip rule cleanup
+ ip_rule_search = [
+ ['fwmark ' + hex(table_mark_offset - int(table_id)), 'lookup ' + table_id]
+ ]
+
+ self.verify_rules(ip_rule_search, inverse=True)
def verify_nftables(self, nftables_search, table, inverse=False):
nftables_output = cmd(f'sudo nft list table {table}')
for search in nftables_search:
matched = False
for line in nftables_output.split("\n"):
if all(item in line for item in search):
matched = True
break
self.assertTrue(not matched if inverse else matched, msg=search)
+ def verify_rules(self, rules_search, inverse=False):
+ rule_output = cmd('ip rule show')
+
+ for search in rules_search:
+ matched = False
+ for line in rule_output.split("\n"):
+ if all(item in line for item in search):
+ matched = True
+ break
+ self.assertTrue(not matched if inverse else matched, msg=search)
+
def test_pbr_group(self):
self.cli_set(['firewall', 'group', 'network-group', 'smoketest_network', 'network', '172.16.99.0/24'])
self.cli_set(['firewall', 'group', 'network-group', 'smoketest_network1', 'network', '172.16.101.0/24'])
self.cli_set(['firewall', 'group', 'network-group', 'smoketest_network1', 'include', 'smoketest_network'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'source', 'group', 'network-group', 'smoketest_network'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'destination', 'group', 'network-group', 'smoketest_network1'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'set', 'mark', mark])
-
- self.cli_set(['interfaces', 'ethernet', interface, 'policy', 'route', 'smoketest'])
+ self.cli_set(['policy', 'route', 'smoketest', 'interface', interface])
self.cli_commit()
nftables_search = [
[f'iifname "{interface}"','jump VYOS_PBR_smoketest'],
['ip daddr @N_smoketest_network1', 'ip saddr @N_smoketest_network'],
]
- self.verify_nftables(nftables_search, 'ip mangle')
+ self.verify_nftables(nftables_search, 'ip vyos_mangle')
self.cli_delete(['firewall'])
def test_pbr_mark(self):
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'source', 'address', '172.16.20.10'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'destination', 'address', '172.16.10.10'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'set', 'mark', mark])
-
- self.cli_set(['interfaces', 'ethernet', interface, 'policy', 'route', 'smoketest'])
+ self.cli_set(['policy', 'route', 'smoketest', 'interface', interface])
self.cli_commit()
mark_hex = "{0:#010x}".format(int(mark))
nftables_search = [
[f'iifname "{interface}"','jump VYOS_PBR_smoketest'],
['ip daddr 172.16.10.10', 'ip saddr 172.16.20.10', 'meta mark set ' + mark_hex],
]
- self.verify_nftables(nftables_search, 'ip mangle')
+ self.verify_nftables(nftables_search, 'ip vyos_mangle')
def test_pbr_table(self):
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'protocol', 'tcp'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'destination', 'port', '8888'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'tcp', 'flags', 'syn'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'tcp', 'flags', 'not', 'ack'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'set', 'table', table_id])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '1', 'protocol', 'tcp_udp'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '1', 'destination', 'port', '8888'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '1', 'set', 'table', table_id])
- self.cli_set(['interfaces', 'ethernet', interface, 'policy', 'route', 'smoketest'])
- self.cli_set(['interfaces', 'ethernet', interface, 'policy', 'route6', 'smoketest6'])
+ self.cli_set(['policy', 'route', 'smoketest', 'interface', interface])
+ self.cli_set(['policy', 'route6', 'smoketest6', 'interface', interface])
self.cli_commit()
mark_hex = "{0:#010x}".format(table_mark_offset - int(table_id))
# IPv4
nftables_search = [
[f'iifname "{interface}"', 'jump VYOS_PBR_smoketest'],
['tcp flags syn / syn,ack', 'tcp dport 8888', 'meta mark set ' + mark_hex]
]
- self.verify_nftables(nftables_search, 'ip mangle')
+ self.verify_nftables(nftables_search, 'ip vyos_mangle')
# IPv6
nftables6_search = [
[f'iifname "{interface}"', 'jump VYOS_PBR6_smoketest'],
['meta l4proto { tcp, udp }', 'th dport 8888', 'meta mark set ' + mark_hex]
]
- self.verify_nftables(nftables6_search, 'ip6 mangle')
+ self.verify_nftables(nftables6_search, 'ip6 vyos_mangle')
# IP rule fwmark -> table
ip_rule_search = [
['fwmark ' + hex(table_mark_offset - int(table_id)), 'lookup ' + table_id]
]
- ip_rule_output = cmd('ip rule show')
-
- for search in ip_rule_search:
- matched = False
- for line in ip_rule_output.split("\n"):
- if all(item in line for item in search):
- matched = True
- break
- self.assertTrue(matched)
+ self.verify_rules(ip_rule_search)
def test_pbr_matching_criteria(self):
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'protocol', 'udp'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'action', 'drop'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '2', 'protocol', 'tcp'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '2', 'tcp', 'flags', 'syn'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '2', 'tcp', 'flags', 'not', 'ack'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '2', 'set', 'table', table_id])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '3', 'source', 'address', '198.51.100.0/24'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '3', 'protocol', 'tcp'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '3', 'destination', 'port', '22'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '3', 'state', 'new', 'enable'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '3', 'ttl', 'gt', '2'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '3', 'set', 'table', table_id])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '4', 'protocol', 'icmp'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '4', 'icmp', 'type-name', 'echo-request'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '4', 'packet-length', '128'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '4', 'packet-length', '1024-2048'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '4', 'log', 'enable'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '4', 'set', 'table', table_id])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '5', 'dscp', '41'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '5', 'dscp', '57-59'])
self.cli_set(['policy', 'route', 'smoketest', 'rule', '5', 'set', 'table', table_id])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '1', 'protocol', 'udp'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '1', 'action', 'drop'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '2', 'protocol', 'tcp'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '2', 'tcp', 'flags', 'syn'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '2', 'tcp', 'flags', 'not', 'ack'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '2', 'set', 'table', table_id])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '3', 'source', 'address', '2001:db8::0/64'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '3', 'protocol', 'tcp'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '3', 'destination', 'port', '22'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '3', 'state', 'new', 'enable'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '3', 'hop-limit', 'gt', '2'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '3', 'set', 'table', table_id])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '4', 'protocol', 'icmpv6'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '4', 'icmpv6', 'type', 'echo-request'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '4', 'packet-length-exclude', '128'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '4', 'packet-length-exclude', '1024-2048'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '4', 'log', 'enable'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '4', 'set', 'table', table_id])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '5', 'dscp-exclude', '61'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '5', 'dscp-exclude', '14-19'])
self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '5', 'set', 'table', table_id])
- self.cli_set(['interfaces', 'ethernet', interface, 'policy', 'route', 'smoketest'])
- self.cli_set(['interfaces', 'ethernet', interface, 'policy', 'route6', 'smoketest6'])
+ self.cli_set(['policy', 'route', 'smoketest', 'interface', interface])
+ self.cli_set(['policy', 'route6', 'smoketest6', 'interface', interface])
self.cli_commit()
mark_hex = "{0:#010x}".format(table_mark_offset - int(table_id))
# IPv4
nftables_search = [
[f'iifname "{interface}"', 'jump VYOS_PBR_smoketest'],
['meta l4proto udp', 'drop'],
['tcp flags syn / syn,ack', 'meta mark set ' + mark_hex],
['ct state new', 'tcp dport 22', 'ip saddr 198.51.100.0/24', 'ip ttl > 2', 'meta mark set ' + mark_hex],
['meta l4proto icmp', 'log prefix "[smoketest-4-A]"', 'icmp type echo-request', 'ip length { 128, 1024-2048 }', 'meta mark set ' + mark_hex],
['ip dscp { 0x29, 0x39-0x3b }', 'meta mark set ' + mark_hex]
]
- self.verify_nftables(nftables_search, 'ip mangle')
+ self.verify_nftables(nftables_search, 'ip vyos_mangle')
# IPv6
nftables6_search = [
[f'iifname "{interface}"', 'jump VYOS_PBR6_smoketest'],
['meta l4proto udp', 'drop'],
['tcp flags syn / syn,ack', 'meta mark set ' + mark_hex],
['ct state new', 'tcp dport 22', 'ip6 saddr 2001:db8::/64', 'ip6 hoplimit > 2', 'meta mark set ' + mark_hex],
['meta l4proto ipv6-icmp', 'log prefix "[smoketest6-4-A]"', 'icmpv6 type echo-request', 'ip6 length != { 128, 1024-2048 }', 'meta mark set ' + mark_hex],
['ip6 dscp != { 0x0e-0x13, 0x3d }', 'meta mark set ' + mark_hex]
]
- self.verify_nftables(nftables6_search, 'ip6 mangle')
+ self.verify_nftables(nftables6_search, 'ip6 vyos_mangle')
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/src/conf_mode/policy-route-interface.py b/src/conf_mode/policy-route-interface.py
deleted file mode 100755
index 58c5fd93d..000000000
--- a/src/conf_mode/policy-route-interface.py
+++ /dev/null
@@ -1,132 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2021 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
-import re
-
-from sys import argv
-from sys import exit
-
-from vyos.config import Config
-from vyos.ifconfig import Section
-from vyos.template import render
-from vyos.util import cmd
-from vyos.util import run
-from vyos import ConfigError
-from vyos import airbag
-airbag.enable()
-
-def get_config(config=None):
- if config:
- conf = config
- else:
- conf = Config()
-
- ifname = argv[1]
- ifpath = Section.get_config_path(ifname)
- if_policy_path = f'interfaces {ifpath} policy'
-
- if_policy = conf.get_config_dict(if_policy_path, key_mangling=('-', '_'), get_first_key=True,
- no_tag_node_value_mangle=True)
-
- if_policy['ifname'] = ifname
- if_policy['policy'] = conf.get_config_dict(['policy'], key_mangling=('-', '_'), get_first_key=True,
- no_tag_node_value_mangle=True)
-
- return if_policy
-
-def verify_chain(table, chain):
- # Verify policy route applied
- code = run(f'nft list chain {table} {chain}')
- return code == 0
-
-def verify(if_policy):
- # bail out early - looks like removal from running config
- if not if_policy:
- return None
-
- for route in ['route', 'route6']:
- if route in if_policy:
- if route not in if_policy['policy']:
- raise ConfigError('Policy route not configured')
-
- route_name = if_policy[route]
-
- if route_name not in if_policy['policy'][route]:
- raise ConfigError(f'Invalid policy route name "{name}"')
-
- nft_prefix = 'VYOS_PBR6_' if route == 'route6' else 'VYOS_PBR_'
- nft_table = 'ip6 mangle' if route == 'route6' else 'ip mangle'
-
- if not verify_chain(nft_table, nft_prefix + route_name):
- raise ConfigError('Policy route did not apply')
-
- return None
-
-def generate(if_policy):
- return None
-
-def cleanup_rule(table, chain, ifname, new_name=None):
- results = cmd(f'nft -a list chain {table} {chain}').split("\n")
- retval = None
- for line in results:
- if f'ifname "{ifname}"' in line:
- if new_name and f'jump {new_name}' in line:
- # new_name is used to clear rules for any previously referenced chains
- # returns true when rule exists and doesn't need to be created
- retval = True
- continue
-
- handle_search = re.search('handle (\d+)', line)
- if handle_search:
- cmd(f'nft delete rule {table} {chain} handle {handle_search[1]}')
- return retval
-
-def apply(if_policy):
- ifname = if_policy['ifname']
-
- route_chain = 'VYOS_PBR_PREROUTING'
- ipv6_route_chain = 'VYOS_PBR6_PREROUTING'
-
- if 'route' in if_policy:
- name = 'VYOS_PBR_' + if_policy['route']
- rule_exists = cleanup_rule('ip mangle', route_chain, ifname, name)
-
- if not rule_exists:
- cmd(f'nft insert rule ip mangle {route_chain} iifname {ifname} counter jump {name}')
- else:
- cleanup_rule('ip mangle', route_chain, ifname)
-
- if 'route6' in if_policy:
- name = 'VYOS_PBR6_' + if_policy['route6']
- rule_exists = cleanup_rule('ip6 mangle', ipv6_route_chain, ifname, name)
-
- if not rule_exists:
- cmd(f'nft insert rule ip6 mangle {ipv6_route_chain} iifname {ifname} counter jump {name}')
- else:
- cleanup_rule('ip6 mangle', ipv6_route_chain, ifname)
-
- return None
-
-if __name__ == '__main__':
- try:
- c = get_config()
- verify(c)
- generate(c)
- apply(c)
- except ConfigError as e:
- print(e)
- exit(1)
diff --git a/src/conf_mode/policy-route.py b/src/conf_mode/policy-route.py
index 00539b9c7..1d016695e 100755
--- a/src/conf_mode/policy-route.py
+++ b/src/conf_mode/policy-route.py
@@ -1,294 +1,194 @@
#!/usr/bin/env python3
#
# Copyright (C) 2021 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
-import re
from json import loads
from sys import exit
from vyos.base import Warning
from vyos.config import Config
from vyos.template import render
from vyos.util import cmd
from vyos.util import dict_search_args
-from vyos.util import dict_search_recursive
from vyos.util import run
from vyos import ConfigError
from vyos import airbag
airbag.enable()
mark_offset = 0x7FFFFFFF
nftables_conf = '/run/nftables_policy.conf'
-ROUTE_PREFIX = 'VYOS_PBR_'
-ROUTE6_PREFIX = 'VYOS_PBR6_'
-
-preserve_chains = [
- 'VYOS_PBR_PREROUTING',
- 'VYOS_PBR_POSTROUTING',
- 'VYOS_PBR6_PREROUTING',
- 'VYOS_PBR6_POSTROUTING'
-]
-
valid_groups = [
'address_group',
+ 'domain_group',
'network_group',
'port_group'
]
-group_set_prefix = {
- 'A_': 'address_group',
- 'A6_': 'ipv6_address_group',
-# 'D_': 'domain_group',
- 'M_': 'mac_group',
- 'N_': 'network_group',
- 'N6_': 'ipv6_network_group',
- 'P_': 'port_group'
-}
-
-def get_policy_interfaces(conf):
- out = {}
- interfaces = conf.get_config_dict(['interfaces'], key_mangling=('-', '_'), get_first_key=True,
- no_tag_node_value_mangle=True)
- def find_interfaces(iftype_conf, output={}, prefix=''):
- for ifname, if_conf in iftype_conf.items():
- if 'policy' in if_conf:
- output[prefix + ifname] = if_conf['policy']
- for vif in ['vif', 'vif_s', 'vif_c']:
- if vif in if_conf:
- output.update(find_interfaces(if_conf[vif], output, f'{prefix}{ifname}.'))
- return output
- for iftype, iftype_conf in interfaces.items():
- out.update(find_interfaces(iftype_conf))
- return out
-
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
base = ['policy']
policy = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True,
no_tag_node_value_mangle=True)
policy['firewall_group'] = conf.get_config_dict(['firewall', 'group'], key_mangling=('-', '_'), get_first_key=True,
no_tag_node_value_mangle=True)
- policy['interfaces'] = get_policy_interfaces(conf)
return policy
def verify_rule(policy, name, rule_conf, ipv6, rule_id):
icmp = 'icmp' if not ipv6 else 'icmpv6'
if icmp in rule_conf:
icmp_defined = False
if 'type_name' in rule_conf[icmp]:
icmp_defined = True
if 'code' in rule_conf[icmp] or 'type' in rule_conf[icmp]:
raise ConfigError(f'{name} rule {rule_id}: Cannot use ICMP type/code with ICMP type-name')
if 'code' in rule_conf[icmp]:
icmp_defined = True
if 'type' not in rule_conf[icmp]:
raise ConfigError(f'{name} rule {rule_id}: ICMP code can only be defined if ICMP type is defined')
if 'type' in rule_conf[icmp]:
icmp_defined = True
if icmp_defined and 'protocol' not in rule_conf or rule_conf['protocol'] != icmp:
raise ConfigError(f'{name} rule {rule_id}: ICMP type/code or type-name can only be defined if protocol is ICMP')
if 'set' in rule_conf:
if 'tcp_mss' in rule_conf['set']:
tcp_flags = dict_search_args(rule_conf, 'tcp', 'flags')
if not tcp_flags or 'syn' not in tcp_flags:
raise ConfigError(f'{name} rule {rule_id}: TCP SYN flag must be set to modify TCP-MSS')
tcp_flags = dict_search_args(rule_conf, 'tcp', 'flags')
if tcp_flags:
if dict_search_args(rule_conf, 'protocol') != 'tcp':
raise ConfigError('Protocol must be tcp when specifying tcp flags')
not_flags = dict_search_args(rule_conf, 'tcp', 'flags', 'not')
if not_flags:
duplicates = [flag for flag in tcp_flags if flag in not_flags]
if duplicates:
raise ConfigError(f'Cannot match a tcp flag as set and not set')
for side in ['destination', 'source']:
if side in rule_conf:
side_conf = rule_conf[side]
if 'group' in side_conf:
- if {'address_group', 'network_group'} <= set(side_conf['group']):
- raise ConfigError('Only one address-group or network-group can be specified')
+ if len({'address_group', 'domain_group', 'network_group'} & set(side_conf['group'])) > 1:
+ raise ConfigError('Only one address-group, domain-group or network-group can be specified')
for group in valid_groups:
if group in side_conf['group']:
group_name = side_conf['group'][group]
if group_name.startswith('!'):
group_name = group_name[1:]
fw_group = f'ipv6_{group}' if ipv6 and group in ['address_group', 'network_group'] else group
error_group = fw_group.replace("_", "-")
group_obj = dict_search_args(policy['firewall_group'], fw_group, group_name)
if group_obj is None:
raise ConfigError(f'Invalid {error_group} "{group_name}" on policy route rule')
if not group_obj:
Warning(f'{error_group} "{group_name}" has no members')
if 'port' in side_conf or dict_search_args(side_conf, 'group', 'port_group'):
if 'protocol' not in rule_conf:
raise ConfigError('Protocol must be defined if specifying a port or port-group')
if rule_conf['protocol'] not in ['tcp', 'udp', 'tcp_udp']:
raise ConfigError('Protocol must be tcp, udp, or tcp_udp when specifying a port or port-group')
def verify(policy):
for route in ['route', 'route6']:
ipv6 = route == 'route6'
if route in policy:
for name, pol_conf in policy[route].items():
if 'rule' in pol_conf:
for rule_id, rule_conf in pol_conf['rule'].items():
verify_rule(policy, name, rule_conf, ipv6, rule_id)
- for ifname, if_policy in policy['interfaces'].items():
- name = dict_search_args(if_policy, 'route')
- ipv6_name = dict_search_args(if_policy, 'route6')
-
- if name and not dict_search_args(policy, 'route', name):
- raise ConfigError(f'Policy route "{name}" is still referenced on interface {ifname}')
-
- if ipv6_name and not dict_search_args(policy, 'route6', ipv6_name):
- raise ConfigError(f'Policy route6 "{ipv6_name}" is still referenced on interface {ifname}')
-
return None
-def cleanup_commands(policy):
- commands = []
- commands_chains = []
- commands_sets = []
- for table in ['ip mangle', 'ip6 mangle']:
- route_node = 'route' if table == 'ip mangle' else 'route6'
- chain_prefix = ROUTE_PREFIX if table == 'ip mangle' else ROUTE6_PREFIX
-
- json_str = cmd(f'nft -t -j list table {table}')
- obj = loads(json_str)
- if 'nftables' not in obj:
- continue
- for item in obj['nftables']:
- if 'chain' in item:
- chain = item['chain']['name']
- if chain in preserve_chains or not chain.startswith("VYOS_PBR"):
- continue
-
- if dict_search_args(policy, route_node, chain.replace(chain_prefix, "", 1)) != None:
- commands.append(f'flush chain {table} {chain}')
- else:
- commands_chains.append(f'delete chain {table} {chain}')
-
- if 'rule' in item:
- rule = item['rule']
- chain = rule['chain']
- handle = rule['handle']
-
- if chain not in preserve_chains:
- continue
-
- target, _ = next(dict_search_recursive(rule['expr'], 'target'))
-
- if target.startswith(chain_prefix):
- if dict_search_args(policy, route_node, target.replace(chain_prefix, "", 1)) == None:
- commands.append(f'delete rule {table} {chain} handle {handle}')
-
- if 'set' in item:
- set_name = item['set']['name']
-
- for prefix, group_type in group_set_prefix.items():
- if set_name.startswith(prefix):
- group_name = set_name.replace(prefix, "", 1)
- if dict_search_args(policy, 'firewall_group', group_type, group_name) != None:
- commands_sets.append(f'flush set {table} {set_name}')
- else:
- commands_sets.append(f'delete set {table} {set_name}')
-
- return commands + commands_chains + commands_sets
-
def generate(policy):
if not os.path.exists(nftables_conf):
policy['first_install'] = True
- else:
- policy['cleanup_commands'] = cleanup_commands(policy)
render(nftables_conf, 'firewall/nftables-policy.j2', policy)
return None
def apply_table_marks(policy):
for route in ['route', 'route6']:
if route in policy:
cmd_str = 'ip' if route == 'route' else 'ip -6'
tables = []
for name, pol_conf in policy[route].items():
if 'rule' in pol_conf:
for rule_id, rule_conf in pol_conf['rule'].items():
set_table = dict_search_args(rule_conf, 'set', 'table')
if set_table:
if set_table == 'main':
set_table = '254'
if set_table in tables:
continue
tables.append(set_table)
table_mark = mark_offset - int(set_table)
cmd(f'{cmd_str} rule add pref {set_table} fwmark {table_mark} table {set_table}')
def cleanup_table_marks():
for cmd_str in ['ip', 'ip -6']:
json_rules = cmd(f'{cmd_str} -j -N rule list')
rules = loads(json_rules)
for rule in rules:
if 'fwmark' not in rule or 'table' not in rule:
continue
fwmark = rule['fwmark']
table = int(rule['table'])
if fwmark[:2] == '0x':
fwmark = int(fwmark, 16)
if (int(fwmark) == (mark_offset - table)):
cmd(f'{cmd_str} rule del fwmark {fwmark} table {table}')
def apply(policy):
install_result = run(f'nft -f {nftables_conf}')
if install_result == 1:
raise ConfigError('Failed to apply policy based routing')
if 'first_install' not in policy:
cleanup_table_marks()
apply_table_marks(policy)
return None
if __name__ == '__main__':
try:
c = get_config()
verify(c)
generate(c)
apply(c)
except ConfigError as e:
print(e)
exit(1)
diff --git a/src/helpers/vyos-domain-resolver.py b/src/helpers/vyos-domain-resolver.py
index 035c208b2..e31d9238e 100755
--- a/src/helpers/vyos-domain-resolver.py
+++ b/src/helpers/vyos-domain-resolver.py
@@ -1,183 +1,183 @@
#!/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 json
import os
import time
from vyos.configdict import dict_merge
from vyos.configquery import ConfigTreeQuery
from vyos.firewall import fqdn_config_parse
from vyos.firewall import fqdn_resolve
from vyos.util import cmd
from vyos.util import commit_in_progress
from vyos.util import dict_search_args
from vyos.util import run
from vyos.xml import defaults
base = ['firewall']
timeout = 300
cache = False
domain_state = {}
ipv4_tables = {
- 'ip mangle',
+ 'ip vyos_mangle',
'ip vyos_filter',
'ip vyos_nat'
}
ipv6_tables = {
- 'ip6 mangle',
+ 'ip6 vyos_mangle',
'ip6 vyos_filter'
}
def get_config(conf):
firewall = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True,
no_tag_node_value_mangle=True)
default_values = defaults(base)
for tmp in ['name', 'ipv6_name']:
if tmp in default_values:
del default_values[tmp]
if 'zone' in default_values:
del default_values['zone']
firewall = dict_merge(default_values, firewall)
global timeout, cache
if 'resolver_interval' in firewall:
timeout = int(firewall['resolver_interval'])
if 'resolver_cache' in firewall:
cache = True
fqdn_config_parse(firewall)
return firewall
def resolve(domains, ipv6=False):
global domain_state
ip_list = set()
for domain in domains:
resolved = fqdn_resolve(domain, ipv6=ipv6)
if resolved and cache:
domain_state[domain] = resolved
elif not resolved:
if domain not in domain_state:
continue
resolved = domain_state[domain]
ip_list = ip_list | resolved
return ip_list
def nft_output(table, set_name, ip_list):
output = [f'flush set {table} {set_name}']
if ip_list:
ip_str = ','.join(ip_list)
output.append(f'add element {table} {set_name} {{ {ip_str} }}')
return output
def nft_valid_sets():
try:
valid_sets = []
sets_json = cmd('nft -j list sets')
sets_obj = json.loads(sets_json)
for obj in sets_obj['nftables']:
if 'set' in obj:
family = obj['set']['family']
table = obj['set']['table']
name = obj['set']['name']
valid_sets.append((f'{family} {table}', name))
return valid_sets
except:
return []
def update(firewall):
conf_lines = []
count = 0
valid_sets = nft_valid_sets()
domain_groups = dict_search_args(firewall, 'group', 'domain_group')
if domain_groups:
for set_name, domain_config in domain_groups.items():
if 'address' not in domain_config:
continue
nft_set_name = f'D_{set_name}'
domains = domain_config['address']
ip_list = resolve(domains, ipv6=False)
for table in ipv4_tables:
if (table, nft_set_name) in valid_sets:
conf_lines += nft_output(table, nft_set_name, ip_list)
ip6_list = resolve(domains, ipv6=True)
for table in ipv6_tables:
if (table, nft_set_name) in valid_sets:
conf_lines += nft_output(table, nft_set_name, ip6_list)
count += 1
for set_name, domain in firewall['ip_fqdn'].items():
table = 'ip vyos_filter'
nft_set_name = f'FQDN_{set_name}'
ip_list = resolve([domain], ipv6=False)
if (table, nft_set_name) in valid_sets:
conf_lines += nft_output(table, nft_set_name, ip_list)
count += 1
for set_name, domain in firewall['ip6_fqdn'].items():
table = 'ip6 vyos_filter'
nft_set_name = f'FQDN_{set_name}'
ip_list = resolve([domain], ipv6=True)
if (table, nft_set_name) in valid_sets:
conf_lines += nft_output(table, nft_set_name, ip_list)
count += 1
nft_conf_str = "\n".join(conf_lines) + "\n"
code = run(f'nft -f -', input=nft_conf_str)
print(f'Updated {count} sets - result: {code}')
if __name__ == '__main__':
print(f'VyOS domain resolver')
count = 1
while commit_in_progress():
if ( count % 60 == 0 ):
print(f'Commit still in progress after {count}s - waiting')
count += 1
time.sleep(1)
conf = ConfigTreeQuery()
firewall = get_config(conf)
print(f'interval: {timeout}s - cache: {cache}')
while True:
update(firewall)
time.sleep(timeout)
diff --git a/src/migration-scripts/policy/4-to-5 b/src/migration-scripts/policy/4-to-5
new file mode 100755
index 000000000..33c9e6ade
--- /dev/null
+++ b/src/migration-scripts/policy/4-to-5
@@ -0,0 +1,92 @@
+#!/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/>.
+
+# T2199: Migrate interface policy nodes to policy route <name> interface <ifname>
+
+import re
+
+from sys import argv
+from sys import exit
+
+from vyos.configtree import ConfigTree
+from vyos.ifconfig import Section
+
+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()
+
+base4 = ['policy', 'route']
+base6 = ['policy', 'route6']
+config = ConfigTree(config_file)
+
+if not config.exists(base4) and not config.exists(base6):
+ # Nothing to do
+ exit(0)
+
+def migrate_interface(config, iftype, ifname, vif=None, vifs=None, vifc=None):
+ if_path = ['interfaces', iftype, ifname]
+ ifname_full = ifname
+
+ if vif:
+ if_path += ['vif', vif]
+ ifname_full = f'{ifname}.{vif}'
+ elif vifs:
+ if_path += ['vif-s', vifs]
+ ifname_full = f'{ifname}.{vifs}'
+ if vifc:
+ if_path += ['vif-c', vifc]
+ ifname_full = f'{ifname}.{vifs}.{vifc}'
+
+ if not config.exists(if_path + ['policy']):
+ return
+
+ if config.exists(if_path + ['policy', 'route']):
+ route_name = config.return_value(if_path + ['policy', 'route'])
+ config.set(base4 + [route_name, 'interface'], value=ifname_full, replace=False)
+
+ if config.exists(if_path + ['policy', 'route6']):
+ route_name = config.return_value(if_path + ['policy', 'route6'])
+ config.set(base6 + [route_name, 'interface'], value=ifname_full, replace=False)
+
+ config.delete(if_path + ['policy'])
+
+for iftype in config.list_nodes(['interfaces']):
+ for ifname in config.list_nodes(['interfaces', iftype]):
+ migrate_interface(config, iftype, ifname)
+
+ if config.exists(['interfaces', iftype, ifname, 'vif']):
+ for vif in config.list_nodes(['interfaces', iftype, ifname, 'vif']):
+ migrate_interface(config, iftype, ifname, vif=vif)
+
+ if config.exists(['interfaces', iftype, ifname, 'vif-s']):
+ for vifs in config.list_nodes(['interfaces', iftype, ifname, 'vif-s']):
+ migrate_interface(config, iftype, ifname, vifs=vifs)
+
+ if config.exists(['interfaces', iftype, ifname, 'vif-s', vifs, 'vif-c']):
+ for vifc in config.list_nodes(['interfaces', iftype, ifname, 'vif-s', vifs, 'vif-c']):
+ migrate_interface(config, iftype, ifname, vifs=vifs, vifc=vifc)
+
+try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+except OSError as e:
+ print("Failed to save the modified config: {}".format(e))
+ exit(1)
diff --git a/src/op_mode/policy_route.py b/src/op_mode/policy_route.py
index 5be40082f..5953786f3 100755
--- a/src/op_mode/policy_route.py
+++ b/src/op_mode/policy_route.py
@@ -1,189 +1,149 @@
#!/usr/bin/env python3
#
# Copyright (C) 2021 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 argparse
import re
import tabulate
from vyos.config import Config
from vyos.util import cmd
from vyos.util import dict_search_args
-def get_policy_interfaces(conf, policy, name=None, ipv6=False):
- interfaces = conf.get_config_dict(['interfaces'], key_mangling=('-', '_'),
- get_first_key=True, no_tag_node_value_mangle=True)
-
- routes = ['route', 'route6']
-
- def parse_if(ifname, if_conf):
- if 'policy' in if_conf:
- for route in routes:
- if route in if_conf['policy']:
- route_name = if_conf['policy'][route]
- name_str = f'({ifname},{route})'
-
- if not name:
- policy[route][route_name]['interface'].append(name_str)
- elif not ipv6 and name == route_name:
- policy['interface'].append(name_str)
-
- for iftype in ['vif', 'vif_s', 'vif_c']:
- if iftype in if_conf:
- for vifname, vif_conf in if_conf[iftype].items():
- parse_if(f'{ifname}.{vifname}', vif_conf)
-
- for iftype, iftype_conf in interfaces.items():
- for ifname, if_conf in iftype_conf.items():
- parse_if(ifname, if_conf)
-
-def get_config_policy(conf, name=None, ipv6=False, interfaces=True):
+def get_config_policy(conf, name=None, ipv6=False):
config_path = ['policy']
if name:
config_path += ['route6' if ipv6 else 'route', name]
policy = conf.get_config_dict(config_path, key_mangling=('-', '_'),
get_first_key=True, no_tag_node_value_mangle=True)
- if policy and interfaces:
- if name:
- policy['interface'] = []
- else:
- if 'route' in policy:
- for route_name, route_conf in policy['route'].items():
- route_conf['interface'] = []
-
- if 'route6' in policy:
- for route_name, route_conf in policy['route6'].items():
- route_conf['interface'] = []
-
- get_policy_interfaces(conf, policy, name, ipv6)
return policy
def get_nftables_details(name, ipv6=False):
suffix = '6' if ipv6 else ''
command = f'sudo nft list chain ip{suffix} mangle VYOS_PBR{suffix}_{name}'
try:
results = cmd(command)
except:
return {}
out = {}
for line in results.split('\n'):
comment_search = re.search(rf'{name}[\- ](\d+|default-action)', line)
if not comment_search:
continue
rule = {}
rule_id = comment_search[1]
counter_search = re.search(r'counter packets (\d+) bytes (\d+)', line)
if counter_search:
rule['packets'] = counter_search[1]
rule['bytes'] = counter_search[2]
rule['conditions'] = re.sub(r'(\b(counter packets \d+ bytes \d+|drop|reject|return|log)\b|comment "[\w\-]+")', '', line).strip()
out[rule_id] = rule
return out
def output_policy_route(name, route_conf, ipv6=False, single_rule_id=None):
ip_str = 'IPv6' if ipv6 else 'IPv4'
print(f'\n---------------------------------\n{ip_str} Policy Route "{name}"\n')
if route_conf['interface']:
print('Active on: {0}\n'.format(" ".join(route_conf['interface'])))
details = get_nftables_details(name, ipv6)
rows = []
if 'rule' in route_conf:
for rule_id, rule_conf in route_conf['rule'].items():
if single_rule_id and rule_id != single_rule_id:
continue
if 'disable' in rule_conf:
continue
action = rule_conf['action'] if 'action' in rule_conf else 'set'
protocol = rule_conf['protocol'] if 'protocol' in rule_conf else 'all'
row = [rule_id, action, protocol]
if rule_id in details:
rule_details = details[rule_id]
row.append(rule_details.get('packets', 0))
row.append(rule_details.get('bytes', 0))
row.append(rule_details['conditions'])
rows.append(row)
if 'default_action' in route_conf and not single_rule_id:
row = ['default', route_conf['default_action'], 'all']
if 'default-action' in details:
rule_details = details['default-action']
row.append(rule_details.get('packets', 0))
row.append(rule_details.get('bytes', 0))
rows.append(row)
if rows:
header = ['Rule', 'Action', 'Protocol', 'Packets', 'Bytes', 'Conditions']
print(tabulate.tabulate(rows, header) + '\n')
def show_policy(ipv6=False):
print('Ruleset Information')
conf = Config()
policy = get_config_policy(conf)
if not policy:
return
if not ipv6 and 'route' in policy:
for route, route_conf in policy['route'].items():
output_policy_route(route, route_conf, ipv6=False)
if ipv6 and 'route6' in policy:
for route, route_conf in policy['route6'].items():
output_policy_route(route, route_conf, ipv6=True)
def show_policy_name(name, ipv6=False):
print('Ruleset Information')
conf = Config()
policy = get_config_policy(conf, name, ipv6)
if policy:
output_policy_route(name, policy, ipv6)
def show_policy_rule(name, rule_id, ipv6=False):
print('Rule Information')
conf = Config()
policy = get_config_policy(conf, name, ipv6)
if policy:
output_policy_route(name, policy, ipv6, rule_id)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--action', help='Action', required=False)
parser.add_argument('--name', help='Policy name', required=False, action='store', nargs='?', default='')
parser.add_argument('--rule', help='Policy Rule ID', required=False)
parser.add_argument('--ipv6', help='IPv6 toggle', action='store_true')
args = parser.parse_args()
if args.action == 'show':
if not args.rule:
show_policy_name(args.name, args.ipv6)
else:
show_policy_rule(args.name, args.rule, args.ipv6)
elif args.action == 'show_all':
show_policy(args.ipv6)

File Metadata

Mime Type
text/x-diff
Expires
Fri, Nov 6, 6:59 AM (17 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4640967
Default Alt Text
(215 KB)

Event Timeline