From 11ac6ab650c79bc520e9ad7266c8abc2ed131d6b Mon Sep 17 00:00:00 2001 From: Jonathan Voss Date: Thu, 13 Mar 2025 22:04:48 +0000 Subject: [PATCH] topotests: extend bgp_srv6_l3vpn_to_bgp_vrf4 test with bgp peers This test ensures route redistribution across an srv6 VPN network is well taken into account. Signed-off-by: Jonathan Voss Signed-off-by: Philippe Guibert --- .../bgp_srv6l3vpn_to_bgp_vrf4/ce1/bgpd.conf | 43 ++++++ .../bgp_srv6l3vpn_to_bgp_vrf4/ce1/ip_rib.json | 59 ++++++++ .../ce1/ipv6_rib.json | 59 ++++++++ .../bgp_srv6l3vpn_to_bgp_vrf4/ce1/setup.sh | 1 + .../bgp_srv6l3vpn_to_bgp_vrf4/ce1/zebra.conf | 16 ++ .../bgp_srv6l3vpn_to_bgp_vrf4/ce2/bgpd.conf | 43 ++++++ .../bgp_srv6l3vpn_to_bgp_vrf4/ce2/ip_rib.json | 59 ++++++++ .../ce2/ipv6_rib.json | 59 ++++++++ .../bgp_srv6l3vpn_to_bgp_vrf4/ce2/setup.sh | 1 + .../bgp_srv6l3vpn_to_bgp_vrf4/ce2/zebra.conf | 16 ++ .../bgp_srv6l3vpn_to_bgp_vrf4/r1/bgpd.conf | 71 +++++++++ .../bgp_srv6l3vpn_to_bgp_vrf4/r1/setup.sh | 4 + .../r1/vpnv4_rib.json | 64 ++++++++ .../r1/vpnv6_rib.json | 63 ++++++++ .../r1/vrf10v4_rib.json | 62 ++++++++ .../r1/vrf10v6_rib.json | 63 ++++++++ .../bgp_srv6l3vpn_to_bgp_vrf4/r1/zebra.conf | 25 +++ .../bgp_srv6l3vpn_to_bgp_vrf4/r2/bgpd.conf | 71 +++++++++ .../bgp_srv6l3vpn_to_bgp_vrf4/r2/setup.sh | 4 + .../r2/vpnv4_rib.json | 64 ++++++++ .../r2/vpnv6_rib.json | 63 ++++++++ .../r2/vrf10v4_rib.json | 63 ++++++++ .../r2/vrf10v6_rib.json | 63 ++++++++ .../bgp_srv6l3vpn_to_bgp_vrf4/r2/zebra.conf | 25 +++ .../test_bgp_srv6l3vpn_to_bgp_vrf4.py | 143 ++++++++++++++++++ 25 files changed, 1204 insertions(+) create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/bgpd.conf create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/ip_rib.json create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/ipv6_rib.json create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/setup.sh create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/zebra.conf create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/bgpd.conf create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/ip_rib.json create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/ipv6_rib.json create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/setup.sh create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/zebra.conf create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/bgpd.conf create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/setup.sh create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vpnv4_rib.json create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vpnv6_rib.json create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vrf10v4_rib.json create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vrf10v6_rib.json create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/zebra.conf create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/bgpd.conf create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/setup.sh create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vpnv4_rib.json create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vpnv6_rib.json create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vrf10v4_rib.json create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vrf10v6_rib.json create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/zebra.conf create mode 100644 tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/test_bgp_srv6l3vpn_to_bgp_vrf4.py diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/bgpd.conf new file mode 100644 index 0000000000..224d59b37d --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/bgpd.conf @@ -0,0 +1,43 @@ +frr defaults traditional +! +bgp send-extra-data zebra +! +hostname ce1 +password zebra +! +log stdout notifications +log commands +! +!debug bgp neighbor-events +!debug bgp zebra +!debug bgp vnc verbose +!debug bgp update-groups +!debug bgp updates in +!debug bgp updates out +!debug bgp vpn label +!debug bgp vpn leak-from-vrf +!debug bgp vpn leak-to-vrf +!debug bgp vpn rmap-event +! +router bgp 65001 + bgp router-id 1.0.0.1 + no bgp ebgp-requires-policy + !no bgp default ipv4-unicast + neighbor fd01::1 remote-as 1 + neighbor fd01::1 timers 3 10 + neighbor fd01::1 timers connect 1 + neighbor fd01::1 interface eth0 + neighbor fd01::1 update-source fd01::2 + neighbor fd01::1 capability extended-nexthop + ! + address-family ipv4 unicast + network 192.168.1.0 mask 255.255.255.0 + neighbor fd01::1 activate + exit-address-family + ! + address-family ipv6 unicast + network 2001:1::/64 + neighbor fd01::1 activate + exit-address-family + ! +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/ip_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/ip_rib.json new file mode 100644 index 0000000000..352c48b1b2 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/ip_rib.json @@ -0,0 +1,59 @@ +{ + "192.168.1.0/24": [ + { + "prefix": "192.168.1.0/24", + "prefixLen": 24, + "protocol": "connected", + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 0, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "dum0", + "active": true, + "weight": 1 + } + ] + } + ], + "192.168.2.0/24": [ + { + "prefix": "192.168.2.0/24", + "prefixLen": 24, + "protocol": "bgp", + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ], + "asPath": "1 2 65002" + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/ipv6_rib.json new file mode 100644 index 0000000000..fd10ee326f --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/ipv6_rib.json @@ -0,0 +1,59 @@ +{ + "2001:1::/64": [ + { + "prefix": "2001:1::/64", + "prefixLen": 64, + "protocol": "connected", + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 0, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "dum0", + "active": true, + "weight": 1 + } + ] + } + ], + "2001:2::/64": [ + { + "prefix": "2001:2::/64", + "prefixLen": 64, + "protocol": "bgp", + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ], + "asPath": "1 2 65002" + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/setup.sh b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/setup.sh new file mode 100644 index 0000000000..88bdcbda82 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/setup.sh @@ -0,0 +1 @@ +ip link add dum0 type dummy diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/zebra.conf new file mode 100644 index 0000000000..b6866f8a43 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/zebra.conf @@ -0,0 +1,16 @@ +log file zebra.log +! +hostname ce1 +! +interface eth0 + ipv6 address fd01::2/64 +! +interface dum0 + ip address 192.168.1.1/24 + ipv6 address 2001:1::1/64 +! +ip forwarding +ipv6 forwarding +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/bgpd.conf new file mode 100644 index 0000000000..df9a93b033 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/bgpd.conf @@ -0,0 +1,43 @@ +frr defaults traditional +! +bgp send-extra-data zebra +! +hostname ce2 +password zebra +! +log stdout notifications +log commands +! +!debug bgp neighbor-events +!debug bgp zebra +!debug bgp vnc verbose +!debug bgp update-groups +!debug bgp updates in +!debug bgp updates out +!debug bgp vpn label +!debug bgp vpn leak-from-vrf +!debug bgp vpn leak-to-vrf +!debug bgp vpn rmap-event +! +router bgp 65002 + bgp router-id 2.0.0.2 + no bgp ebgp-requires-policy + !no bgp default ipv4-unicast + neighbor fd02::1 remote-as 2 + neighbor fd02::1 timers 3 10 + neighbor fd02::1 timers connect 1 + neighbor fd02::1 interface eth0 + neighbor fd02::1 update-source fd02::2 + neighbor fd02::1 capability extended-nexthop + ! + address-family ipv4 unicast + network 192.168.2.0 mask 255.255.255.0 + neighbor fd02::1 activate + exit-address-family + ! + address-family ipv6 unicast + network 2001:2::/64 + neighbor fd02::1 activate + exit-address-family + ! +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/ip_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/ip_rib.json new file mode 100644 index 0000000000..936f239ea6 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/ip_rib.json @@ -0,0 +1,59 @@ +{ + "192.168.1.0/24": [ + { + "prefix": "192.168.1.0/24", + "prefixLen": 24, + "protocol": "bgp", + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ], + "asPath": "2 1 65001" + } + ], + "192.168.2.0/24": [ + { + "prefix": "192.168.2.0/24", + "prefixLen": 24, + "protocol": "connected", + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 0, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "dum0", + "active": true, + "weight": 1 + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/ipv6_rib.json new file mode 100644 index 0000000000..260adbc20c --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/ipv6_rib.json @@ -0,0 +1,59 @@ +{ + "2001:1::/64": [ + { + "prefix": "2001:1::/64", + "prefixLen": 64, + "protocol": "bgp", + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ], + "asPath": "2 1 65001" + } + ], + "2001:2::/64": [ + { + "prefix": "2001:2::/64", + "prefixLen": 64, + "protocol": "connected", + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 0, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "dum0", + "active": true, + "weight": 1 + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/setup.sh b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/setup.sh new file mode 100644 index 0000000000..88bdcbda82 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/setup.sh @@ -0,0 +1 @@ +ip link add dum0 type dummy diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/zebra.conf new file mode 100644 index 0000000000..0faa8a7a05 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/zebra.conf @@ -0,0 +1,16 @@ +log file zebra.log +! +hostname ce1 +! +interface eth0 + ipv6 address fd02::2/64 +! +interface dum0 + ip address 192.168.2.1/24 + ipv6 address 2001:2::1/64 +! +ip forwarding +ipv6 forwarding +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/bgpd.conf new file mode 100644 index 0000000000..b26326ea10 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/bgpd.conf @@ -0,0 +1,71 @@ +frr defaults traditional +! +bgp send-extra-data zebra +! +hostname r1 +password zebra +! +log stdout notifications +log commands +! +!debug bgp neighbor-events +!debug bgp nht +!debug bgp zebra +!debug bgp vnc verbose +!debug bgp update-groups +!debug bgp updates in +!debug bgp updates out +!debug bgp vpn label +!debug bgp vpn leak-from-vrf +!debug bgp vpn leak-to-vrf +!debug bgp vpn rmap-event +! +router bgp 1 + bgp router-id 1.1.1.1 + no bgp default ipv4-unicast + no bgp ebgp-requires-policy + neighbor 2001::2 remote-as 2 + neighbor 2001::2 timers 3 10 + neighbor 2001::2 timers connect 1 + neighbor 2001::2 capability extended-nexthop + ! + address-family ipv4 vpn + neighbor 2001::2 activate + exit-address-family + ! + address-family ipv6 vpn + neighbor 2001::2 activate + exit-address-family + ! + segment-routing srv6 + locator loc1 + ! +! +router bgp 1 vrf vrf10 + bgp router-id 1.1.1.1 + no bgp ebgp-requires-policy + sid vpn per-vrf export auto + neighbor fd01::2 remote-as 65001 + neighbor fd01::2 capability extended-nexthop + neighbor fd01::2 description ce1 + neighbor fd01::2 interface eth1 + neighbor fd01::2 update-source fd01::1 + ! + address-family ipv4 unicast + nexthop vpn export 2001::1 + rd vpn export 1:10 + rt vpn both 99:99 + import vpn + export vpn + neighbor fd01::2 activate + exit-address-family + ! + address-family ipv6 unicast + nexthop vpn export 2001::1 + rd vpn export 1:10 + rt vpn both 99:99 + import vpn + export vpn + neighbor fd01::2 activate + exit-address-family +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/setup.sh b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/setup.sh new file mode 100644 index 0000000000..ac1844f733 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/setup.sh @@ -0,0 +1,4 @@ +sysctl net.vrf.strict_mode=1 +ip link add vrf10 type vrf table 10 +ip link set vrf10 up +ip link set eth1 master vrf10 diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vpnv4_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vpnv4_rib.json new file mode 100644 index 0000000000..6cdeac2991 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vpnv4_rib.json @@ -0,0 +1,64 @@ +{ + "vrfId": 0, + "vrfName": "default", + "routerId": "1.1.1.1", + "defaultLocPrf": 100, + "localAS": 1, + "routes": { + "routeDistinguishers": { + "1:10": { + "192.168.1.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.1.0", + "prefixLen": 24, + "network": "192.168.1.0/24", + "metric": 0, + "weight": 0, + "peerId": "(unspec)", + "path": "65001", + "origin": "IGP", + "nhVrfName": "vrf10", + "nexthops": [ + { + "ip": "2001::1", + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "2:10": { + "192.168.2.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.2.0", + "prefixLen": 24, + "network": "192.168.2.0/24", + "metric": 0, + "weight": 0, + "peerId": "2001::2", + "path": "2 65002", + "origin": "IGP", + "nexthops": [ + { + "ip": "2001::2", + "hostname": "r2", + "afi": "ipv6", + "used": true + } + ] + } + ] + } + } + } +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vpnv6_rib.json new file mode 100644 index 0000000000..77b272de65 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vpnv6_rib.json @@ -0,0 +1,63 @@ +{ + "vrfId": 0, + "vrfName": "default", + "routerId": "1.1.1.1", + "defaultLocPrf": 100, + "localAS": 1, + "routes": { + "routeDistinguishers": { + "1:10": { + "2001:1::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:1::", + "prefixLen": 64, + "network": "2001:1::/64", + "metric": 0, + "weight": 0, + "peerId": "(unspec)", + "path": "65001", + "origin": "IGP", + "nhVrfName": "vrf10", + "nexthops": [ + { + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "2:10": { + "2001:2::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:2::", + "prefixLen": 64, + "network": "2001:2::/64", + "metric": 0, + "weight": 0, + "peerId": "2001::2", + "path": "2 65002", + "origin": "IGP", + "nexthops": [ + { + "ip": "2001::2", + "hostname": "r2", + "afi": "ipv6", + "used": true + } + ] + } + ] + } + } + } +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vrf10v4_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vrf10v4_rib.json new file mode 100644 index 0000000000..f7da30637b --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vrf10v4_rib.json @@ -0,0 +1,62 @@ +{ + "192.168.1.0/24": [ + { + "prefix": "192.168.1.0/24", + "prefixLen": 24, + "protocol": "bgp", + "vrfName": "vrf10", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 10, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth1", + "active": true + } + ], + "asPath": "65001" + } + ], + "192.168.2.0/24": [ + { + "prefix": "192.168.2.0/24", + "prefixLen": 24, + "protocol": "bgp", + "vrfName": "vrf10", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 10, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth0", + "vrf": "default", + "active": true, + "seg6": { + "segs": "2001:db8:2:2:1::" + } + } + ], + "asPath": "2 65002" + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vrf10v6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vrf10v6_rib.json new file mode 100644 index 0000000000..12e7087060 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vrf10v6_rib.json @@ -0,0 +1,63 @@ +{ + "2001:1::/64": [ + { + "prefix": "2001:1::/64", + "prefixLen": 64, + "protocol": "bgp", + "vrfName": "vrf10", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 10, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth1", + "active": true, + "weight": 1 + } + ], + "asPath": "65001" + } + ], + "2001:2::/64": [ + { + "prefix": "2001:2::/64", + "prefixLen": 64, + "protocol": "bgp", + "vrfName": "vrf10", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 10, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth0", + "vrf": "default", + "active": true, + "seg6": { + "segs": "2001:db8:2:2:1::" + } + } + ], + "asPath": "2 65002" + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/zebra.conf new file mode 100644 index 0000000000..78aa81fcb8 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/zebra.conf @@ -0,0 +1,25 @@ +log file zebra.log +! +hostname r1 +! +interface eth0 + ipv6 address 2001::1/64 +! +interface eth1 vrf vrf10 + ipv6 address fd01::1/64 +! +segment-routing + srv6 + locators + locator loc1 + prefix 2001:db8:1:1::/64 + ! + ! +! +ip forwarding +ipv6 forwarding +! +ipv6 route 2001:db8:2:2::/64 2001::2 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/bgpd.conf new file mode 100644 index 0000000000..63dce15ff7 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/bgpd.conf @@ -0,0 +1,71 @@ +frr defaults traditional +! +bgp send-extra-data zebra +! +hostname r2 +password zebra +! +log stdout notifications +log commands +! +!debug bgp neighbor-events +!debug bgp nht +!debug bgp zebra +!debug bgp vnc verbose +!debug bgp update-groups +!debug bgp updates in +!debug bgp updates out +!debug bgp vpn label +!debug bgp vpn leak-from-vrf +!debug bgp vpn leak-to-vrf +!debug bgp vpn rmap-event +! +router bgp 2 + bgp router-id 2.2.2.2 + no bgp default ipv4-unicast + no bgp ebgp-requires-policy + neighbor 2001::1 remote-as 1 + neighbor 2001::1 timers 3 10 + neighbor 2001::1 timers connect 1 + neighbor 2001::1 capability extended-nexthop + ! + address-family ipv4 vpn + neighbor 2001::1 activate + exit-address-family + ! + address-family ipv6 vpn + neighbor 2001::1 activate + exit-address-family + ! + segment-routing srv6 + locator loc1 + ! +! +router bgp 2 vrf vrf10 + bgp router-id 2.2.2.2 + no bgp ebgp-requires-policy + sid vpn per-vrf export auto + neighbor fd02::2 remote-as 65002 + neighbor fd02::2 capability extended-nexthop + neighbor fd02::2 description ce2 + neighbor fd02::2 interface eth1 + neighbor fd02::2 update-source fd02::1 + ! + address-family ipv4 unicast + nexthop vpn export 2001::2 + rd vpn export 2:10 + rt vpn both 99:99 + import vpn + export vpn + neighbor fd02::2 activate + exit-address-family + ! + address-family ipv6 unicast + nexthop vpn export 2001::2 + rd vpn export 2:10 + rt vpn both 99:99 + import vpn + export vpn + neighbor fd02::2 activate + exit-address-family +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/setup.sh b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/setup.sh new file mode 100644 index 0000000000..ac1844f733 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/setup.sh @@ -0,0 +1,4 @@ +sysctl net.vrf.strict_mode=1 +ip link add vrf10 type vrf table 10 +ip link set vrf10 up +ip link set eth1 master vrf10 diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vpnv4_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vpnv4_rib.json new file mode 100644 index 0000000000..c1f67a771c --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vpnv4_rib.json @@ -0,0 +1,64 @@ +{ + "vrfId": 0, + "vrfName": "default", + "routerId": "2.2.2.2", + "defaultLocPrf": 100, + "localAS": 2, + "routes": { + "routeDistinguishers": { + "1:10": { + "192.168.1.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.1.0", + "prefixLen": 24, + "network": "192.168.1.0/24", + "metric": 0, + "weight": 0, + "peerId": "2001::1", + "path": "1 65001", + "origin": "IGP", + "nexthops": [ + { + "ip": "2001::1", + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "2:10": { + "192.168.2.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.2.0", + "prefixLen": 24, + "network": "192.168.2.0/24", + "metric": 0, + "weight": 0, + "peerId": "(unspec)", + "path": "65002", + "origin": "IGP", + "nhVrfName": "vrf10", + "nexthops": [ + { + "ip": "2001::2", + "hostname": "r2", + "afi": "ipv6", + "used": true + } + ] + } + ] + } + } + } +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vpnv6_rib.json new file mode 100644 index 0000000000..da3ddd0699 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vpnv6_rib.json @@ -0,0 +1,63 @@ +{ + "vrfId": 0, + "vrfName": "default", + "routerId": "2.2.2.2", + "defaultLocPrf": 100, + "localAS": 2, + "routes": { + "routeDistinguishers": { + "1:10": { + "2001:1::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:1::", + "prefixLen": 64, + "network": "2001:1::/64", + "metric": 0, + "weight": 0, + "peerId": "2001::1", + "path": "1 65001", + "origin": "IGP", + "nexthops": [ + { + "ip": "2001::1", + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "2:10": { + "2001:2::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:2::", + "prefixLen": 64, + "network": "2001:2::/64", + "metric": 0, + "weight": 0, + "peerId": "(unspec)", + "path": "65002", + "origin": "IGP", + "nhVrfName": "vrf10", + "nexthops": [ + { + "hostname": "r2", + "afi": "ipv6", + "used": true + } + ] + } + ] + } + } + } +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vrf10v4_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vrf10v4_rib.json new file mode 100644 index 0000000000..5cc093fea8 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vrf10v4_rib.json @@ -0,0 +1,63 @@ +{ + "192.168.1.0/24": [ + { + "prefix": "192.168.1.0/24", + "prefixLen": 24, + "protocol": "bgp", + "vrfName": "vrf10", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 10, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth0", + "vrf": "default", + "active": true, + "seg6": { + "segs": "2001:db8:1:1:1::" + } + } + ], + "asPath": "1 65001" + } + ], + "192.168.2.0/24": [ + { + "prefix": "192.168.2.0/24", + "prefixLen": 24, + "protocol": "bgp", + "vrfName": "vrf10", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 10, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth1", + "active": true, + "weight": 1 + } + ], + "asPath": "65002" + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vrf10v6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vrf10v6_rib.json new file mode 100644 index 0000000000..5e8114e17b --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vrf10v6_rib.json @@ -0,0 +1,63 @@ +{ + "2001:1::/64": [ + { + "prefix": "2001:1::/64", + "prefixLen": 64, + "protocol": "bgp", + "vrfName": "vrf10", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 10, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth0", + "vrf": "default", + "active": true, + "seg6": { + "segs": "2001:db8:1:1:1::" + } + } + ], + "asPath": "1 65001" + } + ], + "2001:2::/64": [ + { + "prefix": "2001:2::/64", + "prefixLen": 64, + "protocol": "bgp", + "vrfName": "vrf10", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 10, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth1", + "active": true, + "weight": 1 + } + ], + "asPath": "65002" + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/zebra.conf new file mode 100644 index 0000000000..d7ae058a83 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/zebra.conf @@ -0,0 +1,25 @@ +log file zebra.log +! +hostname r2 +! +interface eth0 + ipv6 address 2001::2/64 +! +interface eth1 vrf vrf10 + ipv6 address fd02::1/64 +! +segment-routing + srv6 + locators + locator loc1 + prefix 2001:db8:2:2::/64 + ! + ! +! +ip forwarding +ipv6 forwarding +! +ipv6 route 2001:db8:1:1::/64 2001::1 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/test_bgp_srv6l3vpn_to_bgp_vrf4.py b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/test_bgp_srv6l3vpn_to_bgp_vrf4.py new file mode 100644 index 0000000000..88bc9847f3 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/test_bgp_srv6l3vpn_to_bgp_vrf4.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# Copyright (c) 2025, Onvox LLC +# Authored by Jonathan Voss +# +# Test SRv6 L3VPN with CE BGP peers within a VRF +# + +import os +import re +import sys +import json +import functools +import pytest + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger +from lib.common_config import required_linux_kernel_version +from lib.checkping import check_ping + +pytestmark = [pytest.mark.bgpd] + + +def build_topo(tgen): + tgen.add_router("r1") + tgen.add_router("r2") + tgen.add_router("ce1") + tgen.add_router("ce2") + + tgen.add_link(tgen.gears["r1"], tgen.gears["r2"], "eth0", "eth0") + tgen.add_link(tgen.gears["ce1"], tgen.gears["r1"], "eth0", "eth1") + tgen.add_link(tgen.gears["ce2"], tgen.gears["r2"], "eth0", "eth1") + + +def setup_module(mod): + result = required_linux_kernel_version("5.14") + if result is not True: + pytest.skip("Kernel requirements are not met") + + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + for rname, router in tgen.routers().items(): + if os.path.exists("{}/{}/setup.sh".format(CWD, rname)): + router.run("/bin/bash {}/{}/setup.sh".format(CWD, rname)) + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) + ) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def open_json_file(filename): + try: + with open(filename, "r") as f: + return json.load(f) + except IOError: + assert False, "Could not read file {}".format(filename) + + +def check_rib(name, cmd, expected_file, count=30, wait=0.5): + def _check(name, dest_addr, match): + logger.info("polling") + tgen = get_topogen() + router = tgen.gears[name] + output = json.loads(router.vtysh_cmd(cmd)) + expected = open_json_file("{}/{}".format(CWD, expected_file)) + return topotest.json_cmp(output, expected) + + logger.info('[+] check {} "{}" {}'.format(name, cmd, expected_file)) + tgen = get_topogen() + func = functools.partial(_check, name, cmd, expected_file) + _, result = topotest.run_and_expect(func, None, count, wait) + assert result is None, "Failed" + + +def test_rib(): + check_rib("r1", "show bgp ipv4 vpn json", "r1/vpnv4_rib.json", 120, 1) + check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib.json") + check_rib("r1", "show ip route vrf vrf10 json", "r1/vrf10v4_rib.json") + check_rib("r2", "show ip route vrf vrf10 json", "r2/vrf10v4_rib.json") + check_rib("ce1", "show ip route json", "ce1/ip_rib.json") + check_rib("ce2", "show ip route json", "ce2/ip_rib.json") + + check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib.json") + check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib.json") + check_rib("r1", "show ipv6 route vrf vrf10 json", "r1/vrf10v6_rib.json") + check_rib("r2", "show ipv6 route vrf vrf10 json", "r2/vrf10v6_rib.json") + check_rib("ce1", "show ipv6 route json", "ce1/ipv6_rib.json") + check_rib("ce2", "show ipv6 route json", "ce2/ipv6_rib.json") + + +def test_ping(): + # IPv4 CE1 to CE2 + check_ping("ce1", "192.168.2.1", True, 10, 3, "192.168.1.1") + # IPv4 CE2 to CE1 + check_ping("ce2", "192.168.1.1", True, 10, 3, "192.168.2.1") + # IPv6 CE1 to CE2 + check_ping("ce1", "2001:2::1", True, 10, 3, "2001:1::1") + # IPv6 CE2 to CE1 + check_ping("ce2", "2001:1::1", True, 10, 3, "2001:2::1") + + +def test_ce_neighbor_reset(): + # Clear CE to R peerings and ensure route exports after + # re-established propogate to VPNv4/VPNv6 and function correctly + tgen = get_topogen() + + for router in ["ce1", "ce2"]: + tgen.gears[router].vtysh_cmd("clear bgp *") + + test_ping() + test_rib() + + +def test_pe_neighbor_reset(): + # Clear R to R peering and ensure route exports after + # re-established propogate to VPNv4/VPNv6 and function correctly + tgen = get_topogen() + + tgen.gears["r1"].vtysh_cmd("clear bgp *") + + test_ping() + test_rib() + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) -- 2.39.5