File Index
Files and directories
Sign in
FILE

bond_options.sh

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/drivers/net/bonding/bond_options.sh BASH
  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	fail_over_mac
 11	vlan_over_bond
 12"
 13
 14lib_dir=$(dirname "$0")
 15source ${lib_dir}/bond_topo_3d1c.sh
 16c_maddr="33:33:ff:00:00:10"
 17g_maddr="33:33:ff:00:02:54"
 18
 19skip_prio()
 20{
 21	local skip=1
 22
 23	# check if iproute support prio option
 24	ip -n ${s_ns} link set eth0 type bond_slave prio 10
 25	[[ $? -ne 0 ]] && skip=0
 26
 27	# check if kernel support prio option
 28	ip -n ${s_ns} -d link show eth0 | grep -q "prio 10"
 29	[[ $? -ne 0 ]] && skip=0
 30
 31	return $skip
 32}
 33
 34skip_ns()
 35{
 36	local skip=1
 37
 38	# check if iproute support ns_ip6_target option
 39	ip -n ${s_ns} link add bond1 type bond ns_ip6_target ${g_ip6}
 40	[[ $? -ne 0 ]] && skip=0
 41
 42	# check if kernel support ns_ip6_target option
 43	ip -n ${s_ns} -d link show bond1 | grep -q "ns_ip6_target ${g_ip6}"
 44	[[ $? -ne 0 ]] && skip=0
 45
 46	ip -n ${s_ns} link del bond1
 47
 48	return $skip
 49}
 50
 51active_slave=""
 52active_slave_changed()
 53{
 54	local old_active_slave=$1
 55	local new_active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" \
 56				".[].linkinfo.info_data.active_slave")
 57	[ "$new_active_slave" != "$old_active_slave" -a "$new_active_slave" != "null" ]
 58}
 59
 60check_active_slave()
 61{
 62	local target_active_slave=$1
 63	slowwait 5 active_slave_changed $active_slave
 64	active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
 65	test "$active_slave" = "$target_active_slave"
 66	check_err $? "Current active slave is $active_slave but not $target_active_slave"
 67}
 68
 69# Test bonding prio option
 70prio_test()
 71{
 72	local param="$1"
 73	RET=0
 74
 75	# create bond
 76	bond_reset "${param}"
 77	# set active_slave to primary eth1 specifically
 78	ip -n ${s_ns} link set bond0 type bond active_slave eth1
 79
 80	# check bonding member prio value
 81	ip -n ${s_ns} link set eth0 type bond_slave prio 0
 82	ip -n ${s_ns} link set eth1 type bond_slave prio 10
 83	ip -n ${s_ns} link set eth2 type bond_slave prio 11
 84	cmd_jq "ip -n ${s_ns} -d -j link show eth0" \
 85		".[].linkinfo.info_slave_data | select (.prio == 0)" "-e" &> /dev/null
 86	check_err $? "eth0 prio is not 0"
 87	cmd_jq "ip -n ${s_ns} -d -j link show eth1" \
 88		".[].linkinfo.info_slave_data | select (.prio == 10)" "-e" &> /dev/null
 89	check_err $? "eth1 prio is not 10"
 90	cmd_jq "ip -n ${s_ns} -d -j link show eth2" \
 91		".[].linkinfo.info_slave_data | select (.prio == 11)" "-e" &> /dev/null
 92	check_err $? "eth2 prio is not 11"
 93
 94	bond_check_connection "setup"
 95
 96	# active slave should be the primary slave
 97	check_active_slave eth1
 98
 99	# active slave should be the higher prio slave
100	ip -n ${s_ns} link set $active_slave down
101	check_active_slave eth2
102	bond_check_connection "fail over"
103
104	# when only 1 slave is up
105	ip -n ${s_ns} link set $active_slave down
106	check_active_slave eth0
107	bond_check_connection "only 1 slave up"
108
109	# when a higher prio slave change to up
110	ip -n ${s_ns} link set eth2 up
111	bond_check_connection "higher prio slave up"
112	case $primary_reselect in
113		"0")
114			check_active_slave "eth2"
115			;;
116		"1")
117			check_active_slave "eth0"
118			;;
119		"2")
120			check_active_slave "eth0"
121			;;
122	esac
123	local pre_active_slave=$active_slave
124
125	# when the primary slave change to up
126	ip -n ${s_ns} link set eth1 up
127	bond_check_connection "primary slave up"
128	case $primary_reselect in
129		"0")
130			check_active_slave "eth1"
131			;;
132		"1")
133			check_active_slave "$pre_active_slave"
134			;;
135		"2")
136			check_active_slave "$pre_active_slave"
137			ip -n ${s_ns} link set $active_slave down
138			bond_check_connection "pre_active slave down"
139			check_active_slave "eth1"
140			;;
141	esac
142
143	# Test changing bond slave prio
144	if [[ "$primary_reselect" == "0" ]];then
145		ip -n ${s_ns} link set eth0 type bond_slave prio 1000000
146		ip -n ${s_ns} link set eth1 type bond_slave prio 0
147		ip -n ${s_ns} link set eth2 type bond_slave prio -50
148		ip -n ${s_ns} -d link show eth0 | grep -q 'prio 1000000'
149		check_err $? "eth0 prio is not 1000000"
150		ip -n ${s_ns} -d link show eth1 | grep -q 'prio 0'
151		check_err $? "eth1 prio is not 0"
152		ip -n ${s_ns} -d link show eth2 | grep -q 'prio -50'
153		check_err $? "eth3 prio is not -50"
154		check_active_slave "eth1"
155
156		ip -n ${s_ns} link set $active_slave down
157		check_active_slave "eth0"
158		bond_check_connection "change slave prio"
159	fi
160}
161
162prio_miimon()
163{
164	local primary_reselect
165	local mode=$1
166
167	for primary_reselect in 0 1 2; do
168		prio_test "mode $mode miimon 100 primary eth1 primary_reselect $primary_reselect"
169		log_test "prio" "$mode miimon primary_reselect $primary_reselect"
170	done
171}
172
173prio_arp()
174{
175	local primary_reselect
176	local mode=$1
177
178	for primary_reselect in 0 1 2; do
179		prio_test "mode $mode arp_interval 100 arp_ip_target ${g_ip4} primary eth1 primary_reselect $primary_reselect"
180		log_test "prio" "$mode arp_ip_target primary_reselect $primary_reselect"
181	done
182}
183
184prio_ns()
185{
186	local primary_reselect
187	local mode=$1
188
189	if skip_ns; then
190		log_test_skip "prio ns" "Current iproute or kernel doesn't support bond option 'ns_ip6_target'."
191		return 0
192	fi
193
194	for primary_reselect in 0 1 2; do
195		prio_test "mode $mode arp_interval 100 ns_ip6_target ${g_ip6} primary eth1 primary_reselect $primary_reselect"
196		log_test "prio" "$mode ns_ip6_target primary_reselect $primary_reselect"
197	done
198}
199
200prio()
201{
202	local mode modes="active-backup balance-tlb balance-alb"
203
204	if skip_prio; then
205		log_test_skip "prio" "Current iproute or kernel doesn't support bond option 'prio'."
206		return 0
207	fi
208
209	for mode in $modes; do
210		prio_miimon $mode
211	done
212	prio_arp "active-backup"
213	prio_ns "active-backup"
214}
215
216wait_mii_up()
217{
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		[ ${mii_status} != "UP" ] && return 1
221	done
222	return 0
223}
224
225arp_validate_test()
226{
227	local param="$1"
228	RET=0
229
230	# create bond
231	bond_reset "${param}"
232
233	bond_check_connection
234	[ $RET -ne 0 ] && log_test "arp_validate" "$retmsg"
235
236	# wait for a while to make sure the mii status stable
237	slowwait 5 wait_mii_up
238	for i in $(seq 0 2); do
239		mii_status=$(cmd_jq "ip -n ${s_ns} -j -d link show eth$i" ".[].linkinfo.info_slave_data.mii_status")
240		if [ ${mii_status} != "UP" ]; then
241			RET=1
242			log_test "arp_validate" "interface eth$i mii_status $mii_status"
243		fi
244	done
245}
246
247# Testing correct multicast groups are added to slaves for ns targets
248arp_validate_mcast()
249{
250	RET=0
251	local arp_valid=$(cmd_jq "ip -n ${s_ns} -j -d link show bond0" ".[].linkinfo.info_data.arp_validate")
252	local active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
253
254	for i in $(seq 0 2); do
255		maddr_list=$(ip -n ${s_ns} maddr show dev eth${i})
256
257		# arp_valid == 0 or active_slave should not join any maddrs
258		if { [ "$arp_valid" == "null" ] || [ "eth${i}" == ${active_slave} ]; } && \
259			echo "$maddr_list" | grep -qE "${c_maddr}|${g_maddr}"; then
260			RET=1
261			check_err 1 "arp_valid $arp_valid active_slave $active_slave, eth$i has mcast group"
262		# arp_valid != 0 and backup_slave should join both maddrs
263		elif [ "$arp_valid" != "null" ] && [ "eth${i}" != ${active_slave} ] && \
264		     ( ! echo "$maddr_list" | grep -q "${c_maddr}" || \
265		       ! echo "$maddr_list" | grep -q "${m_maddr}"); then
266			RET=1
267			check_err 1 "arp_valid $arp_valid active_slave $active_slave, eth$i has mcast group"
268		fi
269	done
270
271	# Do failover
272	ip -n ${s_ns} link set ${active_slave} down
273	# wait for active link change
274	slowwait 2 active_slave_changed $active_slave
275	active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
276
277	for i in $(seq 0 2); do
278		maddr_list=$(ip -n ${s_ns} maddr show dev eth${i})
279
280		# arp_valid == 0 or active_slave should not join any maddrs
281		if { [ "$arp_valid" == "null" ] || [ "eth${i}" == ${active_slave} ]; } && \
282			echo "$maddr_list" | grep -qE "${c_maddr}|${g_maddr}"; then
283			RET=1
284			check_err 1 "arp_valid $arp_valid active_slave $active_slave, eth$i has mcast group"
285		# arp_valid != 0 and backup_slave should join both maddrs
286		elif [ "$arp_valid" != "null" ] && [ "eth${i}" != ${active_slave} ] && \
287		     ( ! echo "$maddr_list" | grep -q "${c_maddr}" || \
288		       ! echo "$maddr_list" | grep -q "${m_maddr}"); then
289			RET=1
290			check_err 1 "arp_valid $arp_valid active_slave $active_slave, eth$i has mcast group"
291		fi
292	done
293}
294
295arp_validate_arp()
296{
297	local mode=$1
298	local val
299	for val in $(seq 0 6); do
300		arp_validate_test "mode $mode arp_interval 100 arp_ip_target ${g_ip4} arp_validate $val"
301		log_test "arp_validate" "$mode arp_ip_target arp_validate $val"
302	done
303}
304
305arp_validate_ns()
306{
307	local mode=$1
308	local val
309
310	if skip_ns; then
311		log_test_skip "arp_validate ns" "Current iproute or kernel doesn't support bond option 'ns_ip6_target'."
312		return 0
313	fi
314
315	for val in $(seq 0 6); do
316		arp_validate_test "mode $mode arp_interval 100 ns_ip6_target ${g_ip6},${c_ip6} arp_validate $val"
317		log_test "arp_validate" "$mode ns_ip6_target arp_validate $val"
318		arp_validate_mcast
319		log_test "arp_validate" "join mcast group"
320	done
321}
322
323arp_validate()
324{
325	arp_validate_arp "active-backup"
326	arp_validate_ns "active-backup"
327}
328
329garp_test()
330{
331	local param="$1"
332	local active_slave exp_num real_num i
333	RET=0
334
335	# create bond
336	bond_reset "${param}"
337
338	bond_check_connection
339	[ $RET -ne 0 ] && log_test "num_grat_arp" "$retmsg"
340
341
342	# Add tc rules to count GARP number
343	for i in $(seq 0 2); do
344		tc -n ${g_ns} filter add dev s$i ingress protocol arp pref 1 handle 101 \
345			flower skip_hw arp_op request arp_sip ${s_ip4} arp_tip ${s_ip4} action pass
346	done
347
348	# Do failover
349	active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
350	ip -n ${s_ns} link set ${active_slave} down
351
352	# wait for active link change
353	slowwait 2 active_slave_changed $active_slave
354
355	exp_num=$(echo "${param}" | cut -f6 -d ' ')
356	active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
357	slowwait_for_counter $((exp_num + 5)) $exp_num tc_rule_handle_stats_get \
358		"dev s${active_slave#eth} ingress" 101 ".packets" "-n ${g_ns}" &> /dev/null
359
360	# check result
361	real_num=$(tc_rule_handle_stats_get "dev s${active_slave#eth} ingress" 101 ".packets" "-n ${g_ns}")
362	if [ "${real_num}" -ne "${exp_num}" ]; then
363		echo "$real_num garp packets sent on active slave ${active_slave}"
364		RET=1
365	fi
366
367	for i in $(seq 0 2); do
368		tc -n ${g_ns} filter del dev s$i ingress
369	done
370}
371
372num_grat_arp()
373{
374	local val
375	for val in 10 20 30; do
376		garp_test "mode active-backup miimon 10 num_grat_arp $val peer_notify_delay 100"
377		log_test "num_grat_arp" "active-backup miimon num_grat_arp $val"
378	done
379}
380
381check_all_mac_same()
382{
383	RET=0
384	# all slaves should have same mac address (with the first port's mac)
385	local bond_mac=$(ip -n "$s_ns" -j link show bond0 | jq -r '.[]["address"]')
386	local eth0_mac=$(ip -n "$s_ns" -j link show eth0 | jq -r '.[]["address"]')
387	local eth1_mac=$(ip -n "$s_ns" -j link show eth1 | jq -r '.[]["address"]')
388	local eth2_mac=$(ip -n "$s_ns" -j link show eth2 | jq -r '.[]["address"]')
389	if [ "$bond_mac" != "${mac[0]}" ] || [ "$eth0_mac" != "$bond_mac" ] || \
390		[ "$eth1_mac" != "$bond_mac" ] || [ "$eth2_mac" != "$bond_mac" ]; then
391		RET=1
392	fi
393}
394
395check_bond_mac_same_with_first()
396{
397	RET=0
398	# bond mac address should be same with the first added slave
399	local bond_mac=$(ip -n "$s_ns" -j link show bond0 | jq -r '.[]["address"]')
400	if [ "$bond_mac" != "${mac[0]}" ]; then
401		RET=1
402	fi
403}
404
405check_bond_mac_same_with_active()
406{
407	RET=0
408	# bond mac address should be same with active slave
409	local bond_mac=$(ip -n "$s_ns" -j link show bond0 | jq -r '.[]["address"]')
410	local active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
411	local active_slave_mac=$(ip -n "$s_ns" -j link show "$active_slave" | jq -r '.[]["address"]')
412	if [ "$bond_mac" != "$active_slave_mac" ]; then
413		RET=1
414	fi
415}
416
417check_backup_slave_mac_not_change()
418{
419	RET=0
420	# backup slave's mac address is not changed
421	if ip -n "$s_ns" -d -j link show type bond_slave | jq -e '.[]
422		| select(.linkinfo.info_slave_data.state=="BACKUP")
423		| select(.address != .linkinfo.info_slave_data.perm_hwaddr)' &> /dev/null; then
424		RET=1
425	fi
426}
427
428check_backup_slave_mac_inherit()
429{
430	local backup_mac
431	RET=0
432
433	# backup slaves should use mac[1] or mac[2]
434	local backup_macs=$(ip -n "$s_ns" -d -j link show type bond_slave | \
435		jq -r '.[] | select(.linkinfo.info_slave_data.state=="BACKUP") | .address')
436	for backup_mac in $backup_macs; do
437		if [ "$backup_mac" != "${mac[1]}" ] && [ "$backup_mac" != "${mac[2]}" ]; then
438			RET=1
439		fi
440	done
441}
442
443check_first_slave_random_mac()
444{
445	RET=0
446	# remove the first added slave and added it back
447	ip -n "$s_ns" link set eth0 nomaster
448	ip -n "$s_ns" link set eth0 master bond0
449
450	# the first slave should use random mac address
451	eth0_mac=$(ip -n "$s_ns" -j link show eth0 | jq -r '.[]["address"]')
452	[ "$eth0_mac" = "${mac[0]}" ] && RET=1
453	log_test "bond fail_over_mac follow" "random first slave mac"
454
455	# remove the first slave, the permanent MAC address should be restored back
456	ip -n "$s_ns" link set eth0 nomaster
457	eth0_mac=$(ip -n "$s_ns" -j link show eth0 | jq -r '.[]["address"]')
458	[ "$eth0_mac" != "${mac[0]}" ] && RET=1
459}
460
461do_active_backup_failover()
462{
463	local active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
464	ip -n ${s_ns} link set ${active_slave} down
465	slowwait 2 active_slave_changed $active_slave
466	ip -n ${s_ns} link set ${active_slave} up
467}
468
469fail_over_mac()
470{
471	# Bring down the first interface on the switch to force the bond to
472	# select another active interface instead of the first one that joined.
473	ip -n "$g_ns" link set s0 down
474
475	# fail_over_mac none
476	bond_reset "mode active-backup miimon 100 fail_over_mac 0"
477	check_all_mac_same
478	log_test "fail_over_mac 0" "all slaves have same mac"
479	do_active_backup_failover
480	check_all_mac_same
481	log_test "fail_over_mac 0" "failover: all slaves have same mac"
482
483	# fail_over_mac active
484	bond_reset "mode active-backup miimon 100 fail_over_mac 1"
485	check_bond_mac_same_with_active
486	log_test "fail_over_mac 1" "bond mac is same with active slave mac"
487	check_backup_slave_mac_not_change
488	log_test "fail_over_mac 1" "backup slave mac is not changed"
489	do_active_backup_failover
490	check_bond_mac_same_with_active
491	log_test "fail_over_mac 1" "failover: bond mac is same with active slave mac"
492	check_backup_slave_mac_not_change
493	log_test "fail_over_mac 1" "failover: backup slave mac is not changed"
494
495	# fail_over_mac follow
496	bond_reset "mode active-backup miimon 100 fail_over_mac 2"
497	check_bond_mac_same_with_first
498	log_test "fail_over_mac 2" "bond mac is same with first slave mac"
499	check_bond_mac_same_with_active
500	log_test "fail_over_mac 2" "bond mac is same with active slave mac"
501	check_backup_slave_mac_inherit
502	log_test "fail_over_mac 2" "backup slave mac inherit"
503	do_active_backup_failover
504	check_bond_mac_same_with_first
505	log_test "fail_over_mac 2" "failover: bond mac is same with first slave mac"
506	check_bond_mac_same_with_active
507	log_test "fail_over_mac 2" "failover: bond mac is same with active slave mac"
508	check_backup_slave_mac_inherit
509	log_test "fail_over_mac 2" "failover: backup slave mac inherit"
510	check_first_slave_random_mac
511	log_test "fail_over_mac 2" "first slave mac random"
512}
513
514vlan_over_bond_arp()
515{
516	local mode="$1"
517	RET=0
518
519	bond_reset "mode $mode arp_interval 100 arp_ip_target 192.0.3.10"
520	ip -n "${s_ns}" link add bond0.3 link bond0 type vlan id 3
521	ip -n "${s_ns}" link set bond0.3 up
522	ip -n "${s_ns}" addr add 192.0.3.1/24 dev bond0.3
523	ip -n "${s_ns}" addr add 2001:db8::3:1/64 dev bond0.3
524
525	slowwait_for_counter 5 5 tc_rule_handle_stats_get \
526		"dev eth0.3 ingress" 101 ".packets" "-n ${c_ns}" &> /dev/null || RET=1
527	log_test "vlan over bond arp" "$mode"
528}
529
530vlan_over_bond_ns()
531{
532	local mode="$1"
533	RET=0
534
535	if skip_ns; then
536		log_test_skip "vlan_over_bond ns" "$mode"
537		return 0
538	fi
539
540	bond_reset "mode $mode arp_interval 100 ns_ip6_target 2001:db8::3:10"
541	ip -n "${s_ns}" link add bond0.3 link bond0 type vlan id 3
542	ip -n "${s_ns}" link set bond0.3 up
543	ip -n "${s_ns}" addr add 192.0.3.1/24 dev bond0.3
544	ip -n "${s_ns}" addr add 2001:db8::3:1/64 dev bond0.3
545
546	slowwait_for_counter 5 5 tc_rule_handle_stats_get \
547		"dev eth0.3 ingress" 102 ".packets" "-n ${c_ns}" &> /dev/null || RET=1
548	log_test "vlan over bond ns" "$mode"
549}
550
551vlan_over_bond()
552{
553	# add vlan 3 for client
554	ip -n "${c_ns}" link add eth0.3 link eth0 type vlan id 3
555	ip -n "${c_ns}" link set eth0.3 up
556	ip -n "${c_ns}" addr add 192.0.3.10/24 dev eth0.3
557	ip -n "${c_ns}" addr add 2001:db8::3:10/64 dev eth0.3
558
559	# Add tc rule to check the vlan pkts
560	tc -n "${c_ns}" qdisc add dev eth0.3 clsact
561	tc -n "${c_ns}" filter add dev eth0.3 ingress protocol arp \
562		handle 101 flower skip_hw arp_op request \
563		arp_sip 192.0.3.1 arp_tip 192.0.3.10 action pass
564	tc -n "${c_ns}" filter add dev eth0.3 ingress protocol ipv6 \
565		handle 102 flower skip_hw ip_proto icmpv6 \
566		type 135 src_ip 2001:db8::3:1 action pass
567
568	vlan_over_bond_arp "active-backup"
569	vlan_over_bond_ns "active-backup"
570}
571
572trap cleanup EXIT
573
574setup_prepare
575setup_wait
576tests_run
577
578exit $EXIT_STATUS
~/ Read-only file preview.