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