]> git.puffer.fish Git - mirror/frr.git/commitdiff
topotests: bgp_srv6l3vpn_to_bgp_vrf (step4)
authorHiroki Shirokura <slank.dev@gmail.com>
Fri, 18 Dec 2020 23:40:22 +0000 (08:40 +0900)
committerMark Stapp <mjs@voltanet.io>
Wed, 2 Jun 2021 14:24:48 +0000 (10:24 -0400)
Signed-off-by: Hiroki Shirokura <slank.dev@gmail.com>
29 files changed:
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce1/ipv6_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce1/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce2/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce2/ipv6_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce2/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce3/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce3/ipv6_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce3/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce4/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce4/ipv6_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce4/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce5/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce5/ipv6_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce5/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce6/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce6/ipv6_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce6/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vrf10_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vrf20_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vrf10_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vrf20_rib.json [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/test_bgp_srv6l3vpn_to_bgp_vrf.py [new file with mode: 0755]

diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce1/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce1/bgpd.conf
new file mode 100644 (file)
index 0000000..3459796
--- /dev/null
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce1
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce1/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce1/ipv6_rib.json
new file mode 100644 (file)
index 0000000..d19e315
--- /dev/null
@@ -0,0 +1,58 @@
+{
+  "::/0": [
+    {
+      "prefix": "::/0",
+      "protocol": "static",
+      "vrfId": 0,
+      "vrfName": "default",
+      "selected": true,
+      "destSelected": true,
+      "distance": 1,
+      "metric": 0,
+      "installed": true,
+      "table": 254,
+      "internalStatus": 16,
+      "internalFlags": 73,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "ip": "2001:1::1",
+          "afi": "ipv6",
+          "interfaceName": "eth0",
+          "active": true,
+          "weight": 1
+        }
+      ]
+    }
+  ],
+  "2001:1::/64": [
+    {
+      "prefix": "2001:1::/64",
+      "protocol": "connected",
+      "vrfId": 0,
+      "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": "eth0",
+          "active": true
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce1/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce1/zebra.conf
new file mode 100644 (file)
index 0000000..665808a
--- /dev/null
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce1
+!
+interface eth0
+ ipv6 address 2001:1::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:1::1
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce2/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce2/bgpd.conf
new file mode 100644 (file)
index 0000000..8ed9978
--- /dev/null
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce2
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce2/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce2/ipv6_rib.json
new file mode 100644 (file)
index 0000000..35ff14e
--- /dev/null
@@ -0,0 +1,58 @@
+{
+  "::/0": [
+    {
+      "prefix": "::/0",
+      "protocol": "static",
+      "vrfId": 0,
+      "vrfName": "default",
+      "selected": true,
+      "destSelected": true,
+      "distance": 1,
+      "metric": 0,
+      "installed": true,
+      "table": 254,
+      "internalStatus": 16,
+      "internalFlags": 73,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "ip": "2001:2::1",
+          "afi": "ipv6",
+          "interfaceName": "eth0",
+          "active": true,
+          "weight": 1
+        }
+      ]
+    }
+  ],
+  "2001:2::/64": [
+    {
+      "prefix": "2001:2::/64",
+      "protocol": "connected",
+      "vrfId": 0,
+      "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": "eth0",
+          "active": true
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce2/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce2/zebra.conf
new file mode 100644 (file)
index 0000000..cc9b90a
--- /dev/null
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce2
+!
+interface eth0
+ ipv6 address 2001:2::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:2::1
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce3/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce3/bgpd.conf
new file mode 100644 (file)
index 0000000..a85d970
--- /dev/null
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce3
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce3/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce3/ipv6_rib.json
new file mode 100644 (file)
index 0000000..2f2931f
--- /dev/null
@@ -0,0 +1,58 @@
+{
+  "::/0": [
+    {
+      "prefix": "::/0",
+      "protocol": "static",
+      "vrfId": 0,
+      "vrfName": "default",
+      "selected": true,
+      "destSelected": true,
+      "distance": 1,
+      "metric": 0,
+      "installed": true,
+      "table": 254,
+      "internalStatus": 16,
+      "internalFlags": 73,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "ip": "2001:3::1",
+          "afi": "ipv6",
+          "interfaceName": "eth0",
+          "active": true,
+          "weight": 1
+        }
+      ]
+    }
+  ],
+  "2001:3::/64": [
+    {
+      "prefix": "2001:3::/64",
+      "protocol": "connected",
+      "vrfId": 0,
+      "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": "eth0",
+          "active": true
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce3/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce3/zebra.conf
new file mode 100644 (file)
index 0000000..beca0b1
--- /dev/null
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce3
+!
+interface eth0
+ ipv6 address 2001:3::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:3::1
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce4/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce4/bgpd.conf
new file mode 100644 (file)
index 0000000..93fb32f
--- /dev/null
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce4
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce4/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce4/ipv6_rib.json
new file mode 100644 (file)
index 0000000..8a98768
--- /dev/null
@@ -0,0 +1,58 @@
+{
+  "::/0": [
+    {
+      "prefix": "::/0",
+      "protocol": "static",
+      "vrfId": 0,
+      "vrfName": "default",
+      "selected": true,
+      "destSelected": true,
+      "distance": 1,
+      "metric": 0,
+      "installed": true,
+      "table": 254,
+      "internalStatus": 16,
+      "internalFlags": 73,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "ip": "2001:4::1",
+          "afi": "ipv6",
+          "interfaceName": "eth0",
+          "active": true,
+          "weight": 1
+        }
+      ]
+    }
+  ],
+  "2001:4::/64": [
+    {
+      "prefix": "2001:4::/64",
+      "protocol": "connected",
+      "vrfId": 0,
+      "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": "eth0",
+          "active": true
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce4/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce4/zebra.conf
new file mode 100644 (file)
index 0000000..7b21074
--- /dev/null
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce4
+!
+interface eth0
+ ipv6 address 2001:4::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:4::1
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce5/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce5/bgpd.conf
new file mode 100644 (file)
index 0000000..2ab6f2d
--- /dev/null
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce5
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce5/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce5/ipv6_rib.json
new file mode 100644 (file)
index 0000000..80ff52a
--- /dev/null
@@ -0,0 +1,58 @@
+{
+  "::/0": [
+    {
+      "prefix": "::/0",
+      "protocol": "static",
+      "vrfId": 0,
+      "vrfName": "default",
+      "selected": true,
+      "destSelected": true,
+      "distance": 1,
+      "metric": 0,
+      "installed": true,
+      "table": 254,
+      "internalStatus": 16,
+      "internalFlags": 73,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "ip": "2001:5::1",
+          "afi": "ipv6",
+          "interfaceName": "eth0",
+          "active": true,
+          "weight": 1
+        }
+      ]
+    }
+  ],
+  "2001:5::/64": [
+    {
+      "prefix": "2001:5::/64",
+      "protocol": "connected",
+      "vrfId": 0,
+      "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": "eth0",
+          "active": true
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce5/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce5/zebra.conf
new file mode 100644 (file)
index 0000000..b5ad48e
--- /dev/null
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce5
+!
+interface eth0
+ ipv6 address 2001:5::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:5::1
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce6/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce6/bgpd.conf
new file mode 100644 (file)
index 0000000..e0b6540
--- /dev/null
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce6
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce6/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce6/ipv6_rib.json
new file mode 100644 (file)
index 0000000..ace6136
--- /dev/null
@@ -0,0 +1,58 @@
+{
+  "::/0": [
+    {
+      "prefix": "::/0",
+      "protocol": "static",
+      "vrfId": 0,
+      "vrfName": "default",
+      "selected": true,
+      "destSelected": true,
+      "distance": 1,
+      "metric": 0,
+      "installed": true,
+      "table": 254,
+      "internalStatus": 16,
+      "internalFlags": 73,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "ip": "2001:6::1",
+          "afi": "ipv6",
+          "interfaceName": "eth0",
+          "active": true,
+          "weight": 1
+        }
+      ]
+    }
+  ],
+  "2001:6::/64": [
+    {
+      "prefix": "2001:6::/64",
+      "protocol": "connected",
+      "vrfId": 0,
+      "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": "eth0",
+          "active": true
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce6/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/ce6/zebra.conf
new file mode 100644 (file)
index 0000000..7d19d98
--- /dev/null
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce6
+!
+interface eth0
+ ipv6 address 2001:6::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:6::1
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/bgpd.conf
new file mode 100644 (file)
index 0000000..d07d053
--- /dev/null
@@ -0,0 +1,64 @@
+frr defaults traditional
+!
+hostname r1
+password zebra
+!
+log stdout notifications
+log monitor 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 1
+ bgp router-id 1.1.1.1
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ neighbor 2001::2 remote-as 2
+ neighbor 2001::2 timers 3 10
+ neighbor 2001::2 timers connect 1
+ !
+ 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
+ no bgp default ipv4-unicast
+ !
+ address-family ipv6 unicast
+  sid vpn export auto
+  rd vpn export 1:10
+  rt vpn both 99:99
+  import vpn
+  export vpn
+  redistribute connected
+ exit-address-family
+!
+router bgp 1 vrf vrf20
+ bgp router-id 1.1.1.1
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ !
+ address-family ipv6 unicast
+  sid vpn export auto
+  rd vpn export 1:20
+  rt vpn both 88:88
+  import vpn
+  export vpn
+  redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json
new file mode 100644 (file)
index 0000000..25b7a86
--- /dev/null
@@ -0,0 +1,170 @@
+{
+  "vrfId": 0,
+  "vrfName": "default",
+  "tableVersion": 2,
+  "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": 32768,
+            "peerId": "(unspec)",
+            "path": "",
+            "origin": "incomplete",
+            "announceNexthopSelf": true,
+            "nhVrfName": "vrf10",
+            "nexthops": [
+              {
+                "ip": "::",
+                "hostname": "r1",
+                "afi": "ipv6",
+                "used": true
+              }
+            ]
+          }
+        ],
+        "2001:3::/64": [
+          {
+            "valid": true,
+            "bestpath": true,
+            "selectionReason": "First path received",
+            "pathFrom": "external",
+            "prefix": "2001:3::",
+            "prefixLen": 64,
+            "network": "2001:3::/64",
+            "metric": 0,
+            "weight": 32768,
+            "peerId": "(unspec)",
+            "path": "",
+            "origin": "incomplete",
+            "announceNexthopSelf": true,
+            "nhVrfName": "vrf10",
+            "nexthops": [
+              {
+                "ip": "::",
+                "hostname": "r1",
+                "afi": "ipv6",
+                "used": true
+              }
+            ]
+          }
+        ]
+      },
+      "1:20": {
+        "2001:5::/64": [
+          {
+            "valid": true,
+            "bestpath": true,
+            "selectionReason": "First path received",
+            "pathFrom": "external",
+            "prefix": "2001:5::",
+            "prefixLen": 64,
+            "network": "2001:5::/64",
+            "metric": 0,
+            "weight": 32768,
+            "peerId": "(unspec)",
+            "path": "",
+            "origin": "incomplete",
+            "announceNexthopSelf": true,
+            "nhVrfName": "vrf20",
+            "nexthops": [
+              {
+                "ip": "::",
+                "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",
+            "origin": "incomplete",
+            "nexthops": [
+              {
+                "ip": "2001::2",
+                "hostname": "r2",
+                "afi": "ipv6",
+                "used": true
+              }
+            ]
+          }
+        ]
+      },
+      "2:20": {
+        "2001:4::/64": [
+          {
+            "valid": true,
+            "bestpath": true,
+            "selectionReason": "First path received",
+            "pathFrom": "external",
+            "prefix": "2001:4::",
+            "prefixLen": 64,
+            "network": "2001:4::/64",
+            "metric": 0,
+            "weight": 0,
+            "peerId": "2001::2",
+            "path": "2",
+            "origin": "incomplete",
+            "nexthops": [
+              {
+                "ip": "2001::2",
+                "hostname": "r2",
+                "afi": "ipv6",
+                "used": true
+              }
+            ]
+          }
+        ],
+        "2001:6::/64": [
+          {
+            "valid": true,
+            "bestpath": true,
+            "selectionReason": "First path received",
+            "pathFrom": "external",
+            "prefix": "2001:6::",
+            "prefixLen": 64,
+            "network": "2001:6::/64",
+            "metric": 0,
+            "weight": 0,
+            "peerId": "2001::2",
+            "path": "2",
+            "origin": "incomplete",
+            "nexthops": [
+              {
+                "ip": "2001::2",
+                "hostname": "r2",
+                "afi": "ipv6",
+                "used": true
+              }
+            ]
+          }
+        ]
+      }
+    }
+  }
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vrf10_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vrf10_rib.json
new file mode 100644 (file)
index 0000000..9219d9a
--- /dev/null
@@ -0,0 +1,89 @@
+{
+  "2001:1::/64": [
+    {
+      "prefix": "2001:1::/64",
+      "protocol": "connected",
+      "vrfName": "vrf10",
+      "selected": true,
+      "destSelected": true,
+      "distance": 0,
+      "metric": 0,
+      "installed": true,
+      "table": 10,
+      "internalStatus": 16,
+      "internalFlags": 8,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "directlyConnected": true,
+          "interfaceName": "eth1",
+          "active": true
+        }
+      ]
+    }
+  ],
+  "2001:2::/64": [
+    {
+      "prefix": "2001:2::/64",
+      "protocol": "bgp",
+      "vrfName": "vrf10",
+      "selected": true,
+      "destSelected": true,
+      "distance": 20,
+      "metric": 0,
+      "installed": true,
+      "table": 10,
+      "internalStatus": 16,
+      "internalFlags": 1032,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "afi": "ipv6",
+          "interfaceName": "eth0",
+          "vrf": "default",
+          "active": true,
+          "labels": [
+            3
+          ],
+          "weight": 1,
+          "seg6": {
+            "segs": "2001:db8:2:2::100"
+          }
+        }
+      ],
+      "asPath": "2"
+    }
+  ],
+  "2001:3::/64": [
+    {
+      "prefix": "2001:3::/64",
+      "protocol": "connected",
+      "vrfName": "vrf10",
+      "selected": true,
+      "destSelected": true,
+      "distance": 0,
+      "metric": 0,
+      "installed": true,
+      "table": 10,
+      "internalStatus": 16,
+      "internalFlags": 8,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "directlyConnected": true,
+          "interfaceName": "eth2",
+          "active": true
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vrf20_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vrf20_rib.json
new file mode 100644 (file)
index 0000000..cd4c7d5
--- /dev/null
@@ -0,0 +1,98 @@
+{
+  "2001:4::/64": [
+    {
+      "prefix": "2001:4::/64",
+      "protocol": "bgp",
+      "vrfName": "vrf20",
+      "selected": true,
+      "destSelected": true,
+      "distance": 20,
+      "metric": 0,
+      "installed": true,
+      "table": 20,
+      "internalStatus": 16,
+      "internalFlags": 1032,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "afi": "ipv6",
+          "interfaceName": "eth0",
+          "vrf": "default",
+          "active": true,
+          "labels": [
+            3
+          ],
+          "weight": 1,
+          "seg6": {
+            "segs": "2001:db8:2:2::200"
+          }
+        }
+      ],
+      "asPath": "2"
+    }
+  ],
+  "2001:5::/64": [
+    {
+      "prefix": "2001:5::/64",
+      "protocol": "connected",
+      "vrfName": "vrf20",
+      "selected": true,
+      "destSelected": true,
+      "distance": 0,
+      "metric": 0,
+      "installed": true,
+      "table": 20,
+      "internalStatus": 16,
+      "internalFlags": 8,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "directlyConnected": true,
+          "interfaceName": "eth3",
+          "active": true
+        }
+      ]
+    }
+  ],
+  "2001:6::/64": [
+    {
+      "prefix": "2001:6::/64",
+      "protocol": "bgp",
+      "vrfName": "vrf20",
+      "selected": true,
+      "destSelected": true,
+      "distance": 20,
+      "metric": 0,
+      "installed": true,
+      "table": 20,
+      "internalStatus": 16,
+      "internalFlags": 1032,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "afi": "ipv6",
+          "interfaceName": "eth0",
+          "vrf": "default",
+          "active": true,
+          "labels": [
+            3
+          ],
+          "weight": 1,
+          "seg6": {
+            "segs": "2001:db8:2:2::200"
+          }
+        }
+      ],
+      "asPath": "2"
+    }
+  ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/zebra.conf
new file mode 100644 (file)
index 0000000..ec36870
--- /dev/null
@@ -0,0 +1,40 @@
+log file zebra.log
+!
+hostname r1
+password zebra
+!
+log stdout notifications
+log monitor notifications
+log commands
+!
+debug zebra packet
+debug zebra dplane
+debug zebra kernel
+!
+interface eth0
+ ipv6 address 2001::1/64
+!
+interface eth1 vrf vrf10
+ ipv6 address 2001:1::1/64
+!
+interface eth2 vrf vrf10
+ ipv6 address 2001:3::1/64
+!
+interface eth3 vrf vrf20
+ ipv6 address 2001:5::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_vrf/r2/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/bgpd.conf
new file mode 100644 (file)
index 0000000..d0b3ea8
--- /dev/null
@@ -0,0 +1,65 @@
+frr defaults traditional
+!
+hostname r2
+password zebra
+!
+log stdout notifications
+log monitor 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 updates
+!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 ebgp-requires-policy
+ no bgp default ipv4-unicast
+ neighbor 2001::1 remote-as 1
+ neighbor 2001::1 timers 3 10
+ neighbor 2001::1 timers connect 1
+ !
+ 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
+ no bgp default ipv4-unicast
+ !
+ address-family ipv6 unicast
+  sid vpn export auto
+  rd vpn export 2:10
+  rt vpn both 99:99
+  import vpn
+  export vpn
+  redistribute connected
+ exit-address-family
+!
+router bgp 2 vrf vrf20
+ bgp router-id 2.2.2.2
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ !
+ address-family ipv6 unicast
+  sid vpn export auto
+  rd vpn export 2:20
+  rt vpn both 88:88
+  import vpn
+  export vpn
+  redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json
new file mode 100644 (file)
index 0000000..2cd47b9
--- /dev/null
@@ -0,0 +1,170 @@
+{
+  "vrfId": 0,
+  "vrfName": "default",
+  "tableVersion": 2,
+  "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",
+            "origin": "incomplete",
+            "nexthops": [
+              {
+                "ip": "2001::1",
+                "hostname": "r1",
+                "afi": "ipv6",
+                "used": true
+              }
+            ]
+          }
+        ],
+        "2001:3::/64": [
+          {
+            "valid": true,
+            "bestpath": true,
+            "selectionReason": "First path received",
+            "pathFrom": "external",
+            "prefix": "2001:3::",
+            "prefixLen": 64,
+            "network": "2001:3::/64",
+            "metric": 0,
+            "weight": 0,
+            "peerId": "2001::1",
+            "path": "1",
+            "origin": "incomplete",
+            "nexthops": [
+              {
+                "ip": "2001::1",
+                "hostname": "r1",
+                "afi": "ipv6",
+                "used": true
+              }
+            ]
+          }
+        ]
+      },
+      "1:20": {
+        "2001:5::/64": [
+          {
+            "valid": true,
+            "bestpath": true,
+            "selectionReason": "First path received",
+            "pathFrom": "external",
+            "prefix": "2001:5::",
+            "prefixLen": 64,
+            "network": "2001:5::/64",
+            "metric": 0,
+            "weight": 0,
+            "peerId": "2001::1",
+            "path": "1",
+            "origin": "incomplete",
+            "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": 32768,
+            "peerId": "(unspec)",
+            "path": "",
+            "origin": "incomplete",
+            "announceNexthopSelf": true,
+            "nhVrfName": "vrf10",
+            "nexthops": [
+              {
+                "ip": "::",
+                "hostname": "r2",
+                "afi": "ipv6",
+                "used": true
+              }
+            ]
+          }
+        ]
+      },
+      "2:20": {
+        "2001:4::/64": [
+          {
+            "valid": true,
+            "bestpath": true,
+            "selectionReason": "First path received",
+            "pathFrom": "external",
+            "prefix": "2001:4::",
+            "prefixLen": 64,
+            "network": "2001:4::/64",
+            "metric": 0,
+            "weight": 32768,
+            "peerId": "(unspec)",
+            "path": "",
+            "origin": "incomplete",
+            "announceNexthopSelf": true,
+            "nhVrfName": "vrf20",
+            "nexthops": [
+              {
+                "ip": "::",
+                "hostname": "r2",
+                "afi": "ipv6",
+                "used": true
+              }
+            ]
+          }
+        ],
+        "2001:6::/64": [
+          {
+            "valid": true,
+            "bestpath": true,
+            "selectionReason": "First path received",
+            "pathFrom": "external",
+            "prefix": "2001:6::",
+            "prefixLen": 64,
+            "network": "2001:6::/64",
+            "metric": 0,
+            "weight": 32768,
+            "peerId": "(unspec)",
+            "path": "",
+            "origin": "incomplete",
+            "announceNexthopSelf": true,
+            "nhVrfName": "vrf20",
+            "nexthops": [
+              {
+                "ip": "::",
+                "hostname": "r2",
+                "afi": "ipv6",
+                "used": true
+              }
+            ]
+          }
+        ]
+      }
+    }
+  }
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vrf10_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vrf10_rib.json
new file mode 100644 (file)
index 0000000..5ae377c
--- /dev/null
@@ -0,0 +1,98 @@
+{
+  "2001:1::/64": [
+    {
+      "prefix": "2001:1::/64",
+      "protocol": "bgp",
+      "vrfName": "vrf10",
+      "selected": true,
+      "destSelected": true,
+      "distance": 20,
+      "metric": 0,
+      "installed": true,
+      "table": 10,
+      "internalStatus": 16,
+      "internalFlags": 1032,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "afi": "ipv6",
+          "interfaceName": "eth0",
+          "vrf": "default",
+          "active": true,
+          "labels": [
+            3
+          ],
+          "weight": 1,
+          "seg6": {
+            "segs": "2001:db8:1:1::100"
+          }
+        }
+      ],
+      "asPath": "1"
+    }
+  ],
+  "2001:2::/64": [
+    {
+      "prefix": "2001:2::/64",
+      "protocol": "connected",
+      "vrfName": "vrf10",
+      "selected": true,
+      "destSelected": true,
+      "distance": 0,
+      "metric": 0,
+      "installed": true,
+      "table": 10,
+      "internalStatus": 16,
+      "internalFlags": 8,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "directlyConnected": true,
+          "interfaceName": "eth1",
+          "active": true
+        }
+      ]
+    }
+  ],
+  "2001:3::/64": [
+    {
+      "prefix": "2001:3::/64",
+      "protocol": "bgp",
+      "vrfName": "vrf10",
+      "selected": true,
+      "destSelected": true,
+      "distance": 20,
+      "metric": 0,
+      "installed": true,
+      "table": 10,
+      "internalStatus": 16,
+      "internalFlags": 1032,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "afi": "ipv6",
+          "interfaceName": "eth0",
+          "vrf": "default",
+          "active": true,
+          "labels": [
+            3
+          ],
+          "weight": 1,
+          "seg6": {
+            "segs": "2001:db8:1:1::100"
+          }
+        }
+      ],
+      "asPath": "1"
+    }
+  ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vrf20_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vrf20_rib.json
new file mode 100644 (file)
index 0000000..ea1fe4c
--- /dev/null
@@ -0,0 +1,89 @@
+{
+  "2001:4::/64": [
+    {
+      "prefix": "2001:4::/64",
+      "protocol": "connected",
+      "vrfName": "vrf20",
+      "selected": true,
+      "destSelected": true,
+      "distance": 0,
+      "metric": 0,
+      "installed": true,
+      "table": 20,
+      "internalStatus": 16,
+      "internalFlags": 8,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "directlyConnected": true,
+          "interfaceName": "eth2",
+          "active": true
+        }
+      ]
+    }
+  ],
+  "2001:5::/64": [
+    {
+      "prefix": "2001:5::/64",
+      "protocol": "bgp",
+      "vrfName": "vrf20",
+      "selected": true,
+      "destSelected": true,
+      "distance": 20,
+      "metric": 0,
+      "installed": true,
+      "table": 20,
+      "internalStatus": 16,
+      "internalFlags": 1032,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "afi": "ipv6",
+          "interfaceName": "eth0",
+          "vrf": "default",
+          "active": true,
+          "labels": [
+            3
+          ],
+          "weight": 1,
+          "seg6": {
+            "segs": "2001:db8:1:1::200"
+          }
+        }
+      ],
+      "asPath": "1"
+    }
+  ],
+  "2001:6::/64": [
+    {
+      "prefix": "2001:6::/64",
+      "protocol": "connected",
+      "vrfName": "vrf20",
+      "selected": true,
+      "destSelected": true,
+      "distance": 0,
+      "metric": 0,
+      "installed": true,
+      "table": 20,
+      "internalStatus": 16,
+      "internalFlags": 8,
+      "internalNextHopNum": 1,
+      "internalNextHopActiveNum": 1,
+      "nexthops": [
+        {
+          "flags": 3,
+          "fib": true,
+          "directlyConnected": true,
+          "interfaceName": "eth3",
+          "active": true
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/zebra.conf
new file mode 100644 (file)
index 0000000..f3e025d
--- /dev/null
@@ -0,0 +1,40 @@
+log file zebra.log
+!
+hostname r2
+password zebra
+!
+log stdout notifications
+log monitor notifications
+log commands
+!
+debug zebra packet
+debug zebra dplane
+debug zebra kernel
+!
+interface eth0
+ ipv6 address 2001::2/64
+!
+interface eth1 vrf vrf10
+ ipv6 address 2001:2::1/64
+!
+interface eth2 vrf vrf20
+ ipv6 address 2001:4::1/64
+!
+interface eth3 vrf vrf20
+ ipv6 address 2001:6::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_vrf/test_bgp_srv6l3vpn_to_bgp_vrf.py b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/test_bgp_srv6l3vpn_to_bgp_vrf.py
new file mode 100755 (executable)
index 0000000..2d80c66
--- /dev/null
@@ -0,0 +1,204 @@
+#!/usr/bin/env python
+
+#
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2018, LabN Consulting, L.L.C.
+# Authored by Lou Berger <lberger@labn.net>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+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 mininet.topo import Topo
+
+
+class Topology(Topo):
+    """
+      CE1     CE3      CE5
+    (eth0)  (eth0)   (eth0)
+      :2      :2      :2
+       |       |       |
+     2001:   2001:   2001:
+     1::/64  3::/64  5::/64
+       |       |       |
+      :1      :1      :1
+   +-(eth1)--(eth2)---(eth3)-+
+   |     \   /          |    |
+   |    (vrf10)     (vrf20)  |
+   |             R1          |
+   +----------(eth0)---------+
+                :1
+                |
+            2001::/64
+                |
+                :2
+              (eth0)
+    +----------(eth0)--------------+
+    |            R2                |
+    |   (vrf10)       (vrf20)      |
+    |     /           /     \      |
+    +-(eth1)-----(eth2)-----(eth3)-+
+        :1         :1          :1
+         |          |           |
+      +------+   +------+   +------+
+     /  2001: \ /  2001: \ /  2001: \
+     \ 2::/64 / \ 4::/64 / \ 6::/64 /
+      +------+   +------+   +------+
+         |           |          |
+        :2          :2         :2
+      (eth0)      (eth0)      (eth0)
+        CE2         CE4         CE6
+    """
+    def build(self, *_args, **_opts):
+        tgen = get_topogen(self)
+        tgen.add_router("r1")
+        tgen.add_router("r2")
+        tgen.add_router("ce1")
+        tgen.add_router("ce2")
+        tgen.add_router("ce3")
+        tgen.add_router("ce4")
+        tgen.add_router("ce5")
+        tgen.add_router("ce6")
+
+        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")
+        tgen.add_link(tgen.gears["ce3"], tgen.gears["r1"], "eth0", "eth2")
+        tgen.add_link(tgen.gears["ce4"], tgen.gears["r2"], "eth0", "eth2")
+        tgen.add_link(tgen.gears["ce5"], tgen.gears["r1"], "eth0", "eth3")
+        tgen.add_link(tgen.gears["ce6"], tgen.gears["r2"], "eth0", "eth3")
+
+
+def setup_module(mod):
+    result = required_linux_kernel_version("4.15")
+    if result is not True:
+        pytest.skip("Kernel requirements are not met")
+
+    tgen = Topogen(Topology, mod.__name__)
+    tgen.start_topology()
+    router_list = tgen.routers()
+    for rname, router in tgen.routers().items():
+        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.gears["r1"].run("ip link add vrf10 type vrf table 10")
+    tgen.gears["r1"].run("ip link set vrf10 up")
+    tgen.gears["r1"].run("ip link add vrf20 type vrf table 20")
+    tgen.gears["r1"].run("ip link set vrf20 up")
+    tgen.gears["r1"].run("ip link set eth1 master vrf10")
+    tgen.gears["r1"].run("ip link set eth2 master vrf10")
+    tgen.gears["r1"].run("ip link set eth3 master vrf20")
+
+    tgen.gears["r2"].run("ip link add vrf10 type vrf table 10")
+    tgen.gears["r2"].run("ip link set vrf10 up")
+    tgen.gears["r2"].run("ip link add vrf20 type vrf table 20")
+    tgen.gears["r2"].run("ip link set vrf20 up")
+    tgen.gears["r2"].run("ip link set eth1 master vrf10")
+    tgen.gears["r2"].run("ip link set eth2 master vrf20")
+    tgen.gears["r2"].run("ip link set eth3 master vrf20")
+    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 test_rib():
+    def _check(name, cmd, expected_file):
+        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)
+
+    def check(name, cmd, expected_file):
+        logger.info("[+] check {} \"{}\" {}".format(name, cmd, expected_file))
+        tgen = get_topogen()
+        func = functools.partial(_check, name, cmd, expected_file)
+        success, result = topotest.run_and_expect(func, None, count=10, wait=0.5)
+        assert result is None, 'Failed'
+
+    check("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib.json")
+    check("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib.json")
+    check("r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_rib.json")
+    check("r1", "show ipv6 route vrf vrf20 json", "r1/vrf20_rib.json")
+    check("r2", "show ipv6 route vrf vrf10 json", "r2/vrf10_rib.json")
+    check("r2", "show ipv6 route vrf vrf20 json", "r2/vrf20_rib.json")
+    check("ce1", "show ipv6 route json", "ce1/ipv6_rib.json")
+    check("ce2", "show ipv6 route json", "ce2/ipv6_rib.json")
+    check("ce3", "show ipv6 route json", "ce3/ipv6_rib.json")
+    check("ce4", "show ipv6 route json", "ce4/ipv6_rib.json")
+    check("ce5", "show ipv6 route json", "ce5/ipv6_rib.json")
+    check("ce6", "show ipv6 route json", "ce6/ipv6_rib.json")
+
+
+def test_ping():
+    def _check(name, dest_addr, match):
+        tgen = get_topogen()
+        output = tgen.gears[name].run("ping6 {} -c 1 -w 1".format(dest_addr))
+        logger.info(output)
+        assert match in output, "ping fail"
+
+    def check(name, dest_addr, match):
+        logger.info("[+] check {} {} {}".format(name, dest_addr, match))
+        tgen = get_topogen()
+        func = functools.partial(_check, name, dest_addr, match)
+        success, result = topotest.run_and_expect(func, None, count=10, wait=0.5)
+        assert result is None, 'Failed'
+
+    check("ce1", "2001:2::2", " 0% packet loss")
+    check("ce1", "2001:3::2", " 0% packet loss")
+    check("ce1", "2001:4::2", " 100% packet loss")
+    check("ce1", "2001:5::2", " 100% packet loss")
+    check("ce1", "2001:6::2", " 100% packet loss")
+    check("ce4", "2001:1::2", " 100% packet loss")
+    check("ce4", "2001:2::2", " 100% packet loss")
+    check("ce4", "2001:3::2", " 100% packet loss")
+    check("ce4", "2001:5::2", " 0% packet loss")
+    check("ce4", "2001:6::2", " 0% packet loss")
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))