]> git.puffer.fish Git - matthieu/frr.git/commitdiff
topotests: extend bgp_srv6_l3vpn_to_bgp_vrf4 test with bgp peers
authorJonathan Voss <jvoss@onvox.net>
Thu, 13 Mar 2025 22:04:48 +0000 (22:04 +0000)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Mon, 24 Mar 2025 08:17:01 +0000 (09:17 +0100)
This test ensures route redistribution across an srv6 VPN network
is well taken into account.

Signed-off-by: Jonathan Voss <jvoss@onvox.net>
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
25 files changed:
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/ip_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/ipv6_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/setup.sh [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce1/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/ip_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/ipv6_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/setup.sh [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/ce2/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/setup.sh [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vpnv4_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vpnv6_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vrf10v4_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/vrf10v6_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r1/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/setup.sh [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vpnv4_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vpnv6_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vrf10v4_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/vrf10v6_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/r2/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf4/test_bgp_srv6l3vpn_to_bgp_vrf4.py [new file with mode: 0644]

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 (file)
index 0000000..224d59b
--- /dev/null
@@ -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 (file)
index 0000000..352c48b
--- /dev/null
@@ -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 (file)
index 0000000..fd10ee3
--- /dev/null
@@ -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 (file)
index 0000000..88bdcbd
--- /dev/null
@@ -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 (file)
index 0000000..b6866f8
--- /dev/null
@@ -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 (file)
index 0000000..df9a93b
--- /dev/null
@@ -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 (file)
index 0000000..936f239
--- /dev/null
@@ -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 (file)
index 0000000..260adbc
--- /dev/null
@@ -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 (file)
index 0000000..88bdcbd
--- /dev/null
@@ -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 (file)
index 0000000..0faa8a7
--- /dev/null
@@ -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 (file)
index 0000000..b26326e
--- /dev/null
@@ -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 (file)
index 0000000..ac1844f
--- /dev/null
@@ -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 (file)
index 0000000..6cdeac2
--- /dev/null
@@ -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 (file)
index 0000000..77b272d
--- /dev/null
@@ -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 (file)
index 0000000..f7da306
--- /dev/null
@@ -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 (file)
index 0000000..12e7087
--- /dev/null
@@ -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 (file)
index 0000000..78aa81f
--- /dev/null
@@ -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 (file)
index 0000000..63dce15
--- /dev/null
@@ -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 (file)
index 0000000..ac1844f
--- /dev/null
@@ -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 (file)
index 0000000..c1f67a7
--- /dev/null
@@ -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 (file)
index 0000000..da3ddd0
--- /dev/null
@@ -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 (file)
index 0000000..5cc093f
--- /dev/null
@@ -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 (file)
index 0000000..5e8114e
--- /dev/null
@@ -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 (file)
index 0000000..d7ae058
--- /dev/null
@@ -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 (file)
index 0000000..88bc984
--- /dev/null
@@ -0,0 +1,143 @@
+#!/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))