git: 7064c94a02af - main - tests: add routing tests for switching between same prefixes
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 07 Aug 2022 19:46:50 UTC
The branch main has been updated by melifaro: URL: https://cgit.FreeBSD.org/src/commit/?id=7064c94a02af2f8665636a8594557b9e93ad71bf commit 7064c94a02af2f8665636a8594557b9e93ad71bf Author: Alexander V. Chernikov <melifaro@FreeBSD.org> AuthorDate: 2022-08-06 10:36:12 +0000 Commit: Alexander V. Chernikov <melifaro@FreeBSD.org> CommitDate: 2022-08-07 19:45:25 +0000 tests: add routing tests for switching between same prefixes Differential Revision: https://reviews.freebsd.org/D36055 MFC after: 2 weeks --- tests/atf_python/sys/net/tools.py | 15 +++++- tests/atf_python/sys/net/vnet.py | 8 +++- tests/sys/net/routing/Makefile | 1 + tests/sys/net/routing/test_routing_l3.py | 81 ++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 3 deletions(-) diff --git a/tests/atf_python/sys/net/tools.py b/tests/atf_python/sys/net/tools.py index c67941b414fc..23bb5f4b4128 100644 --- a/tests/atf_python/sys/net/tools.py +++ b/tests/atf_python/sys/net/tools.py @@ -41,7 +41,7 @@ class ToolsHelper(object): def get_routes(cls, family: str, fibnum: int = 0): family_key = {"inet": "-4", "inet6": "-6"}.get(family) out = cls.get_output( - "{} {} -rn -F {} --libxo json".format(cls.NETSTAT_PATH, family_key, fibnum) + "{} {} -rnW -F {} --libxo json".format(cls.NETSTAT_PATH, family_key, fibnum) ) js = json.loads(out) js = js["statistics"]["route-information"]["route-table"]["rt-family"] @@ -50,6 +50,19 @@ class ToolsHelper(object): else: return [] + @classmethod + def get_nhops(cls, family: str, fibnum: int = 0): + family_key = {"inet": "-4", "inet6": "-6"}.get(family) + out = cls.get_output( + "{} {} -onW -F {} --libxo json".format(cls.NETSTAT_PATH, family_key, fibnum) + ) + js = json.loads(out) + js = js["statistics"]["route-nhop-information"]["nhop-table"]["rt-family"] + if js: + return js[0]["nh-entry"] + else: + return [] + @classmethod def get_linklocals(cls): ret = {} diff --git a/tests/atf_python/sys/net/vnet.py b/tests/atf_python/sys/net/vnet.py index 663f7695a0cc..0d9f969b28d9 100644 --- a/tests/atf_python/sys/net/vnet.py +++ b/tests/atf_python/sys/net/vnet.py @@ -101,11 +101,15 @@ class VnetInterface(object): addr = ipaddress.ip_interface(_addr) if addr.version == 6: family = "inet6" + cmd = "/sbin/ifconfig {} {} {}".format(self.name, family, addr) else: family = "inet" - cmd = "/sbin/ifconfig {} {} {}".format(self.name, family, addr) + if self.addr_map[family]: + cmd = "/sbin/ifconfig {} alias {}".format(self.name, addr) + else: + cmd = "/sbin/ifconfig {} {} {}".format(self.name, family, addr) self.run_cmd(cmd) - self.addr_map[family][str(addr)] = addr + self.addr_map[family][str(addr.ip)] = addr def delete_addr(self, _addr: str): addr = ipaddress.ip_address(_addr) diff --git a/tests/sys/net/routing/Makefile b/tests/sys/net/routing/Makefile index d71ba828f958..45034ff211b1 100644 --- a/tests/sys/net/routing/Makefile +++ b/tests/sys/net/routing/Makefile @@ -7,6 +7,7 @@ TESTSDIR= ${TESTSBASE}/sys/net/routing ATF_TESTS_C += test_rtsock_l3 ATF_TESTS_C += test_rtsock_lladdr +ATF_TESTS_PYTEST += test_routing_l3.py ATF_TESTS_PYTEST += test_rtsock_multipath.py ${PACKAGE}FILES+= generic_cleanup.sh diff --git a/tests/sys/net/routing/test_routing_l3.py b/tests/sys/net/routing/test_routing_l3.py new file mode 100755 index 000000000000..74017ae0459c --- /dev/null +++ b/tests/sys/net/routing/test_routing_l3.py @@ -0,0 +1,81 @@ +import ipaddress + +import pytest +from atf_python.sys.net.tools import ToolsHelper +from atf_python.sys.net.vnet import VnetTestTemplate + + +class TestIfOps(VnetTestTemplate): + TOPOLOGY = { + "vnet1": {"ifaces": ["if1", "if2"]}, + "if1": {"prefixes4": [], "prefixes6": []}, + "if2": {"prefixes4": [], "prefixes6": []}, + } + + @pytest.mark.parametrize("family", ["inet", "inet6"]) + @pytest.mark.require_user("root") + def test_change_prefix_route(self, family): + """Tests that prefix route changes to the new one upon addr deletion""" + vnet = self.vnet_map["vnet1"] + first_iface = vnet.iface_alias_map["if1"] + second_iface = vnet.iface_alias_map["if2"] + if family == "inet": + first_addr = ipaddress.ip_interface("192.0.2.1/24") + second_addr = ipaddress.ip_interface("192.0.2.2/24") + else: + first_addr = ipaddress.ip_interface("2001:db8::1/64") + second_addr = ipaddress.ip_interface("2001:db8::2/64") + + first_iface.setup_addr(str(first_addr)) + second_iface.setup_addr(str(second_addr)) + + # At this time prefix should be pointing to the first interface + routes = ToolsHelper.get_routes(family) + px = [r for r in routes if r["destination"] == str(first_addr.network)][0] + assert px["interface-name"] == first_iface.name + + # Now delete address from the first interface and verify switchover + first_iface.delete_addr(first_addr.ip) + + routes = ToolsHelper.get_routes(family) + px = [r for r in routes if r["destination"] == str(first_addr.network)][0] + assert px["interface-name"] == second_iface.name + + @pytest.mark.parametrize( + "family", + [ + "inet", + pytest.param("inet6", marks=pytest.mark.xfail(reason="currently fails")), + ], + ) + @pytest.mark.require_user("root") + def test_change_prefix_route_same_iface(self, family): + """Tests that prefix route changes to the new ifa upon addr deletion""" + vnet = self.vnet_map["vnet1"] + first_iface = vnet.iface_alias_map["if1"] + + if family == "inet": + first_addr = ipaddress.ip_interface("192.0.2.1/24") + second_addr = ipaddress.ip_interface("192.0.2.2/24") + else: + first_addr = ipaddress.ip_interface("2001:db8::1/64") + second_addr = ipaddress.ip_interface("2001:db8::2/64") + + first_iface.setup_addr(str(first_addr)) + first_iface.setup_addr(str(second_addr)) + + # At this time prefix should be pointing to the first interface + routes = ToolsHelper.get_routes(family) + px = [r for r in routes if r["destination"] == str(first_addr.network)][0] + assert px["interface-name"] == first_iface.name + + # Now delete address from the first interface and verify switchover + first_iface.delete_addr(str(first_addr.ip)) + + routes = ToolsHelper.get_routes(family) + px = [r for r in routes if r["destination"] == str(first_addr.network)][0] + nhop_kidx = px["nhop"] + assert px["interface-name"] == first_iface.name + nhops = ToolsHelper.get_nhops(family) + nh = [nh for nh in nhops if nh["index"] == nhop_kidx][0] + assert nh["ifa"] == str(second_addr.ip)