diff --git a/data/templates/frr/bgpd.frr.j2 b/data/templates/frr/bgpd.frr.j2
index e5a75090f9..169487dbd5 100644
--- a/data/templates/frr/bgpd.frr.j2
+++ b/data/templates/frr/bgpd.frr.j2
@@ -259,7 +259,11 @@
{# j2lint: disable=jinja-statements-delimeter #}
{%- endmacro -%}
!
-router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
+{% if vrf is vyos_defined %}
+ router bgp {{ dependent_vrfs.default.protocols.bgp.system_as }} vrf {{ vrf }}
+{% else %}
+ router bgp {{ system_as }}
+{% endif %}
{% if parameters.ebgp_requires_policy is vyos_defined %}
bgp ebgp-requires-policy
{% else %}
diff --git a/interface-definitions/include/bgp/protocol-common-config.xml.i b/interface-definitions/include/bgp/protocol-common-config.xml.i
index ab016884e1..6c9424be5c 100644
--- a/interface-definitions/include/bgp/protocol-common-config.xml.i
+++ b/interface-definitions/include/bgp/protocol-common-config.xml.i
@@ -1005,18 +1005,6 @@
-
-
- Autonomous System Number (ASN)
-
- u32:1-4294967294
- Autonomous System Number
-
-
-
-
-
-
BGP neighbor
diff --git a/interface-definitions/include/version/bgp-version.xml.i b/interface-definitions/include/version/bgp-version.xml.i
index c902761515..a283b9dd2c 100644
--- a/interface-definitions/include/version/bgp-version.xml.i
+++ b/interface-definitions/include/version/bgp-version.xml.i
@@ -1,3 +1,3 @@
-
+
diff --git a/interface-definitions/protocols_bgp.xml.in b/interface-definitions/protocols_bgp.xml.in
index e1a8229991..5f932ac86a 100644
--- a/interface-definitions/protocols_bgp.xml.in
+++ b/interface-definitions/protocols_bgp.xml.in
@@ -9,6 +9,18 @@
#include
+
+
+ Autonomous System Number (ASN)
+
+ u32:1-4294967294
+ Autonomous System Number
+
+
+
+
+
+
diff --git a/smoketest/config-tests/bgp-evpn-l3vpn-pe-router b/smoketest/config-tests/bgp-evpn-l3vpn-pe-router
index f867c221e9..0f10475f6f 100644
--- a/smoketest/config-tests/bgp-evpn-l3vpn-pe-router
+++ b/smoketest/config-tests/bgp-evpn-l3vpn-pe-router
@@ -105,12 +105,10 @@ set system syslog local facility all level 'info'
set system syslog local facility local7 level 'debug'
set vrf name blue protocols bgp address-family ipv4-unicast redistribute connected
set vrf name blue protocols bgp address-family l2vpn-evpn advertise ipv4 unicast
-set vrf name blue protocols bgp system-as '100'
set vrf name blue table '2000'
set vrf name blue vni '2000'
set vrf name green protocols bgp address-family ipv4-unicast redistribute connected
set vrf name green protocols bgp address-family l2vpn-evpn advertise ipv4 unicast
-set vrf name green protocols bgp system-as '100'
set vrf name green table '4000'
set vrf name green vni '4000'
set vrf name mgmt protocols static route 0.0.0.0/0 next-hop 192.0.2.62
@@ -118,6 +116,5 @@ set vrf name mgmt protocols static route6 ::/0 next-hop 2001:db8:ffff::1
set vrf name mgmt table '1000'
set vrf name red protocols bgp address-family ipv4-unicast redistribute connected
set vrf name red protocols bgp address-family l2vpn-evpn advertise ipv4 unicast
-set vrf name red protocols bgp system-as '100'
set vrf name red table '3000'
set vrf name red vni '3000'
diff --git a/smoketest/config-tests/bgp-evpn-l3vpn-vrf-different-asn b/smoketest/config-tests/bgp-evpn-l3vpn-vrf-different-asn
new file mode 100644
index 0000000000..5f3f33b8f7
--- /dev/null
+++ b/smoketest/config-tests/bgp-evpn-l3vpn-vrf-different-asn
@@ -0,0 +1,107 @@
+set interfaces bridge br2000 address '10.10.7.1/30'
+set interfaces bridge br2000 description 'customer blue'
+set interfaces bridge br2000 member interface eth2.2600
+set interfaces bridge br2000 member interface vxlan2000
+set interfaces bridge br2000 vrf 'blue'
+set interfaces dummy dum0 address '10.255.253.1/32'
+set interfaces dummy dum0 address '10.255.253.24/32'
+set interfaces ethernet eth0 duplex 'auto'
+set interfaces ethernet eth0 offload gro
+set interfaces ethernet eth0 offload gso
+set interfaces ethernet eth0 offload sg
+set interfaces ethernet eth0 offload tso
+set interfaces ethernet eth0 speed 'auto'
+set interfaces ethernet eth0 vif 6 address '192.168.0.1/24'
+set interfaces ethernet eth0 vif 6 vrf 'green'
+set interfaces ethernet eth1 duplex 'auto'
+set interfaces ethernet eth1 speed 'auto'
+set interfaces ethernet eth1 vif 101 address '192.0.2.1/31'
+set interfaces ethernet eth1 vif 888 address '192.0.2.3/31'
+set interfaces ethernet eth1 vif 888 vrf 'blue'
+set interfaces ethernet eth2 duplex 'auto'
+set interfaces ethernet eth2 speed 'auto'
+set interfaces ethernet eth2 vif 1111 address '192.0.2.11/31'
+set interfaces ethernet eth2 vif 1111 vrf 'red'
+set interfaces ethernet eth2 vif 1113 address '192.0.2.13/31'
+set interfaces ethernet eth2 vif 1113 vrf 'red'
+set interfaces ethernet eth2 vif 2600
+set interfaces vxlan vxlan2000 mtu '1500'
+set interfaces vxlan vxlan2000 parameters nolearning
+set interfaces vxlan vxlan2000 port '4789'
+set interfaces vxlan vxlan2000 source-address '10.255.253.1'
+set interfaces vxlan vxlan2000 vni '2000'
+set protocols bgp address-family l2vpn-evpn advertise ipv4 unicast
+set protocols bgp address-family l2vpn-evpn advertise-all-vni
+set protocols bgp neighbor 10.255.253.9 address-family ipv4-unicast allowas-in number '10'
+set protocols bgp neighbor 10.255.253.9 address-family ipv4-unicast nexthop-self
+set protocols bgp neighbor 10.255.253.9 remote-as 'internal'
+set protocols bgp neighbor 10.255.253.9 update-source '10.255.253.1'
+set protocols bgp neighbor 10.255.253.25 peer-group 'EVPN'
+set protocols bgp parameters log-neighbor-changes
+set protocols bgp parameters network-import-check
+set protocols bgp parameters router-id '10.255.253.1'
+set protocols bgp peer-group EVPN address-family l2vpn-evpn
+set protocols bgp peer-group EVPN remote-as '100'
+set protocols bgp peer-group EVPN update-source 'dum0'
+set protocols bgp system-as '100'
+set protocols ospf interface dum0 area '0'
+set protocols ospf interface eth1.101 area '0'
+set protocols ospf interface eth1.101 network 'broadcast'
+set protocols ospf log-adjacency-changes detail
+set protocols ospf parameters router-id '10.255.253.1'
+set service ntp allow-client address '0.0.0.0/0'
+set service ntp allow-client address '::/0'
+set service ntp server 0.pool.ntp.org
+set service ntp server 1.pool.ntp.org
+set service ntp server 2.pool.ntp.org
+set service ssh disable-host-validation
+set service ssh port '22'
+set system config-management commit-revisions '20'
+set system conntrack modules ftp
+set system conntrack modules h323
+set system conntrack modules nfs
+set system conntrack modules pptp
+set system conntrack modules sip
+set system conntrack modules sqlnet
+set system conntrack modules tftp
+set system console device ttyS0 speed '115200'
+set system domain-name 'vyos.net'
+set system host-name 'evpn-l3vpn-vrf-foo'
+set system login user vyos authentication encrypted-password '$6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0'
+set system login user vyos authentication plaintext-password ''
+set system option ctrl-alt-delete 'reboot'
+set system option reboot-on-panic
+set system syslog console facility all level 'emerg'
+set system syslog console facility mail level 'info'
+set system syslog local facility all level 'info'
+set system syslog local facility local7 level 'debug'
+set system syslog preserve-fqdn
+set system time-zone 'Europe/Berlin'
+set vrf name blue protocols bgp address-family ipv4-unicast redistribute connected
+set vrf name blue protocols bgp neighbor 192.0.2.2 address-family ipv4-unicast allowas-in number '1'
+set vrf name blue protocols bgp neighbor 192.0.2.2 address-family ipv4-unicast maximum-prefix '20'
+set vrf name blue protocols bgp neighbor 192.0.2.2 local-as 667 no-prepend replace-as
+set vrf name blue protocols bgp neighbor 192.0.2.2 remote-as '100'
+set vrf name blue protocols bgp neighbor 192.0.2.4 address-family ipv4-unicast maximum-prefix '40'
+set vrf name blue protocols bgp neighbor 192.0.2.4 local-as 200
+set vrf name blue protocols bgp neighbor 192.0.2.4 remote-as '300'
+set vrf name blue protocols bgp neighbor 192.0.2.6 address-family ipv4-unicast allowas-in number '7'
+set vrf name blue protocols bgp neighbor 192.0.2.6 local-as 667 no-prepend replace-as
+set vrf name blue protocols bgp neighbor 192.0.2.6 remote-as '112'
+set vrf name blue table '2001'
+set vrf name blue vni '2001'
+set vrf name green table '4001'
+set vrf name red protocols bgp address-family ipv4-unicast redistribute connected
+set vrf name red protocols bgp neighbor 192.0.2.10 peer-group 'foo'
+set vrf name red protocols bgp neighbor 192.0.2.12 address-family ipv4-unicast allowas-in number '10'
+set vrf name red protocols bgp neighbor 192.0.2.12 local-as 65412 no-prepend replace-as
+set vrf name red protocols bgp neighbor 192.0.2.12 peer-group 'bar'
+set vrf name red protocols bgp neighbor 192.0.2.14 local-as 1111 no-prepend replace-as
+set vrf name red protocols bgp neighbor 192.0.2.14 peer-group 'foo'
+set vrf name red protocols bgp peer-group bar address-family ipv4-unicast allowas-in number '10'
+set vrf name red protocols bgp peer-group bar remote-as '333'
+set vrf name red protocols bgp peer-group foo address-family ipv4-unicast soft-reconfiguration inbound
+set vrf name red protocols bgp peer-group foo local-as 1000
+set vrf name red protocols bgp peer-group foo remote-as '300'
+set vrf name red table '3001'
+set vrf name red vni '3001'
diff --git a/smoketest/config-tests/vrf-bgp-pppoe-underlay b/smoketest/config-tests/vrf-bgp-pppoe-underlay
index e3c765a9a9..4ce1a43287 100644
--- a/smoketest/config-tests/vrf-bgp-pppoe-underlay
+++ b/smoketest/config-tests/vrf-bgp-pppoe-underlay
@@ -107,6 +107,7 @@ set policy prefix-list6 AS100-origin-v6 rule 10 action 'permit'
set policy prefix-list6 AS100-origin-v6 rule 10 prefix '2001:db8:200::/40'
set policy prefix-list6 AS200-origin-v6 rule 10 action 'permit'
set policy prefix-list6 AS200-origin-v6 rule 10 prefix '2001:db8:100::/40'
+set protocols bgp system-as '100'
set protocols static route 100.64.50.0/23 next-hop 100.64.51.221
set protocols static route 192.0.2.255/32 interface pppoe7
set protocols static route6 2001:db8:ffff:ffff:ffff:ffff:ffff:ffff/128 interface pppoe7
@@ -178,7 +179,6 @@ set vrf name vyos-test-01 protocols bgp peer-group AS100v6 address-family ipv6-u
set vrf name vyos-test-01 protocols bgp peer-group AS100v6 capability dynamic
set vrf name vyos-test-01 protocols bgp peer-group AS100v6 remote-as 'internal'
set vrf name vyos-test-01 protocols bgp peer-group AS100v6 update-source 'dum0'
-set vrf name vyos-test-01 protocols bgp system-as '100'
set vrf name vyos-test-01 protocols static route 100.64.50.0/23 blackhole
set vrf name vyos-test-01 protocols static route 100.64.51.32/27 next-hop 100.64.51.5
set vrf name vyos-test-01 protocols static route 192.168.0.0/24 next-hop 100.64.51.220
diff --git a/smoketest/configs/bgp-evpn-l3vpn-vrf-different-asn b/smoketest/configs/bgp-evpn-l3vpn-vrf-different-asn
new file mode 100644
index 0000000000..b94f76c887
--- /dev/null
+++ b/smoketest/configs/bgp-evpn-l3vpn-vrf-different-asn
@@ -0,0 +1,300 @@
+interfaces {
+ bridge br2000 {
+ address "10.10.7.1/30"
+ description "customer blue"
+ member {
+ interface eth2.2600 {
+ }
+ interface vxlan2000 {
+ }
+ }
+ vrf "blue"
+ }
+ dummy dum0 {
+ address "10.255.253.1/32"
+ address "10.255.253.24/32"
+ }
+ ethernet eth0 {
+ duplex "auto"
+ offload {
+ gro
+ gso
+ sg
+ tso
+ }
+ speed "auto"
+ vif 6 {
+ address "192.168.0.1/24"
+ vrf "green"
+ }
+ }
+ ethernet eth1 {
+ duplex "auto"
+ speed "auto"
+ vif 101 {
+ address "192.0.2.1/31"
+ }
+ vif 888 {
+ address "192.0.2.3/31"
+ vrf "blue"
+ }
+ }
+ ethernet eth2 {
+ duplex "auto"
+ speed "auto"
+ vif 1111 {
+ address "192.0.2.11/31"
+ vrf "red"
+ }
+ vif 1113 {
+ address "192.0.2.13/31"
+ vrf "red"
+ }
+ vif 2600 {
+ }
+ }
+ vxlan vxlan2000 {
+ mtu "1500"
+ parameters {
+ nolearning
+ }
+ port "4789"
+ source-address "10.255.253.1"
+ vni "2000"
+ }
+}
+protocols {
+ bgp {
+ address-family {
+ l2vpn-evpn {
+ advertise {
+ ipv4 {
+ unicast
+ }
+ }
+ advertise-all-vni
+ }
+ }
+ neighbor 10.255.253.9 {
+ address-family {
+ ipv4-unicast {
+ allowas-in {
+ number "10"
+ }
+ nexthop-self
+ }
+ }
+ remote-as "internal"
+ update-source "10.255.253.1"
+ }
+ neighbor 10.255.253.25 {
+ peer-group "EVPN"
+ }
+ parameters {
+ log-neighbor-changes
+ network-import-check
+ router-id "10.255.253.1"
+ }
+ peer-group EVPN {
+ address-family {
+ l2vpn-evpn
+ }
+ remote-as "100"
+ update-source "dum0"
+ }
+ system-as "100"
+ }
+ ospf {
+ interface dum0 {
+ area "0"
+ }
+ interface eth1.101 {
+ area "0"
+ network "broadcast"
+ }
+ log-adjacency-changes {
+ detail
+ }
+ parameters {
+ router-id "10.255.253.1"
+ }
+ }
+}
+service {
+ ntp {
+ allow-client {
+ address "0.0.0.0/0"
+ address "::/0"
+ }
+ server 0.pool.ntp.org {
+ }
+ server 1.pool.ntp.org {
+ }
+ server 2.pool.ntp.org {
+ }
+ }
+ ssh {
+ disable-host-validation
+ port "22"
+ }
+}
+system {
+ config-management {
+ commit-revisions "20"
+ }
+ conntrack {
+ modules {
+ ftp
+ h323
+ nfs
+ pptp
+ sip
+ sqlnet
+ tftp
+ }
+ }
+ console {
+ device ttyS0 {
+ speed "115200"
+ }
+ }
+ domain-name "vyos.net"
+ host-name "evpn-l3vpn-vrf-foo"
+ login {
+ user vyos {
+ authentication {
+ encrypted-password "$6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0"
+ plaintext-password ""
+ }
+ }
+ }
+ option {
+ ctrl-alt-delete "reboot"
+ reboot-on-panic
+ }
+ syslog {
+ console {
+ facility all {
+ level "emerg"
+ }
+ facility mail {
+ level "info"
+ }
+ }
+ global {
+ facility all {
+ level "info"
+ }
+ facility local7 {
+ level "debug"
+ }
+ preserve-fqdn
+ }
+ }
+ time-zone "Europe/Berlin"
+}
+vrf {
+ name blue {
+ protocols {
+ bgp {
+ address-family {
+ ipv4-unicast {
+ redistribute {
+ connected
+ }
+ }
+ }
+ neighbor 192.0.2.2 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix "20"
+ }
+ }
+ remote-as "100"
+ }
+ neighbor 192.0.2.4 {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix "40"
+ }
+ }
+ local-as 200 {
+ }
+ remote-as "300"
+ }
+ neighbor 192.0.2.6 {
+ address-family {
+ ipv4-unicast {
+ allowas-in {
+ number "6"
+ }
+ }
+ }
+ remote-as "112"
+ }
+ system-as "667"
+ }
+ }
+ table "2001"
+ vni "2001"
+ }
+ name green {
+ table "4001"
+ }
+ name red {
+ protocols {
+ bgp {
+ address-family {
+ ipv4-unicast {
+ redistribute {
+ connected
+ }
+ }
+ }
+ neighbor 192.0.2.10 {
+ peer-group "foo"
+ }
+ neighbor 192.0.2.12 {
+ peer-group "bar"
+ }
+ neighbor 192.0.2.14 {
+ local-as 1111 {
+ no-prepend {
+ replace-as
+ }
+ }
+ peer-group "foo"
+ }
+ peer-group bar {
+ address-family {
+ ipv4-unicast {
+ allowas-in {
+ number "10"
+ }
+ }
+ }
+ remote-as "333"
+ }
+ peer-group foo {
+ address-family {
+ ipv4-unicast {
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ }
+ local-as 1000 {
+ }
+ remote-as "300"
+ }
+ system-as "65412"
+ }
+ }
+ table "3001"
+ vni "3001"
+ }
+}
+
+// Warning: Do not remove the following line.
+// vyos-config-version: "bgp@6:broadcast-relay@1:cluster@2:config-management@1:conntrack@6:conntrack-sync@2:container@2:dhcp-relay@2:dhcp-server@8:dhcpv6-server@1:dns-dynamic@4:dns-forwarding@4:firewall@15:flow-accounting@1:https@6:ids@1:interfaces@32:ipoe-server@3:ipsec@13:isis@3:l2tp@9:lldp@2:mdns@1:monitoring@1:nat@8:nat66@3:ntp@3:openconnect@3:ospf@2:pim@1:policy@8:pppoe-server@10:pptp@5:qos@2:quagga@11:reverse-proxy@1:rip@1:rpki@2:salt@1:snmp@3:ssh@2:sstp@6:system@27:vrf@3:vrrp@4:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2"
+// Release version: 1.4.3
diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py
index 43bf00238b..630e267092 100755
--- a/smoketest/scripts/cli/test_protocols_bgp.py
+++ b/smoketest/scripts/cli/test_protocols_bgp.py
@@ -230,7 +230,7 @@ def tearDown(self):
def create_bgp_instances_for_import_test(self):
table = '1000'
self.cli_set(import_vrf_base + [import_vrf, 'table', table])
- self.cli_set(import_vrf_base + [import_vrf, 'protocols', 'bgp', 'system-as', ASN])
+ self.cli_set(import_vrf_base + [import_vrf, 'protocols', 'bgp'])
def verify_frr_config(self, peer, peer_config, frrconfig):
# recurring patterns to verify for both a simple neighbor and a peer-group
@@ -1050,7 +1050,6 @@ def test_bgp_10_vrf_simple(self):
for vrf in vrfs:
vrf_base = ['vrf', 'name', vrf]
self.cli_set(vrf_base + ['table', table])
- self.cli_set(vrf_base + ['protocols', 'bgp', 'system-as', ASN])
self.cli_set(vrf_base + ['protocols', 'bgp', 'parameters', 'router-id', router_id])
table = str(int(table) + 1000)
@@ -1192,31 +1191,7 @@ def test_bgp_14_remote_as_peer_group_override(self):
self.assertIn(f' neighbor {peer_group} peer-group', frrconfig)
self.assertIn(f' neighbor {peer_group} remote-as {remote_asn}', frrconfig)
- def test_bgp_15_local_as_ebgp(self):
- # https://vyos.dev/T4560
- # local-as allowed only for ebgp peers
-
- neighbor = '192.0.2.99'
- remote_asn = '500'
- local_asn = '400'
-
- self.cli_set(base_path + ['neighbor', neighbor, 'remote-as', ASN])
- self.cli_set(base_path + ['neighbor', neighbor, 'local-as', local_asn])
-
- # check validate() - local-as allowed only for ebgp peers
- with self.assertRaises(ConfigSessionError):
- self.cli_commit()
-
- self.cli_set(base_path + ['neighbor', neighbor, 'remote-as', remote_asn])
-
- self.cli_commit()
-
- frrconfig = self.getFRRconfig(f'router bgp {ASN}', endsection='^exit')
- self.assertIn(f'router bgp {ASN}', frrconfig)
- self.assertIn(f' neighbor {neighbor} remote-as {remote_asn}', frrconfig)
- self.assertIn(f' neighbor {neighbor} local-as {local_asn}', frrconfig)
-
- def test_bgp_16_import_rd_rt_compatibility(self):
+ def test_bgp_15_import_rd_rt_compatibility(self):
# Verify if import vrf and rd vpn export
# exist in the same address family
self.create_bgp_instances_for_import_test()
@@ -1229,7 +1204,7 @@ def test_bgp_16_import_rd_rt_compatibility(self):
with self.assertRaises(ConfigSessionError):
self.cli_commit()
- def test_bgp_17_import_rd_rt_compatibility(self):
+ def test_bgp_16_import_rd_rt_compatibility(self):
# Verify if vrf that is in import vrf list contains rd vpn export
self.create_bgp_instances_for_import_test()
self.cli_set(
@@ -1252,7 +1227,7 @@ def test_bgp_17_import_rd_rt_compatibility(self):
with self.assertRaises(ConfigSessionError):
self.cli_commit()
- def test_bgp_18_deleting_import_vrf(self):
+ def test_bgp_17_deleting_import_vrf(self):
# Verify deleting vrf that is in import vrf list
self.create_bgp_instances_for_import_test()
self.cli_set(
@@ -1269,7 +1244,7 @@ def test_bgp_18_deleting_import_vrf(self):
with self.assertRaises(ConfigSessionError):
self.cli_commit()
- def test_bgp_19_deleting_default_vrf(self):
+ def test_bgp_18_deleting_default_vrf(self):
# Verify deleting existent vrf default if other vrfs were created
self.create_bgp_instances_for_import_test()
self.cli_commit()
@@ -1281,7 +1256,7 @@ def test_bgp_19_deleting_default_vrf(self):
with self.assertRaises(ConfigSessionError):
self.cli_commit()
- def test_bgp_20_import_rd_rt_compatibility(self):
+ def test_bgp_19_import_rd_rt_compatibility(self):
# Verify if vrf that has rd vpn export is in import vrf of other vrfs
self.create_bgp_instances_for_import_test()
self.cli_set(
@@ -1303,7 +1278,7 @@ def test_bgp_20_import_rd_rt_compatibility(self):
with self.assertRaises(ConfigSessionError):
self.cli_commit()
- def test_bgp_21_import_unspecified_vrf(self):
+ def test_bgp_20_import_unspecified_vrf(self):
# Verify if vrf that is in import is unspecified
self.create_bgp_instances_for_import_test()
self.cli_set(
@@ -1312,7 +1287,7 @@ def test_bgp_21_import_unspecified_vrf(self):
with self.assertRaises(ConfigSessionError):
self.cli_commit()
- def test_bgp_22_interface_mpls_forwarding(self):
+ def test_bgp_21_interface_mpls_forwarding(self):
interfaces = Section.interfaces('ethernet', vlan=False)
for interface in interfaces:
self.cli_set(base_path + ['interface', interface, 'mpls', 'forwarding'])
@@ -1324,7 +1299,7 @@ def test_bgp_22_interface_mpls_forwarding(self):
self.assertIn(f'interface {interface}', frrconfig)
self.assertIn(f' mpls bgp forwarding', frrconfig)
- def test_bgp_23_vrf_interface_mpls_forwarding(self):
+ def test_bgp_22_vrf_interface_mpls_forwarding(self):
self.create_bgp_instances_for_import_test()
interfaces = Section.interfaces('ethernet', vlan=False)
for interface in interfaces:
@@ -1339,7 +1314,7 @@ def test_bgp_23_vrf_interface_mpls_forwarding(self):
self.assertIn(f' mpls bgp forwarding', frrconfig)
self.cli_delete(['interfaces', 'ethernet', interface, 'vrf'])
- def test_bgp_24_srv6_sid(self):
+ def test_bgp_23_srv6_sid(self):
locator_name = 'VyOS_foo'
sid = 'auto'
nexthop_ipv4 = '192.0.0.1'
@@ -1386,7 +1361,7 @@ def test_bgp_24_srv6_sid(self):
self.assertIn(f' sid vpn export {sid}', afiv6_config)
self.assertIn(f' nexthop vpn export {nexthop_ipv6}', afiv6_config)
- def test_bgp_25_ipv4_labeled_unicast_peer_group(self):
+ def test_bgp_24_ipv4_labeled_unicast_peer_group(self):
pg_ipv4 = 'foo4'
ipv4_max_prefix = '20'
ipv4_prefix = '192.0.2.0/24'
@@ -1411,7 +1386,7 @@ def test_bgp_25_ipv4_labeled_unicast_peer_group(self):
self.assertIn(f' neighbor {pg_ipv4} activate', afiv4_config)
self.assertIn(f' neighbor {pg_ipv4} maximum-prefix {ipv4_max_prefix}', afiv4_config)
- def test_bgp_26_ipv6_labeled_unicast_peer_group(self):
+ def test_bgp_25_ipv6_labeled_unicast_peer_group(self):
pg_ipv6 = 'foo6'
ipv6_max_prefix = '200'
ipv6_prefix = '2001:db8:1000::/64'
@@ -1437,7 +1412,7 @@ def test_bgp_26_ipv6_labeled_unicast_peer_group(self):
self.assertIn(f' neighbor {pg_ipv6} activate', afiv6_config)
self.assertIn(f' neighbor {pg_ipv6} maximum-prefix {ipv6_max_prefix}', afiv6_config)
- def test_bgp_27_route_reflector_client(self):
+ def test_bgp_26_route_reflector_client(self):
int_neighbors = ['192.0.2.2', '192.0.2.3', '192.0.2.4', '192.0.2.5']
int_interfaces = ['dum0', 'dum1', 'dum2', 'dum3']
int_pg_names = ['SMOKETESTINT0', 'SMOKETESTINT1', 'SMOKETESTINT2']
@@ -1472,7 +1447,7 @@ def _set_neighbor_3(neighbor, remote_as_type):
interface_cmd = ['interface'] if neighbor.startswith('dum') else []
self.cli_set(base_path + ['neighbor', neighbor, 'address-family', 'ipv4-unicast', 'route-reflector-client'])
self.cli_set(base_path + ['neighbor', neighbor] + interface_cmd + ['remote-as', remote_as_type])
-
+
set_neighbor_funcs = [_set_neighbor_0, _set_neighbor_1, _set_neighbor_2, _set_neighbor_3]
for remote_as_type in remote_as_types:
for func_count, set_neighbor_func in enumerate(set_neighbor_funcs):
@@ -1484,7 +1459,7 @@ def _set_neighbor_3(neighbor, remote_as_type):
self.cli_discard()
else:
self.cli_commit()
-
+
frrconfig = self.getFRRconfig(f'router bgp {ASN}', endsection='^exit', substring=' address-family ipv4 unicast', endsubsection='^ exit-address-family')
neighbor_has_rr_client = [
int_neighbors[0], int_neighbors[3],
@@ -1497,7 +1472,7 @@ def _set_neighbor_3(neighbor, remote_as_type):
self.cli_delete(['interfaces', 'dummy'])
self.cli_commit()
- def test_bgp_28_peer_group_member_all_internal_or_external(self):
+ def test_bgp_27_peer_group_member_all_internal_or_external(self):
def _common_config_check(conf, include_ras=True):
if include_ras:
self.assertIn(f'neighbor {int_neighbors[0]} remote-as {ASN}', conf)
@@ -1589,13 +1564,12 @@ def test_bgp_29_peer_group_remote_as_equal_local_as(self):
self.assertIn(f'neighbor OVERLAY remote-as {int(ASN) + 1}', conf)
self.assertIn(f'neighbor OVERLAY local-as {int(ASN) + 1}', conf)
- def test_bgp_30_import_vrf_routemap(self):
+ def test_bgp_30_import_vrf_route_map(self):
router_id = '127.0.0.3'
table = '1000'
vrf = 'red'
vrf_base = ['vrf', 'name', vrf]
self.cli_set(vrf_base + ['table', table])
- self.cli_set(vrf_base + ['protocols', 'bgp', 'system-as', ASN])
self.cli_set(
vrf_base + ['protocols', 'bgp', 'parameters', 'router-id',
router_id])
@@ -1682,4 +1656,4 @@ def test_bgp_99_bmp(self):
self.assertIn(f'bmp connect {target_address} port {target_port} min-retry {min_retry} max-retry {max_retry}', frrconfig)
if __name__ == '__main__':
- unittest.main(verbosity=2)
+ unittest.main(verbosity=2, failfast=True)
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index fe5740a185..4e7f09d0e8 100755
--- a/src/conf_mode/protocols_bgp.py
+++ b/src/conf_mode/protocols_bgp.py
@@ -210,8 +210,20 @@ def verify(config_dict):
return None
- if 'system_as' not in bgp:
- raise ConfigError('BGP system-as number must be defined!')
+ ERR_MSG_GLOBAL_VRF_AS_MISSING = 'BGP "system-as" number must be defined! Use "set protocols ' \
+ 'bgp system-as " to define a global BGP instance AS number.'
+ system_as = None
+ if vrf:
+ system_as = dict_search('dependent_vrfs.default.protocols.bgp.system_as', bgp)
+ if not system_as:
+ raise ConfigError(ERR_MSG_GLOBAL_VRF_AS_MISSING)
+
+ elif 'system_as' not in bgp:
+ raise ConfigError(ERR_MSG_GLOBAL_VRF_AS_MISSING)
+
+ # Cache global defined system AS number used in further checks
+ if not system_as:
+ system_as = bgp['system_as']
# Verify BMP
if 'bmp' in bgp:
@@ -257,7 +269,7 @@ def verify(config_dict):
if 'remote_as' in peer_config:
is_ibgp = True
if peer_config['remote_as'] != 'internal' and \
- peer_config['remote_as'] != bgp['system_as']:
+ peer_config['remote_as'] != system_as:
is_ibgp = False
if peer_group not in peer_groups_context:
@@ -278,7 +290,7 @@ def verify(config_dict):
# Neighbor local-as override can not be the same as the local-as
# we use for this BGP instane!
asn = list(peer_config['local_as'].keys())[0]
- if asn == bgp['system_as']:
+ if asn == system_as:
raise ConfigError('Cannot have local-as same as system-as number')
# Neighbor AS specified for local-as and remote-as can not be the same
@@ -369,12 +381,6 @@ def verify(config_dict):
if 'source_interface' in peer_config['interface']:
raise ConfigError(f'"source-interface" option not allowed for neighbor "{peer}"')
- # Local-AS allowed only for EBGP peers
- if 'local_as' in peer_config:
- remote_as = verify_remote_as(peer_config, bgp)
- if remote_as == bgp['system_as']:
- raise ConfigError(f'local-as configured for "{peer}", allowed only for eBGP peers!')
-
for afi in ['ipv4_unicast', 'ipv4_multicast', 'ipv4_labeled_unicast', 'ipv4_flowspec',
'ipv6_unicast', 'ipv6_multicast', 'ipv6_labeled_unicast', 'ipv6_flowspec',
'l2vpn_evpn']:
diff --git a/src/migration-scripts/bgp/6-to-7 b/src/migration-scripts/bgp/6-to-7
new file mode 100644
index 0000000000..7a11bbf3a5
--- /dev/null
+++ b/src/migration-scripts/bgp/6-to-7
@@ -0,0 +1,108 @@
+#!/usr/bin/env python3
+#
+# Copyright 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 .
+
+# T7760: Remove per VRF setting for system-as option and replace it with
+# local-as if required.
+
+from vyos.configtree import ConfigTree
+
+def migrate(config: ConfigTree) -> None:
+ vrf_base = ['vrf', 'name']
+ bgp_base = ['protocols', 'bgp']
+
+ if not config.exists(vrf_base):
+ return
+
+ global_asn = None
+ if config.exists(bgp_base + ['system-as']):
+ global_asn = config.return_value(bgp_base + ['system-as'])
+
+ for vrf in config.list_nodes(vrf_base):
+ # bail out early if there is no per VRF BGP instance defined
+ vrf_bgp_base = vrf_base + [vrf] + bgp_base
+ if not config.exists(vrf_bgp_base):
+ continue
+
+ # This is a mandatory node in the old design but keep it optional
+ # if one want's to load a weird config
+ if config.exists(vrf_bgp_base + ['system-as']):
+ system_as = config.return_value(vrf_bgp_base + ['system-as'])
+ config.delete(vrf_bgp_base + ['system-as'])
+
+ # If there is no existing global BGP instance - start one
+ if not config.exists(bgp_base):
+ config.set(bgp_base + ['system-as'], value=system_as)
+ global_asn = system_as
+
+ vrf_neighbor_base = vrf_bgp_base + ['neighbor']
+ vrf_peer_group_base = vrf_bgp_base + ['peer-group']
+ if config.exists(vrf_neighbor_base):
+ for neighbor in config.list_nodes(vrf_neighbor_base):
+ # Neighbor already has local-as option set, do not touch it
+ if config.exists(vrf_neighbor_base + [neighbor, 'local-as']):
+ #print(f'VRF {vrf} BGP neighbor {neighbor} has local-as set - do not migrate!')
+ continue
+
+ # Check if the neighbor uses a peer-group which has the local-as
+ # option set, do not touch it either
+ peer_group = None
+ if config.exists(vrf_neighbor_base + [neighbor, 'peer-group']):
+ peer_group = config.return_value(vrf_neighbor_base + [neighbor, 'peer-group'])
+ # Check if the peer-group has a local-as option set
+ if config.exists(vrf_peer_group_base + [peer_group, 'local-as']):
+ #print(f'VRF {vrf} BGP neighbor {neighbor} uses peer-group {peer_group} which has local-as set - do not migrate!')
+ continue
+
+ # BGP local-as option is only allowed for eBGP speakers
+ if global_asn == system_as:
+ continue
+
+ config.set(vrf_neighbor_base + [neighbor, 'local-as', system_as, 'no-prepend', 'replace-as'])
+ config.set_tag(vrf_neighbor_base + [neighbor, 'local-as'])
+
+ # We do also need to take care about BGP internas. When using local-as routes with our own AS
+ # previously in the path will get rejected:
+ # bgpd: x.x.x.x(Unknown) rcvd UPDATE about 192.0.2.0/24 IPv4 unicast -- DENIED due to: as-path contains our own AS;
+ # Set allowas-in option
+ allowas_in_numer = ['allowas-in', 'number']
+ for afi in ['ipv4-labeled-unicast', 'ipv4-multicast', 'ipv4-unicast', 'ipv4-vpn',
+ 'ipv6-labeled-unicast', 'ipv6-multicast', 'ipv6-unicast', 'ipv6-vpn']:
+ afi_neighbor_base = vrf_neighbor_base + [neighbor, 'address-family', afi]
+ afi_peer_group_base = vrf_peer_group_base + [peer_group, 'address-family', afi]
+
+ # No need to change anything on an AFI not in use
+ if not config.exists(afi_neighbor_base) and not config.exists(afi_peer_group_base):
+ continue
+
+ allowas_in_value = 0
+ print(neighbor, afi)
+ # Check if there is any allowas-in definition for a peer-group
+ if peer_group and config.exists(afi_peer_group_base + allowas_in_numer):
+ allowas_in_value = int(config.return_value(afi_peer_group_base + allowas_in_numer))
+ #print(f'peer-group {peer_group} allowas-in for {afi} is {allowas_in_value}')
+
+ # Per neighbor "allowas-in" definition takes higher precendence
+ if config.exists(afi_neighbor_base + allowas_in_numer):
+ allowas_in_value = int(config.return_value(afi_neighbor_base + allowas_in_numer))
+ #print(f'neighbor {neighbor} allowas-in for {afi} is {allowas_in_value}')
+
+ # Increment allowas-in by 1 as we now have one more entry
+ allowas_in_value += 1
+ # Clip allowas-in to 10 - max supported by FRR platform
+ if allowas_in_value > 10: allowas_in_value = 10
+
+ # Set per neighbor allowas-in which always takes precedence over the peer-group definition
+ config.set(afi_neighbor_base + allowas_in_numer, value=allowas_in_value, replace=True)
diff --git a/src/migration-scripts/bgp/7-to-8 b/src/migration-scripts/bgp/7-to-8
new file mode 100644
index 0000000000..ced4f837e5
--- /dev/null
+++ b/src/migration-scripts/bgp/7-to-8
@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+#
+# Copyright 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 .
+
+# T7760: Remove per VRF setting for system-as option in VyOS 1.5 and onwards
+
+from vyos.configtree import ConfigTree
+
+def migrate(config: ConfigTree) -> None:
+ vrf_base = ['vrf', 'name']
+ if not config.exists(vrf_base):
+ return
+
+ for vrf in config.list_nodes(vrf_base):
+ # bail out early if there is no per VRF BGP instance defined
+ vrf_bgp_base = vrf_base + [vrf, 'protocols', 'bgp']
+ if config.exists(vrf_bgp_base + ['system-as']):
+ config.delete(vrf_bgp_base + ['system-as'])