mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 21:10:28 +00:00
Merge pull request #4370 from pguibert6WIND/fix_interface_rtadv2
Fix Router advertisements per VRF
This commit is contained in:
commit
f7288f1515
0
tests/topotests/bgp_ipv6_rtadv/__init__.py
Normal file
0
tests/topotests/bgp_ipv6_rtadv/__init__.py
Normal file
13
tests/topotests/bgp_ipv6_rtadv/r1/bgpd.conf
Normal file
13
tests/topotests/bgp_ipv6_rtadv/r1/bgpd.conf
Normal file
@ -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
|
||||
!
|
44
tests/topotests/bgp_ipv6_rtadv/r1/ipv4_routes.json
Normal file
44
tests/topotests/bgp_ipv6_rtadv/r1/ipv4_routes.json
Normal file
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
39
tests/topotests/bgp_ipv6_rtadv/r1/ipv6_routes.json
Normal file
39
tests/topotests/bgp_ipv6_rtadv/r1/ipv6_routes.json
Normal file
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
9
tests/topotests/bgp_ipv6_rtadv/r1/zebra.conf
Normal file
9
tests/topotests/bgp_ipv6_rtadv/r1/zebra.conf
Normal file
@ -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
|
||||
!
|
16
tests/topotests/bgp_ipv6_rtadv/r2/bgpd.conf
Normal file
16
tests/topotests/bgp_ipv6_rtadv/r2/bgpd.conf
Normal file
@ -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
|
||||
!
|
44
tests/topotests/bgp_ipv6_rtadv/r2/ipv4_routes.json
Normal file
44
tests/topotests/bgp_ipv6_rtadv/r2/ipv4_routes.json
Normal file
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
23
tests/topotests/bgp_ipv6_rtadv/r2/ipv6_routes.json
Normal file
23
tests/topotests/bgp_ipv6_rtadv/r2/ipv6_routes.json
Normal file
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
9
tests/topotests/bgp_ipv6_rtadv/r2/zebra.conf
Normal file
9
tests/topotests/bgp_ipv6_rtadv/r2/zebra.conf
Normal file
@ -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
|
||||
!
|
44
tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.dot
Normal file
44
tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.dot
Normal file
@ -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"];
|
||||
|
||||
}
|
142
tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py
Normal file
142
tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py
Normal file
@ -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))
|
0
tests/topotests/bgp_vrf_lite_ipv6_rtadv/__init__.py
Normal file
0
tests/topotests/bgp_vrf_lite_ipv6_rtadv/__init__.py
Normal file
13
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/bgpd.conf
Normal file
13
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/bgpd.conf
Normal file
@ -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
|
||||
!
|
50
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/ipv4_routes.json
Normal file
50
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/ipv4_routes.json
Normal file
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
44
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/ipv6_routes.json
Normal file
44
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/ipv6_routes.json
Normal file
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
9
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/zebra.conf
Normal file
9
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r1/zebra.conf
Normal file
@ -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
|
||||
!
|
16
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/bgpd.conf
Normal file
16
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/bgpd.conf
Normal file
@ -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
|
||||
!
|
50
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/ipv4_routes.json
Normal file
50
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/ipv4_routes.json
Normal file
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
26
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/ipv6_routes.json
Normal file
26
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/ipv6_routes.json
Normal file
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
9
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/zebra.conf
Normal file
9
tests/topotests/bgp_vrf_lite_ipv6_rtadv/r2/zebra.conf
Normal file
@ -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
|
||||
!
|
@ -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"];
|
||||
|
||||
}
|
@ -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))
|
137
zebra/rtadv.c
137
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,7 +520,7 @@ static int rtadv_timer(struct thread *thread)
|
||||
zif->rtadv
|
||||
.MaxRtrAdvInterval;
|
||||
rtadv_send_packet(
|
||||
zrouter.rtadv.sock,
|
||||
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.*/;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user