--- /dev/null
+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
+ !
+!
--- /dev/null
+{
+ "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"
+ }
+ ]
+}
--- /dev/null
+{
+ "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"
+ }
+ ]
+}
--- /dev/null
+ip link add dum0 type dummy
--- /dev/null
+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
+!
--- /dev/null
+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
+ !
+!
--- /dev/null
+{
+ "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
+ }
+ ]
+ }
+ ]
+}
--- /dev/null
+{
+ "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
+ }
+ ]
+ }
+ ]
+}
--- /dev/null
+ip link add dum0 type dummy
--- /dev/null
+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
+!
--- /dev/null
+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
+!
--- /dev/null
+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
--- /dev/null
+{
+ "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
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
--- /dev/null
+{
+ "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
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
--- /dev/null
+{
+ "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"
+ }
+ ]
+}
--- /dev/null
+{
+ "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"
+ }
+ ]
+}
--- /dev/null
+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
+!
--- /dev/null
+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
+!
--- /dev/null
+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
--- /dev/null
+{
+ "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
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
--- /dev/null
+{
+ "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
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
--- /dev/null
+{
+ "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"
+ }
+ ]
+}
--- /dev/null
+{
+ "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"
+ }
+ ]
+}
--- /dev/null
+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
+!
--- /dev/null
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+# Copyright (c) 2025, Onvox LLC
+# Authored by Jonathan Voss <jvoss@onvox.net>
+#
+# 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))