1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4NAMESPACES=""
5
6# Test that a link aggregation device (bonding, team) removes the hardware
7# addresses that it adds on its underlying devices.
8test_LAG_cleanup()
9{
10	local driver=$1
11	local mode=$2
12	local ucaddr="02:00:00:12:34:56"
13	local addr6="fe80::78:9abc/64"
14	local mcaddr="33:33:ff:78:9a:bc"
15	local name
16
17	ip link add dummy1 type dummy
18	ip link add dummy2 type dummy
19	if [ "$driver" = "bonding" ]; then
20		name="bond1"
21		ip link add "$name" up type bond mode "$mode"
22		ip link set dev dummy1 master "$name"
23		ip link set dev dummy2 master "$name"
24	elif [ "$driver" = "team" ]; then
25		name="team0"
26		teamd -d -c '
27			{
28				"device": "'"$name"'",
29				"runner": {
30					"name": "'"$mode"'"
31				},
32				"ports": {
33					"dummy1":
34						{},
35					"dummy2":
36						{}
37				}
38			}
39		'
40		ip link set dev "$name" up
41	else
42		check_err 1
43		log_test test_LAG_cleanup ": unknown driver \"$driver\""
44		return
45	fi
46
47	# Used to test dev->uc handling
48	ip link add mv0 link "$name" up address "$ucaddr" type macvlan
49	# Used to test dev->mc handling
50	ip address add "$addr6" dev "$name"
51
52	# Check that addresses were added as expected
53	(grep_bridge_fdb "$ucaddr" bridge fdb show dev dummy1 ||
54		grep_bridge_fdb "$ucaddr" bridge fdb show dev dummy2) >/dev/null
55	check_err $? "macvlan unicast address not found on a slave"
56
57	# mcaddr is added asynchronously by addrconf_dad_work(), use busywait
58	(busywait 10000 grep_bridge_fdb "$mcaddr" bridge fdb show dev dummy1 ||
59		grep_bridge_fdb "$mcaddr" bridge fdb show dev dummy2) >/dev/null
60	check_err $? "IPv6 solicited-node multicast mac address not found on a slave"
61
62	ip link set dev "$name" down
63	ip link del "$name"
64
65	not grep_bridge_fdb "$ucaddr" bridge fdb show >/dev/null
66	check_err $? "macvlan unicast address still present on a slave"
67
68	not grep_bridge_fdb "$mcaddr" bridge fdb show >/dev/null
69	check_err $? "IPv6 solicited-node multicast mac address still present on a slave"
70
71	cleanup
72
73	log_test "$driver cleanup mode $mode"
74}
75
76# Build a generic 2 node net namespace with 2 connections
77# between the namespaces
78#
79#  +-----------+       +-----------+
80#  | node1     |       | node2     |
81#  |           |       |           |
82#  |           |       |           |
83#  |      eth0 +-------+ eth0      |
84#  |           |       |           |
85#  |      eth1 +-------+ eth1      |
86#  |           |       |           |
87#  +-----------+       +-----------+
88lag_setup2x2()
89{
90	local state=${1:-down}
91	local namespaces="lag_node1 lag_node2"
92
93	# create namespaces
94	for n in ${namespaces}; do
95		ip netns add ${n}
96	done
97
98	# wire up namespaces
99	ip link add name lag1 type veth peer name lag1-end
100	ip link set dev lag1 netns lag_node1 $state name eth0
101	ip link set dev lag1-end netns lag_node2 $state name eth0
102
103	ip link add name lag1 type veth peer name lag1-end
104	ip link set dev lag1 netns lag_node1 $state name eth1
105	ip link set dev lag1-end netns lag_node2 $state name eth1
106
107	NAMESPACES="${namespaces}"
108}
109
110# cleanup all lag related namespaces and remove the bonding module
111lag_cleanup()
112{
113	for n in ${NAMESPACES}; do
114		ip netns delete ${n} >/dev/null 2>&1 || true
115	done
116	modprobe -r bonding
117}
118
119SWITCH="lag_node1"
120CLIENT="lag_node2"
121CLIENTIP="172.20.2.1"
122SWITCHIP="172.20.2.2"
123
124lag_setup_network()
125{
126	lag_setup2x2 "down"
127
128	# create switch
129	ip netns exec ${SWITCH} ip link add br0 up type bridge
130	ip netns exec ${SWITCH} ip link set eth0 master br0 up
131	ip netns exec ${SWITCH} ip link set eth1 master br0 up
132	ip netns exec ${SWITCH} ip addr add ${SWITCHIP}/24 dev br0
133}
134
135lag_reset_network()
136{
137	ip netns exec ${CLIENT} ip link del bond0
138	ip netns exec ${SWITCH} ip link set eth0 up
139	ip netns exec ${SWITCH} ip link set eth1 up
140}
141
142create_bond()
143{
144	# create client
145	ip netns exec ${CLIENT} ip link set eth0 down
146	ip netns exec ${CLIENT} ip link set eth1 down
147
148	ip netns exec ${CLIENT} ip link add bond0 type bond $@
149	ip netns exec ${CLIENT} ip link set eth0 master bond0
150	ip netns exec ${CLIENT} ip link set eth1 master bond0
151	ip netns exec ${CLIENT} ip link set bond0 up
152	ip netns exec ${CLIENT} ip addr add ${CLIENTIP}/24 dev bond0
153}
154
155test_bond_recovery()
156{
157	RET=0
158
159	create_bond $@
160
161	# verify connectivity
162	ip netns exec ${CLIENT} ping ${SWITCHIP} -c 2 >/dev/null 2>&1
163	check_err $? "No connectivity"
164
165	# force the links of the bond down
166	ip netns exec ${SWITCH} ip link set eth0 down
167	sleep 2
168	ip netns exec ${SWITCH} ip link set eth0 up
169	ip netns exec ${SWITCH} ip link set eth1 down
170
171	# re-verify connectivity
172	ip netns exec ${CLIENT} ping ${SWITCHIP} -c 2 >/dev/null 2>&1
173
174	local rc=$?
175	check_err $rc "Bond failed to recover"
176	log_test "$1 ($2) bond recovery"
177	lag_reset_network
178}
179