From 9b7decf28e7d6e9b13b7fa6d0225b3cfa823fdfd Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jakub=20Urba=C5=84czyk?= Date: Tue, 26 May 2020 18:24:16 +0200 Subject: [PATCH] topotest: add pbr test suite MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Add some basic tests for installing PBR rules into the kernel. Signed-off-by: Jakub Urbańczyk --- tests/topotests/lib/topogen.py | 4 +- tests/topotests/lib/topotest.py | 51 +++++++++++++++++++ tests/topotests/pbr-topo1/__init__.py | 0 tests/topotests/pbr-topo1/r1/linux-rules.json | 19 +++++++ tests/topotests/pbr-topo1/test_pbr_topo1.py | 22 ++++++++ 5 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 tests/topotests/pbr-topo1/__init__.py create mode 100644 tests/topotests/pbr-topo1/r1/linux-rules.json diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py index 414dc17874..efd5b90685 100644 --- a/tests/topotests/lib/topogen.py +++ b/tests/topotests/lib/topogen.py @@ -658,7 +658,7 @@ class TopoRouter(TopoGear): Possible daemon values are: TopoRouter.RD_ZEBRA, TopoRouter.RD_RIP, TopoRouter.RD_RIPNG, TopoRouter.RD_OSPF, TopoRouter.RD_OSPF6, TopoRouter.RD_ISIS, TopoRouter.RD_BGP, TopoRouter.RD_LDP, - TopoRouter.RD_PIM. + TopoRouter.RD_PIM, TopoRouter.RD_PBR. """ daemonstr = self.RD.get(daemon) self.logger.info('loading "{}" configuration: {}'.format(daemonstr, source)) @@ -1064,6 +1064,7 @@ def diagnose_env_linux(): "isisd", "pimd", "ldpd", + "pbrd" ]: path = os.path.join(frrdir, fname) if not os.path.isfile(path): @@ -1121,6 +1122,7 @@ def diagnose_env_linux(): "ripngd", "isisd", "pimd", + "pbrd" ]: path = os.path.join(quaggadir, fname) if not os.path.isfile(path): diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index 6262082193..9d945d5262 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -727,6 +727,57 @@ def ip6_route(node): return result +def ip_rules(node): + """ + Gets a structured return of the command 'ip rule'. It can be used in + conjuction with json_cmp() to provide accurate assert explanations. + + Return example: + [ + { + "pref": "0" + "from": "all" + }, + { + "pref": "32766" + "from": "all" + }, + { + "to": "3.4.5.0/24", + "iif": "r1-eth2", + "pref": "304", + "from": "1.2.0.0/16", + "proto": "zebra" + } + ] + """ + output = normalize_text(node.run("ip rule")).splitlines() + result = [] + for line in output: + columns = line.split(" ") + + route = {} + # remove last character, since it is ':' + pref = columns[0][:-1] + route["pref"] = pref + prev = None + for column in columns: + if prev == "from": + route["from"] = column + if prev == "to": + route["to"] = column + if prev == "proto": + route["proto"] = column + if prev == "iif": + route["iif"] = column + if prev == "fwmark": + route["fwmark"] = column + prev = column + + result.append(route) + return result + + def sleep(amount, reason=None): """ Sleep wrapper that registers in the log the amount of sleep diff --git a/tests/topotests/pbr-topo1/__init__.py b/tests/topotests/pbr-topo1/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/pbr-topo1/r1/linux-rules.json b/tests/topotests/pbr-topo1/r1/linux-rules.json new file mode 100644 index 0000000000..5af4363418 --- /dev/null +++ b/tests/topotests/pbr-topo1/r1/linux-rules.json @@ -0,0 +1,19 @@ +[ + { + "iif": "r1-eth1", + "pref": "304", + "from": "4.5.6.7" + }, + { + "to": "3.4.5.0/24", + "iif": "r1-eth2", + "pref": "304", + "from": "1.2.0.0/16" + }, + { + "to": "9.9.9.9", + "iif": "r1-eth1", + "pref": "309", + "from": "all" + } +] diff --git a/tests/topotests/pbr-topo1/test_pbr_topo1.py b/tests/topotests/pbr-topo1/test_pbr_topo1.py index aedc9ca3fc..7de1cfa519 100755 --- a/tests/topotests/pbr-topo1/test_pbr_topo1.py +++ b/tests/topotests/pbr-topo1/test_pbr_topo1.py @@ -201,6 +201,28 @@ def test_pbr_flap(): # Actual output from router actual = router.vtysh_cmd("show pbr interface json", isjson=True) assertmsg = '"show pbr interface" mismatches on {}'.format(router.name) + + assert topotest.json_cmp(actual, expected) is None, assertmsg + + +def test_rule_linux_installation(): + "Ensure that rule is installed in the kernel" + + tgen = get_topogen() + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Checking for installed PBR rules in OS") + + router_list = tgen.routers().values() + for router in router_list: + rules_file = "{}/{}/linux-rules.json".format(CWD, router.name) + + actual = topotest.ip_rules(router) + expected = json.loads(open(rules_file).read()) + + assertmsg = "Router {} OS rules mismatch".format(router.name) assert topotest.json_cmp(actual, expected) is None, assertmsg -- 2.39.5