tests: add basic topotest cases for sbfd Initiator and Reflector

Signed-off-by: wumu.zsl <wumu.zsl@alibaba-inc.com>
This commit is contained in:
wumu.zsl 2025-01-21 08:25:03 +00:00
parent e766b68a18
commit 8653a47708
5 changed files with 309 additions and 0 deletions

View File

View File

@ -0,0 +1,8 @@
ip forwarding
ipv6 forwarding
!
interface r1-eth0
ipv6 address 2001::10/64
!
!

View File

@ -0,0 +1,8 @@
ip forwarding
ipv6 forwarding
!
interface r2-eth0
ipv6 address 2001::20/64
!
!

View File

@ -0,0 +1,45 @@
## 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="template";
# Routers
r1 [
shape=doubleoctagon,
label="A\nAS 100\n1.1.1.1",
fillcolor="#f08080",
style=filled,
];
r2 [
shape=doubleoctagon
label="B\nAS 200\n1.1.1.2",
fillcolor="#f08080",
style=filled,
];
# Switches
s1 [
shape=oval,
label="s1\n192.168.0.0/24",
fillcolor="#d0e0d0",
style=filled,
];
# Connections
r1 -- s1 [label="A-eth0"];
r2 -- s1 [label="B-eth0"];
}

View File

@ -0,0 +1,248 @@
#!/usr/bin/env python
#
# test_sbfd_topo1.py
# basic test cases for sbfd initiator and reflector
#
# Copyright (c) 2025 by Alibaba, Inc.
#
# 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.
#
"""
<template>.py: Test <template>.
"""
import os
import sys
import pytest
import json
import re
import time
import pdb
from functools import partial
# 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
from lib.common_config import required_linux_kernel_version
"""
test_sbfd_topo1.py: test simple sbfd with IPv6 encap. RT1 is sbfd Initiator, RT2 is sbfd Reflector
+----+----+ +----+----+
| | | |
| RT1 | 1 | RT2 |
| +--------+ |
| 2001::10| | 2001::20|
+----+----+ +----+----+
"""
pytestmark = [pytest.mark.bfdd, pytest.mark.sbfd]
def show_bfd_check(router, status, type='echo', encap=None):
output = router.cmd("vtysh -c 'show bfd peers'")
if encap:
# check encap data if any
pattern1 = re.compile(r'encap-data {}'.format(encap))
ret = pattern1.findall(output)
if len(ret) <= 0:
logger.info("encap-data not match")
return False
# check status
pattern2 = re.compile(r'Status: {}'.format(status))
ret = pattern2.findall(output)
if len(ret) <= 0:
logger.info("Status not match")
return False
# check type
pattern3 = re.compile(r'Peer Type: {}'.format(type))
ret = pattern3.findall(output)
if len(ret) <= 0:
logger.info("Peer Type not match")
return False
logger.info("all check passed")
return True
def build_topo(tgen):
"Test topology builder"
# This function only purpose is to define allocation and relationship
# between routers, switches and hosts.
#
# Example
#
# Create 2 routers
for routern in range(1, 3):
tgen.add_router('r{}'.format(routern))
# Create a switch with just one router connected to it to simulate a
# empty network.
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"
# This function initiates the topology build with Topogen...
tgen = Topogen(build_topo, mod.__name__)
# ... and here it calls Mininet initialization functions.
tgen.start_topology()
# This is a sample of configuration loading.
router_list = tgen.routers()
for rname, router in router_list.items():
router.load_frr_config(
os.path.join(CWD, "{}/frr.conf".format(rname)),
[(TopoRouter.RD_ZEBRA, None), (TopoRouter.RD_BFD, None)])
# After loading the configurations, this function loads configured daemons.
tgen.start_router()
# Verify that we are using the proper version and that the BFD
# daemon exists.
for router in router_list.values():
# Check for Version
if router.has_version('<', '5.1'):
tgen.set_error('Unsupported FRR version')
break
def teardown_module(mod):
"Teardown the pytest environment"
tgen = get_topogen()
# This function tears down the whole topology.
tgen.stop_topology()
# step 1 : config sbfd Initiator and reflector
def test_sbfd_config_check():
"Assert that config sbfd and check sbfd status."
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.5")
if result is not True:
pytest.skip("Kernel requirements are not met")
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
# config sbfd
r1 = tgen.net['r1']
r1.cmd("ping -c 5 2001::20")
r1.cmd("vtysh -c 'config t' -c 'bfd' -c 'peer 2001::20 bfd-mode sbfd-init bfd-name 2-44 local-address 2001::10 remote-discr 1234'")
r2 = tgen.net['r2']
r2.cmd("vtysh -c 'config t' -c 'bfd' -c 'sbfd reflector source-address 2001::20 discriminator 1234'")
check_func = partial(
show_bfd_check, r1, 'up', type='sbfd initiator'
)
success, _ = topotest.run_and_expect(check_func, True, count=15, wait=1)
assert success is True, "sbfd not up in 15 seconds"
# step 2: shutdown if and no shutdown if then check sbfd status
def test_sbfd_updown_interface():
"Assert that updown interface then check sbfd status."
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.5")
if result is not True:
pytest.skip("Kernel requirements are not met")
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
r1 = tgen.net['r1']
r2 = tgen.net['r2']
# shutdown interface
r2.cmd("vtysh -c 'config t' -c 'interface r2-eth0' -c 'shutdown'")
check_func = partial(
show_bfd_check, r1, 'down', type='sbfd initiator'
)
success, _ = topotest.run_and_expect(check_func, True, count=15, wait=1)
assert success is True, "sbfd not down in 15 seconds after shut"
# up interface
r2.cmd("vtysh -c 'config t' -c 'interface r2-eth0' -c 'no shutdown'")
check_func = partial(
show_bfd_check, r1, 'up', type='sbfd initiator'
)
success, _ = topotest.run_and_expect(check_func, True, count=15, wait=1)
assert success is True, "sbfd not up in 15 seconds after no shut"
# step 3: change transmit-interval and check sbfd status according to the interval time
def test_sbfd_change_transmit_interval():
"Assert that sbfd status changes align with transmit-interval."
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.5")
if result is not True:
pytest.skip("Kernel requirements are not met")
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
r1 = tgen.net['r1']
r2 = tgen.net['r2']
r1.cmd("vtysh -c 'config t' -c 'bfd' -c 'peer 2001::20 bfd-mode sbfd-init bfd-name 2-44 local-address 2001::10 remote-discr 1234' -c 'transmit-interval 3000'")
#wait sometime for polling finish
time.sleep(1)
# shutdown interface
r2.cmd("vtysh -c 'config t' -c 'interface r2-eth0' -c 'shutdown'")
#wait enough time for timeout
check_func = partial(
show_bfd_check, r1, 'down', type='sbfd initiator'
)
success, _ = topotest.run_and_expect(check_func, True, count=5, wait=3)
assert success is True, "sbfd not down as expected"
r2.cmd("vtysh -c 'config t' -c 'interface r2-eth0' -c 'no shutdown'")
check_func = partial(
show_bfd_check, r1, 'up', type='sbfd initiator'
)
success, _ = topotest.run_and_expect(check_func, True, count=15, wait=1)
assert success is True, "sbfd not up in 15 seconds after no shut"
r1.cmd("vtysh -c 'config t' -c 'bfd' -c 'no peer 2001::20 bfd-mode sbfd-init bfd-name 2-44 local-address 2001::10 remote-discr 1234'")
success = show_bfd_check(r1, 'up', type='sbfd initiator')
assert success is False, "sbfd not deleted as unexpected"
# Memory leak test template
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))