xref: /linux/tools/testing/selftests/net/hsr/link_faults.sh (revision bbbd531faa18b778a9129938d2c8db6c33c106ab)
1ca4a09a9SFelix Maurer#!/bin/bash
2ca4a09a9SFelix Maurer# SPDX-License-Identifier: GPL-2.0
3ca4a09a9SFelix Maurer# shellcheck disable=SC2329
4ca4a09a9SFelix Maurer
5ca4a09a9SFelix Maurersource ../lib.sh
6ca4a09a9SFelix Maurer
7ca4a09a9SFelix MaurerALL_TESTS="
8ca4a09a9SFelix Maurer	test_clean_hsrv0
9ca4a09a9SFelix Maurer	test_cut_link_hsrv0
10*bbbd531fSFelix Maurer	test_packet_loss_hsrv0
11*bbbd531fSFelix Maurer	test_high_packet_loss_hsrv0
12*bbbd531fSFelix Maurer	test_reordering_hsrv0
13*bbbd531fSFelix Maurer
14ca4a09a9SFelix Maurer	test_clean_hsrv1
15ca4a09a9SFelix Maurer	test_cut_link_hsrv1
16*bbbd531fSFelix Maurer	test_packet_loss_hsrv1
17*bbbd531fSFelix Maurer	test_high_packet_loss_hsrv1
18*bbbd531fSFelix Maurer	test_reordering_hsrv1
19*bbbd531fSFelix Maurer
20ca4a09a9SFelix Maurer	test_clean_prp
21ca4a09a9SFelix Maurer	test_cut_link_prp
228908c3c8SFelix Maurer	test_packet_loss_prp
238908c3c8SFelix Maurer	test_high_packet_loss_prp
248908c3c8SFelix Maurer	test_reordering_prp
25ca4a09a9SFelix Maurer"
26ca4a09a9SFelix Maurer
278908c3c8SFelix Maurer# The tests are running ping for 5sec with a relatively short interval in
288908c3c8SFelix Maurer# different scenarios with faulty links (cut links, packet loss, delay,
298908c3c8SFelix Maurer# reordering) that should be recoverable by HSR/PRP. The ping interval (10ms)
308908c3c8SFelix Maurer# is short enough that the base delay (50ms) leads to a queue in the netem
318908c3c8SFelix Maurer# qdiscs which is needed for reordering.
32ca4a09a9SFelix Maurer
33ca4a09a9SFelix Maurersetup_hsr_topo()
34ca4a09a9SFelix Maurer{
35ca4a09a9SFelix Maurer	# Three HSR nodes in a ring, every node has a LAN A interface connected
36ca4a09a9SFelix Maurer	# to the LAN B interface of the next node.
37ca4a09a9SFelix Maurer	#
38ca4a09a9SFelix Maurer	#    node1            node2
39ca4a09a9SFelix Maurer	#
40ca4a09a9SFelix Maurer	#     vethA -------- vethB
41ca4a09a9SFelix Maurer	#   hsr1                 hsr2
42ca4a09a9SFelix Maurer	#     vethB          vethA
43ca4a09a9SFelix Maurer	#         \          /
44ca4a09a9SFelix Maurer	#         vethA  vethB
45ca4a09a9SFelix Maurer	#             hsr3
46ca4a09a9SFelix Maurer	#
47ca4a09a9SFelix Maurer	#            node3
48ca4a09a9SFelix Maurer
49ca4a09a9SFelix Maurer	local ver="$1"
50ca4a09a9SFelix Maurer
51ca4a09a9SFelix Maurer	setup_ns node1 node2 node3
52ca4a09a9SFelix Maurer
53ca4a09a9SFelix Maurer	# veth links
54ca4a09a9SFelix Maurer	# shellcheck disable=SC2154 # variables assigned by setup_ns
55ca4a09a9SFelix Maurer	ip link add vethA netns "$node1" type veth peer name vethB netns "$node2"
56ca4a09a9SFelix Maurer	# shellcheck disable=SC2154 # variables assigned by setup_ns
57ca4a09a9SFelix Maurer	ip link add vethA netns "$node2" type veth peer name vethB netns "$node3"
58ca4a09a9SFelix Maurer	ip link add vethA netns "$node3" type veth peer name vethB netns "$node1"
59ca4a09a9SFelix Maurer
60ca4a09a9SFelix Maurer	# MAC addresses (not needed for HSR operation, but helps with debugging)
61ca4a09a9SFelix Maurer	ip -net "$node1" link set address 00:11:22:00:01:01 dev vethA
62ca4a09a9SFelix Maurer	ip -net "$node1" link set address 00:11:22:00:01:02 dev vethB
63ca4a09a9SFelix Maurer
64ca4a09a9SFelix Maurer	ip -net "$node2" link set address 00:11:22:00:02:01 dev vethA
65ca4a09a9SFelix Maurer	ip -net "$node2" link set address 00:11:22:00:02:02 dev vethB
66ca4a09a9SFelix Maurer
67ca4a09a9SFelix Maurer	ip -net "$node3" link set address 00:11:22:00:03:01 dev vethA
68ca4a09a9SFelix Maurer	ip -net "$node3" link set address 00:11:22:00:03:02 dev vethB
69ca4a09a9SFelix Maurer
70ca4a09a9SFelix Maurer	# HSR interfaces
71ca4a09a9SFelix Maurer	ip -net "$node1" link add name hsr1 type hsr proto 0 version "$ver" \
72ca4a09a9SFelix Maurer		slave1 vethA slave2 vethB supervision 45
73ca4a09a9SFelix Maurer	ip -net "$node2" link add name hsr2 type hsr proto 0 version "$ver" \
74ca4a09a9SFelix Maurer		slave1 vethA slave2 vethB supervision 45
75ca4a09a9SFelix Maurer	ip -net "$node3" link add name hsr3 type hsr proto 0 version "$ver" \
76ca4a09a9SFelix Maurer		slave1 vethA slave2 vethB supervision 45
77ca4a09a9SFelix Maurer
78ca4a09a9SFelix Maurer	# IP addresses
79ca4a09a9SFelix Maurer	ip -net "$node1" addr add 100.64.0.1/24 dev hsr1
80ca4a09a9SFelix Maurer	ip -net "$node2" addr add 100.64.0.2/24 dev hsr2
81ca4a09a9SFelix Maurer	ip -net "$node3" addr add 100.64.0.3/24 dev hsr3
82ca4a09a9SFelix Maurer
83ca4a09a9SFelix Maurer	# Set all links up
84ca4a09a9SFelix Maurer	ip -net "$node1" link set vethA up
85ca4a09a9SFelix Maurer	ip -net "$node1" link set vethB up
86ca4a09a9SFelix Maurer	ip -net "$node1" link set hsr1 up
87ca4a09a9SFelix Maurer
88ca4a09a9SFelix Maurer	ip -net "$node2" link set vethA up
89ca4a09a9SFelix Maurer	ip -net "$node2" link set vethB up
90ca4a09a9SFelix Maurer	ip -net "$node2" link set hsr2 up
91ca4a09a9SFelix Maurer
92ca4a09a9SFelix Maurer	ip -net "$node3" link set vethA up
93ca4a09a9SFelix Maurer	ip -net "$node3" link set vethB up
94ca4a09a9SFelix Maurer	ip -net "$node3" link set hsr3 up
95ca4a09a9SFelix Maurer}
96ca4a09a9SFelix Maurer
97ca4a09a9SFelix Maurersetup_prp_topo()
98ca4a09a9SFelix Maurer{
99ca4a09a9SFelix Maurer	# Two PRP nodes, connected by two links (treated as LAN A and LAN B).
100ca4a09a9SFelix Maurer	#
101ca4a09a9SFelix Maurer	#       vethA ----- vethA
102ca4a09a9SFelix Maurer	#     prp1             prp2
103ca4a09a9SFelix Maurer	#       vethB ----- vethB
104ca4a09a9SFelix Maurer	#
105ca4a09a9SFelix Maurer	#     node1           node2
106ca4a09a9SFelix Maurer
107ca4a09a9SFelix Maurer	setup_ns node1 node2
108ca4a09a9SFelix Maurer
109ca4a09a9SFelix Maurer	# veth links
110ca4a09a9SFelix Maurer	ip link add vethA netns "$node1" type veth peer name vethA netns "$node2"
111ca4a09a9SFelix Maurer	ip link add vethB netns "$node1" type veth peer name vethB netns "$node2"
112ca4a09a9SFelix Maurer
113ca4a09a9SFelix Maurer	# MAC addresses will be copied from LAN A interface
114ca4a09a9SFelix Maurer	ip -net "$node1" link set address 00:11:22:00:00:01 dev vethA
115ca4a09a9SFelix Maurer	ip -net "$node2" link set address 00:11:22:00:00:02 dev vethA
116ca4a09a9SFelix Maurer
117ca4a09a9SFelix Maurer	# PRP interfaces
118ca4a09a9SFelix Maurer	ip -net "$node1" link add name prp1 type hsr \
119ca4a09a9SFelix Maurer		slave1 vethA slave2 vethB supervision 45 proto 1
120ca4a09a9SFelix Maurer	ip -net "$node2" link add name prp2 type hsr \
121ca4a09a9SFelix Maurer		slave1 vethA slave2 vethB supervision 45 proto 1
122ca4a09a9SFelix Maurer
123ca4a09a9SFelix Maurer	# IP addresses
124ca4a09a9SFelix Maurer	ip -net "$node1" addr add 100.64.0.1/24 dev prp1
125ca4a09a9SFelix Maurer	ip -net "$node2" addr add 100.64.0.2/24 dev prp2
126ca4a09a9SFelix Maurer
127ca4a09a9SFelix Maurer	# All links up
128ca4a09a9SFelix Maurer	ip -net "$node1" link set vethA up
129ca4a09a9SFelix Maurer	ip -net "$node1" link set vethB up
130ca4a09a9SFelix Maurer	ip -net "$node1" link set prp1 up
131ca4a09a9SFelix Maurer
132ca4a09a9SFelix Maurer	ip -net "$node2" link set vethA up
133ca4a09a9SFelix Maurer	ip -net "$node2" link set vethB up
134ca4a09a9SFelix Maurer	ip -net "$node2" link set prp2 up
135ca4a09a9SFelix Maurer}
136ca4a09a9SFelix Maurer
137ca4a09a9SFelix Maurerwait_for_hsr_node_table()
138ca4a09a9SFelix Maurer{
139ca4a09a9SFelix Maurer	log_info "Wait for node table entries to be merged."
140ca4a09a9SFelix Maurer	WAIT=5
141ca4a09a9SFelix Maurer	while [ "${WAIT}" -gt 0 ]; do
142ca4a09a9SFelix Maurer		nts=$(cat /sys/kernel/debug/hsr/hsr*/node_table)
143ca4a09a9SFelix Maurer
144ca4a09a9SFelix Maurer		# We need entries in the node tables, and they need to be merged
145ca4a09a9SFelix Maurer		if (echo "$nts" | grep -qE "^([0-9a-f]{2}:){5}") && \
146ca4a09a9SFelix Maurer		    ! (echo "$nts" | grep -q "00:00:00:00:00:00"); then
147ca4a09a9SFelix Maurer			return
148ca4a09a9SFelix Maurer		fi
149ca4a09a9SFelix Maurer
150ca4a09a9SFelix Maurer		sleep 1
151ca4a09a9SFelix Maurer		((WAIT--))
152ca4a09a9SFelix Maurer	done
153ca4a09a9SFelix Maurer	check_err 1 "Failed to wait for merged node table entries"
154ca4a09a9SFelix Maurer}
155ca4a09a9SFelix Maurer
156ca4a09a9SFelix Maurersetup_topo()
157ca4a09a9SFelix Maurer{
158ca4a09a9SFelix Maurer	local proto="$1"
159ca4a09a9SFelix Maurer
160ca4a09a9SFelix Maurer	if [ "$proto" = "HSRv0" ]; then
161ca4a09a9SFelix Maurer		setup_hsr_topo 0
162ca4a09a9SFelix Maurer		wait_for_hsr_node_table
163ca4a09a9SFelix Maurer	elif [ "$proto" = "HSRv1" ]; then
164ca4a09a9SFelix Maurer		setup_hsr_topo 1
165ca4a09a9SFelix Maurer		wait_for_hsr_node_table
166ca4a09a9SFelix Maurer	elif [ "$proto" = "PRP" ]; then
167ca4a09a9SFelix Maurer		setup_prp_topo
168ca4a09a9SFelix Maurer	else
169ca4a09a9SFelix Maurer		check_err 1 "Unknown protocol (${proto})"
170ca4a09a9SFelix Maurer	fi
171ca4a09a9SFelix Maurer}
172ca4a09a9SFelix Maurer
173ca4a09a9SFelix Maurercheck_ping()
174ca4a09a9SFelix Maurer{
175ca4a09a9SFelix Maurer	local node="$1"
176ca4a09a9SFelix Maurer	local dst="$2"
1778908c3c8SFelix Maurer	local accepted_dups="$3"
178ca4a09a9SFelix Maurer	local ping_args="-q -i 0.01 -c 400"
179ca4a09a9SFelix Maurer
180ca4a09a9SFelix Maurer	log_info "Running ping $node -> $dst"
181ca4a09a9SFelix Maurer	# shellcheck disable=SC2086
182ca4a09a9SFelix Maurer	output=$(ip netns exec "$node" ping $ping_args "$dst" | \
183ca4a09a9SFelix Maurer		grep "packets transmitted")
184ca4a09a9SFelix Maurer	log_info "$output"
185ca4a09a9SFelix Maurer
186ca4a09a9SFelix Maurer	dups=0
187ca4a09a9SFelix Maurer	loss=0
188ca4a09a9SFelix Maurer
189ca4a09a9SFelix Maurer	if [[ "$output" =~ \+([0-9]+)" duplicates" ]]; then
190ca4a09a9SFelix Maurer		dups="${BASH_REMATCH[1]}"
191ca4a09a9SFelix Maurer	fi
192ca4a09a9SFelix Maurer	if [[ "$output" =~ ([0-9\.]+\%)" packet loss" ]]; then
193ca4a09a9SFelix Maurer		loss="${BASH_REMATCH[1]}"
194ca4a09a9SFelix Maurer	fi
195ca4a09a9SFelix Maurer
1968908c3c8SFelix Maurer	if [ "$dups" -gt "$accepted_dups" ]; then
1978908c3c8SFelix Maurer		check_err 1 "Unexpected duplicate packets (${dups})"
1988908c3c8SFelix Maurer	fi
199ca4a09a9SFelix Maurer	if [ "$loss" != "0%" ]; then
200ca4a09a9SFelix Maurer		check_err 1 "Unexpected packet loss (${loss})"
201ca4a09a9SFelix Maurer	fi
202ca4a09a9SFelix Maurer}
203ca4a09a9SFelix Maurer
204ca4a09a9SFelix Maurertest_clean()
205ca4a09a9SFelix Maurer{
206ca4a09a9SFelix Maurer	local proto="$1"
207ca4a09a9SFelix Maurer
208ca4a09a9SFelix Maurer	RET=0
209ca4a09a9SFelix Maurer	tname="${FUNCNAME[0]} - ${proto}"
210ca4a09a9SFelix Maurer
211ca4a09a9SFelix Maurer	setup_topo "$proto"
212ca4a09a9SFelix Maurer	if ((RET != ksft_pass)); then
213ca4a09a9SFelix Maurer		log_test "${tname} setup"
214ca4a09a9SFelix Maurer		return
215ca4a09a9SFelix Maurer	fi
216ca4a09a9SFelix Maurer
2178908c3c8SFelix Maurer	check_ping "$node1" "100.64.0.2" 0
218ca4a09a9SFelix Maurer
219ca4a09a9SFelix Maurer	log_test "${tname}"
220ca4a09a9SFelix Maurer}
221ca4a09a9SFelix Maurer
222ca4a09a9SFelix Maurertest_clean_hsrv0()
223ca4a09a9SFelix Maurer{
224ca4a09a9SFelix Maurer	test_clean "HSRv0"
225ca4a09a9SFelix Maurer}
226ca4a09a9SFelix Maurer
227ca4a09a9SFelix Maurertest_clean_hsrv1()
228ca4a09a9SFelix Maurer{
229ca4a09a9SFelix Maurer	test_clean "HSRv1"
230ca4a09a9SFelix Maurer}
231ca4a09a9SFelix Maurer
232ca4a09a9SFelix Maurertest_clean_prp()
233ca4a09a9SFelix Maurer{
234ca4a09a9SFelix Maurer	test_clean "PRP"
235ca4a09a9SFelix Maurer}
236ca4a09a9SFelix Maurer
237ca4a09a9SFelix Maurertest_cut_link()
238ca4a09a9SFelix Maurer{
239ca4a09a9SFelix Maurer	local proto="$1"
240ca4a09a9SFelix Maurer
241ca4a09a9SFelix Maurer	RET=0
242ca4a09a9SFelix Maurer	tname="${FUNCNAME[0]} - ${proto}"
243ca4a09a9SFelix Maurer
244ca4a09a9SFelix Maurer	setup_topo "$proto"
245ca4a09a9SFelix Maurer	if ((RET != ksft_pass)); then
246ca4a09a9SFelix Maurer		log_test "${tname} setup"
247ca4a09a9SFelix Maurer		return
248ca4a09a9SFelix Maurer	fi
249ca4a09a9SFelix Maurer
250ca4a09a9SFelix Maurer	# Cutting link from subshell, so check_ping can run in the normal shell
251ca4a09a9SFelix Maurer	# with access to global variables from the test harness.
252ca4a09a9SFelix Maurer	(
253ca4a09a9SFelix Maurer		sleep 2
254ca4a09a9SFelix Maurer		log_info "Cutting link"
255ca4a09a9SFelix Maurer		ip -net "$node1" link set vethB down
256ca4a09a9SFelix Maurer	) &
2578908c3c8SFelix Maurer	check_ping "$node1" "100.64.0.2" 0
258ca4a09a9SFelix Maurer
259ca4a09a9SFelix Maurer	wait
260ca4a09a9SFelix Maurer	log_test "${tname}"
261ca4a09a9SFelix Maurer}
262ca4a09a9SFelix Maurer
263ca4a09a9SFelix Maurer
264ca4a09a9SFelix Maurertest_cut_link_hsrv0()
265ca4a09a9SFelix Maurer{
266ca4a09a9SFelix Maurer	test_cut_link "HSRv0"
267ca4a09a9SFelix Maurer}
268ca4a09a9SFelix Maurer
269ca4a09a9SFelix Maurertest_cut_link_hsrv1()
270ca4a09a9SFelix Maurer{
271ca4a09a9SFelix Maurer	test_cut_link "HSRv1"
272ca4a09a9SFelix Maurer}
273ca4a09a9SFelix Maurer
274ca4a09a9SFelix Maurertest_cut_link_prp()
275ca4a09a9SFelix Maurer{
276ca4a09a9SFelix Maurer	test_cut_link "PRP"
277ca4a09a9SFelix Maurer}
278ca4a09a9SFelix Maurer
2798908c3c8SFelix Maurertest_packet_loss()
2808908c3c8SFelix Maurer{
2818908c3c8SFelix Maurer	local proto="$1"
2828908c3c8SFelix Maurer	local loss="$2"
2838908c3c8SFelix Maurer
2848908c3c8SFelix Maurer	RET=0
2858908c3c8SFelix Maurer	tname="${FUNCNAME[0]} - ${proto}, ${loss}"
2868908c3c8SFelix Maurer
2878908c3c8SFelix Maurer	setup_topo "$proto"
2888908c3c8SFelix Maurer	if ((RET != ksft_pass)); then
2898908c3c8SFelix Maurer		log_test "${tname} setup"
2908908c3c8SFelix Maurer		return
2918908c3c8SFelix Maurer	fi
2928908c3c8SFelix Maurer
2938908c3c8SFelix Maurer	# Packet loss with lower delay makes sure the packets on the lossy link
2948908c3c8SFelix Maurer	# arrive first.
2958908c3c8SFelix Maurer	tc -net "$node1" qdisc add dev vethA root netem delay 50ms
2968908c3c8SFelix Maurer	tc -net "$node1" qdisc add dev vethB root netem delay 20ms loss "$loss"
2978908c3c8SFelix Maurer
2988908c3c8SFelix Maurer	check_ping "$node1" "100.64.0.2" 40
2998908c3c8SFelix Maurer
3008908c3c8SFelix Maurer	log_test "${tname}"
3018908c3c8SFelix Maurer}
3028908c3c8SFelix Maurer
303*bbbd531fSFelix Maurertest_packet_loss_hsrv0()
304*bbbd531fSFelix Maurer{
305*bbbd531fSFelix Maurer	test_packet_loss "HSRv0" "20%"
306*bbbd531fSFelix Maurer}
307*bbbd531fSFelix Maurer
308*bbbd531fSFelix Maurertest_packet_loss_hsrv1()
309*bbbd531fSFelix Maurer{
310*bbbd531fSFelix Maurer	test_packet_loss "HSRv1" "20%"
311*bbbd531fSFelix Maurer}
312*bbbd531fSFelix Maurer
3138908c3c8SFelix Maurertest_packet_loss_prp()
3148908c3c8SFelix Maurer{
3158908c3c8SFelix Maurer	test_packet_loss "PRP" "20%"
3168908c3c8SFelix Maurer}
3178908c3c8SFelix Maurer
318*bbbd531fSFelix Maurertest_high_packet_loss_hsrv0()
319*bbbd531fSFelix Maurer{
320*bbbd531fSFelix Maurer	test_packet_loss "HSRv0" "80%"
321*bbbd531fSFelix Maurer}
322*bbbd531fSFelix Maurer
323*bbbd531fSFelix Maurertest_high_packet_loss_hsrv1()
324*bbbd531fSFelix Maurer{
325*bbbd531fSFelix Maurer	test_packet_loss "HSRv1" "80%"
326*bbbd531fSFelix Maurer}
327*bbbd531fSFelix Maurer
3288908c3c8SFelix Maurertest_high_packet_loss_prp()
3298908c3c8SFelix Maurer{
3308908c3c8SFelix Maurer	test_packet_loss "PRP" "80%"
3318908c3c8SFelix Maurer}
3328908c3c8SFelix Maurer
3338908c3c8SFelix Maurertest_reordering()
3348908c3c8SFelix Maurer{
3358908c3c8SFelix Maurer	local proto="$1"
3368908c3c8SFelix Maurer
3378908c3c8SFelix Maurer	RET=0
3388908c3c8SFelix Maurer	tname="${FUNCNAME[0]} - ${proto}"
3398908c3c8SFelix Maurer
3408908c3c8SFelix Maurer	setup_topo "$proto"
3418908c3c8SFelix Maurer	if ((RET != ksft_pass)); then
3428908c3c8SFelix Maurer		log_test "${tname} setup"
3438908c3c8SFelix Maurer		return
3448908c3c8SFelix Maurer	fi
3458908c3c8SFelix Maurer
3468908c3c8SFelix Maurer	tc -net "$node1" qdisc add dev vethA root netem delay 50ms
3478908c3c8SFelix Maurer	tc -net "$node1" qdisc add dev vethB root netem delay 50ms reorder 20%
3488908c3c8SFelix Maurer
3498908c3c8SFelix Maurer	check_ping "$node1" "100.64.0.2" 40
3508908c3c8SFelix Maurer
3518908c3c8SFelix Maurer	log_test "${tname}"
3528908c3c8SFelix Maurer}
3538908c3c8SFelix Maurer
354*bbbd531fSFelix Maurertest_reordering_hsrv0()
355*bbbd531fSFelix Maurer{
356*bbbd531fSFelix Maurer	test_reordering "HSRv0"
357*bbbd531fSFelix Maurer}
358*bbbd531fSFelix Maurer
359*bbbd531fSFelix Maurertest_reordering_hsrv1()
360*bbbd531fSFelix Maurer{
361*bbbd531fSFelix Maurer	test_reordering "HSRv1"
362*bbbd531fSFelix Maurer}
363*bbbd531fSFelix Maurer
3648908c3c8SFelix Maurertest_reordering_prp()
3658908c3c8SFelix Maurer{
3668908c3c8SFelix Maurer	test_reordering "PRP"
3678908c3c8SFelix Maurer}
3688908c3c8SFelix Maurer
369ca4a09a9SFelix Maurercleanup()
370ca4a09a9SFelix Maurer{
371ca4a09a9SFelix Maurer	cleanup_all_ns
372ca4a09a9SFelix Maurer}
373ca4a09a9SFelix Maurer
374ca4a09a9SFelix Maurertrap cleanup EXIT
375ca4a09a9SFelix Maurer
376ca4a09a9SFelix Maurertests_run
377ca4a09a9SFelix Maurer
378ca4a09a9SFelix Maurerexit $EXIT_STATUS
379