summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/topotests/bgp_ipv6_rtadv/__init__.py0
-rw-r--r--tests/topotests/bgp_ipv6_rtadv/r1/bgpd.conf13
-rw-r--r--tests/topotests/bgp_ipv6_rtadv/r1/ipv4_routes.json44
-rw-r--r--tests/topotests/bgp_ipv6_rtadv/r1/ipv6_routes.json39
-rw-r--r--tests/topotests/bgp_ipv6_rtadv/r1/zebra.conf9
-rw-r--r--tests/topotests/bgp_ipv6_rtadv/r2/bgpd.conf16
-rw-r--r--tests/topotests/bgp_ipv6_rtadv/r2/ipv4_routes.json44
-rw-r--r--tests/topotests/bgp_ipv6_rtadv/r2/ipv6_routes.json23
-rw-r--r--tests/topotests/bgp_ipv6_rtadv/r2/zebra.conf9
-rw-r--r--tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.dot44
-rw-r--r--tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py142
-rw-r--r--tests/topotests/bgp_vrf_lite_ipv6_rtadv/__init__.py0
-rw-r--r--tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/bgpd.conf13
-rw-r--r--tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/ipv4_routes.json50
-rw-r--r--tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/ipv6_routes.json44
-rw-r--r--tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/zebra.conf9
-rw-r--r--tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/bgpd.conf16
-rw-r--r--tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/ipv4_routes.json50
-rw-r--r--tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/ipv6_routes.json26
-rw-r--r--tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/zebra.conf9
-rw-r--r--tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.dot44
-rw-r--r--tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py154
-rw-r--r--zebra/rtadv.c139
-rw-r--r--zebra/rtadv.h4
-rw-r--r--zebra/zebra_ns.c8
-rw-r--r--zebra/zebra_router.h5
-rw-r--r--zebra/zebra_vrf.c9
-rw-r--r--zebra/zebra_vrf.h4
28 files changed, 895 insertions, 72 deletions
diff --git a/tests/topotests/bgp_ipv6_rtadv/__init__.py b/tests/topotests/bgp_ipv6_rtadv/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_rtadv/__init__.py
diff --git a/tests/topotests/bgp_ipv6_rtadv/r1/bgpd.conf b/tests/topotests/bgp_ipv6_rtadv/r1/bgpd.conf
new file mode 100644
index 0000000000..1623b4578b
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_rtadv/r1/bgpd.conf
@@ -0,0 +1,13 @@
+router bgp 101
+ bgp router-id 10.254.254.1
+ neighbor r2g peer-group
+ neighbor r2g remote-as external
+ neighbor r2g bfd
+ neighbor r1-eth0 interface peer-group r2g
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+ address-family ipv6 unicast
+ neighbor r2g activate
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_ipv6_rtadv/r1/ipv4_routes.json b/tests/topotests/bgp_ipv6_rtadv/r1/ipv4_routes.json
new file mode 100644
index 0000000000..8718e49778
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_rtadv/r1/ipv4_routes.json
@@ -0,0 +1,44 @@
+{
+ "10.254.254.2/32": [
+ {
+ "distance": 20,
+ "protocol": "bgp",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "destSelected": true,
+ "prefix": "10.254.254.2/32",
+ "nexthops": [
+ {
+ "interfaceName": "r1-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv6"
+ }
+ ]
+ }
+ ],
+ "10.254.254.1/32": [
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "destSelected": true,
+ "prefix": "10.254.254.1/32",
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "lo",
+ "interfaceIndex": 1,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_ipv6_rtadv/r1/ipv6_routes.json b/tests/topotests/bgp_ipv6_rtadv/r1/ipv6_routes.json
new file mode 100644
index 0000000000..d0378b5649
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_rtadv/r1/ipv6_routes.json
@@ -0,0 +1,39 @@
+{
+ "2001:db8:1::/64": [
+ {
+ "distance": 20,
+ "protocol": "bgp",
+ "internalFlags": 0,
+ "metric": 0,
+ "prefix": "2001:db8:1::/64",
+ "nexthops": [
+ {
+ "interfaceName": "r1-eth0",
+ "interfaceIndex": 2,
+ "flags": 1,
+ "active": true,
+ "afi": "ipv6"
+ }
+ ]
+ },
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "destSelected": true,
+ "prefix": "2001:db8:1::/64",
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "r1-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_ipv6_rtadv/r1/zebra.conf b/tests/topotests/bgp_ipv6_rtadv/r1/zebra.conf
new file mode 100644
index 0000000000..f95c3b07a7
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_rtadv/r1/zebra.conf
@@ -0,0 +1,9 @@
+debug zebra packet recv
+debug zebra packet send
+log stdout
+interface lo
+ ip address 10.254.254.1/32
+!
+interface r1-eth0
+ ipv6 address 2001:db8:1::1/64
+!
diff --git a/tests/topotests/bgp_ipv6_rtadv/r2/bgpd.conf b/tests/topotests/bgp_ipv6_rtadv/r2/bgpd.conf
new file mode 100644
index 0000000000..bf42d21812
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_rtadv/r2/bgpd.conf
@@ -0,0 +1,16 @@
+router bgp 102
+ bgp router-id 10.254.254.2
+ neighbor r2g peer-group
+ neighbor r2g remote-as external
+ neighbor r2g bfd
+ neighbor r2-eth0 interface peer-group r2g
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+ !
+ address-family ipv6 unicast
+ redistribute connected
+ neighbor r2g activate
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_ipv6_rtadv/r2/ipv4_routes.json b/tests/topotests/bgp_ipv6_rtadv/r2/ipv4_routes.json
new file mode 100644
index 0000000000..fe26937e80
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_rtadv/r2/ipv4_routes.json
@@ -0,0 +1,44 @@
+{
+ "10.254.254.2/32": [
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "destSelected": true,
+ "prefix": "10.254.254.2/32",
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "lo",
+ "interfaceIndex": 1,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ],
+ "10.254.254.1/32": [
+ {
+ "distance": 20,
+ "protocol": "bgp",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "destSelected": true,
+ "prefix": "10.254.254.1/32",
+ "nexthops": [
+ {
+ "interfaceName": "r2-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv6"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_ipv6_rtadv/r2/ipv6_routes.json b/tests/topotests/bgp_ipv6_rtadv/r2/ipv6_routes.json
new file mode 100644
index 0000000000..d5ad1a2c5b
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_rtadv/r2/ipv6_routes.json
@@ -0,0 +1,23 @@
+{
+ "2001:db8:1::/64": [
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "destSelected": true,
+ "prefix": "2001:db8:1::/64",
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "r2-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_ipv6_rtadv/r2/zebra.conf b/tests/topotests/bgp_ipv6_rtadv/r2/zebra.conf
new file mode 100644
index 0000000000..0131a11be0
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_rtadv/r2/zebra.conf
@@ -0,0 +1,9 @@
+ip forwarding
+ipv6 forwarding
+!
+interface lo
+ ip address 10.254.254.2/32
+!
+interface r2-eth0
+ ipv6 address 2001:db8:1::2/64
+!
diff --git a/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.dot b/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.dot
new file mode 100644
index 0000000000..da67c29a09
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.dot
@@ -0,0 +1,44 @@
+## Color coding:
+#########################
+## Main FRR: #f08080 red
+## Switches: #d0e0d0 gray
+## RIP: #19e3d9 Cyan
+## RIPng: #fcb314 dark yellow
+## OSPFv2: #32b835 Green
+## OSPFv3: #19e3d9 Cyan
+## ISIS IPv4 #fcb314 dark yellow
+## ISIS IPv6 #9a81ec purple
+## BGP IPv4 #eee3d3 beige
+## BGP IPv6 #fdff00 yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph template {
+ label="bfd-topo2";
+
+ # Routers
+ r1 [
+ shape=doubleoctagon,
+ label="r1",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r2 [
+ shape=doubleoctagon
+ label="r2",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+
+ # Switches
+ sw1 [
+ shape=oval,
+ label="sw1\n2001:db8:1::/64",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+
+ # Connections
+ r1 -- sw1 [label="eth0"];
+ r2 -- sw1 [label="eth0"];
+
+}
diff --git a/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py b/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py
new file mode 100644
index 0000000000..6cf223af42
--- /dev/null
+++ b/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env python
+
+#
+# test_bgp_ipv6_rtadv.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2019 by 6WIND
+#
+# 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.
+#
+
+"""
+ test_bgp_ipv6_rtadv.py: Test the FRR/Quagga BGP daemon with BGP IPv6 interface
+ with route advertisements on a separate netns.
+"""
+
+import os
+import sys
+import json
+from functools import partial
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+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
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+
+class BGPIPV6RTADVTopo(Topo):
+ "Test topology builder"
+ def build(self, *_args, **_opts):
+ "Build function"
+ tgen = get_topogen(self)
+
+ # Create 2 routers.
+ tgen.add_router('r1')
+ tgen.add_router('r2')
+
+ switch = tgen.add_switch('s1')
+ switch.add_link(tgen.gears['r1'])
+ switch.add_link(tgen.gears['r2'])
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(BGPIPV6RTADVTopo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for rname, router in router_list.iteritems():
+ 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))
+ )
+
+ # Initialize all routers.
+ tgen.start_router()
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+
+ tgen.stop_topology()
+
+
+def test_protocols_convergence():
+ """
+ Assert that all protocols have converged
+ statuses as they depend on it.
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Check IPv4 routing tables.
+ logger.info("Checking IPv4 routes for convergence")
+ for router in tgen.routers().values():
+ json_file = '{}/{}/ipv4_routes.json'.format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ logger.info('skipping file {}'.format(json_file))
+ continue
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(topotest.router_json_cmp,
+ router, 'show ip route json'.format(router.name), expected)
+ _, result = topotest.run_and_expect(test_func, None, count=160,
+ wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+ # Check IPv6 routing tables.
+ logger.info("Checking IPv6 routes for convergence")
+ for router in tgen.routers().values():
+ json_file = '{}/{}/ipv6_routes.json'.format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ logger.info('skipping file {}'.format(json_file))
+ continue
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(topotest.router_json_cmp,
+ router, 'show ipv6 route json'.format(router.name), expected)
+ _, result = topotest.run_and_expect(test_func, None, count=160,
+ wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip('Memory leak test/report is disabled')
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == '__main__':
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/__init__.py b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/__init__.py
diff --git a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/bgpd.conf b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/bgpd.conf
new file mode 100644
index 0000000000..3c974c767f
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/bgpd.conf
@@ -0,0 +1,13 @@
+router bgp 101 vrf r1-cust1
+ bgp router-id 10.254.254.1
+ neighbor r2g peer-group
+ neighbor r2g remote-as external
+ neighbor r2g bfd
+ neighbor r1-eth0 interface peer-group r2g
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+ address-family ipv6 unicast
+ neighbor r2g activate
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/ipv4_routes.json b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/ipv4_routes.json
new file mode 100644
index 0000000000..e32c84b7d5
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/ipv4_routes.json
@@ -0,0 +1,50 @@
+{
+ "10.254.254.2/32": [
+ {
+ "prefix": "10.254.254.2/32",
+ "protocol": "bgp",
+ "vrfId":3,
+ "selected": true,
+ "destSelected": true,
+ "distance": 20,
+ "metric": 0,
+ "installed": true,
+ "internalStatus": 34,
+ "internalFlags": 8,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "afi": "ipv6",
+ "interfaceIndex": 2,
+ "interfaceName": "r1-eth0",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "10.254.254.1/32": [
+ {
+ "prefix": "10.254.254.1/32",
+ "protocol": "connected",
+ "vrfId":3,
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "internalStatus": 32,
+ "internalFlags": 8,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceIndex": 4,
+ "interfaceName": "loop1",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/ipv6_routes.json b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/ipv6_routes.json
new file mode 100644
index 0000000000..88e8c5cd83
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/ipv6_routes.json
@@ -0,0 +1,44 @@
+{
+ "2001:db8:1::/64": [
+ {
+ "prefix": "2001:db8:1::/64",
+ "protocol": "bgp",
+ "vrfId":3,
+ "distance": 20,
+ "metric": 0,
+ "internalStatus": 2,
+ "internalFlags": 0,
+ "nexthops": [
+ {
+ "flags": 1,
+ "afi": "ipv6",
+ "interfaceIndex": 2,
+ "interfaceName": "r1-eth0",
+ "active": true
+ }
+ ]
+ },
+ {
+ "prefix": "2001:db8:1::/64",
+ "protocol": "connected",
+ "vrfId":3,
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "internalStatus": 32,
+ "internalFlags": 8,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceIndex": 2,
+ "interfaceName": "r1-eth0",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/zebra.conf b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/zebra.conf
new file mode 100644
index 0000000000..f19c497208
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/zebra.conf
@@ -0,0 +1,9 @@
+debug zebra packet recv
+debug zebra packet send
+log stdout
+interface loop1 vrf r1-cust1
+ ip address 10.254.254.1/32
+!
+interface r1-eth0 vrf r1-cust1
+ ipv6 address 2001:db8:1::1/64
+!
diff --git a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/bgpd.conf b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/bgpd.conf
new file mode 100644
index 0000000000..39362abd46
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/bgpd.conf
@@ -0,0 +1,16 @@
+router bgp 102 vrf r2-cust1
+ bgp router-id 10.254.254.2
+ neighbor r2g peer-group
+ neighbor r2g remote-as external
+ neighbor r2g bfd
+ neighbor r2-eth0 interface peer-group r2g
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+ !
+ address-family ipv6 unicast
+ redistribute connected
+ neighbor r2g activate
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/ipv4_routes.json b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/ipv4_routes.json
new file mode 100644
index 0000000000..9d7c0e6e4f
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/ipv4_routes.json
@@ -0,0 +1,50 @@
+{
+ "10.254.254.2/32": [
+ {
+ "prefix": "10.254.254.2/32",
+ "protocol": "connected",
+ "vrfId":3,
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "internalStatus": 32,
+ "internalFlags": 8,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceIndex": 4,
+ "interfaceName": "loop1",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "10.254.254.1/32": [
+ {
+ "prefix": "10.254.254.1/32",
+ "protocol": "bgp",
+ "vrfId":3,
+ "selected": true,
+ "destSelected": true,
+ "distance": 20,
+ "metric": 0,
+ "installed": true,
+ "internalStatus": 34,
+ "internalFlags": 8,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "afi": "ipv6",
+ "interfaceIndex": 2,
+ "interfaceName": "r2-eth0",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/ipv6_routes.json b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/ipv6_routes.json
new file mode 100644
index 0000000000..230fe38748
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/ipv6_routes.json
@@ -0,0 +1,26 @@
+{
+ "2001:db8:1::/64": [
+ {
+ "prefix": "2001:db8:1::/64",
+ "protocol": "connected",
+ "vrfId":3,
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "internalStatus": 32,
+ "internalFlags": 8,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceIndex": 2,
+ "interfaceName": "r2-eth0",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/zebra.conf b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/zebra.conf
new file mode 100644
index 0000000000..c3795ab959
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/zebra.conf
@@ -0,0 +1,9 @@
+ip forwarding
+ipv6 forwarding
+!
+interface loop1 vrf r2-cust1
+ ip address 10.254.254.2/32
+!
+interface r2-eth0 vrf r2-cust1
+ ipv6 address 2001:db8:1::2/64
+!
diff --git a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.dot b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.dot
new file mode 100644
index 0000000000..da67c29a09
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.dot
@@ -0,0 +1,44 @@
+## Color coding:
+#########################
+## Main FRR: #f08080 red
+## Switches: #d0e0d0 gray
+## RIP: #19e3d9 Cyan
+## RIPng: #fcb314 dark yellow
+## OSPFv2: #32b835 Green
+## OSPFv3: #19e3d9 Cyan
+## ISIS IPv4 #fcb314 dark yellow
+## ISIS IPv6 #9a81ec purple
+## BGP IPv4 #eee3d3 beige
+## BGP IPv6 #fdff00 yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph template {
+ label="bfd-topo2";
+
+ # Routers
+ r1 [
+ shape=doubleoctagon,
+ label="r1",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r2 [
+ shape=doubleoctagon
+ label="r2",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+
+ # Switches
+ sw1 [
+ shape=oval,
+ label="sw1\n2001:db8:1::/64",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+
+ # Connections
+ r1 -- sw1 [label="eth0"];
+ r2 -- sw1 [label="eth0"];
+
+}
diff --git a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py
new file mode 100644
index 0000000000..6b4df78c69
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python
+
+#
+# test_bgp_ipv6_rtadv.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2019 by 6WIND
+#
+# 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.
+#
+
+"""
+ test_bgp_ipv6_rtadv.py: Test the FRR/Quagga BGP daemon with BGP IPv6 interface
+ with route advertisements on a separate netns.
+"""
+
+import os
+import sys
+import json
+from functools import partial
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+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
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+
+class BGPIPV6RTADVVRFTopo(Topo):
+ "Test topology builder"
+ def build(self, *_args, **_opts):
+ "Build function"
+ tgen = get_topogen(self)
+
+ # Create 2 routers.
+ tgen.add_router('r1')
+ tgen.add_router('r2')
+
+ switch = tgen.add_switch('s1')
+ switch.add_link(tgen.gears['r1'])
+ switch.add_link(tgen.gears['r2'])
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(BGPIPV6RTADVVRFTopo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ logger.info('Testing with VRF Lite support')
+
+ cmds = ['ip link add {0}-cust1 type vrf table 1001',
+ 'ip link add loop1 type dummy',
+ 'ip link set loop1 master {0}-cust1',
+ 'ip link set {0}-eth0 master {0}-cust1']
+
+ for rname, router in router_list.iteritems():
+ for cmd in cmds:
+ output = tgen.net[rname].cmd(cmd.format(rname))
+
+ for rname, router in router_list.iteritems():
+ 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))
+ )
+
+ # Initialize all routers.
+ tgen.start_router()
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+
+ tgen.stop_topology()
+
+
+def test_protocols_convergence():
+ """
+ Assert that all protocols have converged
+ statuses as they depend on it.
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Check IPv4 routing tables.
+ logger.info("Checking IPv4 routes for convergence")
+
+ for router in tgen.routers().values():
+ json_file = '{}/{}/ipv4_routes.json'.format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ logger.info('skipping file {}'.format(json_file))
+ continue
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(topotest.router_json_cmp,
+ router, 'show ip route vrf {}-cust1 json'.format(router.name), expected)
+ _, result = topotest.run_and_expect(test_func, None, count=160,
+ wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+ # Check IPv6 routing tables.
+ logger.info("Checking IPv6 routes for convergence")
+ for router in tgen.routers().values():
+ json_file = '{}/{}/ipv6_routes.json'.format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ logger.info('skipping file {}'.format(json_file))
+ continue
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(topotest.router_json_cmp,
+ router, 'show ipv6 route vrf {}-cust1 json'.format(router.name), expected)
+ _, result = topotest.run_and_expect(test_func, None, count=160,
+ wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip('Memory leak test/report is disabled')
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == '__main__':
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index 5088e2e8e1..e181b495b8 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -42,7 +42,6 @@
#include "zebra/debug.h"
#include "zebra/rib.h"
#include "zebra/zapi_msg.h"
-#include "zebra/zebra_ns.h"
#include "zebra/zebra_vrf.h"
#include "zebra/zebra_errors.h"
#include "zebra/zebra_router.h"
@@ -81,18 +80,25 @@ enum rtadv_event {
RTADV_READ
};
-static void rtadv_event(struct zebra_ns *, enum rtadv_event, int);
+static void rtadv_event(struct zebra_vrf *, enum rtadv_event, int);
static int if_join_all_router(int, struct interface *);
static int if_leave_all_router(int, struct interface *);
-static int rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex)
+static int rtadv_get_socket(struct zebra_vrf *zvrf)
+{
+ if (zvrf->rtadv.sock > 0)
+ return zvrf->rtadv.sock;
+ return zrouter.rtadv_sock;
+}
+
+static int rtadv_increment_received(struct zebra_vrf *zvrf, ifindex_t *ifindex)
{
int ret = -1;
struct interface *iface;
struct zebra_if *zif;
- iface = if_lookup_by_index_per_ns(zns, *ifindex);
+ iface = if_lookup_by_index(*ifindex, zvrf->vrf->vrf_id);
if (iface && iface->info) {
zif = iface->info;
zif->ra_rcvd++;
@@ -101,7 +107,7 @@ static int rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex)
return ret;
}
-static int rtadv_recv_packet(struct zebra_ns *zns, int sock, uint8_t *buf,
+static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf,
int buflen, struct sockaddr_in6 *from,
ifindex_t *ifindex, int *hoplimit)
{
@@ -149,7 +155,7 @@ static int rtadv_recv_packet(struct zebra_ns *zns, int sock, uint8_t *buf,
}
}
- rtadv_increment_received(zns, ifindex);
+ rtadv_increment_received(zvrf, ifindex);
return ret;
}
@@ -461,19 +467,19 @@ no_more_opts:
static int rtadv_timer(struct thread *thread)
{
- struct zebra_ns *zns = THREAD_ARG(thread);
+ struct zebra_vrf *zvrf = THREAD_ARG(thread);
struct vrf *vrf;
struct interface *ifp;
struct zebra_if *zif;
int period;
- zrouter.rtadv.ra_timer = NULL;
- if (zrouter.rtadv.adv_msec_if_count == 0) {
+ zvrf->rtadv.ra_timer = NULL;
+ if (zvrf->rtadv.adv_msec_if_count == 0) {
period = 1000; /* 1 s */
- rtadv_event(zns, RTADV_TIMER, 1 /* 1 s */);
+ rtadv_event(zvrf, RTADV_TIMER, 1 /* 1 s */);
} else {
period = 10; /* 10 ms */
- rtadv_event(zns, RTADV_TIMER_MSEC, 10 /* 10 ms */);
+ rtadv_event(zvrf, RTADV_TIMER_MSEC, 10 /* 10 ms */);
}
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
@@ -500,7 +506,7 @@ static int rtadv_timer(struct thread *thread)
"Fast RA Rexmit on interface %s",
ifp->name);
- rtadv_send_packet(zrouter.rtadv.sock,
+ rtadv_send_packet(rtadv_get_socket(zvrf),
ifp);
} else {
zif->rtadv.AdvIntervalTimer -= period;
@@ -514,8 +520,8 @@ static int rtadv_timer(struct thread *thread)
zif->rtadv
.MaxRtrAdvInterval;
rtadv_send_packet(
- zrouter.rtadv.sock,
- ifp);
+ rtadv_get_socket(zvrf),
+ ifp);
}
}
}
@@ -527,10 +533,9 @@ static int rtadv_timer(struct thread *thread)
static void rtadv_process_solicit(struct interface *ifp)
{
struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
- struct zebra_ns *zns = zvrf->zns;
- assert(zns);
- rtadv_send_packet(zrouter.rtadv.sock, ifp);
+ assert(zvrf);
+ rtadv_send_packet(rtadv_get_socket(zvrf), ifp);
}
/*
@@ -652,7 +657,7 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
static void rtadv_process_packet(uint8_t *buf, unsigned int len,
ifindex_t ifindex, int hoplimit,
struct sockaddr_in6 *from,
- struct zebra_ns *zns)
+ struct zebra_vrf *zvrf)
{
struct icmp6_hdr *icmph;
struct interface *ifp;
@@ -662,7 +667,7 @@ static void rtadv_process_packet(uint8_t *buf, unsigned int len,
inet_ntop(AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN);
/* Interface search. */
- ifp = if_lookup_by_index_per_ns(zns, ifindex);
+ ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
if (ifp == NULL) {
flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
"RA/RS received on unknown IF %u from %s", ifindex,
@@ -724,15 +729,15 @@ static int rtadv_read(struct thread *thread)
struct sockaddr_in6 from;
ifindex_t ifindex = 0;
int hoplimit = -1;
- struct zebra_ns *zns = THREAD_ARG(thread);
+ struct zebra_vrf *zvrf = THREAD_ARG(thread);
sock = THREAD_FD(thread);
- zrouter.rtadv.ra_read = NULL;
+ zvrf->rtadv.ra_read = NULL;
/* Register myself. */
- rtadv_event(zns, RTADV_READ, sock);
+ rtadv_event(zvrf, RTADV_READ, sock);
- len = rtadv_recv_packet(zns, sock, buf, sizeof(buf), &from, &ifindex,
+ len = rtadv_recv_packet(zvrf, sock, buf, sizeof(buf), &from, &ifindex,
&hoplimit);
if (len < 0) {
@@ -742,7 +747,7 @@ static int rtadv_read(struct thread *thread)
return len;
}
- rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zns);
+ rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zvrf);
return 0;
}
@@ -875,29 +880,27 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
{
struct zebra_if *zif;
struct zebra_vrf *zvrf;
- struct zebra_ns *zns;
zif = ifp->info;
zvrf = vrf_info_lookup(ifp->vrf_id);
- zns = zvrf->zns;
if (status == RA_SUPPRESS) {
/* RA is currently enabled */
if (zif->rtadv.AdvSendAdvertisements) {
zif->rtadv.AdvSendAdvertisements = 0;
zif->rtadv.AdvIntervalTimer = 0;
- zrouter.rtadv.adv_if_count--;
+ zvrf->rtadv.adv_if_count--;
- if_leave_all_router(zrouter.rtadv.sock, ifp);
+ if_leave_all_router(rtadv_get_socket(zvrf), ifp);
- if (zrouter.rtadv.adv_if_count == 0)
- rtadv_event(zns, RTADV_STOP, 0);
+ if (zvrf->rtadv.adv_if_count == 0)
+ rtadv_event(zvrf, RTADV_STOP, 0);
}
} else {
if (!zif->rtadv.AdvSendAdvertisements) {
zif->rtadv.AdvSendAdvertisements = 1;
zif->rtadv.AdvIntervalTimer = 0;
- zrouter.rtadv.adv_if_count++;
+ zvrf->rtadv.adv_if_count++;
if (zif->rtadv.MaxRtrAdvInterval >= 1000) {
/* Enable Fast RA only when RA interval is in
@@ -907,11 +910,11 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
RTADV_NUM_FAST_REXMITS;
}
- if_join_all_router(zrouter.rtadv.sock, ifp);
+ if_join_all_router(rtadv_get_socket(zvrf), ifp);
- if (zrouter.rtadv.adv_if_count == 1)
- rtadv_event(zns, RTADV_START,
- zrouter.rtadv.sock);
+ if (zvrf->rtadv.adv_if_count == 1)
+ rtadv_event(zvrf, RTADV_START,
+ rtadv_get_socket(zvrf));
}
}
}
@@ -944,7 +947,7 @@ static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
zebra_route_string(client->proto), ra_interval);
/* Locate interface and check VRF match. */
- ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ifindex);
+ ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
if (!ifp) {
flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
"%u: IF %u RA %s client %s - interface unknown",
@@ -1051,6 +1054,9 @@ DEFUN (ipv6_nd_ra_interval_msec,
VTY_DECLVAR_CONTEXT(interface, ifp);
unsigned interval;
struct zebra_if *zif = ifp->info;
+ struct zebra_vrf *zvrf;
+
+ zvrf = vrf_info_lookup(ifp->vrf_id);
interval = strtoul(argv[idx_number]->arg, NULL, 10);
if ((zif->rtadv.AdvDefaultLifetime != -1
@@ -1061,10 +1067,10 @@ DEFUN (ipv6_nd_ra_interval_msec,
}
if (zif->rtadv.MaxRtrAdvInterval % 1000)
- zrouter.rtadv.adv_msec_if_count--;
+ zvrf->rtadv.adv_msec_if_count--;
if (interval % 1000)
- zrouter.rtadv.adv_msec_if_count++;
+ zvrf->rtadv.adv_msec_if_count++;
SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
zif->rtadv.MaxRtrAdvInterval = interval;
@@ -1086,6 +1092,9 @@ DEFUN (ipv6_nd_ra_interval,
VTY_DECLVAR_CONTEXT(interface, ifp);
unsigned interval;
struct zebra_if *zif = ifp->info;
+ struct zebra_vrf *zvrf;
+
+ zvrf = vrf_info_lookup(ifp->vrf_id);
interval = strtoul(argv[idx_number]->arg, NULL, 10);
if ((zif->rtadv.AdvDefaultLifetime != -1
@@ -1096,7 +1105,7 @@ DEFUN (ipv6_nd_ra_interval,
}
if (zif->rtadv.MaxRtrAdvInterval % 1000)
- zrouter.rtadv.adv_msec_if_count--;
+ zvrf->rtadv.adv_msec_if_count--;
/* convert to milliseconds */
interval = interval * 1000;
@@ -1122,9 +1131,12 @@ DEFUN (no_ipv6_nd_ra_interval,
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info;
+ struct zebra_vrf *zvrf = NULL;
+
+ zvrf = vrf_info_lookup(ifp->vrf_id);
if (zif->rtadv.MaxRtrAdvInterval % 1000)
- zrouter.rtadv.adv_msec_if_count--;
+ zvrf->rtadv.adv_msec_if_count--;
UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
@@ -2094,15 +2106,15 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp)
}
-static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
+static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
{
- struct rtadv *rtadv = &zrouter.rtadv;
+ struct rtadv *rtadv = &zvrf->rtadv;
switch (event) {
case RTADV_START:
- thread_add_read(zrouter.master, rtadv_read, zns, val,
+ thread_add_read(zrouter.master, rtadv_read, zvrf, val,
&rtadv->ra_read);
- thread_add_event(zrouter.master, rtadv_timer, zns, 0,
+ thread_add_event(zrouter.master, rtadv_timer, zvrf, 0,
&rtadv->ra_timer);
break;
case RTADV_STOP:
@@ -2116,15 +2128,15 @@ static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
}
break;
case RTADV_TIMER:
- thread_add_timer(zrouter.master, rtadv_timer, zns, val,
+ thread_add_timer(zrouter.master, rtadv_timer, zvrf, val,
&rtadv->ra_timer);
break;
case RTADV_TIMER_MSEC:
- thread_add_timer_msec(zrouter.master, rtadv_timer, zns, val,
+ thread_add_timer_msec(zrouter.master, rtadv_timer, zvrf, val,
&rtadv->ra_timer);
break;
case RTADV_READ:
- thread_add_read(zrouter.master, rtadv_read, zns, val,
+ thread_add_read(zrouter.master, rtadv_read, zvrf, val,
&rtadv->ra_read);
break;
default:
@@ -2133,21 +2145,30 @@ static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
return;
}
-void rtadv_init(struct zebra_ns *zns)
+void rtadv_init(struct zebra_vrf *zvrf)
{
- zrouter.rtadv.sock = rtadv_make_socket(zns->ns_id);
+ if (vrf_is_backend_netns()) {
+ zvrf->rtadv.sock = rtadv_make_socket(zvrf->zns->ns_id);
+ zrouter.rtadv_sock = -1;
+ } else if (!zrouter.rtadv_sock) {
+ zvrf->rtadv.sock = -1;
+ if (!zrouter.rtadv_sock)
+ zrouter.rtadv_sock = rtadv_make_socket(zvrf->zns->ns_id);
+ }
}
-void rtadv_terminate(struct zebra_ns *zns)
+void rtadv_terminate(struct zebra_vrf *zvrf)
{
- rtadv_event(zns, RTADV_STOP, 0);
- if (zrouter.rtadv.sock >= 0) {
- close(zrouter.rtadv.sock);
- zrouter.rtadv.sock = -1;
+ rtadv_event(zvrf, RTADV_STOP, 0);
+ if (zvrf->rtadv.sock >= 0) {
+ close(zvrf->rtadv.sock);
+ zvrf->rtadv.sock = -1;
+ } else if (zrouter.rtadv_sock >= 0) {
+ close(zrouter.rtadv_sock);
+ zrouter.rtadv_sock = -1;
}
-
- zrouter.rtadv.adv_if_count = 0;
- zrouter.rtadv.adv_msec_if_count = 0;
+ zvrf->rtadv.adv_if_count = 0;
+ zvrf->rtadv.adv_msec_if_count = 0;
}
void rtadv_cmd_init(void)
@@ -2243,11 +2264,11 @@ static int if_leave_all_router(int sock, struct interface *ifp)
}
#else
-void rtadv_init(struct zebra_ns *zns)
+void rtadv_init(struct zebra_vrf *zvrf)
{
/* Empty.*/;
}
-void rtadv_terminate(struct zebra_ns *zns)
+void rtadv_terminate(struct zebra_vrf *zvrf)
{
/* Empty.*/;
}
diff --git a/zebra/rtadv.h b/zebra/rtadv.h
index 53c497fc09..d692ef2417 100644
--- a/zebra/rtadv.h
+++ b/zebra/rtadv.h
@@ -135,8 +135,8 @@ typedef enum {
RA_SUPPRESS,
} ipv6_nd_suppress_ra_status;
-extern void rtadv_init(struct zebra_ns *);
-extern void rtadv_terminate(struct zebra_ns *);
+extern void rtadv_init(struct zebra_vrf *zvrf);
+extern void rtadv_terminate(struct zebra_vrf *zvrf);
extern void rtadv_cmd_init(void);
extern void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS);
extern void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS);
diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c
index 0c743d8678..db4f9d0015 100644
--- a/zebra/zebra_ns.c
+++ b/zebra/zebra_ns.c
@@ -27,7 +27,6 @@
#include "lib/prefix.h"
#include "lib/memory.h"
-#include "rtadv.h"
#include "zebra_ns.h"
#include "zebra_vrf.h"
#include "zebra_memory.h"
@@ -122,10 +121,6 @@ int zebra_ns_enable(ns_id_t ns_id, void **info)
zns->ns_id = ns_id;
-#if defined(HAVE_RTADV)
- rtadv_init(zns);
-#endif
-
kernel_init(zns);
interface_list(zns);
route_read(zns);
@@ -142,9 +137,6 @@ int zebra_ns_enable(ns_id_t ns_id, void **info)
static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete)
{
route_table_finish(zns->if_table);
-#if defined(HAVE_RTADV)
- rtadv_terminate(zns);
-#endif
kernel_terminate(zns, complete);
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index 092cf2e049..e50f8a1186 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -93,9 +93,8 @@ struct zebra_router {
struct hash *iptable_hash;
-#if defined(HAVE_RTADV)
- struct rtadv rtadv;
-#endif /* HAVE_RTADV */
+ /* used if vrf backend is not network namespace */
+ int rtadv_sock;
/* A sequence number used for tracking routes */
_Atomic uint32_t sequence_num;
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index 6343054943..fdf0cbc693 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -29,6 +29,7 @@
#include "vty.h"
#include "zebra/zebra_router.h"
+#include "zebra/rtadv.h"
#include "zebra/debug.h"
#include "zebra/zapi_msg.h"
#include "zebra/rib.h"
@@ -119,6 +120,10 @@ static int zebra_vrf_enable(struct vrf *vrf)
zvrf->zns = zebra_ns_lookup((ns_id_t)vrf->vrf_id);
else
zvrf->zns = zebra_ns_lookup(NS_DEFAULT);
+#if defined(HAVE_RTADV)
+ rtadv_init(zvrf);
+#endif
+
/* Inform clients that the VRF is now active. This is an
* add for the clients.
*/
@@ -161,6 +166,10 @@ static int zebra_vrf_disable(struct vrf *vrf)
/* Stop any VxLAN-EVPN processing. */
zebra_vxlan_vrf_disable(zvrf);
+#if defined(HAVE_RTADV)
+ rtadv_terminate(zvrf);
+#endif
+
/* Inform clients that the VRF is now inactive. This is a
* delete for the clients.
*/
diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h
index febaf3c844..972fe381cc 100644
--- a/zebra/zebra_vrf.h
+++ b/zebra/zebra_vrf.h
@@ -169,6 +169,10 @@ struct zebra_vrf {
uint64_t lsp_removals_queued;
uint64_t lsp_installs;
uint64_t lsp_removals;
+
+#if defined(HAVE_RTADV)
+ struct rtadv rtadv;
+#endif /* HAVE_RTADV */
};
#define PROTO_RM_NAME(zvrf, afi, rtype) zvrf->proto_rm[afi][rtype].name
#define NHT_RM_NAME(zvrf, afi, rtype) zvrf->nht_rm[afi][rtype].name