Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3# shellcheck disable=SC2329
4
5source ../lib.sh
6
7ALL_TESTS="
8 test_clean_hsrv0
9 test_cut_link_hsrv0
10 test_packet_loss_hsrv0
11 test_high_packet_loss_hsrv0
12 test_reordering_hsrv0
13
14 test_clean_hsrv1
15 test_cut_link_hsrv1
16 test_packet_loss_hsrv1
17 test_high_packet_loss_hsrv1
18 test_reordering_hsrv1
19
20 test_clean_prp
21 test_cut_link_prp
22 test_packet_loss_prp
23 test_high_packet_loss_prp
24 test_reordering_prp
25"
26
27# The tests are running ping for 5sec with a relatively short interval in
28# different scenarios with faulty links (cut links, packet loss, delay,
29# reordering) that should be recoverable by HSR/PRP. The ping interval (10ms)
30# is short enough that the base delay (50ms) leads to a queue in the netem
31# qdiscs which is needed for reordering.
32
33setup_hsr_topo()
34{
35 # Three HSR nodes in a ring, every node has a LAN A interface connected
36 # to the LAN B interface of the next node.
37 #
38 # node1 node2
39 #
40 # vethA -------- vethB
41 # hsr1 hsr2
42 # vethB vethA
43 # \ /
44 # vethA vethB
45 # hsr3
46 #
47 # node3
48
49 local ver="$1"
50
51 setup_ns node1 node2 node3
52
53 # veth links
54 # shellcheck disable=SC2154 # variables assigned by setup_ns
55 ip link add vethA netns "$node1" type veth peer name vethB netns "$node2"
56 # shellcheck disable=SC2154 # variables assigned by setup_ns
57 ip link add vethA netns "$node2" type veth peer name vethB netns "$node3"
58 ip link add vethA netns "$node3" type veth peer name vethB netns "$node1"
59
60 # MAC addresses (not needed for HSR operation, but helps with debugging)
61 ip -net "$node1" link set address 00:11:22:00:01:01 dev vethA
62 ip -net "$node1" link set address 00:11:22:00:01:02 dev vethB
63
64 ip -net "$node2" link set address 00:11:22:00:02:01 dev vethA
65 ip -net "$node2" link set address 00:11:22:00:02:02 dev vethB
66
67 ip -net "$node3" link set address 00:11:22:00:03:01 dev vethA
68 ip -net "$node3" link set address 00:11:22:00:03:02 dev vethB
69
70 # HSR interfaces
71 ip -net "$node1" link add name hsr1 type hsr proto 0 version "$ver" \
72 slave1 vethA slave2 vethB supervision 45
73 ip -net "$node2" link add name hsr2 type hsr proto 0 version "$ver" \
74 slave1 vethA slave2 vethB supervision 45
75 ip -net "$node3" link add name hsr3 type hsr proto 0 version "$ver" \
76 slave1 vethA slave2 vethB supervision 45
77
78 # IP addresses
79 ip -net "$node1" addr add 100.64.0.1/24 dev hsr1
80 ip -net "$node2" addr add 100.64.0.2/24 dev hsr2
81 ip -net "$node3" addr add 100.64.0.3/24 dev hsr3
82
83 # Set all links up
84 ip -net "$node1" link set vethA up
85 ip -net "$node1" link set vethB up
86 ip -net "$node1" link set hsr1 up
87
88 ip -net "$node2" link set vethA up
89 ip -net "$node2" link set vethB up
90 ip -net "$node2" link set hsr2 up
91
92 ip -net "$node3" link set vethA up
93 ip -net "$node3" link set vethB up
94 ip -net "$node3" link set hsr3 up
95}
96
97setup_prp_topo()
98{
99 # Two PRP nodes, connected by two links (treated as LAN A and LAN B).
100 #
101 # vethA ----- vethA
102 # prp1 prp2
103 # vethB ----- vethB
104 #
105 # node1 node2
106
107 setup_ns node1 node2
108
109 # veth links
110 ip link add vethA netns "$node1" type veth peer name vethA netns "$node2"
111 ip link add vethB netns "$node1" type veth peer name vethB netns "$node2"
112
113 # MAC addresses will be copied from LAN A interface
114 ip -net "$node1" link set address 00:11:22:00:00:01 dev vethA
115 ip -net "$node2" link set address 00:11:22:00:00:02 dev vethA
116
117 # PRP interfaces
118 ip -net "$node1" link add name prp1 type hsr \
119 slave1 vethA slave2 vethB supervision 45 proto 1
120 ip -net "$node2" link add name prp2 type hsr \
121 slave1 vethA slave2 vethB supervision 45 proto 1
122
123 # IP addresses
124 ip -net "$node1" addr add 100.64.0.1/24 dev prp1
125 ip -net "$node2" addr add 100.64.0.2/24 dev prp2
126
127 # All links up
128 ip -net "$node1" link set vethA up
129 ip -net "$node1" link set vethB up
130 ip -net "$node1" link set prp1 up
131
132 ip -net "$node2" link set vethA up
133 ip -net "$node2" link set vethB up
134 ip -net "$node2" link set prp2 up
135}
136
137wait_for_hsr_node_table()
138{
139 log_info "Wait for node table entries to be merged."
140 WAIT=5
141 while [ "${WAIT}" -gt 0 ]; do
142 nts=$(cat /sys/kernel/debug/hsr/hsr*/node_table)
143
144 # We need entries in the node tables, and they need to be merged
145 if (echo "$nts" | grep -qE "^([0-9a-f]{2}:){5}") && \
146 ! (echo "$nts" | grep -q "00:00:00:00:00:00"); then
147 return
148 fi
149
150 sleep 1
151 ((WAIT--))
152 done
153 check_err 1 "Failed to wait for merged node table entries"
154}
155
156setup_topo()
157{
158 local proto="$1"
159
160 if [ "$proto" = "HSRv0" ]; then
161 setup_hsr_topo 0
162 wait_for_hsr_node_table
163 elif [ "$proto" = "HSRv1" ]; then
164 setup_hsr_topo 1
165 wait_for_hsr_node_table
166 elif [ "$proto" = "PRP" ]; then
167 setup_prp_topo
168 else
169 check_err 1 "Unknown protocol (${proto})"
170 fi
171}
172
173check_ping()
174{
175 local node="$1"
176 local dst="$2"
177 local accepted_dups="$3"
178 local ping_args="-q -i 0.01 -c 400"
179
180 log_info "Running ping $node -> $dst"
181 # shellcheck disable=SC2086
182 output=$(ip netns exec "$node" ping $ping_args "$dst" | \
183 grep "packets transmitted")
184 log_info "$output"
185
186 dups=0
187 loss=0
188
189 if [[ "$output" =~ \+([0-9]+)" duplicates" ]]; then
190 dups="${BASH_REMATCH[1]}"
191 fi
192 if [[ "$output" =~ ([0-9\.]+\%)" packet loss" ]]; then
193 loss="${BASH_REMATCH[1]}"
194 fi
195
196 if [ "$dups" -gt "$accepted_dups" ]; then
197 check_err 1 "Unexpected duplicate packets (${dups})"
198 fi
199 if [ "$loss" != "0%" ]; then
200 check_err 1 "Unexpected packet loss (${loss})"
201 fi
202}
203
204test_clean()
205{
206 local proto="$1"
207
208 RET=0
209 tname="${FUNCNAME[0]} - ${proto}"
210
211 setup_topo "$proto"
212 if ((RET != ksft_pass)); then
213 log_test "${tname} setup"
214 return
215 fi
216
217 check_ping "$node1" "100.64.0.2" 0
218
219 log_test "${tname}"
220}
221
222test_clean_hsrv0()
223{
224 test_clean "HSRv0"
225}
226
227test_clean_hsrv1()
228{
229 test_clean "HSRv1"
230}
231
232test_clean_prp()
233{
234 test_clean "PRP"
235}
236
237test_cut_link()
238{
239 local proto="$1"
240
241 RET=0
242 tname="${FUNCNAME[0]} - ${proto}"
243
244 setup_topo "$proto"
245 if ((RET != ksft_pass)); then
246 log_test "${tname} setup"
247 return
248 fi
249
250 # Cutting link from subshell, so check_ping can run in the normal shell
251 # with access to global variables from the test harness.
252 (
253 sleep 2
254 log_info "Cutting link"
255 ip -net "$node1" link set vethB down
256 ) &
257 check_ping "$node1" "100.64.0.2" 0
258
259 wait
260 log_test "${tname}"
261}
262
263
264test_cut_link_hsrv0()
265{
266 test_cut_link "HSRv0"
267}
268
269test_cut_link_hsrv1()
270{
271 test_cut_link "HSRv1"
272}
273
274test_cut_link_prp()
275{
276 test_cut_link "PRP"
277}
278
279test_packet_loss()
280{
281 local proto="$1"
282 local loss="$2"
283
284 RET=0
285 tname="${FUNCNAME[0]} - ${proto}, ${loss}"
286
287 setup_topo "$proto"
288 if ((RET != ksft_pass)); then
289 log_test "${tname} setup"
290 return
291 fi
292
293 # Packet loss with lower delay makes sure the packets on the lossy link
294 # arrive first.
295 tc -net "$node1" qdisc add dev vethA root netem delay 50ms
296 tc -net "$node1" qdisc add dev vethB root netem delay 20ms loss "$loss"
297
298 check_ping "$node1" "100.64.0.2" 40
299
300 log_test "${tname}"
301}
302
303test_packet_loss_hsrv0()
304{
305 test_packet_loss "HSRv0" "20%"
306}
307
308test_packet_loss_hsrv1()
309{
310 test_packet_loss "HSRv1" "20%"
311}
312
313test_packet_loss_prp()
314{
315 test_packet_loss "PRP" "20%"
316}
317
318test_high_packet_loss_hsrv0()
319{
320 test_packet_loss "HSRv0" "80%"
321}
322
323test_high_packet_loss_hsrv1()
324{
325 test_packet_loss "HSRv1" "80%"
326}
327
328test_high_packet_loss_prp()
329{
330 test_packet_loss "PRP" "80%"
331}
332
333test_reordering()
334{
335 local proto="$1"
336
337 RET=0
338 tname="${FUNCNAME[0]} - ${proto}"
339
340 setup_topo "$proto"
341 if ((RET != ksft_pass)); then
342 log_test "${tname} setup"
343 return
344 fi
345
346 tc -net "$node1" qdisc add dev vethA root netem delay 50ms
347 tc -net "$node1" qdisc add dev vethB root netem delay 50ms reorder 20%
348
349 check_ping "$node1" "100.64.0.2" 40
350
351 log_test "${tname}"
352}
353
354test_reordering_hsrv0()
355{
356 test_reordering "HSRv0"
357}
358
359test_reordering_hsrv1()
360{
361 test_reordering "HSRv1"
362}
363
364test_reordering_prp()
365{
366 test_reordering "PRP"
367}
368
369cleanup()
370{
371 cleanup_all_ns
372}
373
374trap cleanup EXIT
375
376tests_run
377
378exit $EXIT_STATUS