mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 06:14:35 +00:00
topotests: add bfd_vrflite_topo1 test
This tests checks that there are no errors when receiving BFD packets over the various linux vrf interfaces. For example, if an incoming packet is received by the wrong socket, a VRF mismatch error would occur, and BFD flapping would be observed. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
parent
edc3f63167
commit
97413ed778
0
tests/topotests/bfd_vrflite_topo1/__init__.py
Normal file
0
tests/topotests/bfd_vrflite_topo1/__init__.py
Normal file
96
tests/topotests/bfd_vrflite_topo1/r1/bfd_peers_status.json
Normal file
96
tests/topotests/bfd_vrflite_topo1/r1/bfd_peers_status.json
Normal file
@ -0,0 +1,96 @@
|
||||
[
|
||||
{
|
||||
"multihop":false,
|
||||
"peer":"192.168.0.2",
|
||||
"vrf":"vrf1",
|
||||
"passive-mode":false,
|
||||
"status":"up",
|
||||
"diagnostic":"ok",
|
||||
"remote-diagnostic":"ok",
|
||||
"receive-interval":1000,
|
||||
"transmit-interval":1000,
|
||||
"echo-receive-interval":50,
|
||||
"echo-transmit-interval":0,
|
||||
"detect-multiplier":3,
|
||||
"remote-receive-interval":1000,
|
||||
"remote-transmit-interval":1000,
|
||||
"remote-echo-receive-interval":50,
|
||||
"remote-detect-multiplier":3
|
||||
},
|
||||
{
|
||||
"multihop":true,
|
||||
"peer":"192.0.2.2",
|
||||
"local":"192.0.2.1",
|
||||
"vrf":"vrf2",
|
||||
"passive-mode":false,
|
||||
"minimum-ttl":254,
|
||||
"status":"up",
|
||||
"diagnostic":"ok",
|
||||
"remote-diagnostic":"ok",
|
||||
"receive-interval":1000,
|
||||
"transmit-interval":1000,
|
||||
"echo-receive-interval":50,
|
||||
"echo-transmit-interval":0,
|
||||
"detect-multiplier":3,
|
||||
"remote-receive-interval":1000,
|
||||
"remote-transmit-interval":1000,
|
||||
"remote-echo-receive-interval":50,
|
||||
"remote-detect-multiplier":3
|
||||
},
|
||||
{
|
||||
"multihop":false,
|
||||
"peer":"192.168.0.2",
|
||||
"vrf":"vrf2",
|
||||
"passive-mode":false,
|
||||
"status":"up",
|
||||
"diagnostic":"ok",
|
||||
"remote-diagnostic":"ok",
|
||||
"receive-interval":1000,
|
||||
"transmit-interval":1000,
|
||||
"echo-receive-interval":50,
|
||||
"echo-transmit-interval":0,
|
||||
"detect-multiplier":3,
|
||||
"remote-receive-interval":1000,
|
||||
"remote-transmit-interval":1000,
|
||||
"remote-echo-receive-interval":50,
|
||||
"remote-detect-multiplier":3
|
||||
},
|
||||
{
|
||||
"multihop":false,
|
||||
"peer":"192.168.0.2",
|
||||
"vrf":"default",
|
||||
"passive-mode":false,
|
||||
"status":"up",
|
||||
"diagnostic":"ok",
|
||||
"remote-diagnostic":"ok",
|
||||
"receive-interval":1000,
|
||||
"transmit-interval":1000,
|
||||
"echo-receive-interval":50,
|
||||
"echo-transmit-interval":0,
|
||||
"detect-multiplier":3,
|
||||
"remote-receive-interval":1000,
|
||||
"remote-transmit-interval":1000,
|
||||
"remote-echo-receive-interval":50,
|
||||
"remote-detect-multiplier":3
|
||||
},
|
||||
{
|
||||
"multihop":true,
|
||||
"peer":"192.0.2.2",
|
||||
"local":"192.0.2.1",
|
||||
"vrf":"vrf1",
|
||||
"passive-mode":false,
|
||||
"minimum-ttl":254,
|
||||
"status":"up",
|
||||
"diagnostic":"ok",
|
||||
"remote-diagnostic":"ok",
|
||||
"receive-interval":1000,
|
||||
"transmit-interval":1000,
|
||||
"echo-receive-interval":50,
|
||||
"echo-transmit-interval":0,
|
||||
"detect-multiplier":3,
|
||||
"remote-receive-interval":1000,
|
||||
"remote-transmit-interval":1000,
|
||||
"remote-echo-receive-interval":50,
|
||||
"remote-detect-multiplier":3
|
||||
}
|
||||
]
|
26
tests/topotests/bfd_vrflite_topo1/r1/bfdd.conf
Normal file
26
tests/topotests/bfd_vrflite_topo1/r1/bfdd.conf
Normal file
@ -0,0 +1,26 @@
|
||||
!
|
||||
! debug bfd network
|
||||
! debug bfd peer
|
||||
! debug bfd zebra
|
||||
!
|
||||
bfd
|
||||
peer 192.168.0.2 vrf vrf1
|
||||
transmit-interval 1000
|
||||
receive-interval 1000
|
||||
!
|
||||
peer 192.168.0.2 vrf vrf2
|
||||
transmit-interval 1000
|
||||
receive-interval 1000
|
||||
!
|
||||
peer 192.168.0.2
|
||||
transmit-interval 1000
|
||||
receive-interval 1000
|
||||
!
|
||||
peer 192.0.2.2 multihop local-address 192.0.2.1 vrf vrf1
|
||||
transmit-interval 1000
|
||||
receive-interval 1000
|
||||
!
|
||||
peer 192.0.2.2 multihop local-address 192.0.2.1 vrf vrf2
|
||||
transmit-interval 1000
|
||||
receive-interval 1000
|
||||
!
|
24
tests/topotests/bfd_vrflite_topo1/r1/zebra.conf
Normal file
24
tests/topotests/bfd_vrflite_topo1/r1/zebra.conf
Normal file
@ -0,0 +1,24 @@
|
||||
vrf vrf1
|
||||
ip route 192.0.2.2/32 192.168.0.2
|
||||
!
|
||||
vrf vrf2
|
||||
ip route 192.0.2.2/32 192.168.0.2
|
||||
!
|
||||
interface r1-eth0 vrf vrf3
|
||||
ip address 192.168.0.1/24
|
||||
!
|
||||
interface r1-eth0.100 vrf vrf1
|
||||
ip address 192.168.0.1/24
|
||||
!
|
||||
interface r1-eth0.200 vrf vrf2
|
||||
ip address 192.168.0.1/24
|
||||
!
|
||||
interface r1-eth0.300
|
||||
ip address 192.168.0.1/24
|
||||
!
|
||||
interface r1-loop1 vrf vrf1
|
||||
ip address 192.0.2.1/32
|
||||
!
|
||||
interface r1-loop2 vrf vrf2
|
||||
ip address 192.0.2.1/32
|
||||
!
|
26
tests/topotests/bfd_vrflite_topo1/r2/bfdd.conf
Normal file
26
tests/topotests/bfd_vrflite_topo1/r2/bfdd.conf
Normal file
@ -0,0 +1,26 @@
|
||||
!
|
||||
! debug bfd network
|
||||
! debug bfd peer
|
||||
! debug bfd zebra
|
||||
!
|
||||
bfd
|
||||
peer 192.168.0.1 vrf vrf1
|
||||
transmit-interval 1000
|
||||
receive-interval 1000
|
||||
!
|
||||
peer 192.168.0.1 vrf vrf2
|
||||
transmit-interval 1000
|
||||
receive-interval 1000
|
||||
!
|
||||
peer 192.168.0.1
|
||||
transmit-interval 1000
|
||||
receive-interval 1000
|
||||
!
|
||||
peer 192.0.2.1 multihop local-address 192.0.2.2 vrf vrf1
|
||||
transmit-interval 1000
|
||||
receive-interval 1000
|
||||
!
|
||||
peer 192.0.2.1 multihop local-address 192.0.2.2 vrf vrf2
|
||||
transmit-interval 1000
|
||||
receive-interval 1000
|
||||
!
|
24
tests/topotests/bfd_vrflite_topo1/r2/zebra.conf
Normal file
24
tests/topotests/bfd_vrflite_topo1/r2/zebra.conf
Normal file
@ -0,0 +1,24 @@
|
||||
vrf vrf1
|
||||
ip route 192.0.2.1/32 192.168.0.1
|
||||
!
|
||||
vrf vrf2
|
||||
ip route 192.0.2.1/32 192.168.0.1
|
||||
!
|
||||
interface r2-eth0 vrf vrf3
|
||||
ip address 192.168.0.2/24
|
||||
!
|
||||
interface r2-eth0.100 vrf vrf1
|
||||
ip address 192.168.0.2/24
|
||||
!
|
||||
interface r2-eth0.200 vrf vrf2
|
||||
ip address 192.168.0.2/24
|
||||
!
|
||||
interface r2-eth0.300
|
||||
ip address 192.168.0.2/24
|
||||
!
|
||||
interface r2-loop1 vrf vrf1
|
||||
ip address 192.0.2.2/32
|
||||
!
|
||||
interface r2-loop2 vrf vrf2
|
||||
ip address 192.0.2.2/32
|
||||
!
|
153
tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py
Normal file
153
tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py
Normal file
@ -0,0 +1,153 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#
|
||||
# test_bfd_vrflite_topo1.py
|
||||
# Part of NetDEF Topology Tests
|
||||
#
|
||||
# Copyright (c) 2018 by
|
||||
# Network Device Education Foundation, Inc. ("NetDEF")
|
||||
# Copyright (c) 2022 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_bfd_vrflite_topo1.py: Test the FRR BFD daemon.
|
||||
"""
|
||||
|
||||
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.
|
||||
|
||||
pytestmark = [pytest.mark.bfdd, pytest.mark.bgpd]
|
||||
|
||||
|
||||
def build_topo(tgen):
|
||||
# Create 2 routers
|
||||
for routern in range(1, 3):
|
||||
tgen.add_router("r{}".format(routern))
|
||||
|
||||
switch = tgen.add_switch("s1")
|
||||
switch.add_link(tgen.gears["r1"])
|
||||
switch.add_link(tgen.gears["r2"])
|
||||
|
||||
switch = tgen.add_switch("s2")
|
||||
switch.add_link(tgen.gears["r2"])
|
||||
|
||||
switch = tgen.add_switch("s3")
|
||||
switch.add_link(tgen.gears["r1"])
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
"Sets up the pytest environment"
|
||||
tgen = Topogen(build_topo, mod.__name__)
|
||||
tgen.start_topology()
|
||||
|
||||
router_list = tgen.routers()
|
||||
|
||||
logger.info("Testing with Linux VRF support and udp_l3mdev=0")
|
||||
if os.system("echo 0 > /proc/sys/net/ipv4/udp_l3mdev_accept") != 0:
|
||||
return pytest.skip(
|
||||
"Skipping BFD vrflite Topo1 Test. Linux VRF not available on System"
|
||||
)
|
||||
|
||||
for rname, router in router_list.items():
|
||||
router.net.add_l3vrf("vrf1", 10)
|
||||
router.net.add_l3vrf("vrf2", 20)
|
||||
router.net.add_l3vrf("vrf3", 30)
|
||||
router.net.add_vlan(rname + "-eth0.100", rname + "-eth0", 100)
|
||||
router.net.add_vlan(rname + "-eth0.200", rname + "-eth0", 200)
|
||||
router.net.add_vlan(rname + "-eth0.300", rname + "-eth0", 300)
|
||||
router.net.attach_iface_to_l3vrf(rname + "-eth0.100", "vrf1")
|
||||
router.net.attach_iface_to_l3vrf(rname + "-eth0.200", "vrf2")
|
||||
router.net.add_loop(rname + "-loop1")
|
||||
router.net.add_loop(rname + "-loop2")
|
||||
router.net.attach_iface_to_l3vrf(rname + "-loop1", "vrf1")
|
||||
router.net.attach_iface_to_l3vrf(rname + "-loop2", "vrf2")
|
||||
router.net.attach_iface_to_l3vrf(rname + "-eth0", "vrf3")
|
||||
|
||||
for rname, router in router_list.items():
|
||||
router.load_config(
|
||||
TopoRouter.RD_ZEBRA,
|
||||
os.path.join(CWD, "{}/zebra.conf".format(rname))
|
||||
)
|
||||
router.load_config(
|
||||
TopoRouter.RD_BFD, os.path.join(CWD, "{}/bfdd.conf".format(rname))
|
||||
)
|
||||
|
||||
# Initialize all routers.
|
||||
tgen.start_router()
|
||||
|
||||
|
||||
def teardown_module(_mod):
|
||||
"Teardown the pytest environment"
|
||||
tgen = get_topogen()
|
||||
|
||||
# Move interfaces out of vrf namespace and delete the namespace
|
||||
router_list = tgen.routers()
|
||||
for rname, router in router_list.items():
|
||||
router.net.del_iface(rname + "-eth0.100")
|
||||
router.net.del_iface(rname + "-eth0.200")
|
||||
router.net.del_iface(rname + "-eth0.300")
|
||||
router.net.del_iface(rname + "-loop1")
|
||||
router.net.del_iface(rname + "-loop2")
|
||||
|
||||
tgen.stop_topology()
|
||||
|
||||
|
||||
def test_bfd_connection():
|
||||
"Assert that the BFD peers can find themselves."
|
||||
tgen = get_topogen()
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
logger.info("waiting for bfd peers to go up")
|
||||
router = tgen.gears['r1']
|
||||
json_file = "{}/{}/bfd_peers_status.json".format(CWD, 'r1')
|
||||
expected = json.loads(open(json_file).read())
|
||||
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, router, "show bfd peers json", expected
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=16, wait=1)
|
||||
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))
|
@ -599,6 +599,60 @@ class LinuxNamespace(Commander):
|
||||
self.cmd_raises("mkdir -p " + inner)
|
||||
self.cmd_raises("mount --rbind {} {} ".format(outer, inner))
|
||||
|
||||
def add_vlan(self, vlanname, linkiface, vlanid):
|
||||
self.logger.debug("Adding VLAN interface: %s (%s)", vlanname, vlanid)
|
||||
ip_path = self.get_exec_path("ip")
|
||||
assert ip_path, "XXX missing ip command!"
|
||||
self.cmd_raises(
|
||||
[
|
||||
ip_path,
|
||||
"link",
|
||||
"add",
|
||||
"link",
|
||||
linkiface,
|
||||
"name",
|
||||
vlanname,
|
||||
"type",
|
||||
"vlan",
|
||||
"id",
|
||||
vlanid,
|
||||
]
|
||||
)
|
||||
self.cmd_raises([ip_path, "link", "set", "dev", vlanname, "up"])
|
||||
|
||||
def add_loop(self, loopname):
|
||||
self.logger.debug("Adding Linux iface: %s", loopname)
|
||||
ip_path = self.get_exec_path("ip")
|
||||
assert ip_path, "XXX missing ip command!"
|
||||
self.cmd_raises([ip_path, "link", "add", loopname, "type", "dummy"])
|
||||
self.cmd_raises([ip_path, "link", "set", "dev", loopname, "up"])
|
||||
|
||||
def add_l3vrf(self, vrfname, tableid):
|
||||
self.logger.debug("Adding Linux VRF: %s", vrfname)
|
||||
ip_path = self.get_exec_path("ip")
|
||||
assert ip_path, "XXX missing ip command!"
|
||||
self.cmd_raises(
|
||||
[ip_path, "link", "add", vrfname, "type", "vrf", "table", tableid]
|
||||
)
|
||||
self.cmd_raises([ip_path, "link", "set", "dev", vrfname, "up"])
|
||||
|
||||
def del_iface(self, iface):
|
||||
self.logger.debug("Removing Linux Iface: %s", iface)
|
||||
ip_path = self.get_exec_path("ip")
|
||||
assert ip_path, "XXX missing ip command!"
|
||||
self.cmd_raises([ip_path, "link", "del", iface])
|
||||
|
||||
def attach_iface_to_l3vrf(self, ifacename, vrfname):
|
||||
self.logger.debug("Attaching Iface %s to Linux VRF %s", ifacename, vrfname)
|
||||
ip_path = self.get_exec_path("ip")
|
||||
assert ip_path, "XXX missing ip command!"
|
||||
if vrfname:
|
||||
self.cmd_raises(
|
||||
[ip_path, "link", "set", "dev", ifacename, "master", vrfname]
|
||||
)
|
||||
else:
|
||||
self.cmd_raises([ip_path, "link", "set", "dev", ifacename, "nomaster"])
|
||||
|
||||
def add_netns(self, ns):
|
||||
self.logger.debug("Adding network namespace %s", ns)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user