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