1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Test bonding option prio
5#
6
7ALL_TESTS="
8	prio_arp_ip_target_test
9	prio_miimon_test
10"
11
12REQUIRE_MZ=no
13REQUIRE_JQ=no
14NUM_NETIFS=0
15lib_dir=$(dirname "$0")
16source "$lib_dir"/net_forwarding_lib.sh
17
18destroy()
19{
20	ip link del bond0 &>/dev/null
21	ip link del br0 &>/dev/null
22	ip link del veth0 &>/dev/null
23	ip link del veth1 &>/dev/null
24	ip link del veth2 &>/dev/null
25	ip netns del ns1 &>/dev/null
26	ip link del veth3 &>/dev/null
27}
28
29cleanup()
30{
31	pre_cleanup
32
33	destroy
34}
35
36skip()
37{
38        local skip=1
39	ip link add name bond0 type bond mode 1 miimon 100 &>/dev/null
40	ip link add name veth0 type veth peer name veth0_p
41	ip link set veth0 master bond0
42
43	# check if iproute support prio option
44	ip link set dev veth0 type bond_slave prio 10
45	[[ $? -ne 0 ]] && skip=0
46
47	# check if bonding support prio option
48	ip -d link show veth0 | grep -q "prio 10"
49	[[ $? -ne 0 ]] && skip=0
50
51	ip link del bond0 &>/dev/null
52	ip link del veth0
53
54	return $skip
55}
56
57active_slave=""
58check_active_slave()
59{
60	local target_active_slave=$1
61	active_slave="$(cat /sys/class/net/bond0/bonding/active_slave)"
62	test "$active_slave" = "$target_active_slave"
63	check_err $? "Current active slave is $active_slave but not $target_active_slave"
64}
65
66
67# Test bonding prio option with mode=$mode monitor=$monitor
68# and primary_reselect=$primary_reselect
69prio_test()
70{
71	RET=0
72
73	local monitor=$1
74	local mode=$2
75	local primary_reselect=$3
76
77	local bond_ip4="192.169.1.2"
78	local peer_ip4="192.169.1.1"
79	local bond_ip6="2009:0a:0b::02"
80	local peer_ip6="2009:0a:0b::01"
81
82
83	# create veths
84	ip link add name veth0 type veth peer name veth0_p
85	ip link add name veth1 type veth peer name veth1_p
86	ip link add name veth2 type veth peer name veth2_p
87
88	# create bond
89	if [[ "$monitor" == "miimon" ]];then
90		ip link add name bond0 type bond mode $mode miimon 100 primary veth1 primary_reselect $primary_reselect
91	elif [[ "$monitor" == "arp_ip_target" ]];then
92		ip link add name bond0 type bond mode $mode arp_interval 1000 arp_ip_target $peer_ip4 primary veth1 primary_reselect $primary_reselect
93	elif [[ "$monitor" == "ns_ip6_target" ]];then
94		ip link add name bond0 type bond mode $mode arp_interval 1000 ns_ip6_target $peer_ip6 primary veth1 primary_reselect $primary_reselect
95	fi
96	ip link set bond0 up
97	ip link set veth0 master bond0
98	ip link set veth1 master bond0
99	ip link set veth2 master bond0
100	# check bonding member prio value
101	ip link set dev veth0 type bond_slave prio 0
102	ip link set dev veth1 type bond_slave prio 10
103	ip link set dev veth2 type bond_slave prio 11
104	ip -d link show veth0 | grep -q 'prio 0'
105	check_err $? "veth0 prio is not 0"
106	ip -d link show veth1 | grep -q 'prio 10'
107	check_err $? "veth0 prio is not 10"
108	ip -d link show veth2 | grep -q 'prio 11'
109	check_err $? "veth0 prio is not 11"
110
111	ip link set veth0 up
112	ip link set veth1 up
113	ip link set veth2 up
114	ip link set veth0_p up
115	ip link set veth1_p up
116	ip link set veth2_p up
117
118	# prepare ping target
119	ip link add name br0 type bridge
120	ip link set br0 up
121	ip link set veth0_p master br0
122	ip link set veth1_p master br0
123	ip link set veth2_p master br0
124	ip link add name veth3 type veth peer name veth3_p
125	ip netns add ns1
126	ip link set veth3_p master br0 up
127	ip link set veth3 netns ns1 up
128	ip netns exec ns1 ip addr add $peer_ip4/24 dev veth3
129	ip netns exec ns1 ip addr add $peer_ip6/64 dev veth3
130	ip addr add $bond_ip4/24 dev bond0
131	ip addr add $bond_ip6/64 dev bond0
132	sleep 5
133
134	ping $peer_ip4 -c5 -I bond0 &>/dev/null
135	check_err $? "ping failed 1."
136	ping6 $peer_ip6 -c5 -I bond0 &>/dev/null
137	check_err $? "ping6 failed 1."
138
139	# active salve should be the primary slave
140	check_active_slave veth1
141
142	# active slave should be the higher prio slave
143	ip link set $active_slave down
144	ping $peer_ip4 -c5 -I bond0 &>/dev/null
145	check_err $? "ping failed 2."
146	check_active_slave veth2
147
148	# when only 1 slave is up
149	ip link set $active_slave down
150	ping $peer_ip4 -c5 -I bond0 &>/dev/null
151	check_err $? "ping failed 3."
152	check_active_slave veth0
153
154	# when a higher prio slave change to up
155	ip link set veth2 up
156	ping $peer_ip4 -c5 -I bond0 &>/dev/null
157	check_err $? "ping failed 4."
158	case $primary_reselect in
159		"0")
160			check_active_slave "veth2"
161			;;
162		"1")
163			check_active_slave "veth0"
164			;;
165		"2")
166			check_active_slave "veth0"
167			;;
168	esac
169	local pre_active_slave=$active_slave
170
171	# when the primary slave change to up
172	ip link set veth1 up
173	ping $peer_ip4 -c5 -I bond0 &>/dev/null
174	check_err $? "ping failed 5."
175	case $primary_reselect in
176		"0")
177			check_active_slave "veth1"
178			;;
179		"1")
180			check_active_slave "$pre_active_slave"
181			;;
182		"2")
183			check_active_slave "$pre_active_slave"
184			ip link set $active_slave down
185			ping $peer_ip4 -c5 -I bond0 &>/dev/null
186			check_err $? "ping failed 6."
187			check_active_slave "veth1"
188			;;
189	esac
190
191	# Test changing bond salve prio
192	if [[ "$primary_reselect" == "0" ]];then
193		ip link set dev veth0 type bond_slave prio 1000000
194		ip link set dev veth1 type bond_slave prio 0
195		ip link set dev veth2 type bond_slave prio -50
196		ip -d link show veth0 | grep -q 'prio 1000000'
197		check_err $? "veth0 prio is not 1000000"
198		ip -d link show veth1 | grep -q 'prio 0'
199		check_err $? "veth1 prio is not 0"
200		ip -d link show veth2 | grep -q 'prio -50'
201		check_err $? "veth3 prio is not -50"
202		check_active_slave "veth1"
203
204		ip link set $active_slave down
205		ping $peer_ip4 -c5 -I bond0 &>/dev/null
206		check_err $? "ping failed 7."
207		check_active_slave "veth0"
208	fi
209
210	cleanup
211
212	log_test "prio_test" "Test bonding option 'prio' with mode=$mode monitor=$monitor and primary_reselect=$primary_reselect"
213}
214
215prio_miimon_test()
216{
217	local mode
218	local primary_reselect
219
220	for mode in 1 5 6; do
221		for primary_reselect in 0 1 2; do
222			prio_test "miimon" $mode $primary_reselect
223		done
224	done
225}
226
227prio_arp_ip_target_test()
228{
229	local primary_reselect
230
231	for primary_reselect in 0 1 2; do
232		prio_test "arp_ip_target" 1 $primary_reselect
233	done
234}
235
236if skip;then
237	log_test_skip "option_prio.sh" "Current iproute doesn't support 'prio'."
238	exit 0
239fi
240
241trap cleanup EXIT
242
243tests_run
244
245exit "$EXIT_STATUS"
246