From 511528dfc34b330476c2a1d4faec4316ba0bc864 Mon Sep 17 00:00:00 2001 From: Jafar Al-Gharaibeh Date: Tue, 23 Jul 2024 00:57:24 -0500 Subject: [PATCH] tests: add candidate BSR/RP topotest Signed-off-by: Jafar Al-Gharaibeh --- tests/topotests/pim_cand_rp_bsr/__init__.py | 0 tests/topotests/pim_cand_rp_bsr/r1/frr.conf | 24 ++ tests/topotests/pim_cand_rp_bsr/r2/frr.conf | 23 ++ tests/topotests/pim_cand_rp_bsr/r3/frr.conf | 29 +++ tests/topotests/pim_cand_rp_bsr/r4/frr.conf | 31 +++ tests/topotests/pim_cand_rp_bsr/r5/frr.conf | 20 ++ tests/topotests/pim_cand_rp_bsr/r6/frr.conf | 21 ++ .../pim_cand_rp_bsr/test_pim_cand_rp_bsr.py | 234 ++++++++++++++++++ 8 files changed, 382 insertions(+) create mode 100755 tests/topotests/pim_cand_rp_bsr/__init__.py create mode 100644 tests/topotests/pim_cand_rp_bsr/r1/frr.conf create mode 100644 tests/topotests/pim_cand_rp_bsr/r2/frr.conf create mode 100644 tests/topotests/pim_cand_rp_bsr/r3/frr.conf create mode 100644 tests/topotests/pim_cand_rp_bsr/r4/frr.conf create mode 100644 tests/topotests/pim_cand_rp_bsr/r5/frr.conf create mode 100644 tests/topotests/pim_cand_rp_bsr/r6/frr.conf create mode 100644 tests/topotests/pim_cand_rp_bsr/test_pim_cand_rp_bsr.py diff --git a/tests/topotests/pim_cand_rp_bsr/__init__.py b/tests/topotests/pim_cand_rp_bsr/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/tests/topotests/pim_cand_rp_bsr/r1/frr.conf b/tests/topotests/pim_cand_rp_bsr/r1/frr.conf new file mode 100644 index 000000000000..74f5aa8c9b5f --- /dev/null +++ b/tests/topotests/pim_cand_rp_bsr/r1/frr.conf @@ -0,0 +1,24 @@ +! +hostname r1 +password zebra +log file /tmp/r1-frr.log +! +debug pim packet +interface r1-eth0 + ip address 10.0.0.1/24 + ip igmp + ip pim +! +interface r1-eth1 + ip address 10.0.1.1/24 + ip igmp + ip pim +! +router ospf + network 10.0.0.0/16 area 0 +! +router pim + bsr candidate-bsr priority 200 source address 10.0.0.1 +! +ip forwarding +! diff --git a/tests/topotests/pim_cand_rp_bsr/r2/frr.conf b/tests/topotests/pim_cand_rp_bsr/r2/frr.conf new file mode 100644 index 000000000000..b540cb0886f9 --- /dev/null +++ b/tests/topotests/pim_cand_rp_bsr/r2/frr.conf @@ -0,0 +1,23 @@ +! +hostname r2 +password zebra +log file /tmp/r2-frr.log +! +interface r2-eth0 + ip address 10.0.0.2/24 + ip igmp + ip pim +! +interface r2-eth1 + ip address 10.0.2.2/24 + ip igmp + ip pim +! +router ospf + network 10.0.0.0/16 area 0 +! +router pim + bsr candidate-bsr priority 100 source address 10.0.0.2 +! +ip forwarding +! diff --git a/tests/topotests/pim_cand_rp_bsr/r3/frr.conf b/tests/topotests/pim_cand_rp_bsr/r3/frr.conf new file mode 100644 index 000000000000..87ac06c04640 --- /dev/null +++ b/tests/topotests/pim_cand_rp_bsr/r3/frr.conf @@ -0,0 +1,29 @@ +! +hostname r3 +password zebra +log file /tmp/r3-frr.log +! +interface r3-eth0 + ip address 10.0.1.3/24 + ip igmp + ip pim +! +interface r3-eth1 + ip address 10.0.3.3/24 + ip igmp + ip pim +! +interface r3-eth2 + ip address 10.0.4.3/24 + ip igmp + ip pim +! +router ospf + network 10.0.0.0/16 area 0 +! +router pim + bsr candidate-rp group 239.0.0.0/16 + bsr candidate-rp priority 10 source address 10.0.3.3 +! +ip forwarding +! diff --git a/tests/topotests/pim_cand_rp_bsr/r4/frr.conf b/tests/topotests/pim_cand_rp_bsr/r4/frr.conf new file mode 100644 index 000000000000..deb2883db34f --- /dev/null +++ b/tests/topotests/pim_cand_rp_bsr/r4/frr.conf @@ -0,0 +1,31 @@ +! +hostname r4 +password zebra +log file /tmp/r4-frr.log +! +interface r4-eth0 + ip address 10.0.2.4/24 + ip igmp + ip pim +! +interface r4-eth1 + ip address 10.0.3.4/24 + ip igmp + ip pim +! +interface r4-eth2 + ip address 10.0.5.4/24 + ip igmp + ip pim +! +router ospf + network 10.0.0.0/16 area 0 +! +router pim + bsr candidate-rp group 239.0.0.0/24 + bsr candidate-rp group 239.0.0.0/16 + bsr candidate-rp group 239.0.0.0/8 + bsr candidate-rp priority 20 source address 10.0.3.4 +! +ip forwarding +! diff --git a/tests/topotests/pim_cand_rp_bsr/r5/frr.conf b/tests/topotests/pim_cand_rp_bsr/r5/frr.conf new file mode 100644 index 000000000000..48453fdca74e --- /dev/null +++ b/tests/topotests/pim_cand_rp_bsr/r5/frr.conf @@ -0,0 +1,20 @@ +! +hostname r5 +password zebra +log file /tmp/r5-frr.log +! +interface r5-eth0 + ip address 10.0.4.5/24 + ip igmp + ip pim +! +interface r5-eth1 + ip address 10.0.6.5/24 + ip igmp + ip pim +! +router ospf + network 10.0.0.0/16 area 0 +! +ip forwarding +! diff --git a/tests/topotests/pim_cand_rp_bsr/r6/frr.conf b/tests/topotests/pim_cand_rp_bsr/r6/frr.conf new file mode 100644 index 000000000000..6deb90a63662 --- /dev/null +++ b/tests/topotests/pim_cand_rp_bsr/r6/frr.conf @@ -0,0 +1,21 @@ +! +hostname r6 +password zebra +log file /tmp/r6-frr.log +! +interface r6-eth0 + ip address 10.0.5.6/24 + ip igmp + ip pim +! +interface r6-eth1 + ip address 10.0.6.6/24 + ip igmp + ip pim +! +router ospf + network 10.0.0.0/16 area 0 +! +! +ip forwarding +! diff --git a/tests/topotests/pim_cand_rp_bsr/test_pim_cand_rp_bsr.py b/tests/topotests/pim_cand_rp_bsr/test_pim_cand_rp_bsr.py new file mode 100644 index 000000000000..a6d62e25647a --- /dev/null +++ b/tests/topotests/pim_cand_rp_bsr/test_pim_cand_rp_bsr.py @@ -0,0 +1,234 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# +# test_pim_cand_rp_bsr.py +# +# Copyright (c) 2024 ATCorp +# Jafar Al-Gharaibeh +# + +import os +import sys +import pytest +import json +from functools import partial + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, get_topogen +from lib.topolog import logger +from lib.pim import verify_pim_rp_info +from lib.common_config import step, write_test_header, retry + +from time import sleep + +""" +test_pim_cand_rp_bsr.py: Test candidate RP/BSR functionality +""" + +TOPOLOGY = """ + Candidate RP/BSR functionality + + +---+---+ +---+---+ + | C-BSR | 10.0.0.0/24 | C-BSR | + + R1 + <------------------> + R2 | + | | .1 .2 | | + +---+---+ ---------- +---+---+ + .1 | | 10.0.2.0/24 | .2 + | 10.0.1.0/24 ----- | + .3 | | .4 | .4 + +---+---+ --------+---+---+ + | C-RP | 10.0.3.0/24 | C-RP | + + R3 + <------------------> + R4 | + | | .3 .4 | | + +---+---+ +---+---+ + .3 | | .4 + | 10.0.4.0/24 10.0.5.0/24 | + .5 | | .6 + +---+---+ +---+---+ + | | 10.0.6.0/24 | | + + R5 + <------------------> + R6 | + | | .5 .6 | | + +---+---+ +---+---+ +""" + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# Required to instantiate the topology builder class. +pytestmark = [pytest.mark.pimd] + + +def build_topo(tgen): + "Build function" + + # Create 6 routers + for rn in range(1, 7): + tgen.add_router("r{}".format(rn)) + + # Create 7 switches and connect routers + sw = tgen.add_switch("s1") + sw.add_link(tgen.gears["r1"]) + sw.add_link(tgen.gears["r2"]) + + sw = tgen.add_switch("s2") + sw.add_link(tgen.gears["r1"]) + sw.add_link(tgen.gears["r3"]) + + sw = tgen.add_switch("s3") + sw.add_link(tgen.gears["r2"]) + sw.add_link(tgen.gears["r4"]) + + sw = tgen.add_switch("s4") + sw.add_link(tgen.gears["r3"]) + sw.add_link(tgen.gears["r4"]) + + sw = tgen.add_switch("s5") + sw.add_link(tgen.gears["r3"]) + sw.add_link(tgen.gears["r5"]) + + sw = tgen.add_switch("s6") + sw.add_link(tgen.gears["r4"]) + sw.add_link(tgen.gears["r6"]) + + sw = tgen.add_switch("s7") + sw.add_link(tgen.gears["r5"]) + sw.add_link(tgen.gears["r6"]) + +def setup_module(mod): + logger.info("PIM Candidate RP/BSR:\n {}".format(TOPOLOGY)) + + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + for rname, router in router_list.items(): + logger.info("Loading router %s" % rname) + router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname))) + + # Initialize all routers. + tgen.start_router() + for router in router_list.values(): + if router.has_version("<", "4.0"): + tgen.set_error("unsupported version") + + +def teardown_module(mod): + "Teardown the pytest environment" + tgen = get_topogen() + tgen.stop_topology() + +def test_pim_bsr_election(request): + "Test PIM BSR Election" + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + if tgen.routers_have_failure(): + pytest.skip("skipped because of router(s) failure") + + r2 = tgen.gears["r2"] + + expected = { + "bsr":"10.0.0.1", + "priority":200, + "state":"ACCEPT_PREFERRED", + } + + test_func = partial( + topotest.router_json_cmp, r2, "show ip pim bsr json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + + assertmsg = "r2: bsr election mismatch " + assert result is None, assertmsg + +def test_pim_bsr_cand_bsr(request): + "Test PIM BSR candidate BSR" + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + if tgen.routers_have_failure(): + pytest.skip("skipped because of router(s) failure") + + r2 = tgen.gears["r2"] + + # r2 is a candidate bsr with low priority: elected = False + expected = { + "address": "10.0.0.2", + "priority": 100, + "elected": False + } + test_func = partial( + topotest.router_json_cmp, r2, "show ip pim bsr candidate-bsr json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + + assertmsg = "r2: candidate bsr mismatch " + assert result is None, assertmsg + +def test_pim_bsr_cand_rp(request): + "Test PIM BSR candidate RP" + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + if tgen.routers_have_failure(): + pytest.skip("skipped because of router(s) failure") + + r3 = tgen.gears["r3"] + + # r3 is a candidate rp + expected = { + "address":"10.0.3.3", + "priority":10 + } + test_func = partial( + topotest.router_json_cmp, r3, "show ip pim bsr candidate-rp json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + + assertmsg = "r3: bsr candidate rp mismatch " + assert result is None, assertmsg + + +def test_pim_bsr_rp_info(request): + "Test RP info state on r5" + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + if tgen.routers_have_failure(): + pytest.skip("skipped because of router(s) failure") + + # At this point, all nodes, including r5 should have synced the RP state + step("Verify rp-info from BSR") + result = verify_pim_rp_info(tgen, None, "r5", "239.0.0.0/16", "r5-eth0", "10.0.3.3", + "BSR", False, "ipv4", True, retry_timeout = 90) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + result = verify_pim_rp_info(tgen, None, "r5", "239.0.0.0/8", "r5-eth0", "10.0.3.4", + "BSR", False, "ipv4", True, retry_timeout = 30) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + result = verify_pim_rp_info(tgen, None, "r5", "239.0.0.0/24", "r5-eth0", "10.0.3.4", + "BSR", False, "ipv4", True, retry_timeout = 30) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + +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))