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