xref: /freebsd/tests/sys/net/routing/test_routing_l3.py (revision badcb3fd5710a511e35ac3afd724ef68c77614b7)
17064c94aSAlexander V. Chernikovimport ipaddress
2*badcb3fdSAlexander V. Chernikovimport socket
37064c94aSAlexander V. Chernikov
47064c94aSAlexander V. Chernikovimport pytest
5*badcb3fdSAlexander V. Chernikovfrom atf_python.sys.net.rtsock import RtConst
6*badcb3fdSAlexander V. Chernikovfrom atf_python.sys.net.rtsock import Rtsock
7*badcb3fdSAlexander V. Chernikovfrom atf_python.sys.net.rtsock import RtsockRtMessage
8*badcb3fdSAlexander V. Chernikovfrom atf_python.sys.net.rtsock import SaHelper
97064c94aSAlexander V. Chernikovfrom atf_python.sys.net.tools import ToolsHelper
10*badcb3fdSAlexander V. Chernikovfrom atf_python.sys.net.vnet import SingleVnetTestTemplate
117064c94aSAlexander V. Chernikovfrom atf_python.sys.net.vnet import VnetTestTemplate
127064c94aSAlexander V. Chernikov
137064c94aSAlexander V. Chernikov
147064c94aSAlexander V. Chernikovclass TestIfOps(VnetTestTemplate):
157064c94aSAlexander V. Chernikov    TOPOLOGY = {
167064c94aSAlexander V. Chernikov        "vnet1": {"ifaces": ["if1", "if2"]},
177064c94aSAlexander V. Chernikov        "if1": {"prefixes4": [], "prefixes6": []},
187064c94aSAlexander V. Chernikov        "if2": {"prefixes4": [], "prefixes6": []},
197064c94aSAlexander V. Chernikov    }
207064c94aSAlexander V. Chernikov
217064c94aSAlexander V. Chernikov    @pytest.mark.parametrize("family", ["inet", "inet6"])
227064c94aSAlexander V. Chernikov    @pytest.mark.require_user("root")
237064c94aSAlexander V. Chernikov    def test_change_prefix_route(self, family):
247064c94aSAlexander V. Chernikov        """Tests that prefix route changes to the new one upon addr deletion"""
257064c94aSAlexander V. Chernikov        vnet = self.vnet_map["vnet1"]
267064c94aSAlexander V. Chernikov        first_iface = vnet.iface_alias_map["if1"]
277064c94aSAlexander V. Chernikov        second_iface = vnet.iface_alias_map["if2"]
287064c94aSAlexander V. Chernikov        if family == "inet":
297064c94aSAlexander V. Chernikov            first_addr = ipaddress.ip_interface("192.0.2.1/24")
307064c94aSAlexander V. Chernikov            second_addr = ipaddress.ip_interface("192.0.2.2/24")
317064c94aSAlexander V. Chernikov        else:
327064c94aSAlexander V. Chernikov            first_addr = ipaddress.ip_interface("2001:db8::1/64")
337064c94aSAlexander V. Chernikov            second_addr = ipaddress.ip_interface("2001:db8::2/64")
347064c94aSAlexander V. Chernikov
357064c94aSAlexander V. Chernikov        first_iface.setup_addr(str(first_addr))
367064c94aSAlexander V. Chernikov        second_iface.setup_addr(str(second_addr))
377064c94aSAlexander V. Chernikov
387064c94aSAlexander V. Chernikov        # At this time prefix should be pointing to the first interface
397064c94aSAlexander V. Chernikov        routes = ToolsHelper.get_routes(family)
407064c94aSAlexander V. Chernikov        px = [r for r in routes if r["destination"] == str(first_addr.network)][0]
417064c94aSAlexander V. Chernikov        assert px["interface-name"] == first_iface.name
427064c94aSAlexander V. Chernikov
437064c94aSAlexander V. Chernikov        # Now delete address from the first interface and verify switchover
447064c94aSAlexander V. Chernikov        first_iface.delete_addr(first_addr.ip)
457064c94aSAlexander V. Chernikov
467064c94aSAlexander V. Chernikov        routes = ToolsHelper.get_routes(family)
477064c94aSAlexander V. Chernikov        px = [r for r in routes if r["destination"] == str(first_addr.network)][0]
487064c94aSAlexander V. Chernikov        assert px["interface-name"] == second_iface.name
497064c94aSAlexander V. Chernikov
507064c94aSAlexander V. Chernikov    @pytest.mark.parametrize(
517064c94aSAlexander V. Chernikov        "family",
527064c94aSAlexander V. Chernikov        [
537064c94aSAlexander V. Chernikov            "inet",
547064c94aSAlexander V. Chernikov            pytest.param("inet6", marks=pytest.mark.xfail(reason="currently fails")),
557064c94aSAlexander V. Chernikov        ],
567064c94aSAlexander V. Chernikov    )
577064c94aSAlexander V. Chernikov    @pytest.mark.require_user("root")
587064c94aSAlexander V. Chernikov    def test_change_prefix_route_same_iface(self, family):
597064c94aSAlexander V. Chernikov        """Tests that prefix route changes to the new ifa upon addr deletion"""
607064c94aSAlexander V. Chernikov        vnet = self.vnet_map["vnet1"]
617064c94aSAlexander V. Chernikov        first_iface = vnet.iface_alias_map["if1"]
627064c94aSAlexander V. Chernikov
637064c94aSAlexander V. Chernikov        if family == "inet":
647064c94aSAlexander V. Chernikov            first_addr = ipaddress.ip_interface("192.0.2.1/24")
657064c94aSAlexander V. Chernikov            second_addr = ipaddress.ip_interface("192.0.2.2/24")
667064c94aSAlexander V. Chernikov        else:
677064c94aSAlexander V. Chernikov            first_addr = ipaddress.ip_interface("2001:db8::1/64")
687064c94aSAlexander V. Chernikov            second_addr = ipaddress.ip_interface("2001:db8::2/64")
697064c94aSAlexander V. Chernikov
707064c94aSAlexander V. Chernikov        first_iface.setup_addr(str(first_addr))
717064c94aSAlexander V. Chernikov        first_iface.setup_addr(str(second_addr))
727064c94aSAlexander V. Chernikov
737064c94aSAlexander V. Chernikov        # At this time prefix should be pointing to the first interface
747064c94aSAlexander V. Chernikov        routes = ToolsHelper.get_routes(family)
757064c94aSAlexander V. Chernikov        px = [r for r in routes if r["destination"] == str(first_addr.network)][0]
767064c94aSAlexander V. Chernikov        assert px["interface-name"] == first_iface.name
777064c94aSAlexander V. Chernikov
787064c94aSAlexander V. Chernikov        # Now delete address from the first interface and verify switchover
797064c94aSAlexander V. Chernikov        first_iface.delete_addr(str(first_addr.ip))
807064c94aSAlexander V. Chernikov
817064c94aSAlexander V. Chernikov        routes = ToolsHelper.get_routes(family)
827064c94aSAlexander V. Chernikov        px = [r for r in routes if r["destination"] == str(first_addr.network)][0]
837064c94aSAlexander V. Chernikov        nhop_kidx = px["nhop"]
847064c94aSAlexander V. Chernikov        assert px["interface-name"] == first_iface.name
857064c94aSAlexander V. Chernikov        nhops = ToolsHelper.get_nhops(family)
867064c94aSAlexander V. Chernikov        nh = [nh for nh in nhops if nh["index"] == nhop_kidx][0]
877064c94aSAlexander V. Chernikov        assert nh["ifa"] == str(second_addr.ip)
88*badcb3fdSAlexander V. Chernikov
89*badcb3fdSAlexander V. Chernikov
90*badcb3fdSAlexander V. Chernikovclass TestRouteCornerCase1(SingleVnetTestTemplate):
91*badcb3fdSAlexander V. Chernikov    @pytest.mark.parametrize("family", ["inet", "inet6"])
92*badcb3fdSAlexander V. Chernikov    @pytest.mark.require_user("root")
93*badcb3fdSAlexander V. Chernikov    def test_add_direct_route_p2p_wo_ifa(self, family):
94*badcb3fdSAlexander V. Chernikov
95*badcb3fdSAlexander V. Chernikov        tun_ifname = ToolsHelper.get_output("/sbin/ifconfig tun create").rstrip()
96*badcb3fdSAlexander V. Chernikov        tun_ifindex = socket.if_nametoindex(tun_ifname)
97*badcb3fdSAlexander V. Chernikov        assert tun_ifindex > 0
98*badcb3fdSAlexander V. Chernikov        rtsock = Rtsock()
99*badcb3fdSAlexander V. Chernikov
100*badcb3fdSAlexander V. Chernikov        if family == "inet":
101*badcb3fdSAlexander V. Chernikov            prefix = "172.16.0.0/12"
102*badcb3fdSAlexander V. Chernikov        else:
103*badcb3fdSAlexander V. Chernikov            prefix = "2a02:6b8::/64"
104*badcb3fdSAlexander V. Chernikov        IFT_ETHER = 0x06
105*badcb3fdSAlexander V. Chernikov        gw_link = SaHelper.link_sa(ifindex=tun_ifindex, iftype=IFT_ETHER)
106*badcb3fdSAlexander V. Chernikov
107*badcb3fdSAlexander V. Chernikov        msg = rtsock.new_rtm_add(prefix, gw_link)
108*badcb3fdSAlexander V. Chernikov        msg.add_link_attr(RtConst.RTA_IFP, tun_ifindex)
109*badcb3fdSAlexander V. Chernikov        rtsock.write_message(msg)
110*badcb3fdSAlexander V. Chernikov
111*badcb3fdSAlexander V. Chernikov        data = rtsock.read_data(msg.rtm_seq)
112*badcb3fdSAlexander V. Chernikov        msg_in = RtsockRtMessage.from_bytes(data)
113*badcb3fdSAlexander V. Chernikov        msg_in.print_in_message()
114*badcb3fdSAlexander V. Chernikov
115*badcb3fdSAlexander V. Chernikov        desired_sa = {
116*badcb3fdSAlexander V. Chernikov            RtConst.RTA_DST: msg.get_sa(RtConst.RTA_DST),
117*badcb3fdSAlexander V. Chernikov            RtConst.RTA_NETMASK: msg.get_sa(RtConst.RTA_NETMASK),
118*badcb3fdSAlexander V. Chernikov        }
119*badcb3fdSAlexander V. Chernikov
120*badcb3fdSAlexander V. Chernikov        msg_in.verify(msg.rtm_type, desired_sa)
121