1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Test bonding options with mode 1,5,6
5
6ALL_TESTS="
7	prio
8	arp_validate
9	num_grat_arp
10"
11
12lib_dir=$(dirname "$0")
13source ${lib_dir}/bond_topo_3d1c.sh
14
15skip_prio()
16{
17	local skip=1
18
19	# check if iproute support prio option
20	ip -n ${s_ns} link set eth0 type bond_slave prio 10
21	[[ $? -ne 0 ]] && skip=0
22
23	# check if kernel support prio option
24	ip -n ${s_ns} -d link show eth0 | grep -q "prio 10"
25	[[ $? -ne 0 ]] && skip=0
26
27	return $skip
28}
29
30skip_ns()
31{
32	local skip=1
33
34	# check if iproute support ns_ip6_target option
35	ip -n ${s_ns} link add bond1 type bond ns_ip6_target ${g_ip6}
36	[[ $? -ne 0 ]] && skip=0
37
38	# check if kernel support ns_ip6_target option
39	ip -n ${s_ns} -d link show bond1 | grep -q "ns_ip6_target ${g_ip6}"
40	[[ $? -ne 0 ]] && skip=0
41
42	ip -n ${s_ns} link del bond1
43
44	return $skip
45}
46
47active_slave=""
48check_active_slave()
49{
50	local target_active_slave=$1
51	active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
52	test "$active_slave" = "$target_active_slave"
53	check_err $? "Current active slave is $active_slave but not $target_active_slave"
54}
55
56
57# Test bonding prio option
58prio_test()
59{
60	local param="$1"
61	RET=0
62
63	# create bond
64	bond_reset "${param}"
65
66	# check bonding member prio value
67	ip -n ${s_ns} link set eth0 type bond_slave prio 0
68	ip -n ${s_ns} link set eth1 type bond_slave prio 10
69	ip -n ${s_ns} link set eth2 type bond_slave prio 11
70	cmd_jq "ip -n ${s_ns} -d -j link show eth0" \
71		".[].linkinfo.info_slave_data | select (.prio == 0)" "-e" &> /dev/null
72	check_err $? "eth0 prio is not 0"
73	cmd_jq "ip -n ${s_ns} -d -j link show eth1" \
74		".[].linkinfo.info_slave_data | select (.prio == 10)" "-e" &> /dev/null
75	check_err $? "eth1 prio is not 10"
76	cmd_jq "ip -n ${s_ns} -d -j link show eth2" \
77		".[].linkinfo.info_slave_data | select (.prio == 11)" "-e" &> /dev/null
78	check_err $? "eth2 prio is not 11"
79
80	bond_check_connection "setup"
81
82	# active slave should be the primary slave
83	check_active_slave eth1
84
85	# active slave should be the higher prio slave
86	ip -n ${s_ns} link set $active_slave down
87	bond_check_connection "fail over"
88	check_active_slave eth2
89
90	# when only 1 slave is up
91	ip -n ${s_ns} link set $active_slave down
92	bond_check_connection "only 1 slave up"
93	check_active_slave eth0
94
95	# when a higher prio slave change to up
96	ip -n ${s_ns} link set eth2 up
97	bond_check_connection "higher prio slave up"
98	case $primary_reselect in
99		"0")
100			check_active_slave "eth2"
101			;;
102		"1")
103			check_active_slave "eth0"
104			;;
105		"2")
106			check_active_slave "eth0"
107			;;
108	esac
109	local pre_active_slave=$active_slave
110
111	# when the primary slave change to up
112	ip -n ${s_ns} link set eth1 up
113	bond_check_connection "primary slave up"
114	case $primary_reselect in
115		"0")
116			check_active_slave "eth1"
117			;;
118		"1")
119			check_active_slave "$pre_active_slave"
120			;;
121		"2")
122			check_active_slave "$pre_active_slave"
123			ip -n ${s_ns} link set $active_slave down
124			bond_check_connection "pre_active slave down"
125			check_active_slave "eth1"
126			;;
127	esac
128
129	# Test changing bond slave prio
130	if [[ "$primary_reselect" == "0" ]];then
131		ip -n ${s_ns} link set eth0 type bond_slave prio 1000000
132		ip -n ${s_ns} link set eth1 type bond_slave prio 0
133		ip -n ${s_ns} link set eth2 type bond_slave prio -50
134		ip -n ${s_ns} -d link show eth0 | grep -q 'prio 1000000'
135		check_err $? "eth0 prio is not 1000000"
136		ip -n ${s_ns} -d link show eth1 | grep -q 'prio 0'
137		check_err $? "eth1 prio is not 0"
138		ip -n ${s_ns} -d link show eth2 | grep -q 'prio -50'
139		check_err $? "eth3 prio is not -50"
140		check_active_slave "eth1"
141
142		ip -n ${s_ns} link set $active_slave down
143		bond_check_connection "change slave prio"
144		check_active_slave "eth0"
145	fi
146}
147
148prio_miimon()
149{
150	local primary_reselect
151	local mode=$1
152
153	for primary_reselect in 0 1 2; do
154		prio_test "mode $mode miimon 100 primary eth1 primary_reselect $primary_reselect"
155		log_test "prio" "$mode miimon primary_reselect $primary_reselect"
156	done
157}
158
159prio_arp()
160{
161	local primary_reselect
162	local mode=$1
163
164	for primary_reselect in 0 1 2; do
165		prio_test "mode $mode arp_interval 100 arp_ip_target ${g_ip4} primary eth1 primary_reselect $primary_reselect"
166		log_test "prio" "$mode arp_ip_target primary_reselect $primary_reselect"
167	done
168}
169
170prio_ns()
171{
172	local primary_reselect
173	local mode=$1
174
175	if skip_ns; then
176		log_test_skip "prio ns" "Current iproute or kernel doesn't support bond option 'ns_ip6_target'."
177		return 0
178	fi
179
180	for primary_reselect in 0 1 2; do
181		prio_test "mode $mode arp_interval 100 ns_ip6_target ${g_ip6} primary eth1 primary_reselect $primary_reselect"
182		log_test "prio" "$mode ns_ip6_target primary_reselect $primary_reselect"
183	done
184}
185
186prio()
187{
188	local mode modes="active-backup balance-tlb balance-alb"
189
190	if skip_prio; then
191		log_test_skip "prio" "Current iproute or kernel doesn't support bond option 'prio'."
192		return 0
193	fi
194
195	for mode in $modes; do
196		prio_miimon $mode
197	done
198	prio_arp "active-backup"
199	prio_ns "active-backup"
200}
201
202arp_validate_test()
203{
204	local param="$1"
205	RET=0
206
207	# create bond
208	bond_reset "${param}"
209
210	bond_check_connection
211	[ $RET -ne 0 ] && log_test "arp_validate" "$retmsg"
212
213	# wait for a while to make sure the mii status stable
214	sleep 5
215	for i in $(seq 0 2); do
216		mii_status=$(cmd_jq "ip -n ${s_ns} -j -d link show eth$i" ".[].linkinfo.info_slave_data.mii_status")
217		if [ ${mii_status} != "UP" ]; then
218			RET=1
219			log_test "arp_validate" "interface eth$i mii_status $mii_status"
220		fi
221	done
222}
223
224arp_validate_arp()
225{
226	local mode=$1
227	local val
228	for val in $(seq 0 6); do
229		arp_validate_test "mode $mode arp_interval 100 arp_ip_target ${g_ip4} arp_validate $val"
230		log_test "arp_validate" "$mode arp_ip_target arp_validate $val"
231	done
232}
233
234arp_validate_ns()
235{
236	local mode=$1
237	local val
238
239	if skip_ns; then
240		log_test_skip "arp_validate ns" "Current iproute or kernel doesn't support bond option 'ns_ip6_target'."
241		return 0
242	fi
243
244	for val in $(seq 0 6); do
245		arp_validate_test "mode $mode arp_interval 100 ns_ip6_target ${g_ip6} arp_validate $val"
246		log_test "arp_validate" "$mode ns_ip6_target arp_validate $val"
247	done
248}
249
250arp_validate()
251{
252	arp_validate_arp "active-backup"
253	arp_validate_ns "active-backup"
254}
255
256garp_test()
257{
258	local param="$1"
259	local active_slave exp_num real_num i
260	RET=0
261
262	# create bond
263	bond_reset "${param}"
264
265	bond_check_connection
266	[ $RET -ne 0 ] && log_test "num_grat_arp" "$retmsg"
267
268
269	# Add tc rules to count GARP number
270	for i in $(seq 0 2); do
271		tc -n ${g_ns} filter add dev s$i ingress protocol arp pref 1 handle 101 \
272			flower skip_hw arp_op request arp_sip ${s_ip4} arp_tip ${s_ip4} action pass
273	done
274
275	# Do failover
276	active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
277	ip -n ${s_ns} link set ${active_slave} down
278
279	exp_num=$(echo "${param}" | cut -f6 -d ' ')
280	sleep $((exp_num + 2))
281
282	active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
283
284	# check result
285	real_num=$(tc_rule_handle_stats_get "dev s${active_slave#eth} ingress" 101 ".packets" "-n ${g_ns}")
286	if [ "${real_num}" -ne "${exp_num}" ]; then
287		echo "$real_num garp packets sent on active slave ${active_slave}"
288		RET=1
289	fi
290
291	for i in $(seq 0 2); do
292		tc -n ${g_ns} filter del dev s$i ingress
293	done
294}
295
296num_grat_arp()
297{
298	local val
299	for val in 10 20 30 50; do
300		garp_test "mode active-backup miimon 100 num_grat_arp $val peer_notify_delay 1000"
301		log_test "num_grat_arp" "active-backup miimon num_grat_arp $val"
302	done
303}
304
305trap cleanup EXIT
306
307setup_prepare
308setup_wait
309tests_run
310
311exit $EXIT_STATUS
312