xref: /linux/tools/testing/selftests/net/link_netns.py (revision 1a9239bb4253f9076b5b4b2a1a4e8d7defd77a95)
1*85cb3711SXiao Liang#!/usr/bin/env python3
2*85cb3711SXiao Liang# SPDX-License-Identifier: GPL-2.0
3*85cb3711SXiao Liang
4*85cb3711SXiao Liangimport time
5*85cb3711SXiao Liang
6*85cb3711SXiao Liangfrom lib.py import ksft_run, ksft_exit, ksft_true
7*85cb3711SXiao Liangfrom lib.py import ip
8*85cb3711SXiao Liangfrom lib.py import NetNS, NetNSEnter
9*85cb3711SXiao Liangfrom lib.py import RtnlFamily
10*85cb3711SXiao Liang
11*85cb3711SXiao Liang
12*85cb3711SXiao LiangLINK_NETNSID = 100
13*85cb3711SXiao Liang
14*85cb3711SXiao Liang
15*85cb3711SXiao Liangdef test_event() -> None:
16*85cb3711SXiao Liang    with NetNS() as ns1, NetNS() as ns2:
17*85cb3711SXiao Liang        with NetNSEnter(str(ns2)):
18*85cb3711SXiao Liang            rtnl = RtnlFamily()
19*85cb3711SXiao Liang
20*85cb3711SXiao Liang        rtnl.ntf_subscribe("rtnlgrp-link")
21*85cb3711SXiao Liang
22*85cb3711SXiao Liang        ip(f"netns set {ns2} {LINK_NETNSID}", ns=str(ns1))
23*85cb3711SXiao Liang        ip(f"link add netns {ns1} link-netnsid {LINK_NETNSID} dummy1 type dummy")
24*85cb3711SXiao Liang        ip(f"link add netns {ns1} dummy2 type dummy", ns=str(ns2))
25*85cb3711SXiao Liang
26*85cb3711SXiao Liang        ip("link del dummy1", ns=str(ns1))
27*85cb3711SXiao Liang        ip("link del dummy2", ns=str(ns1))
28*85cb3711SXiao Liang
29*85cb3711SXiao Liang        time.sleep(1)
30*85cb3711SXiao Liang        rtnl.check_ntf()
31*85cb3711SXiao Liang        ksft_true(rtnl.async_msg_queue.empty(),
32*85cb3711SXiao Liang                  "Received unexpected link notification")
33*85cb3711SXiao Liang
34*85cb3711SXiao Liang
35*85cb3711SXiao Liangdef validate_link_netns(netns, ifname, link_netnsid) -> bool:
36*85cb3711SXiao Liang    link_info = ip(f"-d link show dev {ifname}", ns=netns, json=True)
37*85cb3711SXiao Liang    if not link_info:
38*85cb3711SXiao Liang        return False
39*85cb3711SXiao Liang    return link_info[0].get("link_netnsid") == link_netnsid
40*85cb3711SXiao Liang
41*85cb3711SXiao Liang
42*85cb3711SXiao Liangdef test_link_net() -> None:
43*85cb3711SXiao Liang    configs = [
44*85cb3711SXiao Liang        # type, common args, type args, fallback to dev_net
45*85cb3711SXiao Liang        ("ipvlan", "link dummy1", "", False),
46*85cb3711SXiao Liang        ("macsec", "link dummy1", "", False),
47*85cb3711SXiao Liang        ("macvlan", "link dummy1", "", False),
48*85cb3711SXiao Liang        ("macvtap", "link dummy1", "", False),
49*85cb3711SXiao Liang        ("vlan", "link dummy1", "id 100", False),
50*85cb3711SXiao Liang        ("gre", "", "local 192.0.2.1", True),
51*85cb3711SXiao Liang        ("vti", "", "local 192.0.2.1", True),
52*85cb3711SXiao Liang        ("ipip", "", "local 192.0.2.1", True),
53*85cb3711SXiao Liang        ("ip6gre", "", "local 2001:db8::1", True),
54*85cb3711SXiao Liang        ("ip6tnl", "", "local 2001:db8::1", True),
55*85cb3711SXiao Liang        ("vti6", "", "local 2001:db8::1", True),
56*85cb3711SXiao Liang        ("sit", "", "local 192.0.2.1", True),
57*85cb3711SXiao Liang        ("xfrm", "", "if_id 1", True),
58*85cb3711SXiao Liang    ]
59*85cb3711SXiao Liang
60*85cb3711SXiao Liang    with NetNS() as ns1, NetNS() as ns2, NetNS() as ns3:
61*85cb3711SXiao Liang        net1, net2, net3 = str(ns1), str(ns2), str(ns3)
62*85cb3711SXiao Liang
63*85cb3711SXiao Liang        # prepare link netnsid  and a dummy link needed by certain drivers
64*85cb3711SXiao Liang        ip(f"netns set {net3} {LINK_NETNSID}", ns=str(net2))
65*85cb3711SXiao Liang        ip("link add dummy1 type dummy", ns=net3)
66*85cb3711SXiao Liang
67*85cb3711SXiao Liang        cases = [
68*85cb3711SXiao Liang            # source, "netns", "link-netns", expected link-netns
69*85cb3711SXiao Liang            (net3, None, None, None, None),
70*85cb3711SXiao Liang            (net3, net2, None, None, LINK_NETNSID),
71*85cb3711SXiao Liang            (net2, None, net3, LINK_NETNSID, LINK_NETNSID),
72*85cb3711SXiao Liang            (net1, net2, net3, LINK_NETNSID, LINK_NETNSID),
73*85cb3711SXiao Liang        ]
74*85cb3711SXiao Liang
75*85cb3711SXiao Liang        for src_net, netns, link_netns, exp1, exp2 in cases:
76*85cb3711SXiao Liang            tgt_net = netns or src_net
77*85cb3711SXiao Liang            for typ, cargs, targs, fb_dev_net in configs:
78*85cb3711SXiao Liang                cmd = "link add"
79*85cb3711SXiao Liang                if netns:
80*85cb3711SXiao Liang                    cmd += f" netns {netns}"
81*85cb3711SXiao Liang                if link_netns:
82*85cb3711SXiao Liang                    cmd += f" link-netns {link_netns}"
83*85cb3711SXiao Liang                cmd += f" {cargs} foo type {typ} {targs}"
84*85cb3711SXiao Liang                ip(cmd, ns=src_net)
85*85cb3711SXiao Liang                if fb_dev_net:
86*85cb3711SXiao Liang                    ksft_true(validate_link_netns(tgt_net, "foo", exp1),
87*85cb3711SXiao Liang                              f"{typ} link_netns validation failed")
88*85cb3711SXiao Liang                else:
89*85cb3711SXiao Liang                    ksft_true(validate_link_netns(tgt_net, "foo", exp2),
90*85cb3711SXiao Liang                              f"{typ} link_netns validation failed")
91*85cb3711SXiao Liang                ip(f"link del foo", ns=tgt_net)
92*85cb3711SXiao Liang
93*85cb3711SXiao Liang
94*85cb3711SXiao Liangdef test_peer_net() -> None:
95*85cb3711SXiao Liang    types = [
96*85cb3711SXiao Liang        "vxcan",
97*85cb3711SXiao Liang        "netkit",
98*85cb3711SXiao Liang        "veth",
99*85cb3711SXiao Liang    ]
100*85cb3711SXiao Liang
101*85cb3711SXiao Liang    with NetNS() as ns1, NetNS() as ns2, NetNS() as ns3, NetNS() as ns4:
102*85cb3711SXiao Liang        net1, net2, net3, net4 = str(ns1), str(ns2), str(ns3), str(ns4)
103*85cb3711SXiao Liang
104*85cb3711SXiao Liang        ip(f"netns set {net3} {LINK_NETNSID}", ns=str(net2))
105*85cb3711SXiao Liang
106*85cb3711SXiao Liang        cases = [
107*85cb3711SXiao Liang            # source, "netns", "link-netns", "peer netns", expected
108*85cb3711SXiao Liang            (net1, None, None, None, None),
109*85cb3711SXiao Liang            (net1, net2, None, None, None),
110*85cb3711SXiao Liang            (net2, None, net3, None, LINK_NETNSID),
111*85cb3711SXiao Liang            (net1, net2, net3, None, None),
112*85cb3711SXiao Liang            (net2, None, None, net3, LINK_NETNSID),
113*85cb3711SXiao Liang            (net1, net2, None, net3, LINK_NETNSID),
114*85cb3711SXiao Liang            (net2, None, net2, net3, LINK_NETNSID),
115*85cb3711SXiao Liang            (net1, net2, net4, net3, LINK_NETNSID),
116*85cb3711SXiao Liang        ]
117*85cb3711SXiao Liang
118*85cb3711SXiao Liang        for src_net, netns, link_netns, peer_netns, exp in cases:
119*85cb3711SXiao Liang            tgt_net = netns or src_net
120*85cb3711SXiao Liang            for typ in types:
121*85cb3711SXiao Liang                cmd = "link add"
122*85cb3711SXiao Liang                if netns:
123*85cb3711SXiao Liang                    cmd += f" netns {netns}"
124*85cb3711SXiao Liang                if link_netns:
125*85cb3711SXiao Liang                    cmd += f" link-netns {link_netns}"
126*85cb3711SXiao Liang                cmd += f" foo type {typ}"
127*85cb3711SXiao Liang                if peer_netns:
128*85cb3711SXiao Liang                    cmd += f" peer netns {peer_netns}"
129*85cb3711SXiao Liang                ip(cmd, ns=src_net)
130*85cb3711SXiao Liang                ksft_true(validate_link_netns(tgt_net, "foo", exp),
131*85cb3711SXiao Liang                          f"{typ} peer_netns validation failed")
132*85cb3711SXiao Liang                ip(f"link del foo", ns=tgt_net)
133*85cb3711SXiao Liang
134*85cb3711SXiao Liang
135*85cb3711SXiao Liangdef main() -> None:
136*85cb3711SXiao Liang    ksft_run([test_event, test_link_net, test_peer_net])
137*85cb3711SXiao Liang    ksft_exit()
138*85cb3711SXiao Liang
139*85cb3711SXiao Liang
140*85cb3711SXiao Liangif __name__ == "__main__":
141*85cb3711SXiao Liang    main()
142