summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/dhcp-server/kea-dhcp6.conf.j24
-rw-r--r--data/templates/frr/bgpd.frr.j26
-rw-r--r--data/templates/ipsec/swanctl/peer.j26
-rw-r--r--interface-definitions/include/bgp/afi-nexthop-vpn-export.xml.i32
-rw-r--r--interface-definitions/include/bgp/afi-sid.xml.i36
-rw-r--r--interface-definitions/include/bgp/protocol-common-config.xml.i4
-rw-r--r--interface-definitions/include/dhcp/option-v6.xml.i110
-rw-r--r--interface-definitions/include/version/ipsec-version.xml.i2
-rw-r--r--interface-definitions/service_dhcpv6-server.xml.in144
-rw-r--r--interface-definitions/vpn_ipsec.xml.in6
-rw-r--r--python/vyos/kea.py43
-rw-r--r--python/vyos/template.py7
-rw-r--r--smoketest/config-tests/bgp-medium-confederation73
-rw-r--r--smoketest/configs/basic-vyos7
-rw-r--r--smoketest/configs/bgp-azure-ipsec-gateway25
-rw-r--r--smoketest/configs/bgp-medium-confederation247
-rw-r--r--smoketest/configs/ospf-small95
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_bgp.py29
-rwxr-xr-xsmoketest/scripts/cli/test_service_dhcpv6-server.py26
-rwxr-xr-xsrc/conf_mode/protocols_bgp.py9
-rwxr-xr-xsrc/conf_mode/service_dhcpv6-server.py44
-rw-r--r--src/etc/dhcp/dhclient-exit-hooks.d/03-vyos-dhclient-hook1
-rwxr-xr-xsrc/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook4
-rwxr-xr-xsrc/migration-scripts/bgp/0-to-12
-rwxr-xr-xsrc/migration-scripts/bgp/1-to-212
-rwxr-xr-xsrc/migration-scripts/dhcpv6-server/3-to-435
-rwxr-xr-xsrc/migration-scripts/ipsec/12-to-1352
-rwxr-xr-xsrc/migration-scripts/nat/5-to-65
-rwxr-xr-xsrc/migration-scripts/ospf/0-to-14
-rwxr-xr-xsrc/op_mode/dhcp.py9
-rwxr-xr-xsrc/op_mode/powerctrl.py4
31 files changed, 846 insertions, 237 deletions
diff --git a/data/templates/dhcp-server/kea-dhcp6.conf.j2 b/data/templates/dhcp-server/kea-dhcp6.conf.j2
index 3ce4e6370..3ab21551b 100644
--- a/data/templates/dhcp-server/kea-dhcp6.conf.j2
+++ b/data/templates/dhcp-server/kea-dhcp6.conf.j2
@@ -1,7 +1,11 @@
{
"Dhcp6": {
"interfaces-config": {
+{% if listen_interface is vyos_defined %}
+ "interfaces": {{ listen_interface | tojson }},
+{% else %}
"interfaces": [ "*" ],
+{% endif %}
"service-sockets-max-retries": 5,
"service-sockets-retry-wait-time": 5000
},
diff --git a/data/templates/frr/bgpd.frr.j2 b/data/templates/frr/bgpd.frr.j2
index 679ba8b04..e02fdd1bb 100644
--- a/data/templates/frr/bgpd.frr.j2
+++ b/data/templates/frr/bgpd.frr.j2
@@ -402,6 +402,9 @@ router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
{% if afi_config.flooding.head_end_replication is vyos_defined %}
flooding head-end-replication
{% endif %}
+{% if afi_config.nexthop.vpn.export is vyos_defined %}
+ nexthop vpn export {{ afi_config.nexthop.vpn.export }}
+{% endif %}
{% if afi_config.rd.vpn.export is vyos_defined %}
rd vpn export {{ afi_config.rd.vpn.export }}
{% endif %}
@@ -436,6 +439,9 @@ router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
{% if afi_config.route_map.vpn.import is vyos_defined %}
route-map vpn import {{ afi_config.route_map.vpn.import }}
{% endif %}
+{% if afi_config.sid.vpn.export is vyos_defined %}
+ sid vpn export {{ afi_config.sid.vpn.export }}
+{% endif %}
{% if afi_config.vni is vyos_defined %}
{% for vni, vni_config in afi_config.vni.items() %}
vni {{ vni }}
diff --git a/data/templates/ipsec/swanctl/peer.j2 b/data/templates/ipsec/swanctl/peer.j2
index 9d95271fe..86a44a0ff 100644
--- a/data/templates/ipsec/swanctl/peer.j2
+++ b/data/templates/ipsec/swanctl/peer.j2
@@ -83,8 +83,7 @@
start_action = none
{% endif %}
{% if ike.dead_peer_detection is vyos_defined %}
-{% set dpd_translate = {'clear': 'clear', 'hold': 'trap', 'restart': 'restart'} %}
- dpd_action = {{ dpd_translate[ike.dead_peer_detection.action] }}
+ dpd_action = {{ ike.dead_peer_detection.action }}
{% endif %}
close_action = {{ {'none': 'none', 'hold': 'trap', 'restart': 'start'}[ike.close_action] }}
}
@@ -134,8 +133,7 @@
start_action = none
{% endif %}
{% if ike.dead_peer_detection is vyos_defined %}
-{% set dpd_translate = {'clear': 'clear', 'hold': 'trap', 'restart': 'restart'} %}
- dpd_action = {{ dpd_translate[ike.dead_peer_detection.action] }}
+ dpd_action = {{ ike.dead_peer_detection.action }}
{% endif %}
close_action = {{ {'none': 'none', 'hold': 'trap', 'restart': 'start'}[ike.close_action] }}
{% if peer_conf.vti.bind is vyos_defined %}
diff --git a/interface-definitions/include/bgp/afi-nexthop-vpn-export.xml.i b/interface-definitions/include/bgp/afi-nexthop-vpn-export.xml.i
new file mode 100644
index 000000000..d90597f37
--- /dev/null
+++ b/interface-definitions/include/bgp/afi-nexthop-vpn-export.xml.i
@@ -0,0 +1,32 @@
+<!-- include start from bgp/afi-nexthop-vpn-export.xml.i -->
+<node name="nexthop">
+ <properties>
+ <help>Specify next hop to use for VRF advertised prefixes</help>
+ </properties>
+ <children>
+ <node name="vpn">
+ <properties>
+ <help>Between current address-family and vpn</help>
+ </properties>
+ <children>
+ <leafNode name="export">
+ <properties>
+ <help>For routes leaked from current address-family to vpn</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>BGP neighbor IP address</description>
+ </valueHelp>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>BGP neighbor IPv6 address</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ip-address"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+</node>
+ <!-- include end -->
diff --git a/interface-definitions/include/bgp/afi-sid.xml.i b/interface-definitions/include/bgp/afi-sid.xml.i
new file mode 100644
index 000000000..38a3dcf9b
--- /dev/null
+++ b/interface-definitions/include/bgp/afi-sid.xml.i
@@ -0,0 +1,36 @@
+<!-- include start from bgp/sid.xml.i -->
+<node name="sid">
+ <properties>
+ <help>SID value for VRF</help>
+ </properties>
+ <children>
+ <node name="vpn">
+ <properties>
+ <help>Between current VRF and VPN</help>
+ </properties>
+ <children>
+ <leafNode name="export">
+ <properties>
+ <help>For routes leaked from current VRF to VPN</help>
+ <completionHelp>
+ <list>auto</list>
+ </completionHelp>
+ <valueHelp>
+ <format>u32:1-1048575</format>
+ <description>SID allocation index</description>
+ </valueHelp>
+ <valueHelp>
+ <format>auto</format>
+ <description>Automatically assign a label</description>
+ </valueHelp>
+ <constraint>
+ <regex>auto</regex>
+ <validator name="numeric" argument="--range 1-1048575"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ <!-- include end -->
diff --git a/interface-definitions/include/bgp/protocol-common-config.xml.i b/interface-definitions/include/bgp/protocol-common-config.xml.i
index bb35efe94..9895b025c 100644
--- a/interface-definitions/include/bgp/protocol-common-config.xml.i
+++ b/interface-definitions/include/bgp/protocol-common-config.xml.i
@@ -120,6 +120,7 @@
#include <include/bgp/afi-rd.xml.i>
#include <include/bgp/afi-route-map-vpn.xml.i>
#include <include/bgp/afi-route-target-vpn.xml.i>
+ #include <include/bgp/afi-nexthop-vpn-export.xml.i>
<node name="redistribute">
<properties>
<help>Redistribute routes from other protocols into BGP</help>
@@ -188,6 +189,7 @@
</leafNode>
</children>
</node>
+ #include <include/bgp/afi-sid.xml.i>
</children>
</node>
<node name="ipv4-multicast">
@@ -495,6 +497,7 @@
#include <include/bgp/afi-rd.xml.i>
#include <include/bgp/afi-route-map-vpn.xml.i>
#include <include/bgp/afi-route-target-vpn.xml.i>
+ #include <include/bgp/afi-nexthop-vpn-export.xml.i>
<node name="redistribute">
<properties>
<help>Redistribute routes from other protocols into BGP</help>
@@ -555,6 +558,7 @@
</leafNode>
</children>
</node>
+ #include <include/bgp/afi-sid.xml.i>
</children>
</node>
<node name="ipv6-multicast">
diff --git a/interface-definitions/include/dhcp/option-v6.xml.i b/interface-definitions/include/dhcp/option-v6.xml.i
new file mode 100644
index 000000000..1df0c3934
--- /dev/null
+++ b/interface-definitions/include/dhcp/option-v6.xml.i
@@ -0,0 +1,110 @@
+<!-- include start from dhcp/option-v6.xml.i -->
+<node name="option">
+ <properties>
+ <help>DHCPv6 option</help>
+ </properties>
+ <children>
+ #include <include/dhcp/captive-portal.xml.i>
+ #include <include/dhcp/domain-search.xml.i>
+ #include <include/name-server-ipv6.xml.i>
+ <leafNode name="nis-domain">
+ <properties>
+ <help>NIS domain name for client to use</help>
+ <constraint>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
+ </constraint>
+ <constraintErrorMessage>Invalid NIS domain name</constraintErrorMessage>
+ </properties>
+ </leafNode>
+ <leafNode name="nis-server">
+ <properties>
+ <help>IPv6 address of a NIS Server</help>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>IPv6 address of NIS server</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv6-address"/>
+ </constraint>
+ <multi/>
+ </properties>
+ </leafNode>
+ <leafNode name="nisplus-domain">
+ <properties>
+ <help>NIS+ domain name for client to use</help>
+ <constraint>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
+ </constraint>
+ <constraintErrorMessage>Invalid NIS+ domain name. May only contain letters, numbers and .-_</constraintErrorMessage>
+ </properties>
+ </leafNode>
+ <leafNode name="nisplus-server">
+ <properties>
+ <help>IPv6 address of a NIS+ Server</help>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>IPv6 address of NIS+ server</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv6-address"/>
+ </constraint>
+ <multi/>
+ </properties>
+ </leafNode>
+ <leafNode name="sip-server">
+ <properties>
+ <help>IPv6 address of SIP server</help>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>IPv6 address of SIP server</description>
+ </valueHelp>
+ <valueHelp>
+ <format>hostname</format>
+ <description>FQDN of SIP server</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv6-address"/>
+ <validator name="fqdn"/>
+ </constraint>
+ <multi/>
+ </properties>
+ </leafNode>
+ <leafNode name="sntp-server">
+ <properties>
+ <help>IPv6 address of an SNTP server for client to use</help>
+ <constraint>
+ <validator name="ipv6-address"/>
+ </constraint>
+ <multi/>
+ </properties>
+ </leafNode>
+ <node name="vendor-option">
+ <properties>
+ <help>Vendor Specific Options</help>
+ </properties>
+ <children>
+ <node name="cisco">
+ <properties>
+ <help>Cisco specific parameters</help>
+ </properties>
+ <children>
+ <leafNode name="tftp-server">
+ <properties>
+ <help>TFTP server name</help>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>TFTP server IPv6 address</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv6-address"/>
+ </constraint>
+ <multi/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/version/ipsec-version.xml.i b/interface-definitions/include/version/ipsec-version.xml.i
index de7a9c088..a4d556cfc 100644
--- a/interface-definitions/include/version/ipsec-version.xml.i
+++ b/interface-definitions/include/version/ipsec-version.xml.i
@@ -1,3 +1,3 @@
<!-- include start from include/version/ipsec-version.xml.i -->
-<syntaxVersion component='ipsec' version='12'></syntaxVersion>
+<syntaxVersion component='ipsec' version='13'></syntaxVersion>
<!-- include end -->
diff --git a/interface-definitions/service_dhcpv6-server.xml.in b/interface-definitions/service_dhcpv6-server.xml.in
index 6934ceeec..07cbfc85d 100644
--- a/interface-definitions/service_dhcpv6-server.xml.in
+++ b/interface-definitions/service_dhcpv6-server.xml.in
@@ -9,6 +9,7 @@
</properties>
<children>
#include <include/generic-disable-node.xml.i>
+ #include <include/listen-interface-multi-broadcast.xml.i>
<node name="global-parameters">
<properties>
<help>Additional global parameters for DHCPv6 server</help>
@@ -89,11 +90,17 @@
</constraint>
</properties>
<children>
- <node name="address-range">
+ #include <include/dhcp/option-v6.xml.i>
+ <tagNode name="range">
<properties>
<help>Parameters setting ranges for assigning IPv6 addresses</help>
+ <constraint>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
+ </constraint>
+ <constraintErrorMessage>Invalid range name, may only be alphanumeric, dot and hyphen</constraintErrorMessage>
</properties>
<children>
+ #include <include/dhcp/option-v6.xml.i>
<leafNode name="prefix">
<properties>
<help>IPv6 prefix defining range of addresses to assign</help>
@@ -104,10 +111,9 @@
<constraint>
<validator name="ipv6-prefix"/>
</constraint>
- <multi/>
</properties>
</leafNode>
- <tagNode name="start">
+ <leafNode name="start">
<properties>
<help>First in range of consecutive IPv6 addresses to assign</help>
<valueHelp>
@@ -118,25 +124,21 @@
<validator name="ipv6-address"/>
</constraint>
</properties>
- <children>
- <leafNode name="stop">
- <properties>
- <help>Last in range of consecutive IPv6 addresses</help>
- <valueHelp>
- <format>ipv6</format>
- <description>IPv6 address</description>
- </valueHelp>
- <constraint>
- <validator name="ipv6-address"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </tagNode>
+ </leafNode>
+ <leafNode name="stop">
+ <properties>
+ <help>Last in range of consecutive IPv6 addresses</help>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>IPv6 address</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv6-address"/>
+ </constraint>
+ </properties>
+ </leafNode>
</children>
- </node>
- #include <include/dhcp/captive-portal.xml.i>
- #include <include/dhcp/domain-search.xml.i>
+ </tagNode>
<node name="lease-time">
<properties>
<help>Parameters relating to the lease time</help>
@@ -180,51 +182,6 @@
</leafNode>
</children>
</node>
- #include <include/name-server-ipv6.xml.i>
- <leafNode name="nis-domain">
- <properties>
- <help>NIS domain name for client to use</help>
- <constraint>
- #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
- </constraint>
- <constraintErrorMessage>Invalid NIS domain name</constraintErrorMessage>
- </properties>
- </leafNode>
- <leafNode name="nis-server">
- <properties>
- <help>IPv6 address of a NIS Server</help>
- <valueHelp>
- <format>ipv6</format>
- <description>IPv6 address of NIS server</description>
- </valueHelp>
- <constraint>
- <validator name="ipv6-address"/>
- </constraint>
- <multi/>
- </properties>
- </leafNode>
- <leafNode name="nisplus-domain">
- <properties>
- <help>NIS+ domain name for client to use</help>
- <constraint>
- #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
- </constraint>
- <constraintErrorMessage>Invalid NIS+ domain name. May only contain letters, numbers and .-_</constraintErrorMessage>
- </properties>
- </leafNode>
- <leafNode name="nisplus-server">
- <properties>
- <help>IPv6 address of a NIS+ Server</help>
- <valueHelp>
- <format>ipv6</format>
- <description>IPv6 address of NIS+ server</description>
- </valueHelp>
- <constraint>
- <validator name="ipv6-address"/>
- </constraint>
- <multi/>
- </properties>
- </leafNode>
<node name="prefix-delegation">
<properties>
<help>Parameters relating to IPv6 prefix delegation</help>
@@ -272,33 +229,6 @@
</tagNode>
</children>
</node>
- <leafNode name="sip-server">
- <properties>
- <help>IPv6 address of SIP server</help>
- <valueHelp>
- <format>ipv6</format>
- <description>IPv6 address of SIP server</description>
- </valueHelp>
- <valueHelp>
- <format>hostname</format>
- <description>FQDN of SIP server</description>
- </valueHelp>
- <constraint>
- <validator name="ipv6-address"/>
- <validator name="fqdn"/>
- </constraint>
- <multi/>
- </properties>
- </leafNode>
- <leafNode name="sntp-server">
- <properties>
- <help>IPv6 address of an SNTP server for client to use</help>
- <constraint>
- <validator name="ipv6-address"/>
- </constraint>
- <multi/>
- </properties>
- </leafNode>
<tagNode name="static-mapping">
<properties>
<help>Hostname for static mapping reservation</help>
@@ -308,6 +238,7 @@
<constraintErrorMessage>Invalid static mapping hostname</constraintErrorMessage>
</properties>
<children>
+ #include <include/dhcp/option-v6.xml.i>
#include <include/generic-disable-node.xml.i>
#include <include/interface/mac.xml.i>
#include <include/interface/duid.xml.i>
@@ -349,33 +280,6 @@
</constraint>
</properties>
</leafNode>
- <node name="vendor-option">
- <properties>
- <help>Vendor Specific Options</help>
- </properties>
- <children>
- <node name="cisco">
- <properties>
- <help>Cisco specific parameters</help>
- </properties>
- <children>
- <leafNode name="tftp-server">
- <properties>
- <help>TFTP server name</help>
- <valueHelp>
- <format>ipv6</format>
- <description>TFTP server IPv6 address</description>
- </valueHelp>
- <constraint>
- <validator name="ipv6-address"/>
- </constraint>
- <multi/>
- </properties>
- </leafNode>
- </children>
- </node>
- </children>
- </node>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/vpn_ipsec.xml.in b/interface-definitions/vpn_ipsec.xml.in
index 1847401b5..76c71949f 100644
--- a/interface-definitions/vpn_ipsec.xml.in
+++ b/interface-definitions/vpn_ipsec.xml.in
@@ -280,10 +280,10 @@
<properties>
<help>Keep-alive failure action</help>
<completionHelp>
- <list>hold clear restart</list>
+ <list>trap clear restart</list>
</completionHelp>
<valueHelp>
- <format>hold</format>
+ <format>trap</format>
<description>Attempt to re-negotiate the connection when matching traffic is seen</description>
</valueHelp>
<valueHelp>
@@ -295,7 +295,7 @@
<description>Attempt to re-negotiate the connection immediately</description>
</valueHelp>
<constraint>
- <regex>(hold|clear|restart)</regex>
+ <regex>(trap|clear|restart)</regex>
</constraint>
</properties>
<defaultValue>clear</defaultValue>
diff --git a/python/vyos/kea.py b/python/vyos/kea.py
index aa4fb7ae5..fb5afc2ce 100644
--- a/python/vyos/kea.py
+++ b/python/vyos/kea.py
@@ -175,16 +175,6 @@ def kea_parse_subnet(subnet, config):
def kea6_parse_options(config):
options = []
- if 'common_options' in config:
- common_opt = config['common_options']
-
- for node, option_name in kea6_options.items():
- if node not in common_opt:
- continue
-
- value = ", ".join(common_opt[node]) if isinstance(common_opt[node], list) else common_opt[node]
- options.append({'name': option_name, 'data': value})
-
for node, option_name in kea6_options.items():
if node not in config:
continue
@@ -218,20 +208,27 @@ def kea6_parse_options(config):
def kea6_parse_subnet(subnet, config):
out = {'subnet': subnet, 'id': int(config['subnet_id'])}
- options = kea6_parse_options(config)
- if 'address_range' in config:
- addr_range = config['address_range']
+ if 'option' in config:
+ out['option-data'] = kea6_parse_options(config['option'])
+
+ if 'range' in config:
pools = []
+ for num, range_config in config['range'].items():
+ pool = {}
- if 'prefix' in addr_range:
- for prefix in addr_range['prefix']:
- pools.append({'pool': prefix})
+ if 'prefix' in range_config:
+ pool['pool'] = range_config['prefix']
- if 'start' in addr_range:
- for start, range_conf in addr_range['start'].items():
- stop = range_conf['stop']
- pools.append({'pool': f'{start} - {stop}'})
+ if 'start' in range_config:
+ start = range_config['start']
+ stop = range_config['stop']
+ pool['pool'] = f'{start} - {stop}'
+
+ if 'option' in range_config:
+ pool['option-data'] = kea6_parse_options(range_config['option'])
+
+ pools.append(pool)
out['pools'] = pools
@@ -278,13 +275,13 @@ def kea6_parse_subnet(subnet, config):
if 'ipv6_prefix' in host_config:
reservation['prefixes'] = [ host_config['ipv6_prefix'] ]
+ if 'option' in host_config:
+ reservation['option-data'] = kea6_parse_options(host_config['option'])
+
reservations.append(reservation)
out['reservations'] = reservations
- if options:
- out['option-data'] = options
-
return out
def kea_parse_leases(lease_path):
diff --git a/python/vyos/template.py b/python/vyos/template.py
index 1368f1f61..456239568 100644
--- a/python/vyos/template.py
+++ b/python/vyos/template.py
@@ -894,7 +894,9 @@ def kea6_shared_network_json(shared_networks):
'name': name,
'subnet6': []
}
- options = kea6_parse_options(config)
+
+ if 'common_options' in config:
+ network['option-data'] = kea6_parse_options(config['common_options'])
if 'interface' in config:
network['interface'] = config['interface']
@@ -903,9 +905,6 @@ def kea6_shared_network_json(shared_networks):
for subnet, subnet_config in config['subnet'].items():
network['subnet6'].append(kea6_parse_subnet(subnet, subnet_config))
- if options:
- network['option-data'] = options
-
out.append(network)
return dumps(out, indent=4)
diff --git a/smoketest/config-tests/bgp-medium-confederation b/smoketest/config-tests/bgp-medium-confederation
new file mode 100644
index 000000000..ea3c2d144
--- /dev/null
+++ b/smoketest/config-tests/bgp-medium-confederation
@@ -0,0 +1,73 @@
+set interfaces dummy dum0 address '1.1.1.1/32'
+set interfaces dummy dum0 address '2001:db8::1/128'
+set interfaces ethernet eth0 address 'fd52:100:200:fffe::1/64'
+set interfaces ethernet eth0 address '192.168.253.1/24'
+set interfaces ethernet eth1
+set interfaces ethernet eth2
+set policy route-map BGP-IN rule 10 action 'permit'
+set policy route-map BGP-OUT rule 10 action 'permit'
+set policy route-map BGP-REDISTRIBUTE rule 10 action 'deny'
+set policy route-map DEFAULT-ZEBRA-IN rule 10 action 'deny'
+set protocols bgp address-family ipv4-unicast redistribute connected route-map 'BGP-REDISTRIBUTE'
+set protocols bgp address-family ipv4-unicast redistribute static route-map 'BGP-REDISTRIBUTE'
+set protocols bgp address-family ipv6-unicast redistribute connected route-map 'BGP-REDISTRIBUTE'
+set protocols bgp neighbor 192.168.253.14 peer-group 'WDC07'
+set protocols bgp neighbor 192.168.253.16 peer-group 'WDC07'
+set protocols bgp neighbor 192.168.253.17 peer-group 'WDC07'
+set protocols bgp neighbor 192.168.253.18 peer-group 'WDC07'
+set protocols bgp neighbor 192.168.253.19 peer-group 'WDC07'
+set protocols bgp neighbor eth1 interface v6only peer-group 'BACKBONE'
+set protocols bgp neighbor eth1 interface v6only remote-as '666'
+set protocols bgp neighbor eth2 interface v6only peer-group 'BACKBONE'
+set protocols bgp neighbor eth2 interface v6only remote-as '666'
+set protocols bgp neighbor fd52:100:200:fffe::14 address-family ipv6-unicast
+set protocols bgp neighbor fd52:100:200:fffe::14 peer-group 'WDC07v6'
+set protocols bgp neighbor fd52:100:200:fffe::16 address-family ipv6-unicast
+set protocols bgp neighbor fd52:100:200:fffe::16 peer-group 'WDC07v6'
+set protocols bgp neighbor fd52:100:200:fffe::17 address-family ipv6-unicast
+set protocols bgp neighbor fd52:100:200:fffe::17 peer-group 'WDC07v6'
+set protocols bgp neighbor fd52:100:200:fffe::18 address-family ipv6-unicast
+set protocols bgp neighbor fd52:100:200:fffe::18 peer-group 'WDC07v6'
+set protocols bgp neighbor fd52:100:200:fffe::19 address-family ipv6-unicast
+set protocols bgp neighbor fd52:100:200:fffe::19 peer-group 'WDC07v6'
+set protocols bgp parameters bestpath as-path confed
+set protocols bgp parameters bestpath as-path multipath-relax
+set protocols bgp parameters confederation identifier '696'
+set protocols bgp parameters confederation peers '668'
+set protocols bgp parameters confederation peers '669'
+set protocols bgp parameters confederation peers '666'
+set protocols bgp parameters graceful-restart
+set protocols bgp parameters router-id '192.168.253.15'
+set protocols bgp peer-group BACKBONE address-family ipv4-unicast nexthop-self
+set protocols bgp peer-group BACKBONE address-family ipv4-unicast route-map export 'BGP-OUT'
+set protocols bgp peer-group BACKBONE address-family ipv4-unicast route-map import 'BGP-IN'
+set protocols bgp peer-group BACKBONE address-family ipv4-unicast soft-reconfiguration inbound
+set protocols bgp peer-group BACKBONE address-family ipv6-unicast nexthop-self
+set protocols bgp peer-group BACKBONE address-family ipv6-unicast route-map export 'BGP-OUT'
+set protocols bgp peer-group BACKBONE address-family ipv6-unicast route-map import 'BGP-IN'
+set protocols bgp peer-group BACKBONE address-family ipv6-unicast soft-reconfiguration inbound
+set protocols bgp peer-group BACKBONE capability extended-nexthop
+set protocols bgp peer-group WDC07 address-family ipv4-unicast default-originate
+set protocols bgp peer-group WDC07 address-family ipv4-unicast nexthop-self
+set protocols bgp peer-group WDC07 address-family ipv4-unicast route-map export 'BGP-OUT'
+set protocols bgp peer-group WDC07 address-family ipv4-unicast route-map import 'BGP-IN'
+set protocols bgp peer-group WDC07 address-family ipv4-unicast soft-reconfiguration inbound
+set protocols bgp peer-group WDC07 remote-as '670'
+set protocols bgp peer-group WDC07 update-source 'dum0'
+set protocols bgp peer-group WDC07v6 address-family ipv6-unicast default-originate
+set protocols bgp peer-group WDC07v6 address-family ipv6-unicast nexthop-self
+set protocols bgp peer-group WDC07v6 address-family ipv6-unicast route-map export 'BGP-OUT'
+set protocols bgp peer-group WDC07v6 address-family ipv6-unicast route-map import 'BGP-IN'
+set protocols bgp peer-group WDC07v6 address-family ipv6-unicast soft-reconfiguration inbound
+set protocols bgp peer-group WDC07v6 remote-as '670'
+set protocols bgp peer-group WDC07v6 update-source 'dum0'
+set protocols bgp system-as '670'
+set system config-management commit-revisions '200'
+set system console device ttyS0 speed '115200'
+set system domain-name 'vyos.net'
+set system host-name 'vyos'
+set system ip protocol bgp route-map 'DEFAULT-ZEBRA-IN'
+set system login user vyos authentication encrypted-password '$6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0'
+set system login user vyos authentication plaintext-password ''
+set system syslog global facility all level 'notice'
+set system syslog global facility local7 level 'debug'
diff --git a/smoketest/configs/basic-vyos b/smoketest/configs/basic-vyos
index fca4964bf..c42f14841 100644
--- a/smoketest/configs/basic-vyos
+++ b/smoketest/configs/basic-vyos
@@ -95,10 +95,15 @@ service {
shared-network-name LAN6 {
subnet fe88::/56 {
address-range {
- prefix fe88::/56 {
+ prefix fe88::/60 {
temporary
}
+ start fe88:0000:0000:fe:: {
+ stop fe88:0000:0000:ff::
+ }
}
+ domain-search vyos.net
+ name-server fe88::1
prefix-delegation {
start fe88:0000:0000:0001:: {
prefix-length 64
diff --git a/smoketest/configs/bgp-azure-ipsec-gateway b/smoketest/configs/bgp-azure-ipsec-gateway
index ddcd459ae..5803e8ce9 100644
--- a/smoketest/configs/bgp-azure-ipsec-gateway
+++ b/smoketest/configs/bgp-azure-ipsec-gateway
@@ -226,6 +226,31 @@ protocols {
}
}
service {
+ snmp {
+ v3 {
+ engineid 0xff42
+ group default {
+ mode ro
+ seclevel priv
+ view default
+ }
+ user VyOS {
+ auth {
+ encrypted-key 0x1ad73f4620b8c0dd2de066622f875b161a14adad
+ type sha
+ }
+ group default
+ privacy {
+ encrypted-key 0x1ad73f4620b8c0dd2de066622f875b16
+ type aes
+ }
+ }
+ view default {
+ oid 1 {
+ }
+ }
+ }
+ }
ssh {
disable-host-validation
port 22
diff --git a/smoketest/configs/bgp-medium-confederation b/smoketest/configs/bgp-medium-confederation
new file mode 100644
index 000000000..dfb944d09
--- /dev/null
+++ b/smoketest/configs/bgp-medium-confederation
@@ -0,0 +1,247 @@
+interfaces {
+ dummy dum0 {
+ address 1.1.1.1/32
+ address 2001:db8::1/128
+ }
+ ethernet eth0 {
+ address 192.168.253.1/24
+ address fd52:100:200:fffe::1/64
+ }
+ ethernet eth1 {
+ }
+ ethernet eth2 {
+ }
+}
+policy {
+ route-map BGP-IN {
+ rule 10 {
+ action permit
+ }
+ }
+ route-map BGP-OUT {
+ rule 10 {
+ action permit
+ }
+ }
+ route-map BGP-REDISTRIBUTE {
+ rule 10 {
+ action deny
+ }
+ }
+ route-map DEFAULT-ZEBRA-IN {
+ rule 10 {
+ action deny
+ }
+ }
+}
+protocols {
+ bgp 670 {
+ address-family {
+ ipv4-unicast {
+ redistribute {
+ connected {
+ route-map BGP-REDISTRIBUTE
+ }
+ static {
+ route-map BGP-REDISTRIBUTE
+ }
+ }
+ }
+ ipv6-unicast {
+ redistribute {
+ connected {
+ route-map BGP-REDISTRIBUTE
+ }
+ }
+ }
+ }
+ neighbor 192.168.253.14 {
+ peer-group WDC07
+ }
+ neighbor 192.168.253.16 {
+ peer-group WDC07
+ }
+ neighbor 192.168.253.17 {
+ peer-group WDC07
+ }
+ neighbor 192.168.253.18 {
+ peer-group WDC07
+ }
+ neighbor 192.168.253.19 {
+ peer-group WDC07
+ }
+ neighbor eth1 {
+ interface {
+ v6only {
+ peer-group BACKBONE
+ remote-as 666
+ }
+ }
+ }
+ neighbor eth2 {
+ interface {
+ v6only {
+ peer-group BACKBONE
+ remote-as 666
+ }
+ }
+ }
+ neighbor fd52:100:200:fffe::14 {
+ address-family {
+ ipv6-unicast {
+ peer-group WDC07v6
+ }
+ }
+ }
+ neighbor fd52:100:200:fffe::16 {
+ address-family {
+ ipv6-unicast {
+ peer-group WDC07v6
+ }
+ }
+ }
+ neighbor fd52:100:200:fffe::17 {
+ address-family {
+ ipv6-unicast {
+ peer-group WDC07v6
+ }
+ }
+ }
+ neighbor fd52:100:200:fffe::18 {
+ address-family {
+ ipv6-unicast {
+ peer-group WDC07v6
+ }
+ }
+ }
+ neighbor fd52:100:200:fffe::19 {
+ address-family {
+ ipv6-unicast {
+ peer-group WDC07v6
+ }
+ }
+ }
+ parameters {
+ bestpath {
+ as-path {
+ confed
+ multipath-relax
+ }
+ }
+ confederation {
+ identifier 696
+ peers 668
+ peers 669
+ peers 666
+ }
+ default {
+ no-ipv4-unicast
+ }
+ graceful-restart {
+ }
+ router-id 192.168.253.15
+ }
+ peer-group BACKBONE {
+ address-family {
+ ipv4-unicast {
+ nexthop-self {
+ }
+ route-map {
+ export BGP-OUT
+ import BGP-IN
+ }
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ ipv6-unicast {
+ nexthop-self {
+ }
+ route-map {
+ export BGP-OUT
+ import BGP-IN
+ }
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ }
+ capability {
+ extended-nexthop
+ }
+ }
+ peer-group WDC07 {
+ address-family {
+ ipv4-unicast {
+ default-originate {
+ }
+ nexthop-self {
+ }
+ route-map {
+ export BGP-OUT
+ import BGP-IN
+ }
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ }
+ remote-as 670
+ update-source dum0
+ }
+ peer-group WDC07v6 {
+ address-family {
+ ipv6-unicast {
+ default-originate {
+ }
+ nexthop-self {
+ }
+ route-map {
+ export BGP-OUT
+ import BGP-IN
+ }
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ }
+ remote-as 670
+ update-source dum0
+ }
+ route-map DEFAULT-ZEBRA-IN
+ }
+}
+system {
+ config-management {
+ commit-revisions 200
+ }
+ console {
+ device ttyS0 {
+ speed 115200
+ }
+ }
+ domain-name vyos.net
+ host-name vyos
+ login {
+ user vyos {
+ authentication {
+ encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0
+ plaintext-password ""
+ }
+ }
+ }
+ syslog {
+ global {
+ facility all {
+ level notice
+ }
+ facility protocols {
+ level debug
+ }
+ }
+ }
+}
+
+// Warning: Do not remove the following line.
+// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@3:conntrack-sync@2:container@1:dhcp-relay@2:dhcp-server@6:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@22:ipoe-server@1:ipsec@5:isis@1:l2tp@3:lldp@1:mdns@1:nat@5:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@8:rpki@1:salt@1:snmp@2:ssh@2:sstp@3:system@21:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2:zone-policy@1"
+// Release version: 1.3.5
diff --git a/smoketest/configs/ospf-small b/smoketest/configs/ospf-small
index b3002b1af..c55627b77 100644
--- a/smoketest/configs/ospf-small
+++ b/smoketest/configs/ospf-small
@@ -1,13 +1,63 @@
interfaces {
dummy dum0 {
- address 172.18.254.201/32
+ address 172.18.254.200/32
}
ethernet eth0 {
duplex auto
smp-affinity auto
speed auto
vif 201 {
- address 172.18.201.10/24
+ address 172.18.201.9/24
+ ip {
+ ospf {
+ authentication {
+ md5 {
+ key-id 10 {
+ md5-key OSPFVyOSNET
+ }
+ }
+ }
+ dead-interval 40
+ hello-interval 10
+ priority 1
+ retransmit-interval 5
+ transmit-delay 1
+ }
+ }
+ ipv6 {
+ ospfv3 {
+ bfd
+ cost 40
+ }
+ }
+ }
+ vif 202 {
+ address 172.18.202.9/24
+ ip {
+ ospf {
+ authentication {
+ md5 {
+ key-id 10 {
+ md5-key OSPFVyOSNET
+ }
+ }
+ }
+ dead-interval 40
+ hello-interval 10
+ priority 1
+ retransmit-interval 5
+ transmit-delay 1
+ }
+ }
+ ipv6 {
+ ospfv3 {
+ bfd
+ cost 40
+ }
+ }
+ }
+ vif 203 {
+ address 172.18.203.9/24
ip {
ospf {
authentication {
@@ -51,48 +101,31 @@ protocols {
ospf {
area 0 {
network 172.18.201.0/24
- network 172.18.254.201/32
+ network 172.18.202.0/24
+ network 172.18.203.0/24
+ network 172.18.254.200/32
}
log-adjacency-changes {
}
parameters {
abr-type cisco
- router-id 172.18.254.201
+ router-id 172.18.254.200
}
passive-interface default
passive-interface-exclude eth0.201
+ passive-interface-exclude eth0.202
+ passive-interface-exclude eth0.203
}
ospfv3 {
area 0.0.0.0 {
- interface eth0
+ interface eth0.201
+ interface eth0.202
+ interface eth0.203
interface eth1
- interface eth2
- }
- }
- static {
- route 0.0.0.0/0 {
- next-hop 172.18.201.254 {
- distance 10
- }
}
}
}
service {
- lldp {
- interface all {
- }
- snmp {
- enable
- }
- }
- snmp {
- community public {
- authorization ro
- network 172.16.100.0/24
- }
- contact "VyOS maintainers and contributors <maintainers@vyos.io>"
- location "Jenkins"
- }
ssh {
disable-host-validation
port 22
@@ -120,11 +153,9 @@ system {
}
name-server 172.16.254.30
ntp {
- server 0.pool.ntp.org {
- }
- server 1.pool.ntp.org {
+ server time1.vyos.net {
}
- server 2.pool.ntp.org {
+ server time2.vyos.net {
}
}
sysctl {
diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py
index d5efae12c..2dbc30a41 100755
--- a/smoketest/scripts/cli/test_protocols_bgp.py
+++ b/smoketest/scripts/cli/test_protocols_bgp.py
@@ -1139,10 +1139,16 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
def test_bgp_24_srv6_sid(self):
locator_name = 'VyOS_foo'
sid = 'auto'
+ nexthop_ipv4 = '192.0.0.1'
+ nexthop_ipv6 = '2001:db8:100:200::2'
self.cli_set(base_path + ['srv6', 'locator', locator_name])
self.cli_set(base_path + ['sid', 'vpn', 'per-vrf', 'export', sid])
-
+ self.cli_set(base_path + ['address-family', 'ipv4-unicast', 'sid', 'vpn', 'export', sid])
+ # verify() - SID per VRF and SID per address-family are mutually exclusive!
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path + ['address-family', 'ipv4-unicast', 'sid'])
self.cli_commit()
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
@@ -1151,6 +1157,27 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
self.assertIn(f' locator {locator_name}', frrconfig)
self.assertIn(f' sid vpn per-vrf export {sid}', frrconfig)
+ # Now test AFI SID
+ self.cli_delete(base_path + ['sid'])
+ self.cli_set(base_path + ['address-family', 'ipv4-unicast', 'sid', 'vpn', 'export', sid])
+ self.cli_set(base_path + ['address-family', 'ipv4-unicast', 'nexthop', 'vpn', 'export', nexthop_ipv4])
+ self.cli_set(base_path + ['address-family', 'ipv6-unicast', 'sid', 'vpn', 'export', sid])
+ self.cli_set(base_path + ['address-family', 'ipv6-unicast', 'nexthop', 'vpn', 'export', nexthop_ipv6])
+
+ self.cli_commit()
+
+ frrconfig = self.getFRRconfig(f'router bgp {ASN}')
+ self.assertIn(f'router bgp {ASN}', frrconfig)
+ self.assertIn(f' segment-routing srv6', frrconfig)
+ self.assertIn(f' locator {locator_name}', frrconfig)
+
+ afiv4_config = self.getFRRconfig(' address-family ipv4 unicast')
+ self.assertIn(f' sid vpn export {sid}', afiv4_config)
+ self.assertIn(f' nexthop vpn export {nexthop_ipv4}', afiv4_config)
+ afiv6_config = self.getFRRconfig(' address-family ipv6 unicast')
+ self.assertIn(f' sid vpn export {sid}', afiv6_config)
+ self.assertIn(f' nexthop vpn export {nexthop_ipv6}', afiv4_config)
+
def test_bgp_25_ipv4_ipv6_labeled_unicast_peer_group(self):
pg_ipv4 = 'foo4'
pg_ipv6 = 'foo6'
diff --git a/smoketest/scripts/cli/test_service_dhcpv6-server.py b/smoketest/scripts/cli/test_service_dhcpv6-server.py
index fcbfeb7be..dcce30f55 100755
--- a/smoketest/scripts/cli/test_service_dhcpv6-server.py
+++ b/smoketest/scripts/cli/test_service_dhcpv6-server.py
@@ -104,24 +104,25 @@ class TestServiceDHCPv6Server(VyOSUnitTestSHIM.TestCase):
self.cli_set(base_path + ['preference', preference])
self.cli_set(pool + ['subnet-id', '1'])
# we use the first subnet IP address as default gateway
- self.cli_set(pool + ['name-server', dns_1])
- self.cli_set(pool + ['name-server', dns_2])
- self.cli_set(pool + ['name-server', dns_2])
self.cli_set(pool + ['lease-time', 'default', lease_time])
self.cli_set(pool + ['lease-time', 'maximum', max_lease_time])
self.cli_set(pool + ['lease-time', 'minimum', min_lease_time])
- self.cli_set(pool + ['nis-domain', domain])
- self.cli_set(pool + ['nisplus-domain', domain])
- self.cli_set(pool + ['sip-server', sip_server])
- self.cli_set(pool + ['sntp-server', sntp_server])
- self.cli_set(pool + ['address-range', 'start', range_start, 'stop', range_stop])
+ self.cli_set(pool + ['option', 'name-server', dns_1])
+ self.cli_set(pool + ['option', 'name-server', dns_2])
+ self.cli_set(pool + ['option', 'name-server', dns_2])
+ self.cli_set(pool + ['option', 'nis-domain', domain])
+ self.cli_set(pool + ['option', 'nisplus-domain', domain])
+ self.cli_set(pool + ['option', 'sip-server', sip_server])
+ self.cli_set(pool + ['option', 'sntp-server', sntp_server])
+ self.cli_set(pool + ['range', '1', 'start', range_start])
+ self.cli_set(pool + ['range', '1', 'stop', range_stop])
for server in nis_servers:
- self.cli_set(pool + ['nis-server', server])
- self.cli_set(pool + ['nisplus-server', server])
+ self.cli_set(pool + ['option', 'nis-server', server])
+ self.cli_set(pool + ['option', 'nisplus-server', server])
for search in search_domains:
- self.cli_set(pool + ['domain-search', search])
+ self.cli_set(pool + ['option', 'domain-search', search])
client_base = 1
for client in ['client1', 'client2', 'client3']:
@@ -217,7 +218,8 @@ class TestServiceDHCPv6Server(VyOSUnitTestSHIM.TestCase):
pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet]
self.cli_set(pool + ['subnet-id', '1'])
- self.cli_set(pool + ['address-range', 'start', range_start, 'stop', range_stop])
+ self.cli_set(pool + ['range', '1', 'start', range_start])
+ self.cli_set(pool + ['range', '1', 'stop', range_stop])
self.cli_set(pool + ['prefix-delegation', 'prefix', delegate_start, 'delegated-length', delegate_len])
self.cli_set(pool + ['prefix-delegation', 'prefix', delegate_start, 'prefix-length', prefix_len])
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index 89e2aab8c..f6f3370c3 100755
--- a/src/conf_mode/protocols_bgp.py
+++ b/src/conf_mode/protocols_bgp.py
@@ -220,9 +220,12 @@ def verify_afi(peer_config, bgp_config):
# If address_family configured under peer-group
# if neighbor interface configured
- peer_group_name = ''
+ peer_group_name = None
if dict_search('interface.peer_group', peer_config):
peer_group_name = peer_config['interface']['peer_group']
+ elif dict_search('interface.v6only.peer_group', peer_config):
+ peer_group_name = peer_config['interface']['v6only']['peer_group']
+
# if neighbor IP configured.
if 'peer_group' in peer_config:
peer_group_name = peer_config['peer_group']
@@ -542,6 +545,10 @@ def verify(bgp):
tmp = dict_search(f'route_map.vpn.{export_import}', afi_config)
if tmp: verify_route_map(tmp, bgp)
+ # per-vrf sid and per-af sid are mutually exclusive
+ if 'sid' in afi_config and 'sid' in bgp:
+ raise ConfigError('SID per VRF and SID per address-family are mutually exclusive!')
+
# Checks only required for L2VPN EVPN
if afi in ['l2vpn_evpn']:
if 'vni' in afi_config:
diff --git a/src/conf_mode/service_dhcpv6-server.py b/src/conf_mode/service_dhcpv6-server.py
index 7cd801cdd..214531904 100755
--- a/src/conf_mode/service_dhcpv6-server.py
+++ b/src/conf_mode/service_dhcpv6-server.py
@@ -81,26 +81,29 @@ def verify(dhcpv6):
subnet_ids.append(subnet_config['subnet_id'])
- if 'address_range' in subnet_config:
- if 'start' in subnet_config['address_range']:
- range6_start = []
- range6_stop = []
- for start, start_config in subnet_config['address_range']['start'].items():
- if 'stop' not in start_config:
- raise ConfigError(f'address-range stop address for start "{start}" is not defined!')
- stop = start_config['stop']
+ if 'range' in subnet_config:
+ range6_start = []
+ range6_stop = []
+
+ for num, range_config in subnet_config['range'].items():
+ if 'start' in range_config:
+ start = range_config['start']
+
+ if 'stop' not in range_config:
+ raise ConfigError(f'Range stop address for start "{start}" is not defined!')
+ stop = range_config['stop']
# Start address must be inside network
if not ip_address(start) in ip_network(subnet):
- raise ConfigError(f'address-range start address "{start}" is not in subnet "{subnet}"!')
+ raise ConfigError(f'Range start address "{start}" is not in subnet "{subnet}"!')
# Stop address must be inside network
if not ip_address(stop) in ip_network(subnet):
- raise ConfigError(f'address-range stop address "{stop}" is not in subnet "{subnet}"!')
+ raise ConfigError(f'Range stop address "{stop}" is not in subnet "{subnet}"!')
# Stop address must be greater or equal to start address
if not ip_address(stop) >= ip_address(start):
- raise ConfigError(f'address-range stop address "{stop}" must be greater then or equal ' \
+ raise ConfigError(f'Range stop address "{stop}" must be greater then or equal ' \
f'to the range start address "{start}"!')
# DHCPv6 range start address must be unique - two ranges can't
@@ -108,6 +111,7 @@ def verify(dhcpv6):
if start in range6_start:
raise ConfigError(f'Conflicting DHCPv6 lease range: '\
f'Pool start address "{start}" defined multipe times!')
+
range6_start.append(start)
# DHCPv6 range stop address must be unique - two ranges can't
@@ -115,12 +119,14 @@ def verify(dhcpv6):
if stop in range6_stop:
raise ConfigError(f'Conflicting DHCPv6 lease range: '\
f'Pool stop address "{stop}" defined multipe times!')
+
range6_stop.append(stop)
- if 'prefix' in subnet_config:
- for prefix in subnet_config['prefix']:
- if ip_network(prefix) not in ip_network(subnet):
- raise ConfigError(f'address-range prefix "{prefix}" is not in subnet "{subnet}""')
+ if 'prefix' in range_config:
+ prefix = range_config['prefix']
+
+ if not ip_network(prefix).subnet_of(ip_network(subnet)):
+ raise ConfigError(f'Range prefix "{prefix}" is not in subnet "{subnet}"')
# Prefix delegation sanity checks
if 'prefix_delegation' in subnet_config:
@@ -151,13 +157,15 @@ def verify(dhcpv6):
raise ConfigError(f'Either MAC address or Client identifier (DUID) is required for '
f'static mapping "{mapping}" within shared-network "{network}, {subnet}"!')
- if 'vendor_option' in subnet_config:
- if len(dict_search('vendor_option.cisco.tftp_server', subnet_config)) > 2:
- raise ConfigError(f'No more then two Cisco tftp-servers should be defined for subnet "{subnet}"!')
+ if 'option' in subnet_config:
+ if 'vendor_option' in subnet_config['option']:
+ if len(dict_search('option.vendor_option.cisco.tftp_server', subnet_config)) > 2:
+ raise ConfigError(f'No more then two Cisco tftp-servers should be defined for subnet "{subnet}"!')
# Subnets must be unique
if subnet in subnets:
raise ConfigError(f'DHCPv6 subnets must be unique! Subnet {subnet} defined multiple times!')
+
subnets.append(subnet)
# DHCPv6 requires at least one configured address range or one static mapping
diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/03-vyos-dhclient-hook b/src/etc/dhcp/dhclient-exit-hooks.d/03-vyos-dhclient-hook
index 35721d009..d5e6462ba 100644
--- a/src/etc/dhcp/dhclient-exit-hooks.d/03-vyos-dhclient-hook
+++ b/src/etc/dhcp/dhclient-exit-hooks.d/03-vyos-dhclient-hook
@@ -29,6 +29,7 @@ fi
if [ "$RUN" = "yes" ]; then
BASE_PATH=$(python3 -c "from vyos.defaults import directories; print(directories['isc_dhclient_dir'])")
+ mkdir -p ${BASE_PATH}
LOG=${BASE_PATH}/dhclient_"$interface"."$proto"lease
echo `date` > $LOG
diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook b/src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook
index c7a92fe26..e6edc1ac3 100755
--- a/src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook
+++ b/src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook
@@ -71,10 +71,6 @@ if __name__ == '__main__':
conf_lines[i] = line.replace(old_ip, new_ip)
found = True
- for i, line in enumerate(secrets_lines):
- if line.find(to_match) > 0:
- secrets_lines[i] = line.replace(old_ip, new_ip)
-
if found:
write_file(SWANCTL_CONF, conf_lines)
ipsec_down(old_ip)
diff --git a/src/migration-scripts/bgp/0-to-1 b/src/migration-scripts/bgp/0-to-1
index 03c45107b..5b8e8a163 100755
--- a/src/migration-scripts/bgp/0-to-1
+++ b/src/migration-scripts/bgp/0-to-1
@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-# T3417: migrate IS-IS tagNode to node as we can only have one IS-IS process
+# T3417: migrate BGP tagNode to node as we can only have one BGP process
from sys import argv
from sys import exit
diff --git a/src/migration-scripts/bgp/1-to-2 b/src/migration-scripts/bgp/1-to-2
index 96b939b47..a40d86e67 100755
--- a/src/migration-scripts/bgp/1-to-2
+++ b/src/migration-scripts/bgp/1-to-2
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2021-2022 VyOS maintainers and contributors
+# Copyright (C) 2021-2024 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# T3741: no-ipv4-unicast is now enabled by default
+# T5937: Migrate IPv6 BGP Neighbor Peer Groups
from sys import argv
from sys import exit
@@ -66,6 +67,15 @@ else:
if not config.exists(afi_ipv4):
config.set(afi_ipv4)
+# Migrate IPv6 AFI peer-group
+if config.exists(base + ['neighbor']):
+ for neighbor in config.list_nodes(base + ['neighbor']):
+ tmp_path = base + ['neighbor', neighbor, 'address-family', 'ipv6-unicast', 'peer-group']
+ if config.exists(tmp_path):
+ peer_group = config.return_value(tmp_path)
+ config.set(base + ['neighbor', neighbor, 'peer-group'], value=peer_group)
+ config.delete(tmp_path)
+
try:
with open(file_name, 'w') as f:
f.write(config.to_string())
diff --git a/src/migration-scripts/dhcpv6-server/3-to-4 b/src/migration-scripts/dhcpv6-server/3-to-4
index c065e3d43..4747ebd60 100755
--- a/src/migration-scripts/dhcpv6-server/3-to-4
+++ b/src/migration-scripts/dhcpv6-server/3-to-4
@@ -16,6 +16,8 @@
# T3316:
# - Add subnet IDs to existing subnets
+# - Move options to option node
+# - Migrate address-range to range tagNode
import sys
import re
@@ -37,6 +39,10 @@ if not config.exists(base):
# Nothing to do
sys.exit(0)
+option_nodes = ['captive-portal', 'domain-search', 'name-server',
+ 'nis-domain', 'nis-server', 'nisplus-domain', 'nisplus-server',
+ 'sip-server', 'sntp-server', 'vendor-option']
+
subnet_id = 1
for network in config.list_nodes(base):
@@ -44,6 +50,35 @@ for network in config.list_nodes(base):
for subnet in config.list_nodes(base + [network, 'subnet']):
base_subnet = base + [network, 'subnet', subnet]
+ if config.exists(base_subnet + ['address-range']):
+ config.set(base_subnet + ['range'])
+ config.set_tag(base_subnet + ['range'])
+
+ range_id = 1
+
+ if config.exists(base_subnet + ['address-range', 'prefix']):
+ for prefix in config.return_values(base_subnet + ['address-range', 'prefix']):
+ config.set(base_subnet + ['range', range_id, 'prefix'], value=prefix)
+
+ range_id += 1
+
+ if config.exists(base_subnet + ['address-range', 'start']):
+ for start in config.list_nodes(base_subnet + ['address-range', 'start']):
+ stop = config.return_value(base_subnet + ['address-range', 'start', start, 'stop'])
+
+ config.set(base_subnet + ['range', range_id, 'start'], value=start)
+ config.set(base_subnet + ['range', range_id, 'stop'], value=stop)
+
+ range_id += 1
+
+ config.delete(base_subnet + ['address-range'])
+
+ for option in option_nodes:
+ if config.exists(base_subnet + [option]):
+ config.set(base_subnet + ['option'])
+ config.copy(base_subnet + [option], base_subnet + ['option', option])
+ config.delete(base_subnet + [option])
+
config.set(base_subnet + ['subnet-id'], value=subnet_id)
subnet_id += 1
diff --git a/src/migration-scripts/ipsec/12-to-13 b/src/migration-scripts/ipsec/12-to-13
new file mode 100755
index 000000000..504a2e9c7
--- /dev/null
+++ b/src/migration-scripts/ipsec/12-to-13
@@ -0,0 +1,52 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 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/>.
+
+# Changed value of dead-peer-detection.action from hold to trap
+
+import re
+
+from sys import argv
+from sys import exit
+
+from vyos.configtree import ConfigTree
+
+if len(argv) < 2:
+ print("Must specify file name!")
+ exit(1)
+
+file_name = argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+base = ['vpn', 'ipsec', 'ike-group']
+config = ConfigTree(config_file)
+
+if not config.exists(base):
+ # Nothing to do
+ exit(0)
+else:
+ for ike_group in config.list_nodes(base):
+ base_dpd_action = base + [ike_group, 'dead-peer-detection', 'action']
+ if config.exists(base_dpd_action) and config.return_value(base_dpd_action) == 'hold':
+ config.set(base_dpd_action, 'trap', replace=True)
+
+try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+except OSError as e:
+ print(f'Failed to save the modified config: {e}')
+ exit(1)
diff --git a/src/migration-scripts/nat/5-to-6 b/src/migration-scripts/nat/5-to-6
index de3830582..c83b93d84 100755
--- a/src/migration-scripts/nat/5-to-6
+++ b/src/migration-scripts/nat/5-to-6
@@ -51,8 +51,9 @@ for direction in ['source', 'destination']:
for iface in ['inbound-interface','outbound-interface']:
if config.exists(base + [iface]):
tmp = config.return_value(base + [iface])
- config.delete(base + [iface])
- config.set(base + [iface, 'interface-name'], value=tmp)
+ if tmp:
+ config.delete(base + [iface])
+ config.set(base + [iface, 'interface-name'], value=tmp)
try:
with open(file_name, 'w') as f:
diff --git a/src/migration-scripts/ospf/0-to-1 b/src/migration-scripts/ospf/0-to-1
index 8f02acada..a6cb9feb8 100755
--- a/src/migration-scripts/ospf/0-to-1
+++ b/src/migration-scripts/ospf/0-to-1
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2021 VyOS maintainers and contributors
+# Copyright (C) 2021-2024 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
@@ -28,6 +28,7 @@ def ospf_passive_migration(config, ospf_base):
default = True
continue
config.set(ospf_base + ['interface', interface, 'passive'])
+ config.set_tag(ospf_base + ['interface'])
config.delete(ospf_base + ['passive-interface'])
config.set(ospf_base + ['passive-interface'], value='default')
@@ -35,6 +36,7 @@ def ospf_passive_migration(config, ospf_base):
if config.exists(ospf_base + ['passive-interface-exclude']):
for interface in config.return_values(ospf_base + ['passive-interface-exclude']):
config.set(ospf_base + ['interface', interface, 'passive', 'disable'])
+ config.set_tag(ospf_base + ['interface'])
config.delete(ospf_base + ['passive-interface-exclude'])
if len(argv) < 2:
diff --git a/src/op_mode/dhcp.py b/src/op_mode/dhcp.py
index 02f4d5bbb..a64acec31 100755
--- a/src/op_mode/dhcp.py
+++ b/src/op_mode/dhcp.py
@@ -194,14 +194,11 @@ def _get_pool_size(pool, family='inet'):
size = 0
subnets = config.list_nodes(f'{base} subnet')
for subnet in subnets:
- if family == 'inet6':
- ranges = config.list_nodes(f'{base} subnet {subnet} address-range start')
- else:
- ranges = config.list_nodes(f'{base} subnet {subnet} range')
+ ranges = config.list_nodes(f'{base} subnet {subnet} range')
for range in ranges:
if family == 'inet6':
- start = config.list_nodes(f'{base} subnet {subnet} address-range start')[0]
- stop = config.value(f'{base} subnet {subnet} address-range start {start} stop')
+ start = config.value(f'{base} subnet {subnet} range {range} start')
+ stop = config.value(f'{base} subnet {subnet} range {range} stop')
else:
start = config.value(f'{base} subnet {subnet} range {range} start')
stop = config.value(f'{base} subnet {subnet} range {range} stop')
diff --git a/src/op_mode/powerctrl.py b/src/op_mode/powerctrl.py
index 3ac5991b4..c07d0c4bd 100755
--- a/src/op_mode/powerctrl.py
+++ b/src/op_mode/powerctrl.py
@@ -191,7 +191,7 @@ def main():
nargs="*",
metavar="HH:MM")
- action.add_argument("--reboot_in", "-i",
+ action.add_argument("--reboot-in", "-i",
help="Reboot the system",
nargs="*",
metavar="Minutes")
@@ -214,7 +214,7 @@ def main():
if args.reboot is not None:
for r in args.reboot:
if ':' not in r and '/' not in r and '.' not in r:
- print("Incorrect format! Use HH:MM")
+ print("Incorrect format! Use HH:MM")
exit(1)
execute_shutdown(args.reboot, reboot=True, ask=args.yes)
if args.reboot_in is not None: