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