summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--data/templates/dhcp-client/ipv6.tmpl6
-rw-r--r--data/templates/frr/ospf.frr.tmpl54
-rw-r--r--data/templates/frr/rpki.frr.tmpl17
-rw-r--r--data/templates/pppoe/ip-down.script.tmpl6
-rw-r--r--interface-definitions/include/bgp-capability-dynamic.xml.i9
-rw-r--r--interface-definitions/include/bgp-capability.xml.i7
-rw-r--r--interface-definitions/include/bgp-neighbor-afi-ipv4-unicast.xml.i1
-rw-r--r--interface-definitions/include/bgp-neighbor-afi-ipv6-unicast.xml.i1
-rw-r--r--interface-definitions/include/ospf-authentication.xml.i45
-rw-r--r--interface-definitions/include/ospf-intervals.xml.i54
-rw-r--r--interface-definitions/include/vif-s.xml.i1
-rw-r--r--interface-definitions/protocols-ospf.xml.in186
-rw-r--r--interface-definitions/protocols-rpki.xml.in85
-rw-r--r--interface-definitions/protocols-vrf.xml.in359
-rw-r--r--op-mode-definitions/generate-ssh-server-key.xml.in24
-rw-r--r--op-mode-definitions/traffic-dump.xml.in4
-rw-r--r--python/vyos/configverify.py22
-rw-r--r--python/vyos/ifconfig/interface.py7
-rw-r--r--smoketest/configs/bgp-big-as-cloud1952
-rw-r--r--smoketest/configs/bgp-small-as (renamed from smoketest/configs/small-as-bgp-vrrp)0
-rw-r--r--smoketest/configs/bgp-small-internet-exchange (renamed from smoketest/configs/bgp-ixp)0
-rw-r--r--smoketest/configs/dialup-router-complex (renamed from smoketest/configs/dmz-guest-lan-nat-pppoe-router)1
-rw-r--r--smoketest/configs/dialup-router-medium-vpn707
-rw-r--r--smoketest/configs/ospf-small (renamed from smoketest/configs/ospf-config)0
-rw-r--r--smoketest/configs/pppoe-client62
-rw-r--r--smoketest/scripts/cli/base_interfaces_test.py9
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_bonding.py40
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_bridge.py35
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_dummy.py8
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_ethernet.py46
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_geneve.py16
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_l2tpv3.py16
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_loopback.py18
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_macsec.py20
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_openvpn.py10
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_pppoe.py21
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_pseudo_ethernet.py26
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_tunnel.py28
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_vxlan.py18
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_wireguard.py2
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_wireless.py14
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_wirelessmodem.py2
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_bgp.py39
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_ospf.py56
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_rpki.py151
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_static.py154
-rwxr-xr-xsmoketest/scripts/cli/test_vrf.py121
-rwxr-xr-xsrc/conf_mode/interfaces-pppoe.py10
-rwxr-xr-xsrc/conf_mode/lldp.py9
-rwxr-xr-xsrc/conf_mode/protocols_ospf.py14
-rwxr-xr-xsrc/conf_mode/protocols_rpki.py139
-rwxr-xr-xsrc/migration-scripts/interfaces/18-to-1981
-rwxr-xr-xsrc/migration-scripts/quagga/6-to-776
-rwxr-xr-xsrc/migration-scripts/rpki/0-to-158
55 files changed, 4374 insertions, 475 deletions
diff --git a/Makefile b/Makefile
index 2ff72cb21..19911fa58 100644
--- a/Makefile
+++ b/Makefile
@@ -47,7 +47,7 @@ interface_definitions: $(config_xml_obj)
rm -f $(TMPL_DIR)/vpn/node.def
rm -f $(TMPL_DIR)/vpn/ipsec/node.def
rm -rf $(TMPL_DIR)/vpn/nipsec
- rm -rf $(TMPL_DIR)/protocols/nrpki
+ rm -rf $(TMPL_DIR)/protocols/nvrf
# XXX: required until OSPF and RIP is migrated from vyatta-cfg-quagga to vyos-1x
mkdir $(TMPL_DIR)/interfaces/loopback/node.tag/ipv6
diff --git a/data/templates/dhcp-client/ipv6.tmpl b/data/templates/dhcp-client/ipv6.tmpl
index 49d0d8c88..c292664e9 100644
--- a/data/templates/dhcp-client/ipv6.tmpl
+++ b/data/templates/dhcp-client/ipv6.tmpl
@@ -2,10 +2,10 @@
# man https://www.unix.com/man-page/debian/5/dhcp6c.conf/
interface {{ ifname }} {
-{% if address is defined and 'dhcpv6' in address %}
-{% if dhcpv6_options is defined and dhcpv6_options.duid is defined and dhcpv6_options.duid is not none %}
+{% if dhcpv6_options is defined and dhcpv6_options.duid is defined and dhcpv6_options.duid is not none %}
send client-id {{ dhcpv6_options.duid }};
-{% endif %}
+{% endif %}
+{% if address is defined and 'dhcpv6' in address %}
request domain-name-servers;
request domain-name;
{% if dhcpv6_options is defined and dhcpv6_options.parameters_only is defined %}
diff --git a/data/templates/frr/ospf.frr.tmpl b/data/templates/frr/ospf.frr.tmpl
index 07699290c..37c21e146 100644
--- a/data/templates/frr/ospf.frr.tmpl
+++ b/data/templates/frr/ospf.frr.tmpl
@@ -1,4 +1,52 @@
!
+{% if interface is defined and interface is not none %}
+{% for iface, iface_config in interface.items() %}
+interface {{ iface }}
+{% if iface_config.authentication is defined and iface_config.authentication is not none %}
+{% if iface_config.authentication.plaintext_password is defined and iface_config.authentication.plaintext_password is not none %}
+ ip ospf authentication-key {{ iface_config.authentication.plaintext_password }}
+{% elif iface_config.authentication.md5 is defined %}
+ ip ospf authentication message-digest
+{% if iface_config.authentication.md5.key_id is defined and iface_config.authentication.md5.key_id is not none %}
+{% for key, key_config in iface_config.authentication.md5.key_id.items() %}
+ ip ospf message-digest-key {{ key }} md5 {{ key_config.md5_key }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% endif %}
+{% if iface_config.cost is defined and iface_config.cost is not none %}
+ ip ospf cost {{ iface_config.cost }}
+{% endif %}
+{% if iface_config.priority is defined and iface_config.priority is not none %}
+ ip ospf priority {{ iface_config.priority }}
+{% endif %}
+{% if iface_config.hello_interval is defined and iface_config.hello_interval is not none %}
+ ip ospf hello-interval {{ iface_config.hello_interval }}
+{% endif %}
+{% if iface_config.retransmit_interval is defined and iface_config.retransmit_interval is not none %}
+ ip ospf retransmit-interval {{ iface_config.retransmit_interval }}
+{% endif %}
+{% if iface_config.transmit_delay is defined and iface_config.transmit_delay is not none %}
+ ip ospf transmit-delay {{ iface_config.transmit_delay }}
+{% endif %}
+{% if iface_config.dead_interval is defined and iface_config.dead_interval is not none %}
+ ip ospf dead-interval {{ iface_config.dead_interval }}
+{% endif %}
+{% if iface_config.bfd is defined %}
+ ip ospf bfd
+{% endif %}
+{% if iface_config.mtu_ignore is defined %}
+ ip ospf mtu-ignore
+{% endif %}
+{% if iface_config.network is defined and iface_config.network is not none %}
+ ip ospf network {{ iface_config.network }}
+{% endif %}
+{% if iface_config.bandwidth is defined and iface_config.bandwidth is not none %}
+ bandwidth {{ iface_config.bandwidth }}
+{% endif %}
+{% endfor %}
+{% endif %}
+!
router ospf
{% if access_list is defined and access_list is not none %}
{% for acl, acl_config in access_list.items() %}
@@ -50,10 +98,8 @@ router ospf
{% endfor %}
{% endif %}
{% endif %}
-{% if link_config.dead_interval is defined and link_config.dead_interval is not none %}
-{# The following values are default values #}
- area {{ area_id }} virtual-link {{ link }} hello-interval {{ link_config.hello_interval }} retransmit-interval {{ link_config.retransmit_interval }} transmit-delay {{ link_config.retransmit_interval }} dead-interval {{ link_config.dead_interval }}
-{% endif %}
+{# The following values are default values #}
+ area {{ area_id }} virtual-link {{ link }} hello-interval {{ link_config.hello_interval }} retransmit-interval {{ link_config.retransmit_interval }} transmit-delay {{ link_config.transmit_delay }} dead-interval {{ link_config.dead_interval }}
{% endfor %}
{% endif %}
{% endfor %}
diff --git a/data/templates/frr/rpki.frr.tmpl b/data/templates/frr/rpki.frr.tmpl
new file mode 100644
index 000000000..346a0caa9
--- /dev/null
+++ b/data/templates/frr/rpki.frr.tmpl
@@ -0,0 +1,17 @@
+!
+{# as FRR does not support deleting the entire rpki section we leave it in place even when it's empty #}
+rpki
+{% if cache is defined and cache is not none %}
+{% for peer, peer_config in cache.items() %}
+{# port is mandatory and preference uses a default value #}
+{% if peer_config.ssh is defined and peer_config.ssh.username is defined and peer_config.ssh.username is not none %}
+ rpki cache {{ peer }} {{ peer_config.port }} {{ peer_config.ssh.username }} {{ peer_config.ssh.private_key_file }} {{ peer_config.ssh.public_key_file }} {{ peer_config.ssh.known_hosts_file }} preference {{ peer_config.preference }}
+{% else %}
+ rpki cache {{ peer }} {{ peer_config.port }} preference {{ peer_config.preference }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if polling_period is defined and polling_period is not none %}
+ rpki polling_period {{ polling_period }}
+{% endif %}
+!
diff --git a/data/templates/pppoe/ip-down.script.tmpl b/data/templates/pppoe/ip-down.script.tmpl
index 5e119f796..bac4155d6 100644
--- a/data/templates/pppoe/ip-down.script.tmpl
+++ b/data/templates/pppoe/ip-down.script.tmpl
@@ -23,10 +23,12 @@ if [ -d /sys/class/net/{{ ifname }}/upper_* ]; then
VRF_NAME="vrf ${VRF_NAME}"
fi
-# Always delete default route when interface goes down
+{% if default_route != 'none' %}
+# Always delete default route when interface goes down if we installed it
vtysh -c "conf t" ${VRF_NAME} -c "no ip route 0.0.0.0/0 {{ ifname }} ${VRF_NAME}"
-{% if ipv6 is defined and ipv6.address is defined and ipv6.address.autoconf is defined %}
+{% if ipv6 is defined and ipv6.address is defined and ipv6.address.autoconf is defined %}
vtysh -c "conf t" ${VRF_NAME} -c "no ipv6 route ::/0 {{ ifname }} ${VRF_NAME}"
+{% endif %}
{% endif %}
{% endif %}
diff --git a/interface-definitions/include/bgp-capability-dynamic.xml.i b/interface-definitions/include/bgp-capability-dynamic.xml.i
deleted file mode 100644
index 3cf300156..000000000
--- a/interface-definitions/include/bgp-capability-dynamic.xml.i
+++ /dev/null
@@ -1,9 +0,0 @@
-<!-- included start from bgp-capability-dynamic.xml.i -->
-<!-- Capability dynamic in the afi ipv6 does nothing T3037 -->
-<leafNode name="dynamic">
- <properties>
- <help>Advertise dynamic capability to this neighbor</help>
- <valueless/>
- </properties>
-</leafNode>
-<!-- included end -->
diff --git a/interface-definitions/include/bgp-capability.xml.i b/interface-definitions/include/bgp-capability.xml.i
index 5940e46e4..8de5bd8ab 100644
--- a/interface-definitions/include/bgp-capability.xml.i
+++ b/interface-definitions/include/bgp-capability.xml.i
@@ -4,7 +4,12 @@
<help>Advertise capabilities to this peer-group</help>
</properties>
<children>
- #include <include/bgp-capability-dynamic.xml.i>
+ <leafNode name="dynamic">
+ <properties>
+ <help>Advertise dynamic capability to this neighbor</help>
+ <valueless/>
+ </properties>
+ </leafNode>
<leafNode name="extended-nexthop">
<properties>
<help>Advertise extended-nexthop capability to this neighbor</help>
diff --git a/interface-definitions/include/bgp-neighbor-afi-ipv4-unicast.xml.i b/interface-definitions/include/bgp-neighbor-afi-ipv4-unicast.xml.i
index 03a859271..8f6cf06b1 100644
--- a/interface-definitions/include/bgp-neighbor-afi-ipv4-unicast.xml.i
+++ b/interface-definitions/include/bgp-neighbor-afi-ipv4-unicast.xml.i
@@ -10,7 +10,6 @@
</properties>
<children>
#include <include/bgp-afi-capability-orf.xml.i>
- #include <include/bgp-capability-dynamic.xml.i>
</children>
</node>
#include <include/bgp-afi-peer-group.xml.i>
diff --git a/interface-definitions/include/bgp-neighbor-afi-ipv6-unicast.xml.i b/interface-definitions/include/bgp-neighbor-afi-ipv6-unicast.xml.i
index e9ba23408..aea10c20c 100644
--- a/interface-definitions/include/bgp-neighbor-afi-ipv6-unicast.xml.i
+++ b/interface-definitions/include/bgp-neighbor-afi-ipv6-unicast.xml.i
@@ -10,7 +10,6 @@
</properties>
<children>
#include <include/bgp-afi-capability-orf.xml.i>
- #include <include/bgp-capability-dynamic.xml.i>
</children>
</node>
#include <include/bgp-afi-peer-group.xml.i>
diff --git a/interface-definitions/include/ospf-authentication.xml.i b/interface-definitions/include/ospf-authentication.xml.i
new file mode 100644
index 000000000..0963e5cc0
--- /dev/null
+++ b/interface-definitions/include/ospf-authentication.xml.i
@@ -0,0 +1,45 @@
+<!-- included start from ospf-authentication.xml.i -->
+<node name="authentication">
+ <properties>
+ <help>Authentication</help>
+ </properties>
+ <children>
+ <node name="md5">
+ <properties>
+ <help>MD5 key id</help>
+ </properties>
+ <children>
+ <tagNode name="key-id">
+ <properties>
+ <help>MD5 key id</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>MD5 key id</description>
+ </valueHelp>
+ </properties>
+ <children>
+ <leafNode name="md5-key">
+ <properties>
+ <help>MD5 authentication type</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>MD5 Key (16 characters or less)</description>
+ </valueHelp>
+ </properties>
+ </leafNode>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+ <leafNode name="plaintext-password">
+ <properties>
+ <help>Plain text password</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Plain text password (8 characters or less)</description>
+ </valueHelp>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- included end -->
diff --git a/interface-definitions/include/ospf-intervals.xml.i b/interface-definitions/include/ospf-intervals.xml.i
new file mode 100644
index 000000000..e532bd14b
--- /dev/null
+++ b/interface-definitions/include/ospf-intervals.xml.i
@@ -0,0 +1,54 @@
+<!-- included start from ospf-intervals.xml.i -->
+<leafNode name="dead-interval">
+ <properties>
+ <help>Interval after which a neighbor is declared dead (default: 40)</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Neighbor dead interval (seconds)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ <defaultValue>40</defaultValue>
+</leafNode>
+<leafNode name="hello-interval">
+ <properties>
+ <help>Interval between hello packets (default: 10)</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Hello interval (seconds)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ <defaultValue>10</defaultValue>
+</leafNode>
+<leafNode name="retransmit-interval">
+ <properties>
+ <help>Interval between retransmitting lost link state advertisements (default: 5)</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Retransmit interval (seconds)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ <defaultValue>5</defaultValue>
+</leafNode>
+<leafNode name="transmit-delay">
+ <properties>
+ <help>Link state transmit delay (default: 1)</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Link state transmit delay (seconds)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ <defaultValue>1</defaultValue>
+</leafNode>
+<!-- included end -->
diff --git a/interface-definitions/include/vif-s.xml.i b/interface-definitions/include/vif-s.xml.i
index 6ba7e0b99..01cb59efc 100644
--- a/interface-definitions/include/vif-s.xml.i
+++ b/interface-definitions/include/vif-s.xml.i
@@ -61,6 +61,7 @@
#include <include/interface-vrf.xml.i>
</children>
</tagNode>
+ #include <include/interface-vrf.xml.i>
</children>
</tagNode>
<!-- included end -->
diff --git a/interface-definitions/protocols-ospf.xml.in b/interface-definitions/protocols-ospf.xml.in
index 074d0db63..1051e3741 100644
--- a/interface-definitions/protocols-ospf.xml.in
+++ b/interface-definitions/protocols-ospf.xml.in
@@ -275,101 +275,8 @@
</constraint>
</properties>
<children>
- <node name="authentication">
- <properties>
- <help>Authentication</help>
- </properties>
- <children>
- <node name="md5">
- <properties>
- <help>MD5 key id</help>
- </properties>
- <children>
- <tagNode name="key-id">
- <properties>
- <help>MD5 key id</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>MD5 key id</description>
- </valueHelp>
- </properties>
- <children>
- <leafNode name="md5-key">
- <properties>
- <help>MD5 authentication type</help>
- <valueHelp>
- <format>txt</format>
- <description>MD5 Key (16 characters or less)</description>
- </valueHelp>
- </properties>
- </leafNode>
- </children>
- </tagNode>
- </children>
- </node>
- <leafNode name="plaintext-password">
- <properties>
- <help>Plain text password</help>
- <valueHelp>
- <format>txt</format>
- <description>Plain text password (8 characters or less)</description>
- </valueHelp>
- </properties>
- </leafNode>
- </children>
- </node>
- <leafNode name="dead-interval">
- <properties>
- <help>Interval after which a neighbor is declared dead (default: 40)</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Neighbor dead interval (seconds)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
- <defaultValue>40</defaultValue>
- </leafNode>
- <leafNode name="hello-interval">
- <properties>
- <help>Interval between hello packets (default: 10)</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Hello interval (seconds)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
- <defaultValue>10</defaultValue>
- </leafNode>
- <leafNode name="retransmit-interval">
- <properties>
- <help>Interval between retransmitting lost link state advertisements (default: 5)</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Retransmit interval (seconds)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
- <defaultValue>5</defaultValue>
- </leafNode>
- <leafNode name="transmit-delay">
- <properties>
- <help>Link state transmit delay (default: 1)</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Link state transmit delay (seconds)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
- <defaultValue>1</defaultValue>
- </leafNode>
+ #include <include/ospf-authentication.xml.i>
+ #include <include/ospf-intervals.xml.i>
</children>
</tagNode>
</children>
@@ -491,6 +398,95 @@
</node>
</children>
</node>
+ <tagNode name="interface">
+ <properties>
+ <help>Interface related configuration</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ </properties>
+ <children>
+ #include <include/ospf-authentication.xml.i>
+ #include <include/ospf-intervals.xml.i>
+ <leafNode name="bandwidth">
+ <properties>
+ <help>Bandwidth of interface (Megabit/sec)</help>
+ <valueHelp>
+ <format>u32:1-100000</format>
+ <description>Bandwidth in Megabit/sec (for calculating OSPF cost)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-100000"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="bfd">
+ <properties>
+ <help>Enable Bidirectional Forwarding Detection (BFD) support</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="cost">
+ <properties>
+ <help>Interface cost</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>OSPF interface cost</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="mtu-ignore">
+ <properties>
+ <help>Disable Maximum Transmission Unit (MTU) mismatch detection</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="network">
+ <properties>
+ <help>Network type</help>
+ <completionHelp>
+ <list>broadcast non-broadcast point-to-multipoint point-to-point</list>
+ </completionHelp>
+ <valueHelp>
+ <format>broadcast</format>
+ <description>Broadcast network type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>non-broadcast</format>
+ <description>Non-broadcast network type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>point-to-multipoint</format>
+ <description>Point-to-multipoint network type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>point-to-point</format>
+ <description>Point-to-point network type</description>
+ </valueHelp>
+ <constraint>
+ <regex>^(broadcast|non-broadcast|point-to-multipoint|point-to-point)$</regex>
+ </constraint>
+ <constraintErrorMessage>Must be broadcast, non-broadcast, point-to-multipoint or point-to-point</constraintErrorMessage>
+ </properties>
+ </leafNode>
+ <leafNode name="priority">
+ <properties>
+ <help>Router priority (default: 1)</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>OSPF router priority cost</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+ <defaultValue>1</defaultValue>
+ </leafNode>
+ </children>
+ </tagNode>
<node name="log-adjacency-changes">
<properties>
<help>Log changes in adjacency state</help>
diff --git a/interface-definitions/protocols-rpki.xml.in b/interface-definitions/protocols-rpki.xml.in
index b8db49e36..94fab54a5 100644
--- a/interface-definitions/protocols-rpki.xml.in
+++ b/interface-definitions/protocols-rpki.xml.in
@@ -1,32 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Protocol RPKI configuration -->
<interfaceDefinition>
<node name="protocols">
<children>
- <node name="nrpki" owner="${vyos_conf_scripts_dir}/protocols_rpki.py">
+ <node name="rpki" owner="${vyos_conf_scripts_dir}/protocols_rpki.py">
<properties>
<help>BGP prefix origin validation</help>
</properties>
<children>
<tagNode name="cache">
<properties>
- <help>RPKI cache server instance</help>
+ <help>RPKI cache server address</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>IP address of NTP server</description>
+ </valueHelp>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>IPv6 address of NTP server</description>
+ </valueHelp>
+ <valueHelp>
+ <format>hostname</format>
+ <description>Fully qualified domain name of NTP server</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-address"/>
+ <validator name="ipv6-address"/>
+ <validator name="fqdn"/>
+ </constraint>
</properties>
<children>
- <leafNode name="address">
+ #include <include/port-number.xml.i>
+ <leafNode name="preference">
<properties>
- <help>RPKI cache server address</help>
- </properties>
- </leafNode>
- <leafNode name="port">
- <properties>
- <help>TCP port number</help>
+ <help>Preference of the cache server</help>
<valueHelp>
- <format>u32:1-65535</format>
- <description>TCP port number</description>
+ <format>u32:1-255</format>
+ <description>Polling period</description>
</valueHelp>
<constraint>
- <validator name="numeric" argument="--range 1-65535"/>
+ <validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
@@ -68,55 +80,20 @@
</node>
</children>
</tagNode>
- <leafNode name="initial-synchronization-timeout">
- <properties>
- <help>Initial RPKI cache synchronization timeout</help>
- <valueHelp>
- <format>u32:0-4294967295</format>
- <description>Initial RPKI cache synchronization timeout</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-4294967295"/>
- </constraint>
- </properties>
- </leafNode>
<leafNode name="polling-period">
<properties>
- <help>RPKI cache polling period</help>
- <valueHelp>
- <format>u32:1-1300</format>
- <description>Polling period</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-1300"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="preference">
- <properties>
- <help>RPKI cache preference</help>
- <valueHelp>
- <format>u32:0-4294967295</format>
- <description>RPKI cache preference</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-4294967295"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="timeout">
- <properties>
- <help>RPKI cache reply timeout</help>
+ <help>RPKI cache polling period (default: 300)</help>
<valueHelp>
- <format>u32:0-4294967295</format>
- <description>RPKI cache reply timeout</description>
+ <format>u32:1-86400</format>
+ <description>Polling period in seconds</description>
</valueHelp>
<constraint>
- <validator name="numeric" argument="--range 0-4294967295"/>
+ <validator name="numeric" argument="--range 1-86400"/>
</constraint>
</properties>
+ <defaultValue>300</defaultValue>
</leafNode>
- </children>
+ </children>
</node>
</children>
</node>
diff --git a/interface-definitions/protocols-vrf.xml.in b/interface-definitions/protocols-vrf.xml.in
new file mode 100644
index 000000000..d58f85b02
--- /dev/null
+++ b/interface-definitions/protocols-vrf.xml.in
@@ -0,0 +1,359 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Protocol VRF configuration -->
+<interfaceDefinition>
+ <node name="protocols">
+ <children>
+ <tagNode name="nvrf" owner="${vyos_conf_scripts_dir}/vrf.py">
+ <properties>
+ <help>Name of VRF to add route for</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Name of VRF to add route for</description>
+ </valueHelp>
+ <completionHelp>
+ <path>protocols vrf</path>
+ </completionHelp>
+ </properties>
+ <children>
+ <node name="static">
+ <properties>
+ <help>Static route parameters</help>
+ </properties>
+ <children>
+ <tagNode name="interface-route">
+ <properties>
+ <help>Interface based static route</help>
+ <valueHelp>
+ <format>ipv4net</format>
+ <description>Interface based static route</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-prefix"/>
+ </constraint>
+ </properties>
+ <children>
+ <tagNode name="next-hop-interface">
+ <properties>
+ <help>Next-hop interface [REQUIRED]</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ </properties>
+ <children>
+ <leafNode name="disable">
+ <properties>
+ <help>Disable IPv4 interface static route</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="distance">
+ <properties>
+ <help>Distance for this route</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Distance for this route</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="next-hop-vrf">
+ <properties>
+ <help>VRF to leak route</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Name of VRF to leak to</description>
+ </valueHelp>
+ <valueHelp>
+ <format>default</format>
+ <description>Name of VRF to leak to</description>
+ </valueHelp>
+ <completionHelp>
+ <list>default</list>
+ <path>protocols vrf</path>
+ </completionHelp>
+ <constraint>
+ <regex>^[a-zA-Z0-9\-_]{1,100}$</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </tagNode>
+ </children>
+ </tagNode>
+ <tagNode name="interface-route6">
+ <properties>
+ <help>Interface based IPv6 static route</help>
+ <valueHelp>
+ <format>ipv6net</format>
+ <description>Interface based IPv6 static route</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv6-prefix"/>
+ </constraint>
+ </properties>
+ <children>
+ <tagNode name="next-hop-interface">
+ <properties>
+ <help>Next-hop interface [REQUIRED]</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ </properties>
+ <children>
+ <leafNode name="disable">
+ <properties>
+ <help>Disable IPv6 interface static route</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="distance">
+ <properties>
+ <help>Distance for this route</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Distance for this route</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="next-hop-vrf">
+ <properties>
+ <help>VRF to leak route</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Name of VRF to leak to</description>
+ </valueHelp>
+ <valueHelp>
+ <format>default</format>
+ <description>Name of VRF to leak to</description>
+ </valueHelp>
+ <completionHelp>
+ <list>default</list>
+ <path>protocols vrf</path>
+ </completionHelp>
+ <constraint>
+ <regex>^[a-zA-Z0-9\-_]{1,100}$</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </tagNode>
+ </children>
+ </tagNode>
+ <tagNode name="route">
+ <properties>
+ <help>VRF static IPv4 route</help>
+ <valueHelp>
+ <format>ipv4net</format>
+ <description>VRF static IPv4 route</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-prefix"/>
+ </constraint>
+ </properties>
+ <children>
+ <node name="blackhole">
+ <properties>
+ <help>Silently discard pkts when matched</help>
+ </properties>
+ <children>
+ <leafNode name="distance">
+ <properties>
+ <help>Distance value for this route</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Distance for this route</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <leafNode name="dhcp-interface">
+ <properties>
+ <help>DHCP interface that supplies the next-hop IP address for this static route</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>DHCP interface</description>
+ </valueHelp>
+ </properties>
+ </leafNode>
+ <tagNode name="next-hop">
+ <properties>
+ <help>Next-hop router</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>Next-hop router</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-address"/>
+ </constraint>
+ </properties>
+ <children>
+ <leafNode name="disable">
+ <properties>
+ <help>Disable IPv4 interface static route</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="distance">
+ <properties>
+ <help>Distance for this route</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Distance for this route</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="next-hop-interface">
+ <properties>
+ <help>IPv4 gateway interface name</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>IPv4 gateway interface name</description>
+ </valueHelp>
+ </properties>
+ </leafNode>
+ <leafNode name="next-hop-vrf">
+ <properties>
+ <help>VRF to leak route</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Name of VRF to leak to</description>
+ </valueHelp>
+ <valueHelp>
+ <format>default</format>
+ <description>Name of VRF to leak to</description>
+ </valueHelp>
+ <completionHelp>
+ <list>default</list>
+ <path>protocols vrf</path>
+ </completionHelp>
+ <constraint>
+ <regex>^[a-zA-Z0-9\-_]{1,100}$</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </tagNode>
+ </children>
+ </tagNode>
+ <tagNode name="route6">
+ <properties>
+ <help>VRF static IPv6 route</help>
+ <valueHelp>
+ <format>ipv6net</format>
+ <description>VRF static IPv6 route</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv6-prefix"/>
+ </constraint>
+ </properties>
+ <children>
+ <node name="blackhole">
+ <properties>
+ <help>Silently discard pkts when matched</help>
+ </properties>
+ <children>
+ <leafNode name="distance">
+ <properties>
+ <help>Distance value for this route</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Distance for this route</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <tagNode name="next-hop">
+ <properties>
+ <help>Next-hop IPv6 router [REQUIRED]</help>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>Next-hop IPv6 router [REQUIRED]</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv6-address"/>
+ </constraint>
+ </properties>
+ <children>
+ <leafNode name="disable">
+ <properties>
+ <help>Disable IPv6 interface static route</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="distance">
+ <properties>
+ <help>Distance for this route</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Distance for this route</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="interface">
+ <properties>
+ <help>IPv6 gateway interface name</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>IPv6 gateway interface name</description>
+ </valueHelp>
+ </properties>
+ </leafNode>
+ <leafNode name="next-hop-vrf">
+ <properties>
+ <help>VRF to leak route</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Name of VRF to leak to</description>
+ </valueHelp>
+ <valueHelp>
+ <format>default</format>
+ <description>Name of VRF to leak to</description>
+ </valueHelp>
+ <completionHelp>
+ <list>default</list>
+ <path>protocols vrf</path>
+ </completionHelp>
+ <constraint>
+ <regex>^[a-zA-Z0-9\-_]{1,100}$</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </tagNode>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/op-mode-definitions/generate-ssh-server-key.xml.in b/op-mode-definitions/generate-ssh-server-key.xml.in
index a6ebf1b78..86bb1b1bd 100644
--- a/op-mode-definitions/generate-ssh-server-key.xml.in
+++ b/op-mode-definitions/generate-ssh-server-key.xml.in
@@ -2,14 +2,30 @@
<interfaceDefinition>
<node name="generate">
<properties>
- <help>Generate an object</help>
+ <help>Generate an object/key</help>
</properties>
<children>
- <node name="ssh-server-key">
+ <node name="ssh">
<properties>
- <help>Regenerate the host SSH keys and restart the SSH server</help>
+ <help>Generate SSH related keypairs</help>
</properties>
- <command>${vyos_op_scripts_dir}/generate_ssh_server_key.py</command>
+ <children>
+ <node name="server-key">
+ <properties>
+ <help>Re-generate SSH host keys and restart SSH server</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/generate_ssh_server_key.py</command>
+ </node>
+ <tagNode name="client-key">
+ <properties>
+ <help>Re-generate SSH client keypair</help>
+ <completionHelp>
+ <list>&lt;filename&gt;</list>
+ </completionHelp>
+ </properties>
+ <command>ssh-keygen -t rsa -f "$4" -N ""</command>
+ </tagNode>
+ </children>
</node>
</children>
</node>
diff --git a/op-mode-definitions/traffic-dump.xml.in b/op-mode-definitions/traffic-dump.xml.in
index cd0d459ca..76e3ddce5 100644
--- a/op-mode-definitions/traffic-dump.xml.in
+++ b/op-mode-definitions/traffic-dump.xml.in
@@ -16,7 +16,7 @@
</completionHelp>
</properties>
<children>
- <tagNode name="verbose">
+ <node name="verbose">
<command>sudo tcpdump -vvv -ne -i $4</command>
<properties>
<help>Provide more detailed packets for each monitored traffic</help>
@@ -43,7 +43,7 @@
</children>
</tagNode>
</children>
- </tagNode>
+ </node>
<tagNode name="filter">
<command>sudo tcpdump -n -i $4 "${@:6}"</command>
<properties>
diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py
index abd91583d..a888791ba 100644
--- a/python/vyos/configverify.py
+++ b/python/vyos/configverify.py
@@ -217,17 +217,17 @@ def verify_vlan_config(config):
verify_vrf(vlan)
# 802.1ad (Q-in-Q) VLANs
- for vlan in config.get('vif_s', {}):
- vlan = config['vif_s'][vlan]
- verify_dhcpv6(vlan)
- verify_address(vlan)
- verify_vrf(vlan)
-
- for vlan in config.get('vif_s', {}).get('vif_c', {}):
- vlan = config['vif_c'][vlan]
- verify_dhcpv6(vlan)
- verify_address(vlan)
- verify_vrf(vlan)
+ for s_vlan in config.get('vif_s', {}):
+ s_vlan = config['vif_s'][s_vlan]
+ verify_dhcpv6(s_vlan)
+ verify_address(s_vlan)
+ verify_vrf(s_vlan)
+
+ for c_vlan in s_vlan.get('vif_c', {}):
+ c_vlan = s_vlan['vif_c'][c_vlan]
+ verify_dhcpv6(c_vlan)
+ verify_address(c_vlan)
+ verify_vrf(c_vlan)
def verify_accel_ppp_base_service(config):
"""
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index 3b92ce463..8528c4a81 100644
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -1102,9 +1102,10 @@ class Interface(Control):
self.del_addr('dhcp')
# always ensure DHCPv6 client is stopped (when not configured as client
- # for IPv6 address or prefix delegation
+ # for IPv6 address or prefix delegation)
dhcpv6pd = dict_search('dhcpv6_options.pd', config)
- if 'dhcpv6' not in new_addr or dhcpv6pd == None:
+ dhcpv6pd = dhcpv6pd != None and len(dhcpv6pd) != 0
+ if 'dhcpv6' not in new_addr and not dhcpv6pd:
self.del_addr('dhcpv6')
# determine IP addresses which are assigned to the interface and build a
@@ -1124,7 +1125,7 @@ class Interface(Control):
self.add_addr(addr)
# start DHCPv6 client when only PD was configured
- if dhcpv6pd != None:
+ if dhcpv6pd:
self.set_dhcpv6(True)
# There are some items in the configuration which can only be applied
diff --git a/smoketest/configs/bgp-big-as-cloud b/smoketest/configs/bgp-big-as-cloud
new file mode 100644
index 000000000..df3ae015c
--- /dev/null
+++ b/smoketest/configs/bgp-big-as-cloud
@@ -0,0 +1,1952 @@
+firewall {
+ all-ping enable
+ broadcast-ping disable
+ config-trap disable
+ group {
+ address-group bgp-peers-4 {
+ address 192.0.68.3
+ address 192.0.68.2
+ address 192.0.176.193
+ address 192.0.52.0-192.0.52.255
+ address 192.0.53.0-192.0.53.255
+ address 192.0.16.209
+ address 192.0.192.0-192.0.192.255
+ address 192.0.193.0-192.0.193.255
+ address 192.0.194.0-192.0.194.255
+ address 192.0.195.0-192.0.195.255
+ address 192.0.196.0-192.0.196.255
+ address 192.0.197.0-192.0.197.255
+ address 192.0.198.0-192.0.198.255
+ address 192.0.199.0-192.0.199.255
+ }
+ address-group vrrp-peers-4 {
+ address 192.0.68.3
+ address 192.0.160.3
+ address 192.0.98.3
+ address 192.0.71.131
+ address 192.0.84.67
+ address 192.0.71.195
+ address 192.0.71.115
+ address 192.0.70.195
+ address 192.0.70.179
+ address 192.0.70.163
+ address 192.0.70.147
+ address 192.0.70.131
+ address 192.0.70.19
+ address 192.0.70.3
+ address 192.0.71.99
+ address 192.0.68.67
+ address 192.0.71.67
+ address 192.0.71.3
+ address 192.0.68.35
+ address 192.0.68.131
+ address 192.0.69.2
+ address 192.0.70.35
+ address 192.0.70.67
+ }
+ ipv6-address-group bgp-peers-6 {
+ address 2001:db8:c::3
+ address 2001:db8:1000::2e9
+ address 2001:db8:24::fb
+ address 2001:db8:24::fc
+ address 2001:db8:24::fd
+ address 2001:db8:24::2e
+ address 2001:db8:24::3d
+ address 2001:db8:24::4a
+ address 2001:db8:24::5e
+ address 2001:db8:24::7
+ address 2001:db8:24::11
+ address 2001:db8:24::18
+ address 2001:db8:24::20
+ address 2001:db8:24::22
+ address 2001:db8:24::31
+ address 2001:db8:24::58
+ address 2001:db8:24::64
+ address 2001:db8:24::a5
+ address 2001:db8:24::aa
+ address 2001:db8:24::ab
+ address 2001:db8:24::b0
+ address 2001:db8:24::b3
+ address 2001:db8:24::bd
+ address 2001:db8:24::c
+ address 2001:db8:24::d2
+ address 2001:db8:24::d3
+ address 2001:db8:838::1
+ address 2001:db8::1a27:5051:c09d
+ address 2001:db8::1a27:5051:c19d
+ address 2001:db8::20ad:0:1
+ address 2001:db8::2306:0:1
+ address 2001:db8::2ca:0:1
+ address 2001:db8::2ca:0:2
+ address 2001:db8::2ca:0:3
+ address 2001:db8::2ca:0:4
+ }
+ ipv6-address-group vrrp-peers-6 {
+ address fe80::fe89:15cf
+ }
+ ipv6-network-group AS64512-6 {
+ network 2001::/29
+ }
+ network-group AS64512-4 {
+ network 192.0.68.0/22
+ network 192.0.98.0/24
+ network 192.0.160.0/24
+ network 192.0.84.0/22
+ }
+ }
+ ipv6-name management-to-local-6 {
+ default-action reject
+ enable-default-log
+ }
+ ipv6-name management-to-peers-6 {
+ default-action reject
+ enable-default-log
+ }
+ ipv6-name management-to-servers-6 {
+ default-action reject
+ enable-default-log
+ }
+ ipv6-name peers-to-local-6 {
+ default-action reject
+ enable-default-log
+ rule 500 {
+ action accept
+ protocol icmpv6
+ }
+ rule 501 {
+ action accept
+ protocol vrrp
+ source {
+ group {
+ address-group vrrp-peers-6
+ }
+ }
+ }
+ rule 502 {
+ action accept
+ destination {
+ port bgp
+ }
+ protocol tcp
+ source {
+ group {
+ address-group bgp-peers-6
+ }
+ }
+ }
+ rule 503 {
+ action accept
+ protocol tcp
+ source {
+ group {
+ address-group bgp-peers-6
+ }
+ port bgp
+ }
+ }
+ }
+ ipv6-name peers-to-management-6 {
+ default-action reject
+ enable-default-log
+ }
+ ipv6-name peers-to-servers-6 {
+ default-action reject
+ enable-default-log
+ rule 9990 {
+ action reject
+ source {
+ group {
+ network-group AS64512-6
+ }
+ }
+ }
+ rule 9999 {
+ action accept
+ destination {
+ group {
+ network-group AS64512-6
+ }
+ }
+ }
+ }
+ ipv6-name servers-to-local-6 {
+ default-action reject
+ enable-default-log
+ rule 500 {
+ action accept
+ protocol icmpv6
+ }
+ rule 501 {
+ action accept
+ protocol vrrp
+ source {
+ group {
+ address-group vrrp-peers-6
+ }
+ }
+ }
+ rule 511 {
+ action accept
+ protocol tcp_udp
+ source {
+ port 53
+ }
+ }
+ }
+ ipv6-name servers-to-management-6 {
+ default-action reject
+ enable-default-log
+ }
+ ipv6-name servers-to-peers-6 {
+ default-action reject
+ enable-default-log
+ rule 51 {
+ action accept
+ source {
+ group {
+ network-group AS64512-6
+ }
+ }
+ }
+ }
+ ipv6-receive-redirects disable
+ ipv6-src-route disable
+ ip-src-route disable
+ log-martians enable
+ name management-to-local-4 {
+ default-action reject
+ enable-default-log
+ rule 500 {
+ action accept
+ protocol icmp
+ }
+ rule 501 {
+ action accept
+ destination {
+ port 22
+ }
+ protocol tcp
+ }
+ rule 502 {
+ action accept
+ destination {
+ port snmp
+ }
+ protocol udp
+ }
+ }
+ name management-to-peers-4 {
+ default-action reject
+ enable-default-log
+ }
+ name management-to-servers-4 {
+ default-action reject
+ enable-default-log
+ }
+ name peers-to-local-4 {
+ default-action reject
+ enable-default-log
+ rule 500 {
+ action accept
+ protocol icmp
+ }
+ rule 501 {
+ action accept
+ protocol vrrp
+ source {
+ group {
+ address-group vrrp-peers-4
+ }
+ }
+ }
+ rule 502 {
+ action accept
+ destination {
+ port bgp
+ }
+ protocol tcp
+ source {
+ group {
+ address-group bgp-peers-4
+ }
+ }
+ }
+ rule 503 {
+ action accept
+ protocol tcp
+ source {
+ group {
+ address-group bgp-peers-4
+ }
+ port bgp
+ }
+ }
+ }
+ name peers-to-management-4 {
+ default-action reject
+ enable-default-log
+ }
+ name peers-to-servers-4 {
+ default-action reject
+ enable-default-log
+ rule 9990 {
+ action reject
+ source {
+ group {
+ network-group AS64512-4
+ }
+ }
+ }
+ rule 9999 {
+ action accept
+ destination {
+ group {
+ network-group AS64512-4
+ }
+ }
+ }
+ }
+ name servers-to-local-4 {
+ default-action reject
+ enable-default-log
+ rule 500 {
+ action accept
+ protocol icmp
+ }
+ rule 501 {
+ action accept
+ protocol vrrp
+ source {
+ group {
+ address-group vrrp-peers-4
+ }
+ }
+ }
+ rule 511 {
+ action accept
+ protocol tcp_udp
+ source {
+ port 53
+ }
+ }
+ }
+ name servers-to-management-4 {
+ default-action reject
+ enable-default-log
+ }
+ name servers-to-peers-4 {
+ default-action reject
+ enable-default-log
+ rule 51 {
+ action accept
+ source {
+ group {
+ network-group AS64512-4
+ }
+ }
+ }
+ }
+ receive-redirects disable
+ send-redirects enable
+ source-validation disable
+ syn-cookies enable
+ twa-hazards-protection disable
+}
+high-availability {
+ vrrp {
+ group 11-4 {
+ interface eth0.11
+ priority 200
+ virtual-address 192.0.68.1/27
+ vrid 4
+ }
+ group 11-6 {
+ interface eth0.11
+ priority 200
+ virtual-address 2001:db8:c::1/64
+ vrid 6
+ }
+ group 102-4 {
+ interface eth0.102
+ priority 200
+ virtual-address 192.0.98.1/24
+ vrid 4
+ }
+ group 102-6 {
+ interface eth0.102
+ priority 200
+ virtual-address 2001:db8:0:102::1/64
+ vrid 6
+ }
+ group 105-4 {
+ interface eth0.105
+ priority 200
+ virtual-address 192.0.160.1/24
+ vrid 4
+ }
+ group 105-6 {
+ interface eth0.105
+ priority 200
+ virtual-address 2001:db8:0:105::1/64
+ vrid 6
+ }
+ group 1001-4 {
+ interface eth0.1001
+ priority 200
+ virtual-address 192.0.68.33/27
+ vrid 4
+ }
+ group 1001-6 {
+ interface eth0.1001
+ priority 200
+ virtual-address 2001:db8:0:1001::1/64
+ vrid 6
+ }
+ group 1002-4 {
+ interface eth0.1002
+ priority 200
+ virtual-address 192.0.68.65/26
+ vrid 4
+ }
+ group 1002-6 {
+ interface eth0.1002
+ priority 200
+ virtual-address 2001:db8:0:1002::1/64
+ vrid 6
+ }
+ group 1003-4 {
+ interface eth0.1003
+ priority 200
+ virtual-address 192.0.68.129/25
+ vrid 4
+ }
+ group 1003-6 {
+ interface eth0.1003
+ priority 200
+ virtual-address 2001:db8:0:1003::1/64
+ vrid 6
+ }
+ group 1004-4 {
+ interface eth0.1004
+ priority 200
+ virtual-address 192.0.69.1/24
+ vrid 4
+ }
+ group 1004-6 {
+ interface eth0.1004
+ priority 200
+ virtual-address 2001:db8:0:1004::1/64
+ vrid 6
+ }
+ group 1005-4 {
+ interface eth0.1005
+ priority 200
+ virtual-address 192.0.70.1/28
+ vrid 4
+ }
+ group 1005-6 {
+ interface eth0.1005
+ priority 200
+ virtual-address 2001:db8:0:1005::1/64
+ vrid 6
+ }
+ group 1006-4 {
+ interface eth0.1006
+ priority 200
+ virtual-address 192.0.70.17/28
+ vrid 4
+ }
+ group 1006-6 {
+ interface eth0.1006
+ priority 200
+ virtual-address 2001:db8:0:1006::1/64
+ vrid 6
+ }
+ group 1007-4 {
+ interface eth0.1007
+ priority 200
+ virtual-address 192.0.70.33/27
+ vrid 4
+ }
+ group 1007-6 {
+ interface eth0.1007
+ priority 200
+ virtual-address 2001:db8:0:1007::1/64
+ vrid 6
+ }
+ group 1008-4 {
+ interface eth0.1008
+ priority 200
+ virtual-address 192.0.70.65/26
+ vrid 4
+ }
+ group 1008-6 {
+ interface eth0.1008
+ priority 200
+ virtual-address 2001:db8:0:1008::1/64
+ vrid 6
+ }
+ group 1009-4 {
+ interface eth0.1009
+ priority 200
+ virtual-address 192.0.70.129/28
+ vrid 4
+ }
+ group 1009-6 {
+ interface eth0.1009
+ priority 200
+ virtual-address 2001:db8:0:1009::1/64
+ vrid 6
+ }
+ group 1010-4 {
+ interface eth0.1010
+ priority 200
+ virtual-address 192.0.70.145/28
+ vrid 4
+ }
+ group 1010-6 {
+ interface eth0.1010
+ priority 200
+ virtual-address 2001:db8:0:1010::1/64
+ vrid 6
+ }
+ group 1011-4 {
+ interface eth0.1011
+ priority 200
+ virtual-address 192.0.70.161/28
+ vrid 4
+ }
+ group 1011-6 {
+ interface eth0.1011
+ priority 200
+ virtual-address 2001:db8:0:1011::1/64
+ vrid 6
+ }
+ group 1012-4 {
+ interface eth0.1012
+ priority 200
+ virtual-address 192.0.70.177/28
+ vrid 4
+ }
+ group 1012-6 {
+ interface eth0.1012
+ priority 200
+ virtual-address 2001:db8:0:1012::1/64
+ vrid 6
+ }
+ group 1013-4 {
+ interface eth0.1013
+ priority 200
+ virtual-address 192.0.70.193/27
+ vrid 4
+ }
+ group 1013-6 {
+ interface eth0.1013
+ priority 200
+ virtual-address 2001:db8:0:1013::1/64
+ vrid 6
+ }
+ group 1014-4 {
+ interface eth0.1014
+ priority 200
+ virtual-address 192.0.84.65/26
+ vrid 4
+ }
+ group 1014-6 {
+ interface eth0.1014
+ priority 200
+ virtual-address 2001:db8:0:1014::1/64
+ vrid 6
+ }
+ group 1015-4 {
+ interface eth0.1015
+ priority 200
+ virtual-address 192.0.71.1/26
+ vrid 4
+ }
+ group 1015-6 {
+ interface eth0.1015
+ priority 200
+ virtual-address 2001:db8:0:1015::1/64
+ vrid 6
+ }
+ group 1016-4 {
+ interface eth0.1016
+ priority 200
+ virtual-address 192.0.71.65/27
+ vrid 4
+ }
+ group 1016-6 {
+ interface eth0.1016
+ priority 200
+ virtual-address 2001:db8:0:1016::1/64
+ vrid 6
+ }
+ group 1017-4 {
+ interface eth0.1017
+ priority 200
+ virtual-address 192.0.71.97/28
+ vrid 4
+ }
+ group 1017-6 {
+ interface eth0.1017
+ priority 200
+ virtual-address 2001:db8:0:1017::1/64
+ vrid 6
+ }
+ group 1018-4 {
+ interface eth0.1018
+ priority 200
+ virtual-address 192.0.71.113/28
+ vrid 4
+ }
+ group 1018-6 {
+ interface eth0.1018
+ priority 200
+ virtual-address 2001:db8:0:1018::1/64
+ vrid 6
+ }
+ group 1019-4 {
+ interface eth0.1019
+ priority 200
+ virtual-address 192.0.71.129/26
+ vrid 4
+ }
+ group 1019-6 {
+ interface eth0.1019
+ priority 200
+ virtual-address 2001:db8:0:1019::1/64
+ vrid 6
+ }
+ group 1020-4 {
+ interface eth0.1020
+ priority 200
+ virtual-address 192.0.71.193/26
+ vrid 4
+ }
+ group 1020-6 {
+ interface eth0.1020
+ priority 200
+ virtual-address 2001:db8:0:1020::1/64
+ vrid 6
+ }
+ }
+}
+interfaces {
+ ethernet eth0 {
+ address 192.0.0.11/16
+ duplex auto
+ smp-affinity auto
+ speed auto
+ vif 11 {
+ address 192.0.68.2/27
+ address 2001:db8:c::2/64
+ }
+ vif 102 {
+ address 192.0.98.2/24
+ address 2001:db8:0:102::2/64
+ }
+ vif 105 {
+ address 192.0.160.2/24
+ address 2001:db8:0:105::2/64
+ }
+ vif 838 {
+ address 192.0.16.210/30
+ address 2001:db8:838::2/64
+ }
+ vif 886 {
+ address 192.0.193.224/21
+ address 2001:db8::3:669:0:1/64
+ }
+ vif 1001 {
+ address 192.0.68.34/27
+ address 2001:db8:0:1001::2/64
+ }
+ vif 1002 {
+ address 192.0.68.66/26
+ address 2001:db8:0:1002::2/64
+ }
+ vif 1003 {
+ address 192.0.68.130/25
+ address 2001:db8:0:1003::2/64
+ }
+ vif 1004 {
+ address 192.0.69.2/24
+ address 2001:db8:0:1004::2/64
+ }
+ vif 1005 {
+ address 192.0.70.2/28
+ address 2001:db8:0:1005::2/64
+ }
+ vif 1006 {
+ address 192.0.70.18/28
+ address 2001:db8:0:1006::2/64
+ }
+ vif 1007 {
+ address 192.0.70.34/27
+ address 2001:db8:0:1007::2/64
+ }
+ vif 1008 {
+ address 192.0.70.66/26
+ address 2001:db8:0:1008::2/64
+ }
+ vif 1009 {
+ address 192.0.70.130/28
+ address 2001:db8:0:1009::2/64
+ }
+ vif 1010 {
+ address 192.0.70.146/28
+ address 2001:db8:0:1010::2/64
+ }
+ vif 1011 {
+ address 192.0.70.162/28
+ address 2001:db8:0:1011::2/64
+ }
+ vif 1012 {
+ address 192.0.70.178/28
+ address 2001:db8:0:1012::2/64
+ }
+ vif 1013 {
+ address 192.0.70.194/27
+ address 2001:db8:0:1013::3/64
+ }
+ vif 1014 {
+ address 192.0.84.66/26
+ address 2001:db8:0:1014::2/64
+ }
+ vif 1015 {
+ address 192.0.71.2/26
+ address 2001:db8:0:1015::2/64
+ }
+ vif 1016 {
+ address 192.0.71.66/27
+ address 2001:db8:0:1016::2/64
+ }
+ vif 1017 {
+ address 192.0.71.98/28
+ address 2001:db8:0:1017::2/64
+ }
+ vif 1018 {
+ address 192.0.71.114/28
+ address 2001:db8:0:1018::2/64
+ }
+ vif 1019 {
+ address 192.0.71.130/26
+ address 2001:db8:0:1019::2/64
+ }
+ vif 1020 {
+ address 192.0.71.194/26
+ address 2001:db8:0:1020::2/64
+ }
+ vif 4088 {
+ address 2001:db8:24::c7/64
+ address 192.0.52.199/23
+ }
+ vif 4089 {
+ address 192.0.176.194/30
+ address 2001:db8:1000::2ea/126
+ }
+ }
+ loopback lo {
+ }
+}
+policy {
+ as-path-list AS64513-AS64514 {
+ rule 10 {
+ action permit
+ regex "^64513 64514$"
+ }
+ }
+ as-path-list AS64512 {
+ rule 10 {
+ action permit
+ regex ^$
+ }
+ }
+ prefix-list defaultV4 {
+ rule 10 {
+ action permit
+ prefix 0.0.0.0/0
+ }
+ }
+ prefix-list hostrouteV4 {
+ rule 10 {
+ action permit
+ ge 32
+ prefix 192.0.160.0/24
+ }
+ rule 20 {
+ action permit
+ ge 32
+ prefix 192.0.98.0/24
+ }
+ rule 30 {
+ action permit
+ ge 32
+ prefix 192.0.68.0/22
+ }
+ rule 40 {
+ action permit
+ ge 32
+ prefix 192.0.84.0/22
+ }
+ }
+ prefix-list vyosV4 {
+ rule 10 {
+ action permit
+ prefix 192.0.160.0/24
+ }
+ rule 20 {
+ action permit
+ prefix 192.0.98.0/24
+ }
+ rule 30 {
+ action permit
+ prefix 192.0.68.0/22
+ }
+ rule 40 {
+ action permit
+ prefix 192.0.84.0/22
+ }
+ }
+ prefix-list privateV4 {
+ rule 10 {
+ action permit
+ le 32
+ prefix 192.0.0.0/8
+ }
+ rule 20 {
+ action permit
+ le 32
+ prefix 192.0.0.0/12
+ }
+ rule 30 {
+ action permit
+ le 32
+ prefix 192.0.0.0/16
+ }
+ }
+ prefix-list6 all6 {
+ rule 10 {
+ action permit
+ ge 4
+ prefix 2000::/3
+ }
+ }
+ prefix-list6 hostrouteV6 {
+ rule 20 {
+ action permit
+ ge 128
+ prefix 2001:db8::/29
+ }
+ }
+ prefix-list6 vyosV6 {
+ rule 20 {
+ action permit
+ prefix 2001:db8::/29
+ }
+ }
+ prefix-list6 privateV6 {
+ rule 10 {
+ action permit
+ prefix fc00::/7
+ }
+ }
+ route-map ExportRouteMap {
+ rule 5 {
+ action permit
+ match {
+ as-path AS64512
+ ip {
+ address {
+ prefix-list hostrouteV4
+ }
+ }
+ }
+ set {
+ community 65000:666
+ }
+ }
+ rule 10 {
+ action permit
+ match {
+ as-path AS64512
+ ip {
+ address {
+ prefix-list vyosV4
+ }
+ }
+ }
+ }
+ rule 15 {
+ action permit
+ match {
+ as-path AS64512
+ ipv6 {
+ address {
+ prefix-list hostrouteV6
+ }
+ }
+ }
+ set {
+ community 65000:666
+ }
+ }
+ rule 20 {
+ action permit
+ match {
+ as-path AS64512
+ ipv6 {
+ address {
+ prefix-list vyosV6
+ }
+ }
+ }
+ }
+ rule 100 {
+ action deny
+ }
+ }
+ route-map ExportRouteMapAS64515 {
+ rule 10 {
+ action permit
+ match {
+ ipv6 {
+ address {
+ prefix-list all6
+ }
+ }
+ }
+ }
+ rule 20 {
+ action deny
+ match {
+ ip {
+ address {
+ prefix-list defaultV4
+ }
+ }
+ }
+ }
+ rule 100 {
+ action deny
+ }
+ }
+ route-map ExportRouteMapAS64516 {
+ rule 5 {
+ action permit
+ match {
+ as-path AS64512
+ ip {
+ address {
+ prefix-list hostrouteV4
+ }
+ }
+ }
+ set {
+ community 65000:666
+ }
+ }
+ rule 10 {
+ action permit
+ match {
+ as-path AS64512
+ ip {
+ address {
+ prefix-list vyosV4
+ }
+ }
+ }
+ }
+ rule 15 {
+ action permit
+ match {
+ as-path AS64512
+ ipv6 {
+ address {
+ prefix-list hostrouteV6
+ }
+ }
+ }
+ set {
+ community 65000:666
+ }
+ }
+ rule 20 {
+ action permit
+ match {
+ as-path AS64512
+ ipv6 {
+ address {
+ prefix-list vyosV6
+ }
+ }
+ }
+ }
+ rule 100 {
+ action deny
+ }
+ }
+ route-map ExportRouteMapAS64517 {
+ rule 5 {
+ action permit
+ match {
+ as-path AS64512
+ ip {
+ address {
+ prefix-list hostrouteV4
+ }
+ }
+ }
+ set {
+ community 64517:666
+ }
+ }
+ rule 10 {
+ action permit
+ match {
+ as-path AS64512
+ ip {
+ address {
+ prefix-list vyosV4
+ }
+ }
+ }
+ }
+ rule 15 {
+ action permit
+ match {
+ as-path AS64512
+ ipv6 {
+ address {
+ prefix-list hostrouteV6
+ }
+ }
+ }
+ set {
+ community 64517:666
+ }
+ }
+ rule 20 {
+ action permit
+ match {
+ as-path AS64512
+ ipv6 {
+ address {
+ prefix-list vyosV6
+ }
+ }
+ }
+ }
+ rule 100 {
+ action deny
+ }
+ }
+ route-map ExportRouteMapAS64513 {
+ rule 5 {
+ action permit
+ match {
+ as-path AS64512
+ ip {
+ address {
+ prefix-list hostrouteV4
+ }
+ }
+ }
+ set {
+ community 64513:666
+ }
+ }
+ rule 10 {
+ action permit
+ match {
+ as-path AS64512
+ ip {
+ address {
+ prefix-list vyosV4
+ }
+ }
+ }
+ }
+ rule 15 {
+ action permit
+ match {
+ as-path AS64512
+ ipv6 {
+ address {
+ prefix-list hostrouteV6
+ }
+ }
+ }
+ set {
+ community 64513:666
+ }
+ }
+ rule 20 {
+ action permit
+ match {
+ as-path AS64512
+ ipv6 {
+ address {
+ prefix-list vyosV6
+ }
+ }
+ }
+ }
+ rule 100 {
+ action deny
+ }
+ }
+ route-map ImportRouteMap {
+ rule 10 {
+ action deny
+ match {
+ ip {
+ address {
+ prefix-list privateV4
+ }
+ }
+ }
+ }
+ rule 15 {
+ action deny
+ match {
+ ipv6 {
+ address {
+ prefix-list privateV6
+ }
+ }
+ }
+ }
+ rule 20 {
+ action deny
+ match {
+ ip {
+ address {
+ prefix-list vyosV4
+ }
+ }
+ }
+ }
+ rule 30 {
+ action deny
+ match {
+ ipv6 {
+ address {
+ prefix-list vyosV6
+ }
+ }
+ }
+ }
+ rule 40 {
+ action deny
+ match {
+ as-path AS64512
+ }
+ }
+ rule 50 {
+ action permit
+ match {
+ as-path AS64513-AS64514
+ }
+ set {
+ weight 10001
+ }
+ }
+ rule 65535 {
+ action permit
+ }
+ }
+}
+protocols {
+ bgp 64500 {
+ address-family {
+ ipv4-unicast {
+ network 192.0.98.0/24 {
+ }
+ network 192.0.160.0/24 {
+ }
+ network 192.0.68.0/22 {
+ }
+ network 192.0.84.0/22 {
+ }
+ redistribute {
+ static {
+ route-map ExportRouteMap
+ }
+ }
+ }
+ ipv6-unicast {
+ network 2001:db8::/29 {
+ }
+ redistribute {
+ static {
+ route-map ExportRouteMap
+ }
+ }
+ }
+ }
+ neighbor 192.0.16.209 {
+ address-family {
+ ipv4-unicast {
+ route-map {
+ export ExportRouteMapAS64516
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64501
+ }
+ neighbor 192.0.192.6 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 100
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64502
+ }
+ neighbor 192.0.192.157 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 350000
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64503
+ }
+ neighbor 192.0.192.228 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 10000
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64504
+ }
+ neighbor 192.0.193.157 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 350000
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64505
+ }
+ neighbor 192.0.193.202 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 10000
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64506
+ }
+ neighbor 192.0.193.223 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 10000
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64507
+ }
+ neighbor 192.0.194.161 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 10000
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64508
+ }
+ neighbor 192.0.194.171 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 10000
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64509
+ }
+ neighbor 192.0.176.193 {
+ address-family {
+ ipv4-unicast {
+ route-map {
+ export ExportRouteMapAS64516
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64510
+ }
+ neighbor 192.0.52.12 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 300
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64511
+ }
+ neighbor 192.0.52.17 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 75
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ password vyosvyos
+ remote-as 64512
+ }
+ neighbor 192.0.52.24 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 300
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64513
+ }
+ neighbor 192.0.52.32 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 50
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ password vyosfoooo
+ remote-as 64514
+ }
+ neighbor 192.0.52.34 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 10
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64515
+ }
+ neighbor 192.0.52.46 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 10
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64516
+ }
+ neighbor 192.0.52.49 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 75
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ password secret
+ remote-as 64517
+ }
+ neighbor 192.0.52.74 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 15000
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ password secretvyos
+ remote-as 64518
+ }
+ neighbor 192.0.52.94 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 250
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64519
+ }
+ neighbor 192.0.52.100 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 50
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64520
+ }
+ neighbor 192.0.52.119 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 30
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64521
+ }
+ neighbor 192.0.52.165 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 50
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64522
+ }
+ neighbor 192.0.52.170 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 150000
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64523
+ }
+ neighbor 192.0.52.171 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 10000
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64524
+ }
+ neighbor 192.0.52.179 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 20
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64525
+ }
+ neighbor 192.0.52.189 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 1000
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64526
+ }
+ neighbor 192.0.52.210 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 15
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64527
+ }
+ neighbor 192.0.52.211 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 15
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64528
+ }
+ neighbor 192.0.52.251 {
+ address-family {
+ ipv4-unicast {
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ weight 1010
+ }
+ }
+ remote-as 64529
+ }
+ neighbor 192.0.52.252 {
+ address-family {
+ ipv4-unicast {
+ route-map {
+ export ExportRouteMap
+ }
+ weight 1010
+ }
+ }
+ remote-as 64530
+ }
+ neighbor 192.0.52.253 {
+ address-family {
+ ipv4-unicast {
+ route-map {
+ export ExportRouteMapAS64515
+ import ImportRouteMap
+ }
+ }
+ }
+ passive
+ remote-as 64531
+ }
+ neighbor 192.0.68.3 {
+ address-family {
+ ipv4-unicast {
+ nexthop-self
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ }
+ remote-as 64532
+ update-source 192.0.68.2
+ }
+ neighbor 2001:db8:838::1 {
+ address-family {
+ ipv6-unicast {
+ route-map {
+ export ExportRouteMapAS64516
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64533
+ }
+ neighbor 2001:db8:c::3 {
+ address-family {
+ ipv6-unicast {
+ nexthop-self
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ }
+ remote-as 64534
+ update-source 2001:db8:c::2
+ }
+ neighbor 2001:db8:24::2e {
+ address-family {
+ ipv6-unicast {
+ maximum-prefix 5
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ password vyossecret
+ remote-as 64535
+ }
+ neighbor 2001:db8:24::4a {
+ address-family {
+ ipv6-unicast {
+ maximum-prefix 1000
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64536
+ }
+ neighbor 2001:db8:24::5e {
+ address-family {
+ ipv6-unicast {
+ maximum-prefix 200
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64537
+ }
+ neighbor 2001:db8:24::11 {
+ address-family {
+ ipv6-unicast {
+ maximum-prefix 20
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64538
+ }
+ neighbor 2001:db8:24::18 {
+ address-family {
+ ipv6-unicast {
+ maximum-prefix 300
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64539
+ }
+ neighbor 2001:db8:24::20 {
+ address-family {
+ ipv6-unicast {
+ maximum-prefix 10
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64540
+ }
+ neighbor 2001:db8:24::22 {
+ address-family {
+ ipv6-unicast {
+ maximum-prefix 5
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64541
+ }
+ neighbor 2001:db8:24::31 {
+ address-family {
+ ipv6-unicast {
+ maximum-prefix 20
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64542
+ }
+ neighbor 2001:db8:24::58 {
+ address-family {
+ ipv6-unicast {
+ maximum-prefix 15
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64543
+ }
+ neighbor 2001:db8:24::64 {
+ address-family {
+ ipv6-unicast {
+ maximum-prefix 10
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ password geheim
+ remote-as 64544
+ }
+ neighbor 2001:db8:24::a5 {
+ address-family {
+ ipv6-unicast {
+ maximum-prefix 10
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64545
+ }
+ neighbor 2001:db8:24::aa {
+ address-family {
+ ipv6-unicast {
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64546
+ }
+ neighbor 2001:db8:24::ab {
+ address-family {
+ ipv6-unicast {
+ maximum-prefix 1800
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ remote-as 64547
+ }
+ neighbor 2001:db8:24::b0 {
+ address-family {
+ ipv6-unicast {
+ maximum-prefix 5
+ route-map {
+ export ExportRouteMap
+ import ImportRouteMap
+ }
+ }
+ }
+ password secret123
+ remote-as 64548
+ }
+ parameters {
+ default {
+ no-ipv4-unicast
+ }
+ log-neighbor-changes
+ router-id 192.0.68.2
+ }
+ }
+ static {
+ route 192.0.98.0/24 {
+ blackhole {
+ }
+ }
+ route 192.0.160.0/24 {
+ blackhole {
+ }
+ }
+ route 192.0.68.0/22 {
+ blackhole {
+ }
+ }
+ route 192.0.84.0/22 {
+ blackhole {
+ }
+ }
+ route6 2001:db8::/29 {
+ blackhole {
+ }
+ }
+ }
+}
+system {
+ config-management {
+ commit-revisions 100
+ }
+ console {
+ device ttyS0 {
+ speed 115200
+ }
+ }
+ flow-accounting {
+ disable-imt
+ interface eth0.4088
+ interface eth0.4089
+ netflow {
+ engine-id 1
+ server 192.0.2.55 {
+ port 2055
+ }
+ version 9
+ }
+ syslog-facility daemon
+ }
+ host-name vyos
+ login {
+ user vyos {
+ authentication {
+ encrypted-password $6$2Ta6TWHd/U$NmrX0x9kexCimeOcYK1MfhMpITF9ELxHcaBU/znBq.X2ukQOj61fVI2UYP/xBzP4QtiTcdkgs7WOQMHWsRymO/
+ plaintext-password ""
+ }
+ }
+ }
+ name-server 2001:db8::1
+ name-server 2001:db8::2
+ name-server 192.0.2.1
+ name-server 192.0.2.2
+ ntp {
+ server 0.pool.ntp.org {
+ }
+ server 1.pool.ntp.org {
+ }
+ server 2.pool.ntp.org {
+ }
+ }
+ syslog {
+ global {
+ facility all {
+ level all
+ }
+ preserve-fqdn
+ }
+ }
+ time-zone Europe/Zurich
+}
+zone-policy {
+ zone local {
+ default-action drop
+ from management {
+ firewall {
+ ipv6-name management-to-local-6
+ name management-to-local-4
+ }
+ }
+ from peers {
+ firewall {
+ ipv6-name peers-to-local-6
+ name peers-to-local-4
+ }
+ }
+ from servers {
+ firewall {
+ ipv6-name servers-to-local-6
+ name servers-to-local-4
+ }
+ }
+ local-zone
+ }
+ zone management {
+ default-action reject
+ from peers {
+ firewall {
+ ipv6-name peers-to-management-6
+ name peers-to-management-4
+ }
+ }
+ from servers {
+ firewall {
+ ipv6-name servers-to-management-6
+ name servers-to-management-4
+ }
+ }
+ interface eth0
+ }
+ zone peers {
+ default-action reject
+ from management {
+ firewall {
+ ipv6-name management-to-peers-6
+ name management-to-peers-4
+ }
+ }
+ from servers {
+ firewall {
+ ipv6-name servers-to-peers-6
+ name servers-to-peers-4
+ }
+ }
+ interface eth0.4088
+ interface eth0.4089
+ interface eth0.11
+ interface eth0.838
+ interface eth0.886
+ }
+ zone servers {
+ default-action reject
+ from management {
+ firewall {
+ ipv6-name management-to-servers-6
+ name management-to-servers-4
+ }
+ }
+ from peers {
+ firewall {
+ ipv6-name peers-to-servers-6
+ name peers-to-servers-4
+ }
+ }
+ interface eth0.1001
+ interface eth0.105
+ interface eth0.102
+ interface eth0.1019
+ interface eth0.1014
+ interface eth0.1020
+ interface eth0.1018
+ interface eth0.1013
+ interface eth0.1012
+ interface eth0.1011
+ interface eth0.1010
+ interface eth0.1009
+ interface eth0.1006
+ interface eth0.1005
+ interface eth0.1017
+ interface eth0.1016
+ interface eth0.1002
+ interface eth0.1015
+ interface eth0.1003
+ interface eth0.1004
+ interface eth0.1007
+ interface eth0.1008
+ }
+}
+
+
+/* Warning: Do not remove the following line. */
+/* === vyatta-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack-sync@1:conntrack@1:dhcp-relay@2:dhcp-server@5:dns-forwarding@1:firewall@5:ipsec@5:l2tp@1:mdns@1:nat@4:ntp@1:pptp@1:qos@1:quagga@6:snmp@1:ssh@1:system@9:vrrp@2:wanloadbalance@3:webgui@1:webproxy@1:webproxy@2:zone-policy@1" === */
+/* Release version: 1.2.5 */
diff --git a/smoketest/configs/small-as-bgp-vrrp b/smoketest/configs/bgp-small-as
index 61286c324..61286c324 100644
--- a/smoketest/configs/small-as-bgp-vrrp
+++ b/smoketest/configs/bgp-small-as
diff --git a/smoketest/configs/bgp-ixp b/smoketest/configs/bgp-small-internet-exchange
index de6213b50..de6213b50 100644
--- a/smoketest/configs/bgp-ixp
+++ b/smoketest/configs/bgp-small-internet-exchange
diff --git a/smoketest/configs/dmz-guest-lan-nat-pppoe-router b/smoketest/configs/dialup-router-complex
index e671126a6..fef79ea56 100644
--- a/smoketest/configs/dmz-guest-lan-nat-pppoe-router
+++ b/smoketest/configs/dialup-router-complex
@@ -1660,4 +1660,3 @@ zone-policy {
// Warning: Do not remove the following line.
// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@1:conntrack-sync@1:dhcp-relay@2:dhcp-server@5:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@18:ipoe-server@1:ipsec@5:l2tp@3:lldp@1:mdns@1:nat@5:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@6:salt@1:snmp@2:ssh@2:sstp@3:system@20:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2:zone-policy@1"
// Release version: 1.3-beta-202101091250
-
diff --git a/smoketest/configs/dialup-router-medium-vpn b/smoketest/configs/dialup-router-medium-vpn
new file mode 100644
index 000000000..dfb3d9621
--- /dev/null
+++ b/smoketest/configs/dialup-router-medium-vpn
@@ -0,0 +1,707 @@
+firewall {
+ all-ping enable
+ broadcast-ping disable
+ config-trap disable
+ ipv6-receive-redirects disable
+ ipv6-src-route disable
+ ip-src-route disable
+ log-martians enable
+ options {
+ interface vtun0 {
+ adjust-mss 1380
+ }
+ interface vtun1 {
+ adjust-mss 1380
+ }
+ interface vtun2 {
+ adjust-mss 1380
+ }
+ interface wg0 {
+ adjust-mss 1380
+ }
+ interface wg1 {
+ adjust-mss 1380
+ }
+ }
+ receive-redirects disable
+ send-redirects enable
+ source-validation disable
+ syn-cookies disable
+ twa-hazards-protection enable
+}
+high-availability {
+ vrrp {
+ group LAN {
+ hello-source-address 192.168.0.250
+ interface eth1
+ peer-address 192.168.0.251
+ priority 200
+ virtual-address 192.168.0.1/24
+ vrid 1
+ }
+ sync-group failover-group {
+ member LAN
+ }
+ }
+}
+interfaces {
+ ethernet eth0 {
+ duplex auto
+ mtu 9000
+ offload-options {
+ generic-receive on
+ generic-segmentation on
+ scatter-gather on
+ tcp-segmentation on
+ }
+ pppoe 0 {
+ default-route auto
+ mtu 1500
+ name-server auto
+ password password
+ traffic-policy {
+ out shape-17mbit
+ }
+ user-id vyos
+ password vyos
+ }
+ smp-affinity auto
+ speed auto
+ }
+ ethernet eth1 {
+ address 192.168.0.250/24
+ duplex auto
+ ip {
+ source-validation strict
+ }
+ mtu 9000
+ offload-options {
+ generic-receive on
+ generic-segmentation on
+ scatter-gather on
+ tcp-segmentation on
+ }
+ policy {
+ route LAN-POLICY-BASED-ROUTING
+ }
+ smp-affinity auto
+ speed auto
+ traffic-policy {
+ out shape-94mbit
+ }
+ }
+ loopback lo {
+ }
+ openvpn vtun0 {
+ encryption aes256
+ hash sha512
+ ip {
+ source-validation strict
+ }
+ keep-alive {
+ failure-count 3
+ interval 30
+ }
+ mode client
+ openvpn-option "comp-lzo adaptive"
+ openvpn-option fast-io
+ openvpn-option persist-key
+ openvpn-option "reneg-sec 86400"
+ persistent-tunnel
+ remote-host 192.0.2.10
+ tls {
+ ca-cert-file /config/auth/ovpn_test_ca.pem
+ cert-file /config/auth/ovpn_test_server.pem
+ key-file /config/auth/ovpn_test_server.key
+ auth-file /config/auth/ovpn_test_tls_auth.key
+ }
+ }
+ openvpn vtun1 {
+ authentication {
+ password vyos1
+ username vyos1
+ }
+ encryption aes256
+ hash sha1
+ keep-alive {
+ failure-count 3
+ interval 30
+ }
+ mode client
+ openvpn-option "comp-lzo adaptive"
+ openvpn-option "tun-mtu 1500"
+ openvpn-option "tun-mtu-extra 32"
+ openvpn-option "mssfix 1300"
+ openvpn-option persist-key
+ openvpn-option "mute 10"
+ openvpn-option route-nopull
+ openvpn-option fast-io
+ openvpn-option "reneg-sec 86400"
+ persistent-tunnel
+ protocol udp
+ remote-host 01.foo.com
+ remote-port 1194
+ tls {
+ ca-cert-file /config/auth/ovpn_test_ca.pem
+ auth-file /config/auth/ovpn_test_tls_auth.key
+ }
+ }
+ openvpn vtun2 {
+ authentication {
+ password vyos2
+ username vyos2
+ }
+ disable
+ encryption aes256
+ hash sha512
+ keep-alive {
+ failure-count 3
+ interval 30
+ }
+ mode client
+ openvpn-option "tun-mtu 1500"
+ openvpn-option "tun-mtu-extra 32"
+ openvpn-option "mssfix 1300"
+ openvpn-option persist-key
+ openvpn-option "mute 10"
+ openvpn-option route-nopull
+ openvpn-option fast-io
+ openvpn-option remote-random
+ openvpn-option "reneg-sec 86400"
+ persistent-tunnel
+ protocol udp
+ remote-host 01.myvpn.com
+ remote-host 02.myvpn.com
+ remote-host 03.myvpn.com
+ remote-port 1194
+ tls {
+ ca-cert-file /config/auth/ovpn_test_ca.pem
+ auth-file /config/auth/ovpn_test_tls_auth.key
+ }
+ }
+ wireguard wg0 {
+ address 192.168.10.1/24
+ peer red {
+ allowed-ips 192.168.10.4/32
+ persistent-keepalive 20
+ preshared-key CumyXX7osvUT9AwnS+m2TEfCaL0Ptc2LfuZ78Sujuk8=
+ pubkey ALGWvMJCKpHF2tVH3hEIHqUe9iFfAmZATUUok/WQzks=
+ }
+ peer green {
+ allowed-ips 192.168.10.21/32
+ persistent-keepalive 25
+ preshared-key LQ9qmlTh9G4nZu4UgElxRUwg7JB/qoV799aADJOijnY=
+ pubkey 5iQUD3VoCDBTPXAPHOwUJ0p7xzKGHEY/wQmgvBVmaFI=
+ }
+ peer blue {
+ allowed-ips 192.168.10.3/32
+ persistent-keepalive 20
+ preshared-key ztFDOY9UyaDvn8N3X97SFMDwIfv7EEfuUIPP2yab6UI=
+ pubkey G4pZishpMRrLmd96Kr6V7LIuNGdcUb81gWaYZ+FWkG0=
+ }
+ peer pink {
+ allowed-ips 192.168.10.14/32
+ allowed-ips 192.168.10.16/32
+ persistent-keepalive 25
+ preshared-key Qi9Odyx0/5itLPN5C5bEy3uMX+tmdl15QbakxpKlWqQ=
+ pubkey i4qNPmxyy9EETL4tIoZOLKJF4p7IlVmpAE15gglnAk4=
+ }
+ port 7777
+ }
+ wireguard wg1 {
+ address 10.89.90.2/30
+ peer sam {
+ allowed-ips 10.1.1.0/24
+ allowed-ips 10.89.90.1/32
+ endpoint 192.0.2.45:1200
+ persistent-keepalive 20
+ preshared-key XpFtzx2Z+nR8pBv9/sSf7I94OkZkVYTz0AeU5Q/QQUE=
+ pubkey v5zfKGvH6W/lfDXJ0en96lvKo1gfFxMUWxe02+Fj5BU=
+ }
+ port 7778
+ }
+}
+nat {
+ destination {
+ rule 50 {
+ destination {
+ port 49371
+ }
+ inbound-interface pppoe0
+ protocol tcp_udp
+ translation {
+ address 192.168.0.5
+ }
+ }
+ rule 51 {
+ destination {
+ port 58050-58051
+ }
+ inbound-interface pppoe0
+ protocol tcp
+ translation {
+ address 192.168.0.5
+ }
+ }
+ rule 52 {
+ destination {
+ port 22067-22070
+ }
+ inbound-interface pppoe0
+ protocol tcp
+ translation {
+ address 192.168.0.5
+ }
+ }
+ rule 53 {
+ destination {
+ port 34342
+ }
+ inbound-interface pppoe0
+ protocol tcp_udp
+ translation {
+ address 192.168.0.121
+ }
+ }
+ rule 54 {
+ destination {
+ port 45459
+ }
+ inbound-interface pppoe0
+ protocol tcp_udp
+ translation {
+ address 192.168.0.120
+ }
+ }
+ rule 55 {
+ destination {
+ port 22
+ }
+ inbound-interface pppoe0
+ protocol tcp
+ translation {
+ address 192.168.0.5
+ }
+ }
+ rule 56 {
+ destination {
+ port 8920
+ }
+ inbound-interface pppoe0
+ protocol tcp
+ translation {
+ address 192.168.0.5
+ }
+ }
+ rule 60 {
+ destination {
+ port 80,443
+ }
+ inbound-interface pppoe0
+ protocol tcp
+ translation {
+ address 192.168.0.5
+ }
+ }
+ rule 70 {
+ destination {
+ port 5001
+ }
+ inbound-interface pppoe0
+ protocol tcp
+ translation {
+ address 192.168.0.5
+ }
+ }
+ rule 80 {
+ destination {
+ port 25
+ }
+ inbound-interface pppoe0
+ protocol tcp
+ translation {
+ address 192.168.0.5
+ }
+ }
+ rule 90 {
+ destination {
+ port 8123
+ }
+ inbound-interface pppoe0
+ protocol tcp
+ translation {
+ address 192.168.0.7
+ }
+ }
+ rule 91 {
+ destination {
+ port 1880
+ }
+ inbound-interface pppoe0
+ protocol tcp
+ translation {
+ address 192.168.0.7
+ }
+ }
+ rule 500 {
+ destination {
+ address !192.168.0.0/24
+ port 53
+ }
+ inbound-interface eth1
+ protocol tcp_udp
+ source {
+ address !192.168.0.1-192.168.0.5
+ }
+ translation {
+ address 192.168.0.1
+ }
+ }
+ }
+ source {
+ rule 1000 {
+ outbound-interface pppoe0
+ translation {
+ address masquerade
+ }
+ }
+ rule 2000 {
+ outbound-interface vtun0
+ source {
+ address 192.168.0.0/16
+ }
+ translation {
+ address masquerade
+ }
+ }
+ rule 3000 {
+ outbound-interface vtun1
+ translation {
+ address masquerade
+ }
+ }
+ }
+}
+policy {
+ prefix-list user2-routes {
+ rule 1 {
+ action permit
+ prefix 10.1.1.0/24
+ }
+ }
+ prefix-list user1-routes {
+ rule 1 {
+ action permit
+ prefix 192.168.0.0/24
+ }
+ }
+ route LAN-POLICY-BASED-ROUTING {
+ rule 10 {
+ destination {
+ }
+ disable
+ set {
+ table 10
+ }
+ source {
+ address 192.168.0.119/32
+ }
+ }
+ rule 20 {
+ destination {
+ }
+ set {
+ table 100
+ }
+ source {
+ address 192.168.0.240
+ }
+ }
+ }
+ route-map rm-static-to-bgp {
+ rule 10 {
+ action permit
+ match {
+ ip {
+ address {
+ prefix-list user1-routes
+ }
+ }
+ }
+ }
+ rule 100 {
+ action deny
+ }
+ }
+}
+protocols {
+ bgp 64590 {
+ address-family {
+ ipv4-unicast {
+ redistribute {
+ connected {
+ route-map rm-static-to-bgp
+ }
+ }
+ }
+ }
+ neighbor 10.89.90.1 {
+ address-family {
+ ipv4-unicast {
+ nexthop-self
+ prefix-list {
+ export user1-routes
+ import user2-routes
+ }
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ }
+ password ericandre2020
+ remote-as 64589
+ }
+ parameters {
+ log-neighbor-changes
+ router-id 10.89.90.2
+ }
+ }
+ static {
+ interface-route 100.64.160.23/32 {
+ next-hop-interface pppoe0 {
+ }
+ }
+ interface-route 100.64.165.25/32 {
+ next-hop-interface pppoe0 {
+ }
+ }
+ interface-route 100.64.165.26/32 {
+ next-hop-interface pppoe0 {
+ }
+ }
+ interface-route 100.64.198.0/24 {
+ next-hop-interface vtun0 {
+ }
+ }
+ table 10 {
+ interface-route 0.0.0.0/0 {
+ next-hop-interface vtun1 {
+ }
+ }
+ }
+ table 100 {
+ route 0.0.0.0/0 {
+ next-hop 192.168.10.5 {
+ }
+ }
+ }
+ }
+}
+service {
+ conntrack-sync {
+ accept-protocol tcp,udp,icmp
+ disable-external-cache
+ event-listen-queue-size 8
+ expect-sync all
+ failover-mechanism {
+ vrrp {
+ sync-group failover-group
+ }
+ }
+ interface eth1 {
+ peer 192.168.0.251
+ }
+ sync-queue-size 8
+ }
+ dhcp-server {
+ shared-network-name LAN {
+ authoritative
+ subnet 192.168.0.0/24 {
+ default-router 192.168.0.1
+ dns-server 192.168.0.1
+ domain-name vyos.net
+ domain-search vyos.net
+ failover {
+ local-address 192.168.0.250
+ name DHCP02
+ peer-address 192.168.0.251
+ status primary
+ }
+ lease 86400
+ range LANDynamic {
+ start 192.168.0.200
+ stop 192.168.0.240
+ }
+ static-mapping IPTV {
+ ip-address 192.168.0.104
+ mac-address 00:50:01:31:b5:f6
+ }
+ static-mapping McPrintus {
+ ip-address 192.168.0.60
+ mac-address 00:50:01:58:ac:95
+ static-mapping-parameters "option domain-name-servers 192.168.0.6,192.168.0.17;"
+ }
+ static-mapping Audio {
+ ip-address 192.168.0.107
+ mac-address 00:50:01:dc:91:14
+ }
+ static-mapping Mobile01 {
+ ip-address 192.168.0.109
+ mac-address 00:50:01:bc:ac:51
+ static-mapping-parameters "option domain-name-servers 192.168.0.6,192.168.0.17;"
+ }
+ static-mapping sand {
+ ip-address 192.168.0.110
+ mac-address 00:50:01:af:c5:d2
+ }
+ static-mapping pearTV {
+ ip-address 192.168.0.101
+ mac-address 00:50:01:ba:62:79
+ }
+ static-mapping camera1 {
+ ip-address 192.168.0.11
+ mac-address 00:50:01:70:b9:4d
+ static-mapping-parameters "option domain-name-servers 192.168.0.6,192.168.0.17;"
+ }
+ static-mapping camera2 {
+ ip-address 192.168.0.12
+ mac-address 00:50:01:70:b7:4f
+ static-mapping-parameters "option domain-name-servers 192.168.0.6,192.168.0.17;"
+ }
+ }
+ }
+ }
+ dns {
+ forwarding {
+ allow-from 192.168.0.0/16
+ cache-size 8192
+ dnssec off
+ listen-address 192.168.0.1
+ name-server 100.64.0.1
+ name-server 100.64.0.2
+ }
+ }
+ snmp {
+ community AwesomeCommunity {
+ authorization ro
+ client 127.0.0.1
+ network 192.168.0.0/24
+ }
+ }
+ ssh {
+ access-control {
+ allow {
+ user vyos
+ }
+ }
+ client-keepalive-interval 60
+ listen-address 192.168.0.1
+ listen-address 192.168.10.1
+ listen-address 192.168.0.250
+ }
+}
+system {
+ config-management {
+ commit-revisions 100
+ }
+ console {
+ device ttyS0 {
+ speed 115200
+ }
+ }
+ host-name vyos
+ ip {
+ arp {
+ table-size 1024
+ }
+ }
+ login {
+ user vyos {
+ authentication {
+ encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0
+ plaintext-password ""
+ }
+ }
+ }
+ name-server 192.168.0.1
+ ntp {
+ allow-clients {
+ address 192.168.0.0/16
+ }
+ listen-address 192.168.0.1
+ listen-address 192.168.0.250
+ server nz.pool.ntp.org {
+ prefer
+ }
+ }
+ options {
+ beep-if-fully-booted
+ ctrl-alt-del-action ignore
+ reboot-on-panic true
+ }
+ static-host-mapping {
+ host-name host104.vyos.net {
+ inet 192.168.0.104
+ }
+ host-name host60.vyos.net {
+ inet 192.168.0.60
+ }
+ host-name host107.vyos.net {
+ inet 192.168.0.107
+ }
+ host-name host109.vyos.net {
+ inet 192.168.0.109
+ }
+ }
+ sysctl {
+ custom net.core.default_qdisc {
+ value fq
+ }
+ custom net.ipv4.tcp_congestion_control {
+ value bbr
+ }
+ }
+ syslog {
+ global {
+ facility all {
+ level info
+ }
+ }
+ host 192.168.0.252 {
+ facility all {
+ level debug
+ protocol udp
+ }
+ }
+ }
+ task-scheduler {
+ task Update-Blacklists {
+ executable {
+ path /config/scripts/vyos-foo-update.script
+ }
+ interval 3h
+ }
+ }
+ time-zone Pacific/Auckland
+}
+traffic-policy {
+ shaper shape-17mbit {
+ bandwidth 17mbit
+ default {
+ bandwidth 100%
+ burst 15k
+ queue-type fq-codel
+ }
+ }
+ shaper shape-94mbit {
+ bandwidth 94mbit
+ default {
+ bandwidth 100%
+ burst 15k
+ queue-type fq-codel
+ }
+ }
+}
+/* Warning: Do not remove the following line. */
+/* === vyatta-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack-sync@1:conntrack@1:dhcp-relay@2:dhcp-server@5:dns-forwarding@1:firewall@5:ipsec@5:l2tp@1:mdns@1:nat@4:ntp@1:pptp@1:qos@1:quagga@6:snmp@1:ssh@1:system@9:vrrp@2:wanloadbalance@3:webgui@1:webproxy@1:webproxy@2:zone-policy@1" === */
+/* Release version: 1.2.6 */
diff --git a/smoketest/configs/ospf-config b/smoketest/configs/ospf-small
index fe313e4b0..fe313e4b0 100644
--- a/smoketest/configs/ospf-config
+++ b/smoketest/configs/ospf-small
diff --git a/smoketest/configs/pppoe-client b/smoketest/configs/pppoe-client
deleted file mode 100644
index ef6a26423..000000000
--- a/smoketest/configs/pppoe-client
+++ /dev/null
@@ -1,62 +0,0 @@
-interfaces {
- ethernet eth0 {
- }
- loopback lo {
- }
- pppoe pppoe0 {
- authentication {
- password bar
- user foo
- }
- connect-on-demand
- default-route auto
- mtu 1492
- source-interface eth0
- }
-}
-service {
- ssh {
- }
-}
-system {
- config-management {
- commit-revisions 100
- }
- console {
- device ttyS0 {
- speed 115200
- }
- }
- host-name vyos
- login {
- user vyos {
- authentication {
- encrypted-password $6$2Ta6TWHd/U$NmrX0x9kexCimeOcYK1MfhMpITF9ELxHcaBU/znBq.X2ukQOj61fVI2UYP/xBzP4QtiTcdkgs7WOQMHWsRymO/
- plaintext-password ""
- }
- }
- }
- ntp {
- server 0.pool.ntp.org {
- }
- server 1.pool.ntp.org {
- }
- server 2.pool.ntp.org {
- }
- }
- syslog {
- global {
- facility all {
- level info
- }
- facility protocols {
- level debug
- }
- }
- }
-}
-
-
-// Warning: Do not remove the following line.
-// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@1:conntrack-sync@1:dhcp-relay@2:dhcp-server@5:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@13:ipoe-server@1:ipsec@5:l2tp@3:lldp@1:mdns@1:nat@5:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@6:salt@1:snmp@2:ssh@2:sstp@3:system@19:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webgui@1:webproxy@2:zone-policy@1"
-// Release version: 1.3-rolling-202010241631
diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py
index 8f21ec70e..1426e80c2 100644
--- a/smoketest/scripts/cli/base_interfaces_test.py
+++ b/smoketest/scripts/cli/base_interfaces_test.py
@@ -402,12 +402,13 @@ class BasicInterfaceTest:
tmp = read_file(f'/proc/sys/net/ipv6/conf/{interface}/dad_transmits')
self.assertEqual(dad_transmits, tmp)
- def test_dhcpv6_client_options(self):
+ def test_dhcpv6_clinet_options(self):
if not self._test_ipv6_dhcpc6:
self.skipTest('not supported')
- duid = '00:01:00:01:27:71:db:f0:00:50:00:00:00:10'
+ duid_base = 10
for interface in self._interfaces:
+ duid = '00:01:00:01:27:71:db:f0:00:50:00:00:00:{}'.format(duid_base)
path = self._base_path + [interface]
for option in self._options.get(interface, []):
self.session.set(path + option.split())
@@ -417,10 +418,13 @@ class BasicInterfaceTest:
self.session.set(path + ['dhcpv6-options', 'rapid-commit'])
self.session.set(path + ['dhcpv6-options', 'parameters-only'])
self.session.set(path + ['dhcpv6-options', 'duid', duid])
+ duid_base += 1
self.session.commit()
+ duid_base = 10
for interface in self._interfaces:
+ duid = '00:01:00:01:27:71:db:f0:00:50:00:00:00:{}'.format(duid_base)
dhcpc6_config = read_file(f'/run/dhcp6c/dhcp6c.{interface}.conf')
self.assertIn(f'interface {interface} ' + '{', dhcpc6_config)
self.assertIn(f' request domain-name-servers;', dhcpc6_config)
@@ -430,6 +434,7 @@ class BasicInterfaceTest:
self.assertIn(f' send rapid-commit;', dhcpc6_config)
self.assertIn(f' send client-id {duid};', dhcpc6_config)
self.assertIn('};', dhcpc6_config)
+ duid_base += 1
# Check for running process
self.assertTrue(process_named_running('dhcp6c'))
diff --git a/smoketest/scripts/cli/test_interfaces_bonding.py b/smoketest/scripts/cli/test_interfaces_bonding.py
index 882d38760..b65d97d30 100755
--- a/smoketest/scripts/cli/test_interfaces_bonding.py
+++ b/smoketest/scripts/cli/test_interfaces_bonding.py
@@ -25,34 +25,32 @@ from vyos.configsession import ConfigSessionError
from vyos.util import read_file
class BondingInterfaceTest(BasicInterfaceTest.BaseTest):
- def setUp(self):
- self._test_ip = True
- self._test_ipv6 = True
- self._test_ipv6_pd = True
- self._test_ipv6_dhcpc6 = True
- self._test_mtu = True
- self._test_vlan = True
- self._test_qinq = True
- self._base_path = ['interfaces', 'bonding']
- self._interfaces = ['bond0']
- self._mirror_interfaces = ['dum21354']
- self._members = []
+ @classmethod
+ def setUpClass(cls):
+ cls._test_ip = True
+ cls._test_ipv6 = True
+ cls._test_ipv6_pd = True
+ cls._test_ipv6_dhcpc6 = True
+ cls._test_mtu = True
+ cls._test_vlan = True
+ cls._test_qinq = True
+ cls._base_path = ['interfaces', 'bonding']
+ cls._interfaces = ['bond0']
+ cls._mirror_interfaces = ['dum21354']
+ cls._members = []
# we need to filter out VLAN interfaces identified by a dot (.)
# in their name - just in case!
if 'TEST_ETH' in os.environ:
- self._members = os.environ['TEST_ETH'].split()
+ cls._members = os.environ['TEST_ETH'].split()
else:
- for tmp in Section.interfaces("ethernet"):
+ for tmp in Section.interfaces('ethernet'):
if not '.' in tmp:
- self._members.append(tmp)
-
- self._options['bond0'] = []
- for member in self._members:
- self._options['bond0'].append(f'member interface {member}')
-
- super().setUp()
+ cls._members.append(tmp)
+ cls._options['bond0'] = []
+ for member in cls._members:
+ cls._options['bond0'].append(f'member interface {member}')
def test_add_single_ip_address(self):
super().test_add_single_ip_address()
diff --git a/smoketest/scripts/cli/test_interfaces_bridge.py b/smoketest/scripts/cli/test_interfaces_bridge.py
index 33c2e7dad..f64b527b3 100755
--- a/smoketest/scripts/cli/test_interfaces_bridge.py
+++ b/smoketest/scripts/cli/test_interfaces_bridge.py
@@ -28,31 +28,30 @@ from vyos.util import read_file
from vyos.validate import is_intf_addr_assigned
class BridgeInterfaceTest(BasicInterfaceTest.BaseTest):
- def setUp(self):
- self._test_ip = True
- self._test_ipv6 = True
- self._test_ipv6_pd = True
- self._test_ipv6_dhcpc6 = True
- self._test_vlan = True
- self._base_path = ['interfaces', 'bridge']
- self._mirror_interfaces = ['dum21354']
- self._members = []
+ @classmethod
+ def setUpClass(cls):
+ cls._test_ip = True
+ cls._test_ipv6 = True
+ cls._test_ipv6_pd = True
+ cls._test_ipv6_dhcpc6 = True
+ cls._test_vlan = True
+ cls._base_path = ['interfaces', 'bridge']
+ cls._mirror_interfaces = ['dum21354']
+ cls._members = []
# we need to filter out VLAN interfaces identified by a dot (.)
# in their name - just in case!
if 'TEST_ETH' in os.environ:
- self._members = os.environ['TEST_ETH'].split()
+ cls._members = os.environ['TEST_ETH'].split()
else:
- for tmp in Section.interfaces("ethernet"):
+ for tmp in Section.interfaces('ethernet'):
if not '.' in tmp:
- self._members.append(tmp)
+ cls._members.append(tmp)
- self._options['br0'] = []
- for member in self._members:
- self._options['br0'].append(f'member interface {member}')
- self._interfaces = list(self._options)
-
- super().setUp()
+ cls._options['br0'] = []
+ for member in cls._members:
+ cls._options['br0'].append(f'member interface {member}')
+ cls._interfaces = list(cls._options)
def tearDown(self):
for intf in self._interfaces:
diff --git a/smoketest/scripts/cli/test_interfaces_dummy.py b/smoketest/scripts/cli/test_interfaces_dummy.py
index 60465a1d5..6e462bccf 100755
--- a/smoketest/scripts/cli/test_interfaces_dummy.py
+++ b/smoketest/scripts/cli/test_interfaces_dummy.py
@@ -19,10 +19,10 @@ import unittest
from base_interfaces_test import BasicInterfaceTest
class DummyInterfaceTest(BasicInterfaceTest.BaseTest):
- def setUp(self):
- self._base_path = ['interfaces', 'dummy']
- self._interfaces = ['dum435', 'dum8677', 'dum0931', 'dum089']
- super().setUp()
+ @classmethod
+ def setUpClass(cls):
+ cls._base_path = ['interfaces', 'dummy']
+ cls._interfaces = ['dum435', 'dum8677', 'dum0931', 'dum089']
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_interfaces_ethernet.py b/smoketest/scripts/cli/test_interfaces_ethernet.py
index 6c6e66008..772ff248f 100755
--- a/smoketest/scripts/cli/test_interfaces_ethernet.py
+++ b/smoketest/scripts/cli/test_interfaces_ethernet.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020 VyOS maintainers and contributors
+# Copyright (C) 2020-2021 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -35,38 +35,31 @@ def get_wpa_supplicant_value(interface, key):
return tmp[0]
class EthernetInterfaceTest(BasicInterfaceTest.BaseTest):
- def setUp(self):
- self._test_ip = True
- self._test_ipv6 = True
- self._test_ipv6_pd = True
- self._test_ipv6_dhcpc6 = True
- self._test_mtu = True
- self._test_vlan = True
- self._test_qinq = True
- self._base_path = ['interfaces', 'ethernet']
- self._mirror_interfaces = ['dum21354']
+ @classmethod
+ def setUpClass(cls):
+ cls._test_ip = True
+ cls._test_ipv6 = True
+ cls._test_ipv6_pd = True
+ cls._test_ipv6_dhcpc6 = True
+ cls._test_mtu = True
+ cls._test_vlan = True
+ cls._test_qinq = True
+ cls._base_path = ['interfaces', 'ethernet']
+ cls._mirror_interfaces = ['dum21354']
# we need to filter out VLAN interfaces identified by a dot (.)
# in their name - just in case!
if 'TEST_ETH' in os.environ:
tmp = os.environ['TEST_ETH'].split()
- self._interfaces = tmp
+ cls._interfaces = tmp
else:
- for tmp in Section.interfaces("ethernet"):
+ for tmp in Section.interfaces('ethernet'):
if not '.' in tmp:
- self._interfaces.append(tmp)
+ cls._interfaces.append(tmp)
- self._macs = {}
- for interface in self._interfaces:
- try:
- mac = self.session.show_config(self._base_path +
- [interface, 'hw-id']).split()[1]
- except:
- # during initial system startup there is no hw-id node
- mac = read_file(f'/sys/class/net/{interface}/address')
- self._macs[interface] = mac
-
- super().setUp()
+ cls._macs = {}
+ for interface in cls._interfaces:
+ cls._macs[interface] = read_file(f'/sys/class/net/{interface}/address')
def tearDown(self):
@@ -102,8 +95,7 @@ class EthernetInterfaceTest(BasicInterfaceTest.BaseTest):
# Validate interface state
for interface in self._interfaces:
- with open(f'/sys/class/net/{interface}/flags', 'r') as f:
- flags = f.read()
+ flags = read_file(f'/sys/class/net/{interface}/flags')
self.assertEqual(int(flags, 16) & 1, 0)
def test_offloading_rps(self):
diff --git a/smoketest/scripts/cli/test_interfaces_geneve.py b/smoketest/scripts/cli/test_interfaces_geneve.py
index 12cded400..b708b5437 100755
--- a/smoketest/scripts/cli/test_interfaces_geneve.py
+++ b/smoketest/scripts/cli/test_interfaces_geneve.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020 VyOS maintainers and contributors
+# Copyright (C) 2020-2021 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -20,16 +20,16 @@ from vyos.configsession import ConfigSession
from base_interfaces_test import BasicInterfaceTest
class GeneveInterfaceTest(BasicInterfaceTest.BaseTest):
- def setUp(self):
- self._test_ip = True
- self._test_ipv6 = True
- self._base_path = ['interfaces', 'geneve']
- self._options = {
+ @classmethod
+ def setUpClass(cls):
+ cls._test_ip = True
+ cls._test_ipv6 = True
+ cls._base_path = ['interfaces', 'geneve']
+ cls._options = {
'gnv0': ['vni 10', 'remote 127.0.1.1'],
'gnv1': ['vni 20', 'remote 127.0.1.2'],
}
- self._interfaces = list(self._options)
- super().setUp()
+ cls._interfaces = list(cls._options)
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_interfaces_l2tpv3.py b/smoketest/scripts/cli/test_interfaces_l2tpv3.py
index 81af6d7f4..a89895b92 100755
--- a/smoketest/scripts/cli/test_interfaces_l2tpv3.py
+++ b/smoketest/scripts/cli/test_interfaces_l2tpv3.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020 VyOS maintainers and contributors
+# Copyright (C) 2020-2021 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -21,11 +21,12 @@ from base_interfaces_test import BasicInterfaceTest
from vyos.util import cmd
class GeneveInterfaceTest(BasicInterfaceTest.BaseTest):
- def setUp(self):
- self._test_ip = True
- self._test_ipv6 = True
- self._base_path = ['interfaces', 'l2tpv3']
- self._options = {
+ @classmethod
+ def setUpClass(cls):
+ cls._test_ip = True
+ cls._test_ipv6 = True
+ cls._base_path = ['interfaces', 'l2tpv3']
+ cls._options = {
'l2tpeth10': ['local-ip 127.0.0.1', 'remote-ip 127.10.10.10',
'tunnel-id 100', 'peer-tunnel-id 10',
'session-id 100', 'peer-session-id 10',
@@ -35,8 +36,7 @@ class GeneveInterfaceTest(BasicInterfaceTest.BaseTest):
'session-id 20', 'tunnel-id 200',
'source-port 2020', 'destination-port 20202'],
}
- self._interfaces = list(self._options)
- super().setUp()
+ cls._interfaces = list(cls._options)
def test_add_single_ip_address(self):
super().test_add_single_ip_address()
diff --git a/smoketest/scripts/cli/test_interfaces_loopback.py b/smoketest/scripts/cli/test_interfaces_loopback.py
index 36000c3ff..77dd4c1b5 100755
--- a/smoketest/scripts/cli/test_interfaces_loopback.py
+++ b/smoketest/scripts/cli/test_interfaces_loopback.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020 VyOS maintainers and contributors
+# Copyright (C) 2020-2021 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -21,13 +21,13 @@ from netifaces import interfaces
from vyos.validate import is_intf_addr_assigned
+loopbacks = ['127.0.0.1', '::1']
+
class LoopbackInterfaceTest(BasicInterfaceTest.BaseTest):
- def setUp(self):
- super().setUp()
- # these addresses are never allowed to be removed from the system
- self._loopback_addresses = ['127.0.0.1', '::1']
- self._base_path = ['interfaces', 'loopback']
- self._interfaces = ['lo']
+ @classmethod
+ def setUpClass(cls):
+ cls._base_path = ['interfaces', 'loopback']
+ cls._interfaces = ['lo']
def tearDown(self):
self.session.delete(self._base_path)
@@ -40,12 +40,12 @@ class LoopbackInterfaceTest(BasicInterfaceTest.BaseTest):
def test_add_single_ip_address(self):
super().test_add_single_ip_address()
- for addr in self._loopback_addresses:
+ for addr in loopbacks:
self.assertTrue(is_intf_addr_assigned('lo', addr))
def test_add_multiple_ip_addresses(self):
super().test_add_multiple_ip_addresses()
- for addr in self._loopback_addresses:
+ for addr in loopbacks:
self.assertTrue(is_intf_addr_assigned('lo', addr))
def test_interface_disable(self):
diff --git a/smoketest/scripts/cli/test_interfaces_macsec.py b/smoketest/scripts/cli/test_interfaces_macsec.py
index 89743e5fd..3a3e7bff3 100755
--- a/smoketest/scripts/cli/test_interfaces_macsec.py
+++ b/smoketest/scripts/cli/test_interfaces_macsec.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020 VyOS maintainers and contributors
+# Copyright (C) 2020-2021 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -31,19 +31,19 @@ def get_config_value(interface, key):
return tmp[0]
class MACsecInterfaceTest(BasicInterfaceTest.BaseTest):
- def setUp(self):
- super().setUp()
- self._test_ip = True
- self._test_ipv6 = True
- self._base_path = ['interfaces', 'macsec']
- self._options = { 'macsec0': ['source-interface eth0', 'security cipher gcm-aes-128'] }
+ @classmethod
+ def setUpClass(cls):
+ cls._test_ip = True
+ cls._test_ipv6 = True
+ cls._base_path = ['interfaces', 'macsec']
+ cls._options = { 'macsec0': ['source-interface eth0', 'security cipher gcm-aes-128'] }
# if we have a physical eth1 interface, add a second macsec instance
- if 'eth1' in Section.interfaces("ethernet"):
+ if 'eth1' in Section.interfaces('ethernet'):
macsec = { 'macsec1': [f'source-interface eth1', 'security cipher gcm-aes-128'] }
- self._options.update(macsec)
+ cls._options.update(macsec)
- self._interfaces = list(self._options)
+ cls._interfaces = list(cls._options)
def test_macsec_encryption(self):
# MACsec can be operating in authentication and encryption mode - both
diff --git a/smoketest/scripts/cli/test_interfaces_openvpn.py b/smoketest/scripts/cli/test_interfaces_openvpn.py
index 00db3f667..a2a1a85ec 100755
--- a/smoketest/scripts/cli/test_interfaces_openvpn.py
+++ b/smoketest/scripts/cli/test_interfaces_openvpn.py
@@ -625,27 +625,27 @@ if __name__ == '__main__':
# Generate mandatory SSL certificate
tmp = f'openssl req -newkey rsa:4096 -new -nodes -x509 -days 3650 '\
f'-keyout {ssl_key} -out {ssl_cert} -subj {subject}'
- print(cmd(tmp))
+ cmd(tmp)
if not os.path.isfile(ca_cert):
# Generate "CA"
tmp = f'openssl req -new -x509 -key {ssl_key} -out {ca_cert} -subj {subject}'
- print(cmd(tmp))
+ cmd(tmp)
if not os.path.isfile(dh_pem):
# Generate "DH" key
tmp = f'openssl dhparam -out {dh_pem} 2048'
- print(cmd(tmp))
+ cmd(tmp)
if not os.path.isfile(s2s_key):
# Generate site-2-site key
tmp = f'openvpn --genkey --secret {s2s_key}'
- print(cmd(tmp))
+ cmd(tmp)
if not os.path.isfile(auth_key):
# Generate TLS auth key
tmp = f'openvpn --genkey --secret {auth_key}'
- print(cmd(tmp))
+ cmd(tmp)
for file in [ca_cert, ssl_cert, ssl_key, dh_pem, s2s_key, auth_key]:
cmd(f'sudo chown openvpn:openvpn {file}')
diff --git a/smoketest/scripts/cli/test_interfaces_pppoe.py b/smoketest/scripts/cli/test_interfaces_pppoe.py
index 6bfe35d86..285c756e2 100755
--- a/smoketest/scripts/cli/test_interfaces_pppoe.py
+++ b/smoketest/scripts/cli/test_interfaces_pppoe.py
@@ -97,6 +97,27 @@ class PPPoEInterfaceTest(unittest.TestCase):
self.assertTrue(running)
+
+ def test_pppoe_clent_disabled_interface(self):
+ # Check if PPPoE Client can be disabled
+ for interface in self._interfaces:
+ self.session.set(base_path + [interface, 'authentication', 'user', 'vyos'])
+ self.session.set(base_path + [interface, 'authentication', 'password', 'vyos'])
+ self.session.set(base_path + [interface, 'source-interface', self._source_interface])
+ self.session.set(base_path + [interface, 'disable'])
+
+ self.session.commit()
+
+ # Validate PPPoE client process
+ running = False
+ for interface in self._interfaces:
+ for proc in process_iter():
+ if interface in proc.cmdline():
+ running = True
+
+ self.assertFalse(running)
+
+
def test_pppoe_dhcpv6pd(self):
# Check if PPPoE dialer can be configured with DHCPv6-PD
address = '1'
diff --git a/smoketest/scripts/cli/test_interfaces_pseudo_ethernet.py b/smoketest/scripts/cli/test_interfaces_pseudo_ethernet.py
index 1a5debb79..f4cb4cdc9 100755
--- a/smoketest/scripts/cli/test_interfaces_pseudo_ethernet.py
+++ b/smoketest/scripts/cli/test_interfaces_pseudo_ethernet.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020 VyOS maintainers and contributors
+# Copyright (C) 2020-2021 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -19,21 +19,21 @@ import unittest
from base_interfaces_test import BasicInterfaceTest
class PEthInterfaceTest(BasicInterfaceTest.BaseTest):
- def setUp(self):
- self._test_ip = True
- self._test_ipv6 = True
- self._test_ipv6_pd = True
- self._test_ipv6_dhcpc6 = True
- self._test_mtu = True
- self._test_vlan = True
- self._test_qinq = True
- self._base_path = ['interfaces', 'pseudo-ethernet']
- self._options = {
+ @classmethod
+ def setUpClass(cls):
+ cls._test_ip = True
+ cls._test_ipv6 = True
+ cls._test_ipv6_pd = True
+ cls._test_ipv6_dhcpc6 = True
+ cls._test_mtu = True
+ cls._test_vlan = True
+ cls._test_qinq = True
+ cls._base_path = ['interfaces', 'pseudo-ethernet']
+ cls._options = {
'peth0': ['source-interface eth1'],
'peth1': ['source-interface eth1'],
}
- self._interfaces = list(self._options)
- super().setUp()
+ cls._interfaces = list(cls._options)
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_interfaces_tunnel.py b/smoketest/scripts/cli/test_interfaces_tunnel.py
index 8405fc7d0..a9250e3e5 100755
--- a/smoketest/scripts/cli/test_interfaces_tunnel.py
+++ b/smoketest/scripts/cli/test_interfaces_tunnel.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020 VyOS maintainers and contributors
+# Copyright (C) 2020-2021 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -61,22 +61,22 @@ def tunnel_conf(interface):
return json.loads(tmp)[0]
class TunnelInterfaceTest(BasicInterfaceTest.BaseTest):
- def setUp(self):
- self._test_ip = True
- self._test_ipv6 = True
- self._test_mtu = True
- self._base_path = ['interfaces', 'tunnel']
- self.local_v4 = '192.0.2.1'
- self.local_v6 = '2001:db8::1'
-
- self._options = {
- 'tun10': ['encapsulation ipip', 'remote-ip 192.0.2.10', 'local-ip ' + self.local_v4],
- 'tun20': ['encapsulation gre', 'remote-ip 192.0.2.20', 'local-ip ' + self.local_v4],
+ @classmethod
+ def setUpClass(cls):
+ cls._test_ip = True
+ cls._test_ipv6 = True
+ cls._test_mtu = True
+ cls._base_path = ['interfaces', 'tunnel']
+ cls.local_v4 = '192.0.2.1'
+ cls.local_v6 = '2001:db8::1'
+ cls._options = {
+ 'tun10': ['encapsulation ipip', 'remote-ip 192.0.2.10', 'local-ip ' + cls.local_v4],
+ 'tun20': ['encapsulation gre', 'remote-ip 192.0.2.20', 'local-ip ' + cls.local_v4],
}
+ cls._interfaces = list(cls._options)
- self._interfaces = list(self._options)
+ def setUp(self):
super().setUp()
-
self.session.set(['interfaces', 'dummy', source_if, 'address', self.local_v4 + '/32'])
self.session.set(['interfaces', 'dummy', source_if, 'address', self.local_v6 + '/128'])
diff --git a/smoketest/scripts/cli/test_interfaces_vxlan.py b/smoketest/scripts/cli/test_interfaces_vxlan.py
index a726aa610..fcc1b15ce 100755
--- a/smoketest/scripts/cli/test_interfaces_vxlan.py
+++ b/smoketest/scripts/cli/test_interfaces_vxlan.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020 VyOS maintainers and contributors
+# Copyright (C) 2020-2021 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -20,17 +20,17 @@ from vyos.configsession import ConfigSession, ConfigSessionError
from base_interfaces_test import BasicInterfaceTest
class VXLANInterfaceTest(BasicInterfaceTest.BaseTest):
- def setUp(self):
- self._test_ip = True
- self._test_ipv6 = True
- self._test_mtu = True
- self._base_path = ['interfaces', 'vxlan']
- self._options = {
+ @classmethod
+ def setUpClass(cls):
+ cls._test_ip = True
+ cls._test_ipv6 = True
+ cls._test_mtu = True
+ cls._base_path = ['interfaces', 'vxlan']
+ cls._options = {
'vxlan0': ['vni 10', 'remote 127.0.0.2'],
'vxlan1': ['vni 20', 'group 239.1.1.1', 'source-interface eth0'],
}
- self._interfaces = list(self._options)
- super().setUp()
+ cls._interfaces = list(cls._options)
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_interfaces_wireguard.py b/smoketest/scripts/cli/test_interfaces_wireguard.py
index d9a51b146..e70324f96 100755
--- a/smoketest/scripts/cli/test_interfaces_wireguard.py
+++ b/smoketest/scripts/cli/test_interfaces_wireguard.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020 VyOS maintainers and contributors
+# Copyright (C) 2020-2021 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
diff --git a/smoketest/scripts/cli/test_interfaces_wireless.py b/smoketest/scripts/cli/test_interfaces_wireless.py
index 51d97f032..39e8cd5b8 100755
--- a/smoketest/scripts/cli/test_interfaces_wireless.py
+++ b/smoketest/scripts/cli/test_interfaces_wireless.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020 VyOS maintainers and contributors
+# Copyright (C) 2020-2021 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -32,10 +32,11 @@ def get_config_value(interface, key):
return tmp[0]
class WirelessInterfaceTest(BasicInterfaceTest.BaseTest):
- def setUp(self):
- self._test_ip = True
- self._base_path = ['interfaces', 'wireless']
- self._options = {
+ @classmethod
+ def setUpClass(cls):
+ cls._test_ip = True
+ cls._base_path = ['interfaces', 'wireless']
+ cls._options = {
'wlan0': ['physical-device phy0', 'ssid VyOS-WIFI-0',
'type station', 'address 192.0.2.1/30'],
'wlan1': ['physical-device phy0', 'ssid VyOS-WIFI-1', 'country-code se',
@@ -45,8 +46,7 @@ class WirelessInterfaceTest(BasicInterfaceTest.BaseTest):
'wlan11': ['physical-device phy1', 'ssid VyOS-WIFI-3', 'country-code se',
'type access-point', 'address 192.0.2.13/30', 'channel 0'],
}
- self._interfaces = list(self._options)
- super().setUp()
+ cls._interfaces = list(cls._options)
def test_wireless_add_single_ip_address(self):
# derived method to check if member interfaces are enslaved properly
diff --git a/smoketest/scripts/cli/test_interfaces_wirelessmodem.py b/smoketest/scripts/cli/test_interfaces_wirelessmodem.py
index 696a6946b..023f57305 100755
--- a/smoketest/scripts/cli/test_interfaces_wirelessmodem.py
+++ b/smoketest/scripts/cli/test_interfaces_wirelessmodem.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020 VyOS maintainers and contributors
+# Copyright (C) 2020-2021 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py
index 87d10eb85..30d98976d 100755
--- a/smoketest/scripts/cli/test_protocols_bgp.py
+++ b/smoketest/scripts/cli/test_protocols_bgp.py
@@ -122,6 +122,9 @@ class TestProtocolsBGP(unittest.TestCase):
self.session.commit()
del self.session
+ # Check for running process
+ self.assertTrue(process_named_running(PROCESS_NAME))
+
def verify_frr_config(self, peer, peer_config, frrconfig):
# recurring patterns to verify for both a simple neighbor and a peer-group
if 'cap_dynamic' in peer_config:
@@ -182,8 +185,6 @@ class TestProtocolsBGP(unittest.TestCase):
self.assertIn(f' bgp default local-preference {local_pref}', frrconfig)
self.assertIn(f' no bgp default ipv4-unicast', frrconfig)
- # Check for running process
- self.assertTrue(process_named_running(PROCESS_NAME))
def test_bgp_02_neighbors(self):
# Test out individual neighbor configuration items, not all of them are
@@ -419,39 +420,5 @@ class TestProtocolsBGP(unittest.TestCase):
for prefix in listen_ranges:
self.assertIn(f' bgp listen range {prefix} peer-group {peer_group}', frrconfig)
-
- def test_bgp_07_rpki(self):
- rpki_path = ['protocols', 'rpki']
- init_tmo = '50'
- polling = '400'
- preference = '100'
- timeout = '900'
-
- cache = {
- 'foo' : { 'address' : '1.1.1.1', 'port' : '8080' },
-# T3253 only one peer supported
-# 'bar' : { 'address' : '2.2.2.2', 'port' : '9090' },
- }
-
- self.session.set(rpki_path + ['polling-period', polling])
- self.session.set(rpki_path + ['preference', preference])
-
- for name, config in cache.items():
- self.session.set(rpki_path + ['cache', name, 'address', config['address']])
- self.session.set(rpki_path + ['cache', name, 'port', config['port']])
-
- # commit changes
- self.session.commit()
-
- # Verify FRR bgpd configuration
- frrconfig = getFRRRPKIconfig()
- self.assertIn(f'rpki polling_period {polling}', frrconfig)
-
- for name, config in cache.items():
- self.assertIn('rpki cache {address} {port} preference 1'.format(**config), frrconfig)
-
- self.session.delete(rpki_path)
-
-
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py
index d47838d8c..ce30f6a7d 100755
--- a/smoketest/scripts/cli/test_protocols_ospf.py
+++ b/smoketest/scripts/cli/test_protocols_ospf.py
@@ -30,6 +30,9 @@ route_map = 'foo-bar-baz10'
def getFRROSPFconfig():
return cmd('vtysh -c "show run" | sed -n "/router ospf/,/^!/p"')
+def getFRRInterfaceConfig(interface):
+ return cmd(f'vtysh -c "show run" | sed -n "/^interface {interface}$/,/^!/p"')
+
class TestProtocolsOSPF(unittest.TestCase):
def setUp(self):
self.session = ConfigSession(os.getpid())
@@ -232,24 +235,8 @@ class TestProtocolsOSPF(unittest.TestCase):
else:
self.assertIn(f' redistribute {protocol} metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig)
-
- def test_ospf_09_area(self):
- area = '0'
+ def test_ospf_09_virtual_link(self):
networks = ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16']
- for network in networks:
- self.session.set(base_path + ['area', area, 'network', network])
-
- # commit changes
- self.session.commit()
-
- # Verify FRR ospfd configuration
- frrconfig = getFRROSPFconfig()
- self.assertIn(f'router ospf', frrconfig)
- for network in networks:
- self.assertIn(f' network {network} area {area}', frrconfig)
-
-
- def test_ospf_10_virtual_link(self):
area = '10'
shortcut = 'enable'
virtual_link = '192.0.2.1'
@@ -263,6 +250,8 @@ class TestProtocolsOSPF(unittest.TestCase):
self.session.set(base_path + ['area', area, 'virtual-link', virtual_link, 'retransmit-interval', retransmit])
self.session.set(base_path + ['area', area, 'virtual-link', virtual_link, 'transmit-delay', transmit])
self.session.set(base_path + ['area', area, 'virtual-link', virtual_link, 'dead-interval', dead])
+ for network in networks:
+ self.session.set(base_path + ['area', area, 'network', network])
# commit changes
self.session.commit()
@@ -272,6 +261,39 @@ class TestProtocolsOSPF(unittest.TestCase):
self.assertIn(f'router ospf', frrconfig)
self.assertIn(f' area {area} shortcut {shortcut}', frrconfig)
self.assertIn(f' area {area} virtual-link {virtual_link} hello-interval {hello} retransmit-interval {retransmit} transmit-delay {transmit} dead-interval {dead}', frrconfig)
+ for network in networks:
+ self.assertIn(f' network {network} area {area}', frrconfig)
+
+ def test_ospf_10_interface_configureation(self):
+ interfaces = Section.interfaces('ethernet')
+ password = 'vyos1234'
+ bandwidth = '10000'
+ cost = '150'
+ network = 'point-to-point'
+ priority = '200'
+
+ for interface in interfaces:
+ self.session.set(base_path + ['interface', interface, 'authentication', 'plaintext-password', password])
+ self.session.set(base_path + ['interface', interface, 'bandwidth', bandwidth])
+ self.session.set(base_path + ['interface', interface, 'bfd'])
+ self.session.set(base_path + ['interface', interface, 'cost', cost])
+ self.session.set(base_path + ['interface', interface, 'mtu-ignore'])
+ self.session.set(base_path + ['interface', interface, 'network', network])
+ self.session.set(base_path + ['interface', interface, 'priority', priority])
+
+ # commit changes
+ self.session.commit()
+
+ for interface in interfaces:
+ config = getFRRInterfaceConfig(interface)
+ self.assertIn(f'interface {interface}', config)
+ self.assertIn(f' ip ospf authentication-key {password}', config)
+ self.assertIn(f' ip ospf bfd', config)
+ self.assertIn(f' ip ospf cost {cost}', config)
+ self.assertIn(f' ip ospf mtu-ignore', config)
+ self.assertIn(f' ip ospf network {network}', config)
+ self.assertIn(f' ip ospf priority {priority}', config)
+ self.assertIn(f' bandwidth {bandwidth}', config)
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_protocols_rpki.py b/smoketest/scripts/cli/test_protocols_rpki.py
new file mode 100755
index 000000000..1e742b411
--- /dev/null
+++ b/smoketest/scripts/cli/test_protocols_rpki.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import unittest
+
+from vyos.configsession import ConfigSession
+from vyos.configsession import ConfigSessionError
+from vyos.util import cmd
+from vyos.util import process_named_running
+
+base_path = ['protocols', 'rpki']
+PROCESS_NAME = 'bgpd'
+
+rpki_known_hosts = '/config/auth/known_hosts'
+rpki_ssh_key = '/config/auth/id_rsa_rpki'
+rpki_ssh_pub = f'{rpki_ssh_key}.pub'
+
+def getFRRRPKIconfig():
+ return cmd(f'vtysh -c "show run" | sed -n "/rpki/,/^!/p"')
+
+class TestProtocolsRPKI(unittest.TestCase):
+ def setUp(self):
+ self.session = ConfigSession(os.getpid())
+
+ def tearDown(self):
+ self.session.delete(base_path)
+ self.session.commit()
+ del self.session
+
+ # Nothing RPKI specific should be left over in the config
+ #
+ # Disabled until T3266 is resolved
+ # frrconfig = getFRRRPKIconfig()
+ # self.assertNotIn('rpki', frrconfig)
+
+ # Check for running process
+ self.assertTrue(process_named_running(PROCESS_NAME))
+
+ def test_rpki(self):
+ polling = '7200'
+ cache = {
+ '192.0.2.1' : {
+ 'port' : '8080',
+ 'preference' : '1'
+ },
+ '192.0.2.2' : {
+ 'port' : '9090',
+ 'preference' : '2'
+ },
+ }
+
+ self.session.set(base_path + ['polling-period', polling])
+ for peer, peer_config in cache.items():
+ self.session.set(base_path + ['cache', peer, 'port', peer_config['port']])
+ self.session.set(base_path + ['cache', peer, 'preference', peer_config['preference']])
+
+ # commit changes
+ self.session.commit()
+
+ # Verify FRR configuration
+ frrconfig = getFRRRPKIconfig()
+ self.assertIn(f'rpki polling_period {polling}', frrconfig)
+
+ for peer, peer_config in cache.items():
+ port = peer_config['port']
+ preference = peer_config['preference']
+ self.assertIn(f'rpki cache {peer} {port} preference {preference}', frrconfig)
+
+ def test_rpki_ssh(self):
+ polling = '7200'
+ cache = {
+ '192.0.2.3' : {
+ 'port' : '1234',
+ 'username' : 'foo',
+ 'preference' : '10'
+ },
+ '192.0.2.4' : {
+ 'port' : '5678',
+ 'username' : 'bar',
+ 'preference' : '20'
+ },
+ }
+
+ self.session.set(base_path + ['polling-period', polling])
+
+ for peer, peer_config in cache.items():
+ self.session.set(base_path + ['cache', peer, 'port', peer_config['port']])
+ self.session.set(base_path + ['cache', peer, 'preference', peer_config['preference']])
+ self.session.set(base_path + ['cache', peer, 'ssh', 'username', peer_config['username']])
+ self.session.set(base_path + ['cache', peer, 'ssh', 'public-key-file', rpki_ssh_pub])
+ self.session.set(base_path + ['cache', peer, 'ssh', 'private-key-file', rpki_ssh_key])
+ self.session.set(base_path + ['cache', peer, 'ssh', 'known-hosts-file', rpki_known_hosts])
+
+ # commit changes
+ self.session.commit()
+
+ # Verify FRR configuration
+ frrconfig = getFRRRPKIconfig()
+ self.assertIn(f'rpki polling_period {polling}', frrconfig)
+
+ for peer, peer_config in cache.items():
+ port = peer_config['port']
+ preference = peer_config['preference']
+ username = peer_config['username']
+ self.assertIn(f'rpki cache {peer} {port} {username} {rpki_ssh_key} {rpki_known_hosts} preference {preference}', frrconfig)
+
+
+ def test_rpki_verify_preference(self):
+ cache = {
+ '192.0.2.1' : {
+ 'port' : '8080',
+ 'preference' : '1'
+ },
+ '192.0.2.2' : {
+ 'port' : '9090',
+ 'preference' : '1'
+ },
+ }
+
+ for peer, peer_config in cache.items():
+ self.session.set(base_path + ['cache', peer, 'port', peer_config['port']])
+ self.session.set(base_path + ['cache', peer, 'preference', peer_config['preference']])
+
+ # check validate() - preferences must be unique
+ with self.assertRaises(ConfigSessionError):
+ self.session.commit()
+
+
+if __name__ == '__main__':
+ # Create OpenSSH keypair used in RPKI tests
+ if not os.path.isfile(rpki_ssh_key):
+ cmd(f'ssh-keygen -t rsa -f {rpki_ssh_key} -N ""')
+
+ if not os.path.isfile(rpki_known_hosts):
+ cmd(f'touch {rpki_known_hosts}')
+
+ unittest.main(verbosity=2, failfast=True)
diff --git a/smoketest/scripts/cli/test_protocols_static.py b/smoketest/scripts/cli/test_protocols_static.py
new file mode 100755
index 000000000..100fd3387
--- /dev/null
+++ b/smoketest/scripts/cli/test_protocols_static.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import re
+import os
+import json
+import unittest
+
+from netifaces import interfaces
+
+from vyos.configsession import ConfigSession
+from vyos.configsession import ConfigSessionError
+from vyos.ifconfig import Interface
+from vyos.ifconfig import Section
+from vyos.template import is_ipv6
+from vyos.util import cmd
+from vyos.util import read_file
+from vyos.validate import is_intf_addr_assigned
+
+dummy_if = 'dum08765'
+base_path = ['protocols', 'static']
+
+routes = {
+ '10.0.0.0/8' : {
+ 'next_hop' : '192.0.2.2',
+ 'distance' : '200',
+ },
+ '172.16.0.0/12' : {
+ 'next_hop' : '192.0.2.3',
+ },
+ '192.168.0.0/16' : {
+ 'next_hop' : '192.0.2.3',
+ },
+ '2001:db8:1000::/48' : {
+ 'next_hop' : '2001:db8::1000',
+ },
+ '2001:db8:2000::/48' : {
+ 'next_hop' : '2001:db8::2000',
+ },
+}
+
+interface_routes = {
+ '10.0.0.0/8' : {
+ 'next_hop' : dummy_if,
+ 'distance' : '200',
+ },
+ '172.16.0.0/12' : {
+ 'next_hop' : dummy_if,
+ },
+ '192.168.0.0/16' : {
+ 'next_hop' : dummy_if,
+ },
+ '2001:db8:1000::/48' : {
+ 'next_hop' : dummy_if,
+ },
+ '2001:db8:2000::/48' : {
+ 'next_hop' : dummy_if,
+ },
+}
+
+
+class StaticRouteTest(unittest.TestCase):
+ def setUp(self):
+ self.session = ConfigSession(os.getpid())
+ # we need an alive next-hop interface
+ self.session.set(['interfaces', 'dummy', dummy_if, 'address', '192.0.2.1/24'])
+ self.session.set(['interfaces', 'dummy', dummy_if, 'address', '2001:db8::1/64'])
+
+ def tearDown(self):
+ self.session.delete(['interfaces', 'dummy', dummy_if])
+ self.session.commit()
+
+ def test_static_routes(self):
+ for route, route_config in routes.items():
+ route_type = 'route'
+ if is_ipv6(route):
+ route_type = 'route6'
+ self.session.set(base_path + [route_type, route, 'next-hop', route_config['next_hop']])
+ if 'distance' in route_config:
+ self.session.set(base_path + [route_type, route, 'next-hop', route_config['next_hop'], 'distance', route_config['distance']])
+
+ # commit changes
+ self.session.commit()
+
+ # Verify routes
+ for route, route_config in routes.items():
+ ip_ver = '-4'
+ if is_ipv6(route):
+ ip_ver = '-6'
+ tmp = json.loads(cmd(f'ip {ip_ver} -d -j route show {route}'))
+
+ found = False
+ for result in tmp:
+ # unfortunately iproute2 does not return the distance
+ if 'dst' in result and result['dst'] == route:
+ if 'gateway' in result and result['gateway'] == route_config['next_hop']:
+ found = True
+
+ self.assertTrue(found)
+
+ route_type = 'route'
+ if is_ipv6(route):
+ route_type = 'route6'
+ self.session.delete(base_path + [route_type, route])
+
+ def test_interface_routes(self):
+ for route, route_config in interface_routes.items():
+ route_type = 'interface-route'
+ if is_ipv6(route):
+ route_type = 'interface-route6'
+ self.session.set(base_path + [route_type, route, 'next-hop-interface', route_config['next_hop']])
+ if 'distance' in route_config:
+ self.session.set(base_path + [route_type, route, 'next-hop-interface', route_config['next_hop'], 'distance', route_config['distance']])
+
+ # commit changes
+ self.session.commit()
+
+ # Verify routes
+ for route, route_config in interface_routes.items():
+ ip_ver = '-4'
+ if is_ipv6(route):
+ ip_ver = '-6'
+ tmp = json.loads(cmd(f'ip {ip_ver} -d -j route show {route}'))
+
+ found = False
+ for result in tmp:
+ # unfortunately iproute2 does not return the distance
+ if 'dst' in result and result['dst'] == route:
+ if 'dev' in result and result['dev'] == route_config['next_hop']:
+ found = True
+ break
+
+ self.assertTrue(found)
+
+ route_type = 'interface-route'
+ if is_ipv6(route):
+ route_type = 'interface-route6'
+ self.session.delete(base_path + [route_type, route])
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2, failfast=True)
diff --git a/smoketest/scripts/cli/test_vrf.py b/smoketest/scripts/cli/test_vrf.py
index 5270e758a..856baa070 100755
--- a/smoketest/scripts/cli/test_vrf.py
+++ b/smoketest/scripts/cli/test_vrf.py
@@ -16,19 +16,44 @@
import re
import os
+import json
import unittest
+
from netifaces import interfaces
from vyos.configsession import ConfigSession
from vyos.configsession import ConfigSessionError
+from vyos.ifconfig import Interface
+from vyos.ifconfig import Section
+from vyos.template import is_ipv6
+from vyos.util import cmd
from vyos.util import read_file
from vyos.validate import is_intf_addr_assigned
-from vyos.ifconfig import Interface
base_path = ['vrf']
vrfs = ['red', 'green', 'blue', 'foo-bar', 'baz_foo']
+def get_vrf_ipv4_routes(vrf):
+ return json.loads(cmd(f'ip -4 -j route show vrf {vrf}'))
+
+def get_vrf_ipv6_routes(vrf):
+ return json.loads(cmd(f'ip -6 -j route show vrf {vrf}'))
+
class VRFTest(unittest.TestCase):
+ _interfaces = []
+
+ @classmethod
+ def setUpClass(cls):
+ # we need to filter out VLAN interfaces identified by a dot (.)
+ # in their name - just in case!
+ if 'TEST_ETH' in os.environ:
+ tmp = os.environ['TEST_ETH'].split()
+ cls._interfaces = tmp
+ else:
+ for tmp in Section.interfaces('ethernet'):
+ if not '.' in tmp:
+ cls._interfaces.append(tmp)
+
def setUp(self):
self.session = ConfigSession(os.getpid())
@@ -120,5 +145,97 @@ class VRFTest(unittest.TestCase):
with self.assertRaises(ConfigSessionError):
self.session.commit()
+ def test_vrf_assign_interface(self):
+ vrf = vrfs[0]
+ table = '5000'
+ self.session.set(['vrf', 'name', vrf, 'table', table])
+
+ for interface in self._interfaces:
+ section = Section.section(interface)
+ self.session.set(['interfaces', section, interface, 'vrf', vrf])
+
+ # commit changes
+ self.session.commit()
+
+ # Verify & cleanup
+ for interface in self._interfaces:
+ # os.readlink resolves to: '../../../../../virtual/net/foovrf'
+ tmp = os.readlink(f'/sys/class/net/{interface}/master').split('/')[-1]
+ self.assertEqual(tmp, vrf)
+ # cleanup
+ section = Section.section(interface)
+ self.session.delete(['interfaces', section, interface, 'vrf'])
+
+ def test_vrf_static_routes(self):
+ routes = {
+ '10.0.0.0/8' : {
+ 'next_hop' : '192.0.2.2',
+ 'distance' : '200',
+ 'next_hop_vrf' : 'default',
+ },
+ '172.16.0.0/12' : {
+ 'next_hop' : '192.0.2.3',
+ 'next_hop_vrf' : 'default',
+ },
+ '192.168.0.0/16' : {
+ 'next_hop' : '192.0.2.3',
+ },
+ '2001:db8:1000::/48' : {
+ 'next_hop' : '2001:db8::2',
+ },
+ }
+
+ table = '2000'
+ for vrf in vrfs:
+ base = base_path + ['name', vrf]
+ self.session.set(base + ['table', str(table)])
+
+ # required interface for leaking to default table
+ self.session.set(['interfaces', 'ethernet', 'eth0', 'address', '192.0.2.1/24'])
+
+ # we also need an interface in "UP" state to install routes
+ self.session.set(['interfaces', 'dummy', f'dum{table}', 'vrf', vrf])
+ self.session.set(['interfaces', 'dummy', f'dum{table}', 'address', '192.0.2.1/24'])
+ self.session.set(['interfaces', 'dummy', f'dum{table}', 'address', '2001:db8::1/64'])
+ table = str(int(table) + 1)
+
+ proto_base = ['protocols', 'vrf', vrf, 'static']
+ for route, route_config in routes.items():
+ route_type = 'route'
+ if is_ipv6(route):
+ route_type = 'route6'
+ self.session.set(proto_base + [route_type, route, 'next-hop', route_config['next_hop']])
+ if 'distance' in route_config:
+ self.session.set(proto_base + [route_type, route, 'next-hop', route_config['next_hop'], 'distance', route_config['distance']])
+ if 'next_hop_vrf' in route_config:
+ self.session.set(proto_base + [route_type, route, 'next-hop', route_config['next_hop'], 'next-hop-vrf', route_config['next_hop_vrf']])
+
+ # commit changes
+ self.session.commit()
+
+ # Verify routes
+ table = '2000'
+ for vrf in vrfs:
+ for route, route_config in routes.items():
+ if is_ipv6(route):
+ tmp = get_vrf_ipv6_routes(vrf)
+ else:
+ tmp = get_vrf_ipv4_routes(vrf)
+
+ found = False
+ for result in tmp:
+ if 'dst' in result and result['dst'] == route:
+ if 'gateway' in result and result['gateway'] == route_config['next_hop']:
+ found = True
+
+ self.assertTrue(found)
+
+ # Cleanup
+ self.session.delete(['protocols', 'vrf', vrf])
+ self.session.delete(['interfaces', 'dummy', f'dum{table}'])
+ self.session.delete(['interfaces', 'ethernet', 'eth0', 'address', '192.0.2.1/24'])
+
+ table = str(int(table) + 1)
+
if __name__ == '__main__':
- unittest.main(verbosity=2, failfast=True)
+ unittest.main(verbosity=2)
diff --git a/src/conf_mode/interfaces-pppoe.py b/src/conf_mode/interfaces-pppoe.py
index f49792a7a..3675db73b 100755
--- a/src/conf_mode/interfaces-pppoe.py
+++ b/src/conf_mode/interfaces-pppoe.py
@@ -73,7 +73,7 @@ def generate(pppoe):
config_files = [config_pppoe, script_pppoe_pre_up, script_pppoe_ip_up,
script_pppoe_ip_down, script_pppoe_ipv6_up, config_wide_dhcp6c]
- if 'deleted' in pppoe:
+ if 'deleted' in pppoe or 'disable' in pppoe:
# stop DHCPv6-PD client
call(f'systemctl stop dhcp6c@{ifname}.service')
# Hang-up PPPoE connection
@@ -110,13 +110,11 @@ def generate(pppoe):
return None
def apply(pppoe):
- if 'deleted' in pppoe:
- # bail out early
+ if 'deleted' in pppoe or 'disable' in pppoe:
+ call('systemctl stop ppp@{ifname}.service'.format(**pppoe))
return None
- if 'disable' not in pppoe:
- # Dial PPPoE connection
- call('systemctl restart ppp@{ifname}.service'.format(**pppoe))
+ call('systemctl restart ppp@{ifname}.service'.format(**pppoe))
return None
diff --git a/src/conf_mode/lldp.py b/src/conf_mode/lldp.py
index 6b645857a..082c3e128 100755
--- a/src/conf_mode/lldp.py
+++ b/src/conf_mode/lldp.py
@@ -21,7 +21,8 @@ from copy import deepcopy
from sys import exit
from vyos.config import Config
-from vyos.validate import is_addr_assigned,is_loopback_addr
+from vyos.validate import is_addr_assigned
+from vyos.validate import is_loopback_addr
from vyos.version import get_version_data
from vyos import ConfigError
from vyos.util import call
@@ -237,8 +238,10 @@ def apply(lldp):
else:
# LLDP service has been terminated
call('systemctl stop lldpd.service')
- os.unlink(config_file)
- os.unlink(vyos_config_file)
+ if os.path.isfile(config_file):
+ os.unlink(config_file)
+ if os.path.isfile(vyos_config_file):
+ os.unlink(vyos_config_file)
if __name__ == '__main__':
try:
diff --git a/src/conf_mode/protocols_ospf.py b/src/conf_mode/protocols_ospf.py
index 7c0ffbd27..866b2db62 100755
--- a/src/conf_mode/protocols_ospf.py
+++ b/src/conf_mode/protocols_ospf.py
@@ -21,6 +21,7 @@ from sys import exit
from vyos.config import Config
from vyos.configdict import dict_merge
from vyos.configverify import verify_route_maps
+from vyos.configverify import verify_interface_exists
from vyos.template import render
from vyos.template import render_to_string
from vyos.util import call
@@ -76,6 +77,7 @@ def get_config(config=None):
# clean them out and add them manually :(
del default_values['neighbor']
del default_values['area']['virtual_link']
+ del default_values['interface']
# merge in remaining default values
ospf = dict_merge(default_values, ospf)
@@ -94,6 +96,12 @@ def get_config(config=None):
ospf['area'][area]['virtual_link'][virtual_link] = dict_merge(
default_values, ospf['area'][area]['virtual_link'][virtual_link])
+ if 'interface' in ospf:
+ default_values = defaults(base + ['interface'])
+ for interface in ospf['interface']:
+ ospf['interface'][interface] = dict_merge(default_values,
+ ospf['interface'][interface])
+
# We also need some additional information from the config, prefix-lists
# and route-maps for instance. They will be used in verify()
base = ['policy']
@@ -108,6 +116,11 @@ def verify(ospf):
return None
verify_route_maps(ospf)
+
+ if 'interface' in ospf:
+ for interface in ospf['interface']:
+ verify_interface_exists(interface)
+
return None
def generate(ospf):
@@ -125,6 +138,7 @@ def apply(ospf):
# Save original configuration prior to starting any commit actions
frr_cfg = frr.FRRConfig()
frr_cfg.load_configuration(frr_daemon)
+ frr_cfg.modify_section(r'interface \S+', '')
frr_cfg.modify_section('router ospf', '')
frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', ospf['new_frr_config'])
diff --git a/src/conf_mode/protocols_rpki.py b/src/conf_mode/protocols_rpki.py
new file mode 100755
index 000000000..aa6f974ab
--- /dev/null
+++ b/src/conf_mode/protocols_rpki.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+
+from sys import exit
+
+from vyos.config import Config
+from vyos.configdict import dict_merge
+from vyos.configverify import verify_route_maps
+from vyos.template import render
+from vyos.template import render_to_string
+from vyos.util import call
+from vyos.util import dict_search
+from vyos.xml import defaults
+from vyos import ConfigError
+from vyos import frr
+from vyos import airbag
+airbag.enable()
+
+config_file = r'/tmp/rpki.frr'
+frr_daemon = 'bgpd'
+
+DEBUG = os.path.exists('/tmp/rpki.debug')
+if DEBUG:
+ import logging
+ lg = logging.getLogger("vyos.frr")
+ lg.setLevel(logging.DEBUG)
+ ch = logging.StreamHandler()
+ lg.addHandler(ch)
+
+def get_config(config=None):
+ if config:
+ conf = config
+ else:
+ conf = Config()
+ base = ['protocols', 'rpki']
+
+ rpki = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
+ if not conf.exists(base):
+ return rpki
+
+ # We have gathered the dict representation of the CLI, but there are default
+ # options which we need to update into the dictionary retrived.
+ default_values = defaults(base)
+ rpki = dict_merge(default_values, rpki)
+
+ return rpki
+
+def verify(rpki):
+ if not rpki:
+ return None
+
+ if 'cache' in rpki:
+ preferences = []
+ for peer, peer_config in rpki['cache'].items():
+ for mandatory in ['port', 'preference']:
+ if mandatory not in peer_config:
+ raise ConfigError(f'RPKI cache "{peer}" {mandatory} must be defined!')
+
+ if 'preference' in peer_config:
+ preference = peer_config['preference']
+ if preference in preferences:
+ raise ConfigError(f'RPKI cache with preference {preference} already configured!')
+ preferences.append(preference)
+
+ if 'ssh' in peer_config:
+ files = ['private_key_file', 'public_key_file', 'known_hosts_file']
+ for file in files:
+ if file not in peer_config['ssh']:
+ raise ConfigError('RPKI+SSH requires username, public/private ' \
+ 'keys and known-hosts file to be defined!')
+
+ filename = peer_config['ssh'][file]
+ if not os.path.exists(filename):
+ raise ConfigError(f'RPKI SSH {file.replace("-","-")} "{filename}" does not exist!')
+
+ return None
+
+def generate(rpki):
+ # render(config) not needed, its only for debug
+ render(config_file, 'frr/rpki.frr.tmpl', rpki)
+ rpki['new_frr_config'] = render_to_string('frr/rpki.frr.tmpl', rpki)
+
+ return None
+
+def apply(rpki):
+ # Save original configuration prior to starting any commit actions
+ frr_cfg = frr.FRRConfig()
+ frr_cfg.load_configuration(frr_daemon)
+ frr_cfg.modify_section('rpki', '')
+ frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', rpki['new_frr_config'])
+
+ # Debugging
+ if DEBUG:
+ from pprint import pprint
+ print('')
+ print('--------- DEBUGGING ----------')
+ pprint(dir(frr_cfg))
+ print('Existing config:\n')
+ for line in frr_cfg.original_config:
+ print(line)
+ print(f'Replacement config:\n')
+ print(f'{rpki["new_frr_config"]}')
+ print(f'Modified config:\n')
+ print(f'{frr_cfg}')
+
+ frr_cfg.commit_configuration(frr_daemon)
+
+ # If FRR config is blank, re-run the blank commit x times due to frr-reload
+ # behavior/bug not properly clearing out on one commit.
+ if rpki['new_frr_config'] == '':
+ for a in range(5):
+ frr_cfg.commit_configuration(frr_daemon)
+
+ 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/interfaces/18-to-19 b/src/migration-scripts/interfaces/18-to-19
new file mode 100755
index 000000000..e24421c90
--- /dev/null
+++ b/src/migration-scripts/interfaces/18-to-19
@@ -0,0 +1,81 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from sys import exit, argv
+from vyos.configtree import ConfigTree
+
+if __name__ == '__main__':
+ if (len(argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+ file_name = argv[1]
+ with open(file_name, 'r') as f:
+ config_file = f.read()
+
+ config = ConfigTree(config_file)
+
+ #
+ # Migrate "interface ethernet eth0 ip ospf" to "protocols ospf interface eth0"
+ #
+ for type in config.list_nodes(['interfaces']):
+ for interface in config.list_nodes(['interfaces', type]):
+
+ ip_ospf = ['interfaces', type, interface, 'ip', 'ospf']
+ if config.exists(ip_ospf):
+ config.set(['protocols', 'ospf', 'interface'])
+ config.set_tag(['protocols', 'ospf', 'interface'])
+ config.copy(ip_ospf, ['protocols', 'ospf', 'interface', interface])
+ config.delete(ip_ospf)
+
+ vif_path = ['interfaces', type, interface, 'vif']
+ if config.exists(vif_path):
+ for vif in config.list_nodes(vif_path):
+ vif_ospf_path = vif_path + [vif, 'ip', 'ospf']
+ if config.exists(vif_ospf_path):
+ config.set(['protocols', 'ospf', 'interface'])
+ config.set_tag(['protocols', 'ospf', 'interface'])
+ config.copy(vif_ospf_path, ['protocols', 'ospf', 'interface', f'{interface}.{vif}'])
+ config.delete(vif_ospf_path)
+
+ vif_s_path = ['interfaces', type, interface, 'vif-s']
+ if config.exists(vif_s_path):
+ for vif_s in config.list_nodes(vif_s_path):
+ vif_s_ospf_path = vif_s_path + [vif_s, 'ip', 'ospf']
+ if config.exists(vif_s_ospf_path):
+ config.set(['protocols', 'ospf', 'interface'])
+ config.set_tag(['protocols', 'ospf', 'interface'])
+ config.copy(vif_s_ospf_path, ['protocols', 'ospf', 'interface', f'{interface}.{vif_s}'])
+
+ vif_c_path = ['interfaces', type, interface, 'vif-s', vif_s, 'vif-c']
+ if config.exists(vif_c_path):
+ for vif_c in config.list_nodes(vif_c_path):
+ vif_c_ospf_path = vif_c_path + [vif_c, 'ip', 'ospf']
+ if config.exists(vif_c_ospf_path):
+ config.set(['protocols', 'ospf', 'interface'])
+ config.set_tag(['protocols', 'ospf', 'interface'])
+ config.copy(vif_c_ospf_path, ['protocols', 'ospf', 'interface', f'{interface}.{vif_s}.{vif_c}'])
+ config.delete(vif_c_ospf_path)
+
+ config.delete(vif_s_ospf_path)
+
+ try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+ except OSError as e:
+ print("Failed to save the modified config: {}".format(e))
+ exit(1)
+
diff --git a/src/migration-scripts/quagga/6-to-7 b/src/migration-scripts/quagga/6-to-7
new file mode 100755
index 000000000..3a229b5df
--- /dev/null
+++ b/src/migration-scripts/quagga/6-to-7
@@ -0,0 +1,76 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# - T3037, BGP address-family ipv6-unicast capability dynamic does not exist in
+# FRR, there is only a base, per neighbor dynamic capability, migrate config
+
+import sys
+from vyos.configtree import ConfigTree
+
+if (len(sys.argv) < 2):
+ print("Must specify file name!")
+ sys.exit(1)
+
+file_name = sys.argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+base = ['protocols', 'bgp']
+config = ConfigTree(config_file)
+
+if not config.exists(base):
+ # Nothing to do
+ sys.exit(0)
+
+# Check if BGP is actually configured and obtain the ASN
+asn_list = config.list_nodes(base)
+if asn_list:
+ # There's always just one BGP node, if any
+ bgp_base = base + [asn_list[0]]
+
+ for neighbor_type in ['neighbor', 'peer-group']:
+ if not config.exists(bgp_base + [neighbor_type]):
+ continue
+ for neighbor in config.list_nodes(bgp_base + [neighbor_type]):
+ cap_dynamic = False
+ for afi in ['ipv4-unicast', 'ipv6-unicast']:
+ afi_path = bgp_base + [neighbor_type, neighbor, 'address-family', afi, 'capability', 'dynamic']
+ if config.exists(afi_path):
+ cap_dynamic = True
+ config.delete(afi_path)
+
+ # We have now successfully migrated the address-family specific
+ # dynamic capability to the neighbor/peer-group level. If this
+ # has been the only option under the address-family nodes, we
+ # can clean them up by checking if no other nodes are left under
+ # that tree and if so, delete the parent.
+ #
+ # We walk from the most inner node to the most outer one.
+ cleanup = -1
+ while len(config.list_nodes(afi_path[:cleanup])) == 0:
+ config.delete(afi_path[:cleanup])
+ cleanup -= 1
+
+ if cap_dynamic:
+ config.set(bgp_base + [neighbor_type, neighbor, 'capability', 'dynamic'])
+
+try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+except OSError as e:
+ print("Failed to save the modified config: {}".format(e))
+ sys.exit(1)
diff --git a/src/migration-scripts/rpki/0-to-1 b/src/migration-scripts/rpki/0-to-1
new file mode 100755
index 000000000..9058af016
--- /dev/null
+++ b/src/migration-scripts/rpki/0-to-1
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from sys import exit
+from sys import argv
+from vyos.configtree import ConfigTree
+
+if (len(argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+file_name = argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+base = ['protocols', 'rpki']
+config = ConfigTree(config_file)
+
+# Nothing to do
+if not config.exists(base):
+ exit(0)
+
+if config.exists(base + ['cache']):
+ preference = 1
+ for cache in config.list_nodes(base + ['cache']):
+ address_node = base + ['cache', cache, 'address']
+ if config.exists(address_node):
+ address = config.return_value(address_node)
+ # We do not longer support the address leafNode, RPKI cache server
+ # IP address is now used from the tagNode
+ config.delete(address_node)
+ # VyOS 1.2 had no per instance preference, setting new defaults
+ config.set(base + ['cache', cache, 'preference'], value=preference)
+ # Increase preference for the next caching peer - actually VyOS 1.2
+ # supported only one but better save then sorry (T3253)
+ preference += 1
+ config.rename(base + ['cache', cache], address)
+
+try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+except OSError as e:
+ print("Failed to save the modified config: {}".format(e))
+ exit(1)