diff options
77 files changed, 1823 insertions, 40 deletions
@@ -29,6 +29,13 @@ interface_definitions: $(config_xml_obj) # XXX: delete top level node.def's that now live in other packages # IPSec VPN EAP-RADIUS does not support source-address rm -rf $(TMPL_DIR)/vpn/ipsec/remote-access/radius/source-address + + # T4284 neq QoS implementation is not yet live + find $(TMPL_DIR)/interfaces -name traffic-policy -type d -exec rm -rf {} \; + find $(TMPL_DIR)/interfaces -name redirect -type d -exec rm -rf {} \; + rm -rf $(TMPL_DIR)/traffic-policy + rm -rf $(TMPL_DIR)/interfaces/input + # XXX: test if there are empty node.def files - this is not allowed as these # could mask help strings or mandatory priority statements find $(TMPL_DIR) -name node.def -type f -empty -exec false {} + || sh -c 'echo "There are empty node.def files! Check your interface definitions." && exit 1' diff --git a/data/configd-include.json b/data/configd-include.json index c85ab0725..b77d48001 100644 --- a/data/configd-include.json +++ b/data/configd-include.json @@ -48,6 +48,7 @@ "protocols_ripng.py", "protocols_static.py", "protocols_static_multicast.py", +"qos.py", "salt-minion.py", "service_console-server.py", "service_ids_fastnetmon.py", diff --git a/data/templates/frr/isisd.frr.tmpl b/data/templates/frr/isisd.frr.tmpl index b1e3f825b..c68dda443 100644 --- a/data/templates/frr/isisd.frr.tmpl +++ b/data/templates/frr/isisd.frr.tmpl @@ -1,7 +1,7 @@ ! {% if interface is defined and interface is not none %} {% for iface, iface_config in interface.items() %} -interface {{ iface }} {{ 'vrf ' + vrf if vrf is defined and vrf is not none }} +interface {{ iface }} ip router isis VyOS ipv6 router isis VyOS {% if iface_config.bfd is defined %} diff --git a/data/templates/frr/ospf6d.frr.tmpl b/data/templates/frr/ospf6d.frr.tmpl index 8279e5abb..a73c6cac3 100644 --- a/data/templates/frr/ospf6d.frr.tmpl +++ b/data/templates/frr/ospf6d.frr.tmpl @@ -1,7 +1,7 @@ ! {% if interface is defined and interface is not none %} {% for iface, iface_config in interface.items() %} -interface {{ iface }} {{ 'vrf ' + vrf if vrf is defined and vrf is not none }} +interface {{ iface }} {% if iface_config.area is defined and iface_config.area is not none %} ipv6 ospf6 area {{ iface_config.area }} {% endif %} diff --git a/data/templates/frr/ospfd.frr.tmpl b/data/templates/frr/ospfd.frr.tmpl index a6618b6af..59d936b55 100644 --- a/data/templates/frr/ospfd.frr.tmpl +++ b/data/templates/frr/ospfd.frr.tmpl @@ -1,7 +1,7 @@ ! {% if interface is defined and interface is not none %} {% for iface, iface_config in interface.items() %} -interface {{ iface }} {{ 'vrf ' + vrf if vrf is defined and vrf is not none }} +interface {{ iface }} {% if iface_config.authentication is defined and iface_config.authentication is not none %} {% if iface_config.authentication.plaintext_password is defined and iface_config.authentication.plaintext_password is not none %} ip ospf authentication-key {{ iface_config.authentication.plaintext_password }} @@ -97,6 +97,12 @@ router ospf {{ 'vrf ' + vrf if vrf is defined and vrf is not none }} {% endif %} {% endfor %} {% endif %} +{% if area_config.export_list is defined and area_config.export_list is not none %} + area {{ area_id }} export-list {{ area_config.export_list }} +{% endif %} +{% if area_config.import_list is defined and area_config.import_list is not none %} + area {{ area_id }} import-list {{ area_config.import_list }} +{% endif %} {% if area_config.shortcut is defined and area_config.shortcut is not none %} area {{ area_id }} shortcut {{ area_config.shortcut }} {% endif %} diff --git a/data/templates/frr/policy.frr.tmpl b/data/templates/frr/policy.frr.tmpl index 97eb15331..60e15f4fd 100644 --- a/data/templates/frr/policy.frr.tmpl +++ b/data/templates/frr/policy.frr.tmpl @@ -204,7 +204,7 @@ route-map {{ route_map }} {{ rule_config.action }} {{ rule }} match ipv6 address prefix-list {{ rule_config.match.ipv6.address.prefix_list }} {% endif %} {% if rule_config.match.ipv6 is defined and rule_config.match.ipv6.nexthop is defined and rule_config.match.ipv6.nexthop is not none %} - match ipv6 next-hop {{ rule_config.match.ipv6.nexthop }} + match ipv6 next-hop address {{ rule_config.match.ipv6.nexthop }} {% endif %} {% if rule_config.match.large_community is defined and rule_config.match.large_community.large_community_list is defined and rule_config.match.large_community.large_community_list is not none %} match large-community {{ rule_config.match.large_community.large_community_list }} diff --git a/interface-definitions/include/interface/redirect.xml.i b/interface-definitions/include/interface/redirect.xml.i new file mode 100644 index 000000000..3be9ee16b --- /dev/null +++ b/interface-definitions/include/interface/redirect.xml.i @@ -0,0 +1,17 @@ +<!-- include start from interface/redirect.xml.i --> +<leafNode name="redirect"> + <properties> + <help>Incoming packet redirection destination</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>Interface name</description> + </valueHelp> + <constraint> + <validator name="interface-name"/> + </constraint> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/interface/traffic-policy.xml.i b/interface-definitions/include/interface/traffic-policy.xml.i new file mode 100644 index 000000000..cd60b62a5 --- /dev/null +++ b/interface-definitions/include/interface/traffic-policy.xml.i @@ -0,0 +1,43 @@ +<!-- include start from interface/traffic-policy.xml.i --> +<node name="traffic-policy"> + <properties> + <help>Traffic-policy for interface</help> + </properties> + <children> + <leafNode name="in"> + <properties> + <help>Ingress traffic policy for interface</help> + <completionHelp> + <path>traffic-policy drop-tail</path> + <path>traffic-policy fair-queue</path> + <path>traffic-policy fq-codel</path> + <path>traffic-policy limiter</path> + <path>traffic-policy network-emulator</path> + <path>traffic-policy priority-queue</path> + <path>traffic-policy random-detect</path> + <path>traffic-policy rate-control</path> + <path>traffic-policy round-robin</path> + <path>traffic-policy shaper</path> + <path>traffic-policy shaper-hfsc</path> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + </properties> + </leafNode> + <leafNode name="out"> + <properties> + <help>Egress traffic policy for interface</help> + <completionHelp> + <path>traffic-policy</path> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + </properties> + </leafNode> + </children> +</node> +<!-- include end -->
\ No newline at end of file diff --git a/interface-definitions/include/interface/vif-s.xml.i b/interface-definitions/include/interface/vif-s.xml.i index f1a61ff64..59a47b5ff 100644 --- a/interface-definitions/include/interface/vif-s.xml.i +++ b/interface-definitions/include/interface/vif-s.xml.i @@ -64,11 +64,15 @@ #include <include/interface/ipv6-options.xml.i> #include <include/interface/mac.xml.i> #include <include/interface/mtu-68-16000.xml.i> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> #include <include/interface/interface-firewall-vif-c.xml.i> #include <include/interface/interface-policy-vif-c.xml.i> </children> </tagNode> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/include/interface/vif.xml.i b/interface-definitions/include/interface/vif.xml.i index 11ba7e2f8..8a1475711 100644 --- a/interface-definitions/include/interface/vif.xml.i +++ b/interface-definitions/include/interface/vif.xml.i @@ -18,7 +18,6 @@ #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/interface-firewall-vif.xml.i> #include <include/interface/interface-policy-vif.xml.i> <leafNode name="egress-qos"> @@ -51,6 +50,9 @@ #include <include/interface/ipv6-options.xml.i> #include <include/interface/mac.xml.i> #include <include/interface/mtu-68-16000.xml.i> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> + #include <include/interface/vrf.xml.i> </children> </tagNode> <!-- include end --> diff --git a/interface-definitions/include/ospf/protocol-common-config.xml.i b/interface-definitions/include/ospf/protocol-common-config.xml.i index 088bee2de..3a3372e47 100644 --- a/interface-definitions/include/ospf/protocol-common-config.xml.i +++ b/interface-definitions/include/ospf/protocol-common-config.xml.i @@ -256,6 +256,36 @@ </constraint> </properties> </leafNode> + <leafNode name="export-list"> + <properties> + <help>Set the filter for networks announced to other areas</help> + <completionHelp> + <path>policy access-list</path> + </completionHelp> + <valueHelp> + <format>u32</format> + <description>Access-list number</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4294967295"/> + </constraint> + </properties> + </leafNode> + <leafNode name="import-list"> + <properties> + <help>Set the filter for networks from other areas announced</help> + <completionHelp> + <path>policy access-list</path> + </completionHelp> + <valueHelp> + <format>u32</format> + <description>Access-list number</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4294967295"/> + </constraint> + </properties> + </leafNode> <tagNode name="virtual-link"> <properties> <help>Virtual link</help> diff --git a/interface-definitions/include/qos/bandwidth.xml.i b/interface-definitions/include/qos/bandwidth.xml.i new file mode 100644 index 000000000..82af22f42 --- /dev/null +++ b/interface-definitions/include/qos/bandwidth.xml.i @@ -0,0 +1,15 @@ +<!-- include start from qos/bandwidth.xml.i --> +<leafNode name="bandwidth"> + <properties> + <help>Traffic-limit used for this class</help> + <valueHelp> + <format><number></format> + <description>Rate in kbit (kilobit per second)</description> + </valueHelp> + <valueHelp> + <format><number><suffix></format> + <description>Rate with scaling suffix (mbit, mbps, ...)</description> + </valueHelp> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/burst.xml.i b/interface-definitions/include/qos/burst.xml.i new file mode 100644 index 000000000..761618027 --- /dev/null +++ b/interface-definitions/include/qos/burst.xml.i @@ -0,0 +1,16 @@ +<!-- include start from qos/burst.xml.i --> +<leafNode name="burst"> + <properties> + <help>Burst size for this class</help> + <valueHelp> + <format><number></format> + <description>Bytes</description> + </valueHelp> + <valueHelp> + <format><number><suffix></format> + <description>Bytes with scaling suffix (kb, mb, gb)</description> + </valueHelp> + </properties> + <defaultValue>15k</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/codel-quantum.xml.i b/interface-definitions/include/qos/codel-quantum.xml.i new file mode 100644 index 000000000..bc24630b6 --- /dev/null +++ b/interface-definitions/include/qos/codel-quantum.xml.i @@ -0,0 +1,16 @@ +<!-- include start from qos/codel-quantum.xml.i --> +<leafNode name="codel-quantum"> + <properties> + <help>Deficit in the fair queuing algorithm</help> + <valueHelp> + <format>u32:0-1048576</format> + <description>Number of bytes used as 'deficit'</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-1048576"/> + </constraint> + <constraintErrorMessage>Interval must be in range 0 to 1048576</constraintErrorMessage> + </properties> + <defaultValue>1514</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/dscp.xml.i b/interface-definitions/include/qos/dscp.xml.i new file mode 100644 index 000000000..bb90850ac --- /dev/null +++ b/interface-definitions/include/qos/dscp.xml.i @@ -0,0 +1,143 @@ +<!-- include start from qos/dscp.xml.i --> +<leafNode name="dscp"> + <properties> + <help>Match on Differentiated Services Codepoint (DSCP)</help> + <completionHelp> + <list>default reliability throughput lowdelay priority immediate flash flash-override critical internet network AF11 AF12 AF13 AF21 AF22 AF23 AF31 AF32 AF33 AF41 AF42 AF43 CS1 CS2 CS3 CS4 CS5 CS6 CS7 EF</list> + </completionHelp> + <valueHelp> + <format>u32:0-63</format> + <description>Differentiated Services Codepoint (DSCP) value </description> + </valueHelp> + <valueHelp> + <format>default</format> + <description>match DSCP (000000)</description> + </valueHelp> + <valueHelp> + <format>reliability</format> + <description>match DSCP (000001)</description> + </valueHelp> + <valueHelp> + <format>throughput</format> + <description>match DSCP (000010)</description> + </valueHelp> + <valueHelp> + <format>lowdelay</format> + <description>match DSCP (000100)</description> + </valueHelp> + <valueHelp> + <format>priority</format> + <description>match DSCP (001000)</description> + </valueHelp> + <valueHelp> + <format>immediate</format> + <description>match DSCP (010000)</description> + </valueHelp> + <valueHelp> + <format>flash</format> + <description>match DSCP (011000)</description> + </valueHelp> + <valueHelp> + <format>flash-override</format> + <description>match DSCP (100000)</description> + </valueHelp> + <valueHelp> + <format>critical</format> + <description>match DSCP (101000)</description> + </valueHelp> + <valueHelp> + <format>internet</format> + <description>match DSCP (110000)</description> + </valueHelp> + <valueHelp> + <format>network</format> + <description>match DSCP (111000)</description> + </valueHelp> + <valueHelp> + <format>AF11</format> + <description>High-throughput data</description> + </valueHelp> + <valueHelp> + <format>AF12</format> + <description>High-throughput data</description> + </valueHelp> + <valueHelp> + <format>AF13</format> + <description>High-throughput data</description> + </valueHelp> + <valueHelp> + <format>AF21</format> + <description>Low-latency data</description> + </valueHelp> + <valueHelp> + <format>AF22</format> + <description>Low-latency data</description> + </valueHelp> + <valueHelp> + <format>AF23</format> + <description>Low-latency data</description> + </valueHelp> + <valueHelp> + <format>AF31</format> + <description>Multimedia streaming</description> + </valueHelp> + <valueHelp> + <format>AF32</format> + <description>Multimedia streaming</description> + </valueHelp> + <valueHelp> + <format>AF33</format> + <description>Multimedia streaming</description> + </valueHelp> + <valueHelp> + <format>AF41</format> + <description>Multimedia conferencing</description> + </valueHelp> + <valueHelp> + <format>AF42</format> + <description>Multimedia conferencing</description> + </valueHelp> + <valueHelp> + <format>AF43</format> + <description>Multimedia conferencing</description> + </valueHelp> + <valueHelp> + <format>CS1</format> + <description>Low-priority data</description> + </valueHelp> + <valueHelp> + <format>CS2</format> + <description>OAM</description> + </valueHelp> + <valueHelp> + <format>CS3</format> + <description>Broadcast video</description> + </valueHelp> + <valueHelp> + <format>CS4</format> + <description>Real-time interactive</description> + </valueHelp> + <valueHelp> + <format>CS5</format> + <description>Signaling</description> + </valueHelp> + <valueHelp> + <format>CS6</format> + <description>Network control</description> + </valueHelp> + <valueHelp> + <format>CS7</format> + <description></description> + </valueHelp> + <valueHelp> + <format>EF</format> + <description>Expedited Forwarding</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-63"/> + <regex>(default|reliability|throughput|lowdelay|priority|immediate|flash|flash-override|critical|internet|network|AF11|AF12|AF13|AF21|AF22|AF23|AF31|AF32|AF33|AF41|AF42|AF43|CS1|CS2|CS3|CS4|CS5|CS6|CS7|EF)</regex> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 63</constraintErrorMessage> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/flows.xml.i b/interface-definitions/include/qos/flows.xml.i new file mode 100644 index 000000000..a7d7c6422 --- /dev/null +++ b/interface-definitions/include/qos/flows.xml.i @@ -0,0 +1,16 @@ +<!-- include start from qos/flows.xml.i --> +<leafNode name="flows"> + <properties> + <help>Number of flows into which the incoming packets are classified</help> + <valueHelp> + <format>u32:1-65536</format> + <description>Number of flows</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-65536"/> + </constraint> + <constraintErrorMessage>Interval must be in range 1 to 65536</constraintErrorMessage> + </properties> + <defaultValue>1024</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/hfsc-d.xml.i b/interface-definitions/include/qos/hfsc-d.xml.i new file mode 100644 index 000000000..2a513509c --- /dev/null +++ b/interface-definitions/include/qos/hfsc-d.xml.i @@ -0,0 +1,15 @@ +<!-- include start from qos/hfsc-d.xml.i --> +<leafNode name="d"> + <properties> + <help>Service curve delay</help> + <valueHelp> + <format><number></format> + <description>Time in milliseconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-65535"/> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 65535</constraintErrorMessage> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/hfsc-m1.xml.i b/interface-definitions/include/qos/hfsc-m1.xml.i new file mode 100644 index 000000000..749d01f57 --- /dev/null +++ b/interface-definitions/include/qos/hfsc-m1.xml.i @@ -0,0 +1,32 @@ +<!-- include start from qos/hfsc-m1.xml.i --> +<leafNode name="m1"> + <properties> + <help>Linkshare m1 parameter for class traffic</help> + <valueHelp> + <format><number></format> + <description>Rate in kbit (kilobit per second)</description> + </valueHelp> + <valueHelp> + <format><number>%%</format> + <description>Percentage of overall rate</description> + </valueHelp> + <valueHelp> + <format><number>bit</format> + <description>bit(1), kbit(10^3), mbit(10^6), gbit, tbit</description> + </valueHelp> + <valueHelp> + <format><number>ibit</format> + <description>kibit(1024), mibit(1024^2), gibit(1024^3), tbit(1024^4)</description> + </valueHelp> + <valueHelp> + <format><number>ibps</format> + <description>kibps(1024*8), mibps(1024^2*8), gibps, tibps - Byte/sec</description> + </valueHelp> + <valueHelp> + <format><number>bps</format> + <description>bps(8),kbps(8*10^3),mbps(8*10^6), gbps, tbps - Byte/sec</description> + </valueHelp> + </properties> + <defaultValue>100%</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/hfsc-m2.xml.i b/interface-definitions/include/qos/hfsc-m2.xml.i new file mode 100644 index 000000000..24e8f5d63 --- /dev/null +++ b/interface-definitions/include/qos/hfsc-m2.xml.i @@ -0,0 +1,32 @@ +<!-- include start from qos/hfsc-m2.xml.i --> +<leafNode name="m2"> + <properties> + <help>Linkshare m2 parameter for class traffic</help> + <valueHelp> + <format><number></format> + <description>Rate in kbit (kilobit per second)</description> + </valueHelp> + <valueHelp> + <format><number>%%</format> + <description>Percentage of overall rate</description> + </valueHelp> + <valueHelp> + <format><number>bit</format> + <description>bit(1), kbit(10^3), mbit(10^6), gbit, tbit</description> + </valueHelp> + <valueHelp> + <format><number>ibit</format> + <description>kibit(1024), mibit(1024^2), gibit(1024^3), tbit(1024^4)</description> + </valueHelp> + <valueHelp> + <format><number>ibps</format> + <description>kibps(1024*8), mibps(1024^2*8), gibps, tibps - Byte/sec</description> + </valueHelp> + <valueHelp> + <format><number>bps</format> + <description>bps(8),kbps(8*10^3),mbps(8*10^6), gbps, tbps - Byte/sec</description> + </valueHelp> + </properties> + <defaultValue>100%</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/interval.xml.i b/interface-definitions/include/qos/interval.xml.i new file mode 100644 index 000000000..41896ac9c --- /dev/null +++ b/interface-definitions/include/qos/interval.xml.i @@ -0,0 +1,16 @@ +<!-- include start from qos/interval.xml.i --> +<leafNode name="interval"> + <properties> + <help>Interval used to measure the delay</help> + <valueHelp> + <format>u32</format> + <description>Interval in milliseconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4294967295"/> + </constraint> + <constraintErrorMessage>Interval must be in range 0 to 4294967295</constraintErrorMessage> + </properties> + <defaultValue>100</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/match.xml.i b/interface-definitions/include/qos/match.xml.i new file mode 100644 index 000000000..7d89e4460 --- /dev/null +++ b/interface-definitions/include/qos/match.xml.i @@ -0,0 +1,221 @@ +<!-- include start from qos/match.xml.i --> +<tagNode name="match"> + <properties> + <help>Class matching rule name</help> + <constraint> + <regex>[^-].*</regex> + </constraint> + <constraintErrorMessage>Match queue name cannot start with hyphen (-)</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + <node name="ether"> + <properties> + <help>Ethernet header match</help> + </properties> + <children> + <leafNode name="destination"> + <properties> + <help>Ethernet destination address for this match</help> + <valueHelp> + <format>macaddr</format> + <description>MAC address to match</description> + </valueHelp> + <constraint> + <validator name="mac-address"/> + </constraint> + </properties> + </leafNode> + <leafNode name="protocol"> + <properties> + <help>Ethernet protocol for this match</help> + <!-- this refers to /etc/protocols --> + <completionHelp> + <list>all 802.1Q 802_2 802_3 aarp aoe arp atalk dec ip ipv6 ipx lat localtalk rarp snap x25</list> + </completionHelp> + <valueHelp> + <format>u32:0-65535</format> + <description>Ethernet protocol number</description> + </valueHelp> + <valueHelp> + <format>txt</format> + <description>Ethernet protocol name</description> + </valueHelp> + <valueHelp> + <format>all</format> + <description>Any protocol</description> + </valueHelp> + <valueHelp> + <format>ip</format> + <description>Internet IP (IPv4)</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>Internet IP (IPv6)</description> + </valueHelp> + <valueHelp> + <format>arp</format> + <description>Address Resolution Protocol</description> + </valueHelp> + <valueHelp> + <format>atalk</format> + <description>Appletalk</description> + </valueHelp> + <valueHelp> + <format>ipx</format> + <description>Novell Internet Packet Exchange</description> + </valueHelp> + <valueHelp> + <format>802.1Q</format> + <description>802.1Q VLAN tag</description> + </valueHelp> + <constraint> + <validator name="ip-protocol"/> + </constraint> + </properties> + </leafNode> + <leafNode name="source"> + <properties> + <help>Ethernet source address for this match</help> + <valueHelp> + <format>macaddr</format> + <description>MAC address to match</description> + </valueHelp> + <constraint> + <validator name="mac-address"/> + </constraint> + </properties> + </leafNode> + </children> + </node> + #include <include/generic-interface.xml.i> + <node name="ip"> + <properties> + <help>Match IP protocol header</help> + </properties> + <children> + <node name="destination"> + <properties> + <help>Match on destination port or address</help> + </properties> + <children> + <leafNode name="address"> + <properties> + <help>IPv4 destination address for this match</help> + <valueHelp> + <format>ipv4net</format> + <description>IPv4 address and prefix length</description> + </valueHelp> + <constraint> + <validator name="ipv4"/> + </constraint> + </properties> + </leafNode> + #include <include/port-number.xml.i> + </children> + </node> + #include <include/qos/dscp.xml.i> + #include <include/qos/max-length.xml.i> + #include <include/ip-protocol.xml.i> + <node name="source"> + <properties> + <help>Match on source port or address</help> + </properties> + <children> + <leafNode name="address"> + <properties> + <help>IPv4 source address for this match</help> + <valueHelp> + <format>ipv4net</format> + <description>IPv4 address and prefix length</description> + </valueHelp> + <constraint> + <validator name="ipv4"/> + </constraint> + </properties> + </leafNode> + #include <include/port-number.xml.i> + </children> + </node> + #include <include/qos/tcp-flags.xml.i> + </children> + </node> + <node name="ipv6"> + <properties> + <help>Match IPv6 protocol header</help> + </properties> + <children> + <node name="destination"> + <properties> + <help>Match on destination port or address</help> + </properties> + <children> + <leafNode name="address"> + <properties> + <help>IPv6 destination address for this match</help> + <valueHelp> + <format>ipv6net</format> + <description>IPv6 address and prefix length</description> + </valueHelp> + <constraint> + <validator name="ipv6"/> + </constraint> + </properties> + </leafNode> + #include <include/port-number.xml.i> + </children> + </node> + #include <include/qos/dscp.xml.i> + #include <include/qos/max-length.xml.i> + #include <include/ip-protocol.xml.i> + <node name="source"> + <properties> + <help>Match on source port or address</help> + </properties> + <children> + <leafNode name="address"> + <properties> + <help>IPv6 source address for this match</help> + <valueHelp> + <format>ipv6net</format> + <description>IPv6 address and prefix length</description> + </valueHelp> + <constraint> + <validator name="ipv6"/> + </constraint> + </properties> + </leafNode> + #include <include/port-number.xml.i> + </children> + </node> + #include <include/qos/tcp-flags.xml.i> + </children> + </node> + <leafNode name="mark"> + <properties> + <help>Match on mark applied by firewall</help> + <valueHelp> + <format>txt</format> + <description>FW mark to match</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0x0-0xffff"/> + </constraint> + </properties> + </leafNode> + <leafNode name="vif"> + <properties> + <help>Virtual Local Area Network (VLAN) ID for this match</help> + <valueHelp> + <format>u32:0-4095</format> + <description>Virtual Local Area Network (VLAN) tag </description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4095"/> + </constraint> + <constraintErrorMessage>VLAN ID must be between 0 and 4095</constraintErrorMessage> + </properties> + </leafNode> + </children> +</tagNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/max-length.xml.i b/interface-definitions/include/qos/max-length.xml.i new file mode 100644 index 000000000..4cc20f8c4 --- /dev/null +++ b/interface-definitions/include/qos/max-length.xml.i @@ -0,0 +1,15 @@ +<!-- include start from qos/max-length.xml.i --> +<leafNode name="max-length"> + <properties> + <help>Maximum packet length (ipv4)</help> + <valueHelp> + <format>u32:0-65535</format> + <description>Maximum packet/payload length</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-65535"/> + </constraint> + <constraintErrorMessage>Maximum IPv4 total packet length is 65535</constraintErrorMessage> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/queue-limit-1-4294967295.xml.i b/interface-definitions/include/qos/queue-limit-1-4294967295.xml.i new file mode 100644 index 000000000..2f2d44631 --- /dev/null +++ b/interface-definitions/include/qos/queue-limit-1-4294967295.xml.i @@ -0,0 +1,15 @@ +<!-- include start from qos/queue-limit-1-4294967295.xml.i --> +<leafNode name="queue-limit"> + <properties> + <help>Maximum queue size</help> + <valueHelp> + <format>u32:1-4294967295</format> + <description>Queue size in packets</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-4294967295"/> + </constraint> + <constraintErrorMessage>Queue limit must be greater than zero</constraintErrorMessage> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/queue-limit-2-10999.xml.i b/interface-definitions/include/qos/queue-limit-2-10999.xml.i new file mode 100644 index 000000000..7a9c8266b --- /dev/null +++ b/interface-definitions/include/qos/queue-limit-2-10999.xml.i @@ -0,0 +1,16 @@ +<!-- include start from qos/queue-limit.xml.i --> +<leafNode name="queue-limit"> + <properties> + <help>Upper limit of the queue</help> + <valueHelp> + <format>u32:2-10999</format> + <description>Queue size in packets</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 2-10999"/> + </constraint> + <constraintErrorMessage>Queue limit must greater than 1 and less than 11000</constraintErrorMessage> + </properties> + <defaultValue>10240</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/queue-type.xml.i b/interface-definitions/include/qos/queue-type.xml.i new file mode 100644 index 000000000..634f61024 --- /dev/null +++ b/interface-definitions/include/qos/queue-type.xml.i @@ -0,0 +1,30 @@ +<!-- include start from qos/queue-type.xml.i --> +<leafNode name="queue-type"> + <properties> + <help>Queue type for default traffic</help> + <completionHelp> + <list>fq-codel fair-queue drop-tail random-detect</list> + </completionHelp> + <valueHelp> + <format>fq-codel</format> + <description>Fair Queue Codel</description> + </valueHelp> + <valueHelp> + <format>fair-queue</format> + <description>Stochastic Fair Queue (SFQ)</description> + </valueHelp> + <valueHelp> + <format>drop-tail</format> + <description>First-In-First-Out (FIFO)</description> + </valueHelp> + <valueHelp> + <format>random-detect</format> + <description>Random Early Detection (RED)</description> + </valueHelp> + <constraint> + <regex>(fq-codel|fair-queue|drop-tail|random-detect)</regex> + </constraint> + </properties> + <defaultValue>drop-tail</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/set-dscp.xml.i b/interface-definitions/include/qos/set-dscp.xml.i new file mode 100644 index 000000000..55c0ea44d --- /dev/null +++ b/interface-definitions/include/qos/set-dscp.xml.i @@ -0,0 +1,63 @@ +<!-- include start from qos/set-dscp.xml.i --> +<leafNode name="set-dscp"> + <properties> + <help>Change the Differentiated Services (DiffServ) field in the IP header</help> + <completionHelp> + <list>default reliability throughput lowdelay priority immediate flash flash-override critical internet network</list> + </completionHelp> + <valueHelp> + <format>u32:0-63</format> + <description>Priority order for bandwidth pool</description> + </valueHelp> + <valueHelp> + <format>default</format> + <description>match DSCP (000000)</description> + </valueHelp> + <valueHelp> + <format>reliability</format> + <description>match DSCP (000001)</description> + </valueHelp> + <valueHelp> + <format>throughput</format> + <description>match DSCP (000010)</description> + </valueHelp> + <valueHelp> + <format>lowdelay</format> + <description>match DSCP (000100)</description> + </valueHelp> + <valueHelp> + <format>priority</format> + <description>match DSCP (001000)</description> + </valueHelp> + <valueHelp> + <format>immediate</format> + <description>match DSCP (010000)</description> + </valueHelp> + <valueHelp> + <format>flash</format> + <description>match DSCP (011000)</description> + </valueHelp> + <valueHelp> + <format>flash-override</format> + <description>match DSCP (100000)</description> + </valueHelp> + <valueHelp> + <format>critical</format> + <description>match DSCP (101000)</description> + </valueHelp> + <valueHelp> + <format>internet</format> + <description>match DSCP (110000)</description> + </valueHelp> + <valueHelp> + <format>network</format> + <description>match DSCP (111000)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-63"/> + <regex>(default|reliability|throughput|lowdelay|priority|immediate|flash|flash-override|critical|internet|network)</regex> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 63</constraintErrorMessage> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/target.xml.i b/interface-definitions/include/qos/target.xml.i new file mode 100644 index 000000000..bf6342ac9 --- /dev/null +++ b/interface-definitions/include/qos/target.xml.i @@ -0,0 +1,16 @@ +<!-- include start from qos/target.xml.i --> +<leafNode name="target"> + <properties> + <help>Acceptable minimum standing/persistent queue delay</help> + <valueHelp> + <format>u32</format> + <description>Queue delay in milliseconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4294967295"/> + </constraint> + <constraintErrorMessage>Delay must be in range 0 to 4294967295</constraintErrorMessage> + </properties> + <defaultValue>5</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/tcp-flags.xml.i b/interface-definitions/include/qos/tcp-flags.xml.i new file mode 100644 index 000000000..81d70d1f3 --- /dev/null +++ b/interface-definitions/include/qos/tcp-flags.xml.i @@ -0,0 +1,21 @@ +<!-- include start from qos/tcp-flags.xml.i --> +<node name="tcp"> + <properties> + <help>TCP Flags matching</help> + </properties> + <children> + <leafNode name="ack"> + <properties> + <help>Match TCP ACK</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="syn"> + <properties> + <help>Match TCP SYN</help> + <valueless/> + </properties> + </leafNode> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/interfaces-bonding.xml.in b/interface-definitions/interfaces-bonding.xml.in index b98f4b960..20ece5137 100644 --- a/interface-definitions/interfaces-bonding.xml.in +++ b/interface-definitions/interfaces-bonding.xml.in @@ -207,6 +207,8 @@ </constraint> </properties> </leafNode> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> #include <include/interface/vif-s.xml.i> #include <include/interface/vif.xml.i> #include <include/interface/xdp.xml.i> diff --git a/interface-definitions/interfaces-bridge.xml.in b/interface-definitions/interfaces-bridge.xml.in index fabfb917a..6957067cd 100644 --- a/interface-definitions/interfaces-bridge.xml.in +++ b/interface-definitions/interfaces-bridge.xml.in @@ -210,6 +210,8 @@ <valueless/> </properties> </leafNode> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> #include <include/interface/vif.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-dummy.xml.in b/interface-definitions/interfaces-dummy.xml.in index 3bca8b950..109ed1b50 100644 --- a/interface-definitions/interfaces-dummy.xml.in +++ b/interface-definitions/interfaces-dummy.xml.in @@ -30,6 +30,8 @@ </children> </node> #include <include/interface/netns.xml.i> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-ethernet.xml.in b/interface-definitions/interfaces-ethernet.xml.in index be7bddfa4..7d28912c0 100644 --- a/interface-definitions/interfaces-ethernet.xml.in +++ b/interface-definitions/interfaces-ethernet.xml.in @@ -196,6 +196,8 @@ </leafNode> </children> </node> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> #include <include/interface/vif-s.xml.i> #include <include/interface/vif.xml.i> #include <include/interface/vrf.xml.i> diff --git a/interface-definitions/interfaces-geneve.xml.in b/interface-definitions/interfaces-geneve.xml.in index dd4d324d4..aa5809e60 100644 --- a/interface-definitions/interfaces-geneve.xml.in +++ b/interface-definitions/interfaces-geneve.xml.in @@ -50,6 +50,8 @@ </node> </children> </node> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> #include <include/interface/tunnel-remote.xml.i> #include <include/vni.xml.i> </children> diff --git a/interface-definitions/interfaces-input.xml.in b/interface-definitions/interfaces-input.xml.in new file mode 100644 index 000000000..f2eb01c58 --- /dev/null +++ b/interface-definitions/interfaces-input.xml.in @@ -0,0 +1,30 @@ +<?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-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> + </children> + </tagNode> + </children> + </node> +</interfaceDefinition> diff --git a/interface-definitions/interfaces-l2tpv3.xml.in b/interface-definitions/interfaces-l2tpv3.xml.in index ba9bcb0a2..680170b0f 100644 --- a/interface-definitions/interfaces-l2tpv3.xml.in +++ b/interface-definitions/interfaces-l2tpv3.xml.in @@ -86,7 +86,6 @@ </constraint> </properties> </leafNode> - #include <include/interface/mtu-68-16000.xml.i> #include <include/interface/tunnel-remote.xml.i> <leafNode name="session-id"> <properties> @@ -125,6 +124,7 @@ </constraint> </properties> </leafNode> + #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-loopback.xml.in b/interface-definitions/interfaces-loopback.xml.in index 7be15ab89..ffffc0220 100644 --- a/interface-definitions/interfaces-loopback.xml.in +++ b/interface-definitions/interfaces-loopback.xml.in @@ -26,6 +26,8 @@ #include <include/interface/source-validation.xml.i> </children> </node> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in index 7206e57b1..311e95c2f 100644 --- a/interface-definitions/interfaces-macsec.xml.in +++ b/interface-definitions/interfaces-macsec.xml.in @@ -122,6 +122,8 @@ <defaultValue>1460</defaultValue> </leafNode> #include <include/source-interface-ethernet.xml.i> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-openvpn.xml.in b/interface-definitions/interfaces-openvpn.xml.in index eb574eb52..73e30e590 100644 --- a/interface-definitions/interfaces-openvpn.xml.in +++ b/interface-definitions/interfaces-openvpn.xml.in @@ -816,6 +816,8 @@ <valueless/> </properties> </leafNode> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-pppoe.xml.in b/interface-definitions/interfaces-pppoe.xml.in index ed0e45840..1d888236e 100644 --- a/interface-definitions/interfaces-pppoe.xml.in +++ b/interface-definitions/interfaces-pppoe.xml.in @@ -49,7 +49,6 @@ #include <include/interface/dhcpv6-options.xml.i> #include <include/interface/description.xml.i> #include <include/interface/disable.xml.i> - #include <include/interface/vrf.xml.i> <leafNode name="idle-timeout"> <properties> <help>Delay before disconnecting idle session (in seconds)</help> @@ -134,6 +133,9 @@ <constraintErrorMessage>Service name must be alphanumeric only</constraintErrorMessage> </properties> </leafNode> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> + #include <include/interface/vrf.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/interfaces-pseudo-ethernet.xml.in b/interface-definitions/interfaces-pseudo-ethernet.xml.in index bf7055f8d..7baeac537 100644 --- a/interface-definitions/interfaces-pseudo-ethernet.xml.in +++ b/interface-definitions/interfaces-pseudo-ethernet.xml.in @@ -59,6 +59,8 @@ <defaultValue>private</defaultValue> </leafNode> #include <include/interface/mtu-68-16000.xml.i> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> #include <include/interface/vif-s.xml.i> #include <include/interface/vif.xml.i> </children> diff --git a/interface-definitions/interfaces-tunnel.xml.in b/interface-definitions/interfaces-tunnel.xml.in index eb1708aaa..bc9297c86 100644 --- a/interface-definitions/interfaces-tunnel.xml.in +++ b/interface-definitions/interfaces-tunnel.xml.in @@ -20,7 +20,6 @@ #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/vrf.xml.i> #include <include/interface/mtu-64-8024.xml.i> <leafNode name="mtu"> <defaultValue>1476</defaultValue> @@ -288,6 +287,9 @@ </node> </children> </node> + #include <include/interface/vrf.xml.i> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/interfaces-vti.xml.in b/interface-definitions/interfaces-vti.xml.in index f03c7476d..538194c2b 100644 --- a/interface-definitions/interfaces-vti.xml.in +++ b/interface-definitions/interfaces-vti.xml.in @@ -34,6 +34,8 @@ #include <include/interface/ipv4-options.xml.i> #include <include/interface/ipv6-options.xml.i> #include <include/interface/mtu-68-16000.xml.i> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> #include <include/interface/interface-firewall.xml.i> #include <include/interface/interface-policy.xml.i> diff --git a/interface-definitions/interfaces-vxlan.xml.in b/interface-definitions/interfaces-vxlan.xml.in index 0546b4199..18abf9f20 100644 --- a/interface-definitions/interfaces-vxlan.xml.in +++ b/interface-definitions/interfaces-vxlan.xml.in @@ -99,6 +99,8 @@ #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/traffic-policy.xml.i> #include <include/interface/vrf.xml.i> #include <include/vni.xml.i> </children> diff --git a/interface-definitions/interfaces-wireguard.xml.in b/interface-definitions/interfaces-wireguard.xml.in index 1b4b4a816..2f130c6f2 100644 --- a/interface-definitions/interfaces-wireguard.xml.in +++ b/interface-definitions/interfaces-wireguard.xml.in @@ -19,7 +19,6 @@ #include <include/interface/address-ipv4-ipv6.xml.i> #include <include/interface/description.xml.i> #include <include/interface/disable.xml.i> - #include <include/interface/vrf.xml.i> #include <include/port-number.xml.i> #include <include/interface/mtu-68-16000.xml.i> #include <include/interface/interface-firewall.xml.i> @@ -120,6 +119,9 @@ </leafNode> </children> </tagNode> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> + #include <include/interface/vrf.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/interfaces-wireless.xml.in b/interface-definitions/interfaces-wireless.xml.in index 9db9fd757..eebe8f841 100644 --- a/interface-definitions/interfaces-wireless.xml.in +++ b/interface-definitions/interfaces-wireless.xml.in @@ -778,6 +778,8 @@ </properties> <defaultValue>monitor</defaultValue> </leafNode> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> #include <include/interface/vif.xml.i> #include <include/interface/vif-s.xml.i> </children> diff --git a/interface-definitions/interfaces-wwan.xml.in b/interface-definitions/interfaces-wwan.xml.in index 03554feed..7007a67ae 100644 --- a/interface-definitions/interfaces-wwan.xml.in +++ b/interface-definitions/interfaces-wwan.xml.in @@ -30,7 +30,6 @@ #include <include/interface/authentication.xml.i> #include <include/interface/description.xml.i> #include <include/interface/disable.xml.i> - #include <include/interface/vrf.xml.i> #include <include/interface/disable-link-detect.xml.i> #include <include/interface/mtu-68-1500.xml.i> <leafNode name="mtu"> @@ -41,6 +40,9 @@ #include <include/interface/dial-on-demand.xml.i> #include <include/interface/interface-firewall.xml.i> #include <include/interface/interface-policy.xml.i> + #include <include/interface/redirect.xml.i> + #include <include/interface/traffic-policy.xml.i> + #include <include/interface/vrf.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/qos.xml.in b/interface-definitions/qos.xml.in new file mode 100644 index 000000000..d4468543c --- /dev/null +++ b/interface-definitions/qos.xml.in @@ -0,0 +1,721 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="traffic-policy" owner="${vyos_conf_scripts_dir}/qos.py"> + <properties> + <help>Quality of Service (QOS) policy type</help> + <priority>900</priority> + </properties> + <children> + <tagNode name="drop-tail"> + <properties> + <help>Packet limited First In, First Out queue</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + #include <include/qos/queue-limit-1-4294967295.xml.i> + </children> + </tagNode> + <tagNode name="fair-queue"> + <properties> + <help>Stochastic Fairness Queueing</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + <leafNode name="hash-interval"> + <properties> + <help>Interval in seconds for queue algorithm perturbation</help> + <valueHelp> + <format>u32:0</format> + <description>No perturbation</description> + </valueHelp> + <valueHelp> + <format>u32:1-127</format> + <description>Interval in seconds for queue algorithm perturbation (advised: 10)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-127"/> + </constraint> + <constraintErrorMessage>Interval must be in range 0 to 127</constraintErrorMessage> + </properties> + <defaultValue>0</defaultValue> + </leafNode> + <leafNode name="queue-limit"> + <properties> + <help>Upper limit of the SFQ</help> + <valueHelp> + <format>u32:2-127</format> + <description>Queue size in packets</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 2-127"/> + </constraint> + <constraintErrorMessage>Queue limit must greater than 1 and less than 128</constraintErrorMessage> + </properties> + <defaultValue>127</defaultValue> + </leafNode> + </children> + </tagNode> + <tagNode name="fq-codel"> + <properties> + <help>Fair Queuing Controlled Delay</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + #include <include/qos/codel-quantum.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + #include <include/qos/queue-limit-2-10999.xml.i> + #include <include/qos/target.xml.i> + </children> + </tagNode> + <tagNode name="limiter"> + <properties> + <help>Traffic input limiting policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + <tagNode name="class"> + <properties> + <help>Class ID</help> + <valueHelp> + <format>u32:1-4090</format> + <description>Class Identifier</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-4090"/> + </constraint> + <constraintErrorMessage>Class identifier must be between 1 and 4090</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + #include <include/qos/burst.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/match.xml.i> + <leafNode name="priority"> + <properties> + <help>Priority for rule evaluation</help> + <valueHelp> + <format>u32:0-20</format> + <description>Priority for match rule evaluation</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-20"/> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 20</constraintErrorMessage> + </properties> + <defaultValue>20</defaultValue> + </leafNode> + </children> + </tagNode> + <node name="default"> + <properties> + <help>Default policy</help> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + #include <include/qos/burst.xml.i> + </children> + </node> + #include <include/generic-description.xml.i> + </children> + </tagNode> + <tagNode name="network-emulator"> + <properties> + <help>Network emulator policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + #include <include/qos/burst.xml.i> + #include <include/generic-description.xml.i> + <leafNode name="network-delay"> + <properties> + <help>Adds delay to packets outgoing to chosen network interface</help> + <valueHelp> + <format><number></format> + <description>Time in milliseconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-65535"/> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 65535</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="packet-corruption"> + <properties> + <help>Introducing error in a random position for chosen percent of packets</help> + <valueHelp> + <format><number></format> + <description>Percentage of packets affected</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-100"/> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 100</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="packet-loss"> + <properties> + <help>Add independent loss probability to the packets outgoing to chosen network interface</help> + <valueHelp> + <format><number></format> + <description>Percentage of packets affected</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-100"/> + </constraint> + <constraintErrorMessage>Must be between 0 and 100</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="packet-loss"> + <properties> + <help>Add independent loss probability to the packets outgoing to chosen network interface</help> + <valueHelp> + <format><number></format> + <description>Percentage of packets affected</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-100"/> + </constraint> + <constraintErrorMessage>Must be between 0 and 100</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="packet-loss"> + <properties> + <help>Packet reordering percentage</help> + <valueHelp> + <format><number></format> + <description>Percentage of packets affected</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-100"/> + </constraint> + <constraintErrorMessage>Must be between 0 and 100</constraintErrorMessage> + </properties> + </leafNode> + #include <include/qos/queue-limit-1-4294967295.xml.i> + </children> + </tagNode> + <tagNode name="priority-queue"> + <properties> + <help>Priority queuing based policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + <tagNode name="class"> + <properties> + <help>Class Handle</help> + <valueHelp> + <format>u32:1-7</format> + <description>Priority</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-7"/> + </constraint> + <constraintErrorMessage>Class handle must be between 1 and 7</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + #include <include/qos/codel-quantum.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + #include <include/qos/match.xml.i> + #include <include/qos/queue-limit-2-10999.xml.i> + #include <include/qos/target.xml.i> + #include <include/qos/queue-type.xml.i> + </children> + </tagNode> + <node name="default"> + <properties> + <help>Default policy</help> + </properties> + <children> + #include <include/generic-description.xml.i> + #include <include/qos/codel-quantum.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + #include <include/qos/queue-limit-2-10999.xml.i> + #include <include/qos/target.xml.i> + #include <include/qos/queue-type.xml.i> + </children> + </node> + #include <include/generic-description.xml.i> + </children> + </tagNode> + <tagNode name="random-detect"> + <properties> + <help>Priority queuing based policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + <leafNode name="bandwidth"> + <defaultValue>auto</defaultValue> + </leafNode> + #include <include/generic-description.xml.i> + <tagNode name="precedence"> + <properties> + <help>IP precedence</help> + <valueHelp> + <format>u32:0-7</format> + <description>IP precedence value</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-7"/> + </constraint> + <constraintErrorMessage>IP precedence value must be between 0 and 7</constraintErrorMessage> + </properties> + <children> + #include <include/qos/queue-limit-1-4294967295.xml.i> + <leafNode name="average-packet"> + <properties> + <help>Average packet size (bytes)</help> + <valueHelp> + <format>u32:16-10240</format> + <description>Average packet size in bytes</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-100"/> + </constraint> + <constraintErrorMessage>Average packet size must be between 16 and 10240</constraintErrorMessage> + </properties> + <defaultValue>1024</defaultValue> + </leafNode> + <leafNode name="mark-probability"> + <properties> + <help>Mark probability for this precedence</help> + <valueHelp> + <format><number></format> + <description>Numeric value (1/N)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--positive"/> + </constraint> + <constraintErrorMessage>Mark probability must be greater than 0</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="maximum-threshold"> + <properties> + <help>Maximum threshold for random detection</help> + <valueHelp> + <format>u32:0-4096</format> + <description>Maximum Threshold in packets</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4096"/> + </constraint> + <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="minimum-threshold"> + <properties> + <help>Minimum threshold for random detection</help> + <valueHelp> + <format>u32:0-4096</format> + <description>Maximum Threshold in packets</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4096"/> + </constraint> + <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> + </properties> + </leafNode> + </children> + </tagNode> + </children> + </tagNode> + <tagNode name="rate-control"> + <properties> + <help>Rate limiting policy (Token Bucket Filter)</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/burst.xml.i> + <leafNode name="latency"> + <properties> + <help>Maximum latency</help> + <valueHelp> + <format><number></format> + <description>Time in milliseconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4096"/> + </constraint> + <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> + </properties> + <defaultValue>50</defaultValue> + </leafNode> + </children> + </tagNode> + <tagNode name="round-robin"> + <properties> + <help>Round-Robin based policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + <tagNode name="class"> + <properties> + <help>Class ID</help> + <valueHelp> + <format>u32:1-4095</format> + <description>Class Identifier</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-4095"/> + </constraint> + <constraintErrorMessage>Class identifier must be between 1 and 4095</constraintErrorMessage> + </properties> + <children> + #include <include/qos/codel-quantum.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + #include <include/qos/match.xml.i> + <leafNode name="quantum"> + <properties> + <help>Packet scheduling quantum</help> + <valueHelp> + <format>u32:1-4294967295</format> + <description>Packet scheduling quantum (bytes)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-4294967295"/> + </constraint> + <constraintErrorMessage>Quantum must be in range 1 to 4294967295</constraintErrorMessage> + </properties> + </leafNode> + #include <include/qos/queue-limit-1-4294967295.xml.i> + #include <include/qos/queue-type.xml.i> + #include <include/qos/target.xml.i> + </children> + </tagNode> + </children> + </tagNode> + <tagNode name="shaper-hfsc"> + <properties> + <help>Hierarchical Fair Service Curve's policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + <leafNode name="bandwidth"> + <defaultValue>auto</defaultValue> + </leafNode> + #include <include/generic-description.xml.i> + <tagNode name="class"> + <properties> + <help>Class ID</help> + <valueHelp> + <format>u32:1-4095</format> + <description>Class Identifier</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-4095"/> + </constraint> + <constraintErrorMessage>Class identifier must be between 1 and 4095</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + <node name="linkshare"> + <properties> + <help>Linkshare class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + #include <include/qos/match.xml.i> + <node name="realtime"> + <properties> + <help>Realtime class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + <node name="upperlimit"> + <properties> + <help>Upperlimit class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + </children> + </tagNode> + <node name="default"> + <properties> + <help>Default policy</help> + </properties> + <children> + <node name="linkshare"> + <properties> + <help>Linkshare class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + <node name="realtime"> + <properties> + <help>Realtime class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + <node name="upperlimit"> + <properties> + <help>Upperlimit class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + </children> + </node> + </children> + </tagNode> + <tagNode name="shaper"> + <properties> + <help>Traffic shaping based policy (Hierarchy Token Bucket)</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + <leafNode name="bandwidth"> + <defaultValue>auto</defaultValue> + </leafNode> + <tagNode name="class"> + <properties> + <help>Class ID</help> + <valueHelp> + <format>u32:2-4095</format> + <description>Class Identifier</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 2-4095"/> + </constraint> + <constraintErrorMessage>Class identifier must be between 2 and 4095</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + <leafNode name="bandwidth"> + <defaultValue>100%</defaultValue> + </leafNode> + #include <include/qos/burst.xml.i> + <leafNode name="ceiling"> + <properties> + <help>Bandwidth limit for this class</help> + <valueHelp> + <format><number></format> + <description>Rate in kbit (kilobit per second)</description> + </valueHelp> + <valueHelp> + <format><number>%%</format> + <description>Percentage of overall rate</description> + </valueHelp> + <valueHelp> + <format><number>bit</format> + <description>bit(1), kbit(10^3), mbit(10^6), gbit, tbit</description> + </valueHelp> + <valueHelp> + <format><number>ibit</format> + <description>kibit(1024), mibit(1024^2), gibit(1024^3), tbit(1024^4)</description> + </valueHelp> + <valueHelp> + <format><number>ibps</format> + <description>kibps(1024*8), mibps(1024^2*8), gibps, tibps - Byte/sec</description> + </valueHelp> + <valueHelp> + <format><number>bps</format> + <description>bps(8),kbps(8*10^3),mbps(8*10^6), gbps, tbps - Byte/sec</description> + </valueHelp> + </properties> + </leafNode> + #include <include/qos/codel-quantum.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + #include <include/qos/match.xml.i> + <leafNode name="priority"> + <properties> + <help>Priority for usage of excess bandwidth</help> + <valueHelp> + <format>u32:0-7</format> + <description>Priority order for bandwidth pool</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-7"/> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 7</constraintErrorMessage> + </properties> + <defaultValue>20</defaultValue> + </leafNode> + #include <include/qos/queue-limit-1-4294967295.xml.i> + #include <include/qos/queue-type.xml.i> + #include <include/qos/set-dscp.xml.i> + #include <include/qos/target.xml.i> + </children> + </tagNode> + #include <include/generic-description.xml.i> + <node name="default"> + <properties> + <help>Default policy</help> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + #include <include/qos/burst.xml.i> + <leafNode name="ceiling"> + <properties> + <help>Bandwidth limit for this class</help> + <valueHelp> + <format><number></format> + <description>Rate in kbit (kilobit per second)</description> + </valueHelp> + <valueHelp> + <format><number>%%</format> + <description>Percentage of overall rate</description> + </valueHelp> + <valueHelp> + <format><number>bit</format> + <description>bit(1), kbit(10^3), mbit(10^6), gbit, tbit</description> + </valueHelp> + <valueHelp> + <format><number>ibit</format> + <description>kibit(1024), mibit(1024^2), gibit(1024^3), tbit(1024^4)</description> + </valueHelp> + <valueHelp> + <format><number>ibps</format> + <description>kibps(1024*8), mibps(1024^2*8), gibps, tibps - Byte/sec</description> + </valueHelp> + <valueHelp> + <format><number>bps</format> + <description>bps(8),kbps(8*10^3),mbps(8*10^6), gbps, tbps - Byte/sec</description> + </valueHelp> + </properties> + </leafNode> + #include <include/qos/codel-quantum.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + <leafNode name="priority"> + <properties> + <help>Priority for usage of excess bandwidth</help> + <valueHelp> + <format>u32:0-7</format> + <description>Priority order for bandwidth pool</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-7"/> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 7</constraintErrorMessage> + </properties> + <defaultValue>20</defaultValue> + </leafNode> + #include <include/qos/queue-limit-1-4294967295.xml.i> + #include <include/qos/queue-type.xml.i> + #include <include/qos/set-dscp.xml.i> + #include <include/qos/target.xml.i> + </children> + </node> + </children> + </tagNode> + </children> + </node> +</interfaceDefinition> diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py index fab88bc72..7f1258575 100644 --- a/python/vyos/configverify.py +++ b/python/vyos/configverify.py @@ -191,6 +191,19 @@ def verify_mirror(config): raise ConfigError(f'Can not mirror "{direction}" traffic back ' \ 'the originating interface!') +def verify_redirect(config): + """ + Common helper function used by interface implementations to perform + recurring validation of the redirect interface configuration. + + It makes no sense to mirror and redirect traffic at the same time! + """ + if {'mirror', 'redirect'} <= set(config): + raise ConfigError('Can not do both redirect and mirror') + + if dict_search('traffic_policy.in', config) != None: + raise ConfigError('Can not use ingress policy and redirect') + def verify_authentication(config): """ Common helper function used by interface implementations to perform @@ -315,6 +328,7 @@ def verify_vlan_config(config): verify_dhcpv6(vlan) verify_address(vlan) verify_vrf(vlan) + verify_redirect(vlan) verify_mtu_parent(vlan, config) # 802.1ad (Q-in-Q) VLANs @@ -323,6 +337,7 @@ def verify_vlan_config(config): verify_dhcpv6(s_vlan) verify_address(s_vlan) verify_vrf(s_vlan) + verify_redirect(s_vlan) verify_mtu_parent(s_vlan, config) for c_vlan in s_vlan.get('vif_c', {}): @@ -330,6 +345,7 @@ def verify_vlan_config(config): verify_dhcpv6(c_vlan) verify_address(c_vlan) verify_vrf(c_vlan) + verify_redirect(c_vlan) verify_mtu_parent(c_vlan, config) verify_mtu_parent(c_vlan, s_vlan) diff --git a/smoketest/scripts/cli/test_nat66.py b/smoketest/scripts/cli/test_nat66.py index 8afe0da26..6b7b49792 100755 --- a/smoketest/scripts/cli/test_nat66.py +++ b/smoketest/scripts/cli/test_nat66.py @@ -185,4 +185,4 @@ class TestNAT66(VyOSUnitTestSHIM.TestCase): self.cli_commit() if __name__ == '__main__': - unittest.main(verbosity=2, failfast=True) + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_policy.py b/smoketest/scripts/cli/test_policy.py index 491f1766d..0acd41903 100755 --- a/smoketest/scripts/cli/test_policy.py +++ b/smoketest/scripts/cli/test_policy.py @@ -1030,7 +1030,7 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): tmp = f'match ipv6 address prefix-list {rule_config["match"]["ipv6-address-pfx"]}' self.assertIn(tmp, config) if 'ipv6-nexthop' in rule_config['match']: - tmp = f'match ipv6 next-hop {rule_config["match"]["ipv6-nexthop"]}' + tmp = f'match ipv6 next-hop address {rule_config["match"]["ipv6-nexthop"]}' self.assertIn(tmp, config) if 'large-community' in rule_config['match']: tmp = f'match large-community {rule_config["match"]["large-community"]}' diff --git a/smoketest/scripts/cli/test_protocols_mpls.py b/smoketest/scripts/cli/test_protocols_mpls.py index 13d38d01b..b60f0725a 100755 --- a/smoketest/scripts/cli/test_protocols_mpls.py +++ b/smoketest/scripts/cli/test_protocols_mpls.py @@ -114,4 +114,4 @@ class TestProtocolsMPLS(VyOSUnitTestSHIM.TestCase): self.assertIn(f' interface {interface}', afiv4_config) if __name__ == '__main__': - unittest.main(verbosity=2, failfast=True) + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py index ee58b0fe2..5d8e9cff2 100755 --- a/smoketest/scripts/cli/test_protocols_ospf.py +++ b/smoketest/scripts/cli/test_protocols_ospf.py @@ -368,6 +368,30 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): self.cli_delete(['vrf', 'name', vrf]) self.cli_delete(['interfaces', 'ethernet', vrf_iface, 'vrf']) + def test_ospf_13_export_list(self): + # Verify explort-list works on ospf-area + acl = '100' + seq = '10' + area = '0.0.0.10' + network = '10.0.0.0/8' + + + self.cli_set(['policy', 'access-list', acl, 'rule', seq, 'action', 'permit']) + self.cli_set(['policy', 'access-list', acl, 'rule', seq, 'source', 'any']) + self.cli_set(['policy', 'access-list', acl, 'rule', seq, 'destination', 'any']) + self.cli_set(base_path + ['area', area, 'network', network]) + self.cli_set(base_path + ['area', area, 'export-list', acl]) + + # commit changes + self.cli_commit() + + # Verify FRR ospfd configuration + frrconfig = self.getFRRconfig('router ospf') + self.assertIn(f'router ospf', frrconfig) + self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # default + self.assertIn(f' network {network} area {area}', frrconfig) + self.assertIn(f' area {area} export-list {acl}', frrconfig) + if __name__ == '__main__': logging.basicConfig(stream=sys.stderr, level=logging.DEBUG) unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_ospfv3.py b/smoketest/scripts/cli/test_protocols_ospfv3.py index 1327fd910..2fc694fd7 100755 --- a/smoketest/scripts/cli/test_protocols_ospfv3.py +++ b/smoketest/scripts/cli/test_protocols_ospfv3.py @@ -265,8 +265,8 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.assertIn(f'router ospf6', frrconfig) self.assertIn(f' ospf6 router-id {router_id}', frrconfig) - frrconfig = self.getFRRconfig(f'interface {vrf_iface} vrf {vrf}') - self.assertIn(f'interface {vrf_iface} vrf {vrf}', frrconfig) + frrconfig = self.getFRRconfig(f'interface {vrf_iface}') + self.assertIn(f'interface {vrf_iface}', frrconfig) self.assertIn(f' ipv6 ospf6 bfd', frrconfig) frrconfig = self.getFRRconfig(f'router ospf6 vrf {vrf}') @@ -278,4 +278,4 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.cli_delete(['interfaces', 'ethernet', vrf_iface, 'vrf']) if __name__ == '__main__': - unittest.main(verbosity=2, failfast=True) + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_system_login.py b/smoketest/scripts/cli/test_system_login.py index 69a06eeac..095300de3 100755 --- a/smoketest/scripts/cli/test_system_login.py +++ b/smoketest/scripts/cli/test_system_login.py @@ -235,4 +235,4 @@ class TestSystemLogin(VyOSUnitTestSHIM.TestCase): self.assertTrue(tmp) if __name__ == '__main__': - unittest.main(verbosity=2, failfast=True) + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_system_logs.py b/smoketest/scripts/cli/test_system_logs.py index 0c11c4663..92fa9c3d9 100755 --- a/smoketest/scripts/cli/test_system_logs.py +++ b/smoketest/scripts/cli/test_system_logs.py @@ -114,4 +114,4 @@ class TestSystemLogs(VyOSUnitTestSHIM.TestCase): if __name__ == '__main__': - unittest.main(verbosity=2, failfast=True) + unittest.main(verbosity=2) diff --git a/src/conf_mode/interfaces-bonding.py b/src/conf_mode/interfaces-bonding.py index 431d65f1f..661dc2298 100755 --- a/src/conf_mode/interfaces-bonding.py +++ b/src/conf_mode/interfaces-bonding.py @@ -27,8 +27,10 @@ from vyos.configdict import is_source_interface from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_dhcpv6 -from vyos.configverify import verify_source_interface +from vyos.configverify import verify_mirror from vyos.configverify import verify_mtu_ipv6 +from vyos.configverify import verify_redirect +from vyos.configverify import verify_source_interface from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf from vyos.ifconfig import BondIf @@ -132,10 +134,10 @@ def verify(bond): return None if 'arp_monitor' in bond: - if 'target' in bond['arp_monitor'] and len(int(bond['arp_monitor']['target'])) > 16: + if 'target' in bond['arp_monitor'] and len(bond['arp_monitor']['target']) > 16: raise ConfigError('The maximum number of arp-monitor targets is 16') - if 'interval' in bond['arp_monitor'] and len(int(bond['arp_monitor']['interval'])) > 0: + if 'interval' in bond['arp_monitor'] and int(bond['arp_monitor']['interval']) > 0: if bond['mode'] in ['802.3ad', 'balance-tlb', 'balance-alb']: raise ConfigError('ARP link monitoring does not work for mode 802.3ad, ' \ 'transmit-load-balance or adaptive-load-balance') @@ -149,6 +151,8 @@ def verify(bond): verify_address(bond) verify_dhcpv6(bond) verify_vrf(bond) + verify_mirror(bond) + verify_redirect(bond) # use common function to verify VLAN configuration verify_vlan_config(bond) diff --git a/src/conf_mode/interfaces-bridge.py b/src/conf_mode/interfaces-bridge.py index f4dba9d4a..e16c0e9f4 100755 --- a/src/conf_mode/interfaces-bridge.py +++ b/src/conf_mode/interfaces-bridge.py @@ -27,6 +27,8 @@ from vyos.configdict import is_source_interface from vyos.configdict import has_vlan_subinterface_configured from vyos.configdict import dict_merge from vyos.configverify import verify_dhcpv6 +from vyos.configverify import verify_mirror +from vyos.configverify import verify_redirect from vyos.configverify import verify_vrf from vyos.ifconfig import BridgeIf from vyos.validate import has_address_configured @@ -105,6 +107,8 @@ def verify(bridge): verify_dhcpv6(bridge) verify_vrf(bridge) + verify_mirror(bridge) + verify_redirect(bridge) ifname = bridge['ifname'] diff --git a/src/conf_mode/interfaces-dummy.py b/src/conf_mode/interfaces-dummy.py index 55c783f38..4072c4452 100755 --- a/src/conf_mode/interfaces-dummy.py +++ b/src/conf_mode/interfaces-dummy.py @@ -21,6 +21,7 @@ from vyos.configdict import get_interface_dict from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete +from vyos.configverify import verify_redirect from vyos.ifconfig import DummyIf from vyos import ConfigError from vyos import airbag @@ -46,6 +47,7 @@ def verify(dummy): verify_vrf(dummy) verify_address(dummy) + verify_redirect(dummy) return None diff --git a/src/conf_mode/interfaces-ethernet.py b/src/conf_mode/interfaces-ethernet.py index 2a8a126f2..3eeddf190 100755 --- a/src/conf_mode/interfaces-ethernet.py +++ b/src/conf_mode/interfaces-ethernet.py @@ -28,6 +28,7 @@ from vyos.configverify import verify_interface_exists from vyos.configverify import verify_mirror from vyos.configverify import verify_mtu from vyos.configverify import verify_mtu_ipv6 +from vyos.configverify import verify_redirect from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf from vyos.ethtool import Ethtool @@ -84,6 +85,7 @@ def verify(ethernet): verify_vrf(ethernet) verify_eapol(ethernet) verify_mirror(ethernet) + verify_redirect(ethernet) ethtool = Ethtool(ifname) # No need to check speed and duplex keys as both have default values. diff --git a/src/conf_mode/interfaces-geneve.py b/src/conf_mode/interfaces-geneve.py index 2a63b60aa..a94b5e1f7 100755 --- a/src/conf_mode/interfaces-geneve.py +++ b/src/conf_mode/interfaces-geneve.py @@ -24,6 +24,7 @@ from vyos.configdict import get_interface_dict from vyos.configverify import verify_address from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_bridge_delete +from vyos.configverify import verify_redirect from vyos.ifconfig import GeneveIf from vyos import ConfigError @@ -50,6 +51,7 @@ def verify(geneve): verify_mtu_ipv6(geneve) verify_address(geneve) + verify_redirect(geneve) if 'remote' not in geneve: raise ConfigError('Remote side must be configured') diff --git a/src/conf_mode/interfaces-l2tpv3.py b/src/conf_mode/interfaces-l2tpv3.py index 9b6ddd5aa..5ea7159dc 100755 --- a/src/conf_mode/interfaces-l2tpv3.py +++ b/src/conf_mode/interfaces-l2tpv3.py @@ -25,6 +25,7 @@ from vyos.configdict import leaf_node_changed from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 +from vyos.configverify import verify_redirect from vyos.ifconfig import L2TPv3If from vyos.util import check_kmod from vyos.validate import is_addr_assigned @@ -76,6 +77,7 @@ def verify(l2tpv3): verify_mtu_ipv6(l2tpv3) verify_address(l2tpv3) + verify_redirect(l2tpv3) return None def generate(l2tpv3): diff --git a/src/conf_mode/interfaces-loopback.py b/src/conf_mode/interfaces-loopback.py index 193334443..e6a851113 100755 --- a/src/conf_mode/interfaces-loopback.py +++ b/src/conf_mode/interfaces-loopback.py @@ -20,6 +20,7 @@ from sys import exit from vyos.config import Config from vyos.configdict import get_interface_dict +from vyos.configverify import verify_redirect from vyos.ifconfig import LoopbackIf from vyos import ConfigError from vyos import airbag @@ -39,6 +40,7 @@ def get_config(config=None): return loopback def verify(loopback): + verify_redirect(loopback) return None def generate(loopback): diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py index eab69f36e..6a29fdb11 100755 --- a/src/conf_mode/interfaces-macsec.py +++ b/src/conf_mode/interfaces-macsec.py @@ -29,6 +29,7 @@ from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 +from vyos.configverify import verify_redirect from vyos.configverify import verify_source_interface from vyos import ConfigError from vyos import airbag @@ -66,6 +67,7 @@ def verify(macsec): verify_vrf(macsec) verify_mtu_ipv6(macsec) verify_address(macsec) + verify_redirect(macsec) if not (('security' in macsec) and ('cipher' in macsec['security'])): diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index 29a25eedc..c30c0bdd0 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -32,6 +32,7 @@ from shutil import rmtree from vyos.config import Config from vyos.configdict import get_interface_dict +from vyos.configdict import leaf_node_changed from vyos.configverify import verify_vrf from vyos.configverify import verify_bridge_delete from vyos.ifconfig import VTunIf @@ -88,6 +89,9 @@ def get_config(config=None): if 'deleted' not in openvpn: openvpn['pki'] = tmp_pki + tmp = leaf_node_changed(conf, ['openvpn-option']) + if tmp: openvpn['restart_required'] = '' + # We have to get the dict using 'get_config_dict' instead of 'get_interface_dict' # as 'get_interface_dict' merges the defaults in, so we can not check for defaults in there. tmp = conf.get_config_dict(base + [openvpn['ifname']], get_first_key=True) @@ -651,7 +655,10 @@ def apply(openvpn): # No matching OpenVPN process running - maybe it got killed or none # existed - nevertheless, spawn new OpenVPN process - call(f'systemctl reload-or-restart openvpn@{interface}.service') + action = 'reload-or-restart' + if 'restart_required' in openvpn: + action = 'restart' + call(f'systemctl {action} openvpn@{interface}.service') o = VTunIf(**openvpn) o.update(openvpn) diff --git a/src/conf_mode/interfaces-pppoe.py b/src/conf_mode/interfaces-pppoe.py index 584adc75e..9962e0a08 100755 --- a/src/conf_mode/interfaces-pppoe.py +++ b/src/conf_mode/interfaces-pppoe.py @@ -28,6 +28,7 @@ from vyos.configverify import verify_source_interface from vyos.configverify import verify_interface_exists from vyos.configverify import verify_vrf from vyos.configverify import verify_mtu_ipv6 +from vyos.configverify import verify_redirect from vyos.ifconfig import PPPoEIf from vyos.template import render from vyos.util import call @@ -85,6 +86,7 @@ def verify(pppoe): verify_authentication(pppoe) verify_vrf(pppoe) verify_mtu_ipv6(pppoe) + verify_redirect(pppoe) if {'connect_on_demand', 'vrf'} <= set(pppoe): raise ConfigError('On-demand dialing and VRF can not be used at the same time') diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py index 945a2ea9c..f57e41cc4 100755 --- a/src/conf_mode/interfaces-pseudo-ethernet.py +++ b/src/conf_mode/interfaces-pseudo-ethernet.py @@ -25,6 +25,7 @@ from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_source_interface from vyos.configverify import verify_vlan_config from vyos.configverify import verify_mtu_parent +from vyos.configverify import verify_redirect from vyos.ifconfig import MACVLANIf from vyos import ConfigError @@ -60,6 +61,7 @@ def verify(peth): verify_vrf(peth) verify_address(peth) verify_mtu_parent(peth, peth['parent']) + verify_redirect(peth) # use common function to verify VLAN configuration verify_vlan_config(peth) diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py index 433764b8a..005fae5eb 100755 --- a/src/conf_mode/interfaces-tunnel.py +++ b/src/conf_mode/interfaces-tunnel.py @@ -26,6 +26,7 @@ from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_interface_exists from vyos.configverify import verify_mtu_ipv6 +from vyos.configverify import verify_redirect from vyos.configverify import verify_vrf from vyos.configverify import verify_tunnel from vyos.ifconfig import Interface @@ -157,6 +158,7 @@ def verify(tunnel): verify_mtu_ipv6(tunnel) verify_address(tunnel) verify_vrf(tunnel) + verify_redirect(tunnel) if 'source_interface' in tunnel: verify_interface_exists(tunnel['source_interface']) diff --git a/src/conf_mode/interfaces-vti.py b/src/conf_mode/interfaces-vti.py index 57950ffea..30e13536f 100755 --- a/src/conf_mode/interfaces-vti.py +++ b/src/conf_mode/interfaces-vti.py @@ -19,6 +19,7 @@ from sys import exit from vyos.config import Config from vyos.configdict import get_interface_dict +from vyos.configverify import verify_redirect from vyos.ifconfig import VTIIf from vyos.util import dict_search from vyos import ConfigError @@ -39,6 +40,7 @@ def get_config(config=None): return vti def verify(vti): + verify_redirect(vti) return None def generate(vti): diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py index 29b16af89..a29836efd 100755 --- a/src/conf_mode/interfaces-vxlan.py +++ b/src/conf_mode/interfaces-vxlan.py @@ -25,6 +25,7 @@ from vyos.configdict import leaf_node_changed from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 +from vyos.configverify import verify_redirect from vyos.configverify import verify_source_interface from vyos.ifconfig import Interface from vyos.ifconfig import VXLANIf @@ -140,6 +141,7 @@ def verify(vxlan): verify_mtu_ipv6(vxlan) verify_address(vxlan) + verify_redirect(vxlan) return None def generate(vxlan): diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py index da64dd076..dc0fe7b9c 100755 --- a/src/conf_mode/interfaces-wireguard.py +++ b/src/conf_mode/interfaces-wireguard.py @@ -28,6 +28,7 @@ from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 +from vyos.configverify import verify_redirect from vyos.ifconfig import WireGuardIf from vyos.util import check_kmod from vyos.util import check_port_availability @@ -70,6 +71,7 @@ def verify(wireguard): verify_mtu_ipv6(wireguard) verify_address(wireguard) verify_vrf(wireguard) + verify_redirect(wireguard) if 'private_key' not in wireguard: raise ConfigError('Wireguard private-key not defined') diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py index af35b5f03..fdf9e3988 100755 --- a/src/conf_mode/interfaces-wireless.py +++ b/src/conf_mode/interfaces-wireless.py @@ -27,6 +27,7 @@ from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_dhcpv6 from vyos.configverify import verify_source_interface +from vyos.configverify import verify_redirect from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf from vyos.ifconfig import WiFiIf @@ -189,6 +190,7 @@ def verify(wifi): verify_address(wifi) verify_vrf(wifi) + verify_redirect(wifi) # use common function to verify VLAN configuration verify_vlan_config(wifi) diff --git a/src/conf_mode/interfaces-wwan.py b/src/conf_mode/interfaces-wwan.py index a4b033374..367a50e82 100755 --- a/src/conf_mode/interfaces-wwan.py +++ b/src/conf_mode/interfaces-wwan.py @@ -23,6 +23,7 @@ from vyos.config import Config from vyos.configdict import get_interface_dict from vyos.configverify import verify_authentication from vyos.configverify import verify_interface_exists +from vyos.configverify import verify_redirect from vyos.configverify import verify_vrf from vyos.ifconfig import WWANIf from vyos.util import cmd @@ -77,6 +78,7 @@ def verify(wwan): verify_interface_exists(ifname) verify_authentication(wwan) verify_vrf(wwan) + verify_redirect(wwan) return None diff --git a/src/conf_mode/protocols_ospf.py b/src/conf_mode/protocols_ospf.py index 4895cde6f..26d491838 100755 --- a/src/conf_mode/protocols_ospf.py +++ b/src/conf_mode/protocols_ospf.py @@ -25,6 +25,7 @@ from vyos.configdict import node_changed from vyos.configverify import verify_common_route_maps from vyos.configverify import verify_route_map from vyos.configverify import verify_interface_exists +from vyos.configverify import verify_access_list from vyos.template import render_to_string from vyos.util import dict_search from vyos.util import get_interface_config @@ -159,6 +160,16 @@ def verify(ospf): route_map_name = dict_search('default_information.originate.route_map', ospf) if route_map_name: verify_route_map(route_map_name, ospf) + # Validate if configured Access-list exists + if 'area' in ospf: + for area, area_config in ospf['area'].items(): + if 'import_list' in area_config: + acl_import = area_config['import_list'] + if acl_import: verify_access_list(acl_import, ospf) + if 'export_list' in area_config: + acl_export = area_config['export_list'] + if acl_export: verify_access_list(acl_export, ospf) + if 'interface' in ospf: for interface, interface_config in ospf['interface'].items(): verify_interface_exists(interface) diff --git a/src/conf_mode/qos.py b/src/conf_mode/qos.py new file mode 100755 index 000000000..cf447d4b5 --- /dev/null +++ b/src/conf_mode/qos.py @@ -0,0 +1,90 @@ +#!/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/>. + +from sys import exit + +from vyos.config import Config +from vyos.configdict import dict_merge +from vyos.xml import defaults +from vyos import ConfigError +from vyos import airbag +airbag.enable() + +def get_config(config=None): + if config: + conf = config + else: + conf = Config() + base = ['traffic-policy'] + if not conf.exists(base): + return None + + qos = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + + for traffic_policy in ['drop-tail', 'fair-queue', 'fq-codel', 'limiter', + 'network-emulator', 'priority-queue', 'random-detect', + 'rate-control', 'round-robin', 'shaper', 'shaper-hfsc']: + traffic_policy_us = traffic_policy.replace('-','_') + # Individual policy type not present on CLI - no need to blend in + # any default values + if traffic_policy_us not in qos: + continue + + default_values = defaults(base + [traffic_policy_us]) + + # class is another tag node which requires individual handling + class_default_values = defaults(base + [traffic_policy_us, 'class']) + if 'class' in default_values: + del default_values['class'] + + for policy, policy_config in qos[traffic_policy_us].items(): + qos[traffic_policy_us][policy] = dict_merge( + default_values, qos[traffic_policy_us][policy]) + + if 'class' in policy_config: + for policy_class in policy_config['class']: + qos[traffic_policy_us][policy]['class'][policy_class] = dict_merge( + class_default_values, qos[traffic_policy_us][policy]['class'][policy_class]) + + import pprint + pprint.pprint(qos) + return qos + +def verify(qos): + if not qos: + return None + + # network policy emulator + # reorder rerquires delay to be set + + raise ConfigError('123') + return None + +def generate(qos): + return None + +def apply(qos): + 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/migration-scripts/bgp/0-to-1 b/src/migration-scripts/bgp/0-to-1 index b1d5a6514..5e9dffe1f 100755 --- a/src/migration-scripts/bgp/0-to-1 +++ b/src/migration-scripts/bgp/0-to-1 @@ -33,7 +33,7 @@ with open(file_name, 'r') as f: base = ['protocols', 'bgp'] config = ConfigTree(config_file) -if not config.exists(base): +if not config.exists(base) or not config.is_tag(base): # Nothing to do exit(0) diff --git a/src/op_mode/generate_public_key_command.py b/src/op_mode/generate_public_key_command.py index 7a7b6c923..f071ae350 100755 --- a/src/op_mode/generate_public_key_command.py +++ b/src/op_mode/generate_public_key_command.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# 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 @@ -29,8 +29,12 @@ def get_key(path): key_string = vyos.remote.get_remote_config(path) return key_string.split() -username = sys.argv[1] -algorithm, key, identifier = get_key(sys.argv[2]) +try: + username = sys.argv[1] + algorithm, key, identifier = get_key(sys.argv[2]) +except Exception as e: + print("Failed to retrieve the public key: {}".format(e)) + sys.exit(1) print('# To add this key as an embedded key, run the following commands:') print('configure') @@ -39,3 +43,4 @@ print(f'set system login user {username} authentication public-keys {identifier} print('commit') print('save') print('exit') + diff --git a/src/validators/ipv6-range b/src/validators/ipv6-range index a3c401281..7080860c4 100755 --- a/src/validators/ipv6-range +++ b/src/validators/ipv6-range @@ -1,17 +1,20 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 -import sys -import re -from vyos.template import is_ipv6 +from ipaddress import IPv6Address +from sys import argv, exit if __name__ == '__main__': - if len(sys.argv)>1: - ipv6_range = sys.argv[1] - # Regex for ipv6-ipv6 https://regexr.com/ - if re.search('([a-f0-9:]+:+)+[a-f0-9]+-([a-f0-9:]+:+)+[a-f0-9]+', ipv6_range): - for tmp in ipv6_range.split('-'): - if not is_ipv6(tmp): - print(f'Error: {ipv6_range} is not a valid IPv6 range') - sys.exit(1) - - sys.exit(0) + if len(argv) > 1: + # try to pass validation and raise an error if failed + try: + ipv6_range = argv[1] + range_left = ipv6_range.split('-')[0] + range_right = ipv6_range.split('-')[1] + if not IPv6Address(range_left) < IPv6Address(range_right): + raise ValueError(f'left element {range_left} must be less than right element {range_right}') + except Exception as err: + print(f'Error: {ipv6_range} is not a valid IPv6 range: {err}') + exit(1) + else: + print('Error: an IPv6 range argument must be provided') + exit(1) |