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
4# +------------------+
5# | H1 (v$h1) |
6# | 2001:db8:1::2/64 |
7# | 198.51.100.2/28 |
8# | $h1 + |
9# +-------------|----+
10# |
11# +-------------|-------------------------------+
12# | SW1 | |
13# | $rp1 + |
14# | 198.51.100.1/28 |
15# | 2001:db8:1::1/64 |
16# | |
17# | 2001:db8:2::1/64 2001:db8:3::1/64 |
18# | 198.51.100.17/28 198.51.100.33/28 |
19# | $rp2 + $rp3 + |
20# +--------------|--------------------------|---+
21# | |
22# | |
23# +--------------|---+ +--------------|---+
24# | H2 (v$h2) | | | H3 (v$h3) | |
25# | $h2 + | | $h3 + |
26# | 198.51.100.18/28 | | 198.51.100.34/28 |
27# | 2001:db8:2::2/64 | | 2001:db8:3::2/64 |
28# +------------------+ +------------------+
29#
30
31ALL_TESTS="mcast_v4 mcast_v6 rpf_v4 rpf_v6 unres_v4 unres_v6"
32NUM_NETIFS=6
33source lib.sh
34source tc_common.sh
35
36require_command $MCD
37require_command $MC_CLI
38table_name=selftests
39
40h1_create()
41{
42 simple_if_init $h1 198.51.100.2/28 2001:db8:1::2/64
43
44 ip route add 198.51.100.16/28 vrf v$h1 nexthop via 198.51.100.1
45 ip route add 198.51.100.32/28 vrf v$h1 nexthop via 198.51.100.1
46
47 ip route add 2001:db8:2::/64 vrf v$h1 nexthop via 2001:db8:1::1
48 ip route add 2001:db8:3::/64 vrf v$h1 nexthop via 2001:db8:1::1
49
50 tc qdisc add dev $h1 ingress
51}
52
53h1_destroy()
54{
55 tc qdisc del dev $h1 ingress
56
57 ip route del 2001:db8:3::/64 vrf v$h1
58 ip route del 2001:db8:2::/64 vrf v$h1
59
60 ip route del 198.51.100.32/28 vrf v$h1
61 ip route del 198.51.100.16/28 vrf v$h1
62
63 simple_if_fini $h1 198.51.100.2/28 2001:db8:1::2/64
64}
65
66h2_create()
67{
68 simple_if_init $h2 198.51.100.18/28 2001:db8:2::2/64
69
70 ip route add 198.51.100.0/28 vrf v$h2 nexthop via 198.51.100.17
71 ip route add 198.51.100.32/28 vrf v$h2 nexthop via 198.51.100.17
72
73 ip route add 2001:db8:1::/64 vrf v$h2 nexthop via 2001:db8:2::1
74 ip route add 2001:db8:3::/64 vrf v$h2 nexthop via 2001:db8:2::1
75
76 tc qdisc add dev $h2 ingress
77}
78
79h2_destroy()
80{
81 tc qdisc del dev $h2 ingress
82
83 ip route del 2001:db8:3::/64 vrf v$h2
84 ip route del 2001:db8:1::/64 vrf v$h2
85
86 ip route del 198.51.100.32/28 vrf v$h2
87 ip route del 198.51.100.0/28 vrf v$h2
88
89 simple_if_fini $h2 198.51.100.18/28 2001:db8:2::2/64
90}
91
92h3_create()
93{
94 simple_if_init $h3 198.51.100.34/28 2001:db8:3::2/64
95
96 ip route add 198.51.100.0/28 vrf v$h3 nexthop via 198.51.100.33
97 ip route add 198.51.100.16/28 vrf v$h3 nexthop via 198.51.100.33
98
99 ip route add 2001:db8:1::/64 vrf v$h3 nexthop via 2001:db8:3::1
100 ip route add 2001:db8:2::/64 vrf v$h3 nexthop via 2001:db8:3::1
101
102 tc qdisc add dev $h3 ingress
103}
104
105h3_destroy()
106{
107 tc qdisc del dev $h3 ingress
108
109 ip route del 2001:db8:2::/64 vrf v$h3
110 ip route del 2001:db8:1::/64 vrf v$h3
111
112 ip route del 198.51.100.16/28 vrf v$h3
113 ip route del 198.51.100.0/28 vrf v$h3
114
115 simple_if_fini $h3 198.51.100.34/28 2001:db8:3::2/64
116}
117
118router_create()
119{
120 ip link set dev $rp1 up
121 ip link set dev $rp2 up
122 ip link set dev $rp3 up
123
124 ip address add 198.51.100.1/28 dev $rp1
125 ip address add 198.51.100.17/28 dev $rp2
126 ip address add 198.51.100.33/28 dev $rp3
127
128 ip address add 2001:db8:1::1/64 dev $rp1
129 ip address add 2001:db8:2::1/64 dev $rp2
130 ip address add 2001:db8:3::1/64 dev $rp3
131
132 tc qdisc add dev $rp3 ingress
133}
134
135router_destroy()
136{
137 tc qdisc del dev $rp3 ingress
138
139 ip address del 2001:db8:3::1/64 dev $rp3
140 ip address del 2001:db8:2::1/64 dev $rp2
141 ip address del 2001:db8:1::1/64 dev $rp1
142
143 ip address del 198.51.100.33/28 dev $rp3
144 ip address del 198.51.100.17/28 dev $rp2
145 ip address del 198.51.100.1/28 dev $rp1
146
147 ip link set dev $rp3 down
148 ip link set dev $rp2 down
149 ip link set dev $rp1 down
150}
151
152start_mcd()
153{
154 SMCROUTEDIR="$(mktemp -d)"
155
156 for ((i = 1; i <= $NUM_NETIFS; ++i)); do
157 echo "phyint ${NETIFS[p$i]} enable" >> \
158 $SMCROUTEDIR/$table_name.conf
159 done
160
161 $MCD -N -I $table_name -f $SMCROUTEDIR/$table_name.conf \
162 -P $SMCROUTEDIR/$table_name.pid
163}
164
165kill_mcd()
166{
167 pkill $MCD
168 rm -rf $SMCROUTEDIR
169}
170
171setup_prepare()
172{
173 h1=${NETIFS[p1]}
174 rp1=${NETIFS[p2]}
175
176 rp2=${NETIFS[p3]}
177 h2=${NETIFS[p4]}
178
179 rp3=${NETIFS[p5]}
180 h3=${NETIFS[p6]}
181
182 start_mcd
183
184 vrf_prepare
185
186 h1_create
187 h2_create
188 h3_create
189
190 router_create
191
192 forwarding_enable
193}
194
195cleanup()
196{
197 pre_cleanup
198
199 forwarding_restore
200
201 router_destroy
202
203 h3_destroy
204 h2_destroy
205 h1_destroy
206
207 vrf_cleanup
208
209 kill_mcd
210}
211
212create_mcast_sg()
213{
214 local if_name=$1; shift
215 local s_addr=$1; shift
216 local mcast=$1; shift
217 local dest_ifs=${@}
218
219 $MC_CLI -I $table_name add $if_name $s_addr $mcast $dest_ifs
220}
221
222delete_mcast_sg()
223{
224 local if_name=$1; shift
225 local s_addr=$1; shift
226 local mcast=$1; shift
227 local dest_ifs=${@}
228
229 $MC_CLI -I $table_name remove $if_name $s_addr $mcast $dest_ifs
230}
231
232mcast_v4()
233{
234 # Add two interfaces to an MC group, send a packet to the MC group and
235 # verify packets are received on both. Then delete the route and verify
236 # packets are no longer received.
237
238 RET=0
239
240 tc filter add dev $h2 ingress protocol ip pref 1 handle 122 flower \
241 dst_ip 225.1.2.3 action drop
242 tc filter add dev $h3 ingress protocol ip pref 1 handle 133 flower \
243 dst_ip 225.1.2.3 action drop
244
245 create_mcast_sg $rp1 198.51.100.2 225.1.2.3 $rp2 $rp3
246
247 # Send frames with the corresponding L2 destination address.
248 $MZ $h1 -c 5 -p 128 -t udp -a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \
249 -A 198.51.100.2 -B 225.1.2.3 -q
250
251 tc_check_packets "dev $h2 ingress" 122 5
252 check_err $? "Multicast not received on first host"
253 tc_check_packets "dev $h3 ingress" 133 5
254 check_err $? "Multicast not received on second host"
255
256 delete_mcast_sg $rp1 198.51.100.2 225.1.2.3 $rp2 $rp3
257
258 $MZ $h1 -c 5 -p 128 -t udp -a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \
259 -A 198.51.100.2 -B 225.1.2.3 -q
260
261 tc_check_packets "dev $h2 ingress" 122 5
262 check_err $? "Multicast received on host although deleted"
263 tc_check_packets "dev $h3 ingress" 133 5
264 check_err $? "Multicast received on second host although deleted"
265
266 tc filter del dev $h3 ingress protocol ip pref 1 handle 133 flower
267 tc filter del dev $h2 ingress protocol ip pref 1 handle 122 flower
268
269 log_test "mcast IPv4"
270}
271
272mcast_v6()
273{
274 # Add two interfaces to an MC group, send a packet to the MC group and
275 # verify packets are received on both. Then delete the route and verify
276 # packets are no longer received.
277
278 RET=0
279
280 tc filter add dev $h2 ingress protocol ipv6 pref 1 handle 122 flower \
281 dst_ip ff0e::3 action drop
282 tc filter add dev $h3 ingress protocol ipv6 pref 1 handle 133 flower \
283 dst_ip ff0e::3 action drop
284
285 create_mcast_sg $rp1 2001:db8:1::2 ff0e::3 $rp2 $rp3
286
287 # Send frames with the corresponding L2 destination address.
288 $MZ $h1 -6 -c 5 -p 128 -t udp -a 00:11:22:33:44:55 \
289 -b 33:33:00:00:00:03 -A 2001:db8:1::2 -B ff0e::3 -q
290
291 tc_check_packets "dev $h2 ingress" 122 5
292 check_err $? "Multicast not received on first host"
293 tc_check_packets "dev $h3 ingress" 133 5
294 check_err $? "Multicast not received on second host"
295
296 delete_mcast_sg $rp1 2001:db8:1::2 ff0e::3 $rp2 $rp3
297
298 $MZ $h1 -6 -c 5 -p 128 -t udp -a 00:11:22:33:44:55 \
299 -b 33:33:00:00:00:03 -A 2001:db8:1::2 -B ff0e::3 -q
300
301 tc_check_packets "dev $h2 ingress" 122 5
302 check_err $? "Multicast received on first host although deleted"
303 tc_check_packets "dev $h3 ingress" 133 5
304 check_err $? "Multicast received on second host although deleted"
305
306 tc filter del dev $h3 ingress protocol ipv6 pref 1 handle 133 flower
307 tc filter del dev $h2 ingress protocol ipv6 pref 1 handle 122 flower
308
309 log_test "mcast IPv6"
310}
311
312rpf_v4()
313{
314 # Add a multicast route from first router port to the other two. Send
315 # matching packets and test that both hosts receive them. Then, send
316 # the same packets via the third router port and test that they do not
317 # reach any host due to RPF check. A filter with 'skip_hw' is added to
318 # test that devices capable of multicast routing offload trap those
319 # packets. The filter is essentialy a NOP in other scenarios.
320
321 RET=0
322
323 tc filter add dev $h1 ingress protocol ip pref 1 handle 1 flower \
324 dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action drop
325 tc filter add dev $h2 ingress protocol ip pref 1 handle 1 flower \
326 dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action drop
327 tc filter add dev $h3 ingress protocol ip pref 1 handle 1 flower \
328 dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action drop
329 tc filter add dev $rp3 ingress protocol ip pref 1 handle 1 flower \
330 skip_hw dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action pass
331
332 create_mcast_sg $rp1 198.51.100.2 225.1.2.3 $rp2 $rp3
333
334 $MZ $h1 -c 5 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
335 -a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \
336 -A 198.51.100.2 -B 225.1.2.3 -q
337
338 tc_check_packets "dev $h2 ingress" 1 5
339 check_err $? "Multicast not received on first host"
340 tc_check_packets "dev $h3 ingress" 1 5
341 check_err $? "Multicast not received on second host"
342
343 $MZ $h3 -c 5 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
344 -a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \
345 -A 198.51.100.2 -B 225.1.2.3 -q
346
347 tc_check_packets "dev $h1 ingress" 1 0
348 check_err $? "Multicast received on first host when should not"
349 tc_check_packets "dev $h2 ingress" 1 5
350 check_err $? "Multicast received on second host when should not"
351 tc_check_packets "dev $rp3 ingress" 1 5
352 check_err $? "Packets not trapped due to RPF check"
353
354 delete_mcast_sg $rp1 198.51.100.2 225.1.2.3 $rp2 $rp3
355
356 tc filter del dev $rp3 ingress protocol ip pref 1 handle 1 flower
357 tc filter del dev $h3 ingress protocol ip pref 1 handle 1 flower
358 tc filter del dev $h2 ingress protocol ip pref 1 handle 1 flower
359 tc filter del dev $h1 ingress protocol ip pref 1 handle 1 flower
360
361 log_test "RPF IPv4"
362}
363
364rpf_v6()
365{
366 RET=0
367
368 tc filter add dev $h1 ingress protocol ipv6 pref 1 handle 1 flower \
369 dst_ip ff0e::3 ip_proto udp dst_port 12345 action drop
370 tc filter add dev $h2 ingress protocol ipv6 pref 1 handle 1 flower \
371 dst_ip ff0e::3 ip_proto udp dst_port 12345 action drop
372 tc filter add dev $h3 ingress protocol ipv6 pref 1 handle 1 flower \
373 dst_ip ff0e::3 ip_proto udp dst_port 12345 action drop
374 tc filter add dev $rp3 ingress protocol ipv6 pref 1 handle 1 flower \
375 skip_hw dst_ip ff0e::3 ip_proto udp dst_port 12345 action pass
376
377 create_mcast_sg $rp1 2001:db8:1::2 ff0e::3 $rp2 $rp3
378
379 $MZ $h1 -6 -c 5 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
380 -a 00:11:22:33:44:55 -b 33:33:00:00:00:03 \
381 -A 2001:db8:1::2 -B ff0e::3 -q
382
383 tc_check_packets "dev $h2 ingress" 1 5
384 check_err $? "Multicast not received on first host"
385 tc_check_packets "dev $h3 ingress" 1 5
386 check_err $? "Multicast not received on second host"
387
388 $MZ $h3 -6 -c 5 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
389 -a 00:11:22:33:44:55 -b 33:33:00:00:00:03 \
390 -A 2001:db8:1::2 -B ff0e::3 -q
391
392 tc_check_packets "dev $h1 ingress" 1 0
393 check_err $? "Multicast received on first host when should not"
394 tc_check_packets "dev $h2 ingress" 1 5
395 check_err $? "Multicast received on second host when should not"
396 tc_check_packets "dev $rp3 ingress" 1 5
397 check_err $? "Packets not trapped due to RPF check"
398
399 delete_mcast_sg $rp1 2001:db8:1::2 ff0e::3 $rp2 $rp3
400
401 tc filter del dev $rp3 ingress protocol ipv6 pref 1 handle 1 flower
402 tc filter del dev $h3 ingress protocol ipv6 pref 1 handle 1 flower
403 tc filter del dev $h2 ingress protocol ipv6 pref 1 handle 1 flower
404 tc filter del dev $h1 ingress protocol ipv6 pref 1 handle 1 flower
405
406 log_test "RPF IPv6"
407}
408
409unres_v4()
410{
411 # Send a multicast packet not corresponding to an installed route,
412 # causing the kernel to queue the packet for resolution and emit an
413 # IGMPMSG_NOCACHE notification. smcrouted will react to this
414 # notification by consulting its (*, G) list and installing an (S, G)
415 # route, which will be used to forward the queued packet.
416
417 RET=0
418
419 tc filter add dev $h2 ingress protocol ip pref 1 handle 1 flower \
420 dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action drop
421 tc filter add dev $h3 ingress protocol ip pref 1 handle 1 flower \
422 dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action drop
423
424 # Forwarding should fail before installing a matching (*, G).
425 $MZ $h1 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
426 -a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \
427 -A 198.51.100.2 -B 225.1.2.3 -q
428
429 tc_check_packets "dev $h2 ingress" 1 0
430 check_err $? "Multicast received on first host when should not"
431 tc_check_packets "dev $h3 ingress" 1 0
432 check_err $? "Multicast received on second host when should not"
433
434 # Create (*, G). Will not be installed in the kernel.
435 create_mcast_sg $rp1 0.0.0.0 225.1.2.3 $rp2 $rp3
436
437 $MZ $h1 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
438 -a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \
439 -A 198.51.100.2 -B 225.1.2.3 -q
440
441 tc_check_packets "dev $h2 ingress" 1 1
442 check_err $? "Multicast not received on first host"
443 tc_check_packets "dev $h3 ingress" 1 1
444 check_err $? "Multicast not received on second host"
445
446 delete_mcast_sg $rp1 0.0.0.0 225.1.2.3 $rp2 $rp3
447
448 tc filter del dev $h3 ingress protocol ip pref 1 handle 1 flower
449 tc filter del dev $h2 ingress protocol ip pref 1 handle 1 flower
450
451 log_test "Unresolved queue IPv4"
452}
453
454unres_v6()
455{
456 # Send a multicast packet not corresponding to an installed route,
457 # causing the kernel to queue the packet for resolution and emit an
458 # MRT6MSG_NOCACHE notification. smcrouted will react to this
459 # notification by consulting its (*, G) list and installing an (S, G)
460 # route, which will be used to forward the queued packet.
461
462 RET=0
463
464 tc filter add dev $h2 ingress protocol ipv6 pref 1 handle 1 flower \
465 dst_ip ff0e::3 ip_proto udp dst_port 12345 action drop
466 tc filter add dev $h3 ingress protocol ipv6 pref 1 handle 1 flower \
467 dst_ip ff0e::3 ip_proto udp dst_port 12345 action drop
468
469 # Forwarding should fail before installing a matching (*, G).
470 $MZ $h1 -6 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
471 -a 00:11:22:33:44:55 -b 33:33:00:00:00:03 \
472 -A 2001:db8:1::2 -B ff0e::3 -q
473
474 tc_check_packets "dev $h2 ingress" 1 0
475 check_err $? "Multicast received on first host when should not"
476 tc_check_packets "dev $h3 ingress" 1 0
477 check_err $? "Multicast received on second host when should not"
478
479 # Create (*, G). Will not be installed in the kernel.
480 create_mcast_sg $rp1 :: ff0e::3 $rp2 $rp3
481
482 $MZ $h1 -6 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
483 -a 00:11:22:33:44:55 -b 33:33:00:00:00:03 \
484 -A 2001:db8:1::2 -B ff0e::3 -q
485
486 tc_check_packets "dev $h2 ingress" 1 1
487 check_err $? "Multicast not received on first host"
488 tc_check_packets "dev $h3 ingress" 1 1
489 check_err $? "Multicast not received on second host"
490
491 delete_mcast_sg $rp1 :: ff0e::3 $rp2 $rp3
492
493 tc filter del dev $h3 ingress protocol ipv6 pref 1 handle 1 flower
494 tc filter del dev $h2 ingress protocol ipv6 pref 1 handle 1 flower
495
496 log_test "Unresolved queue IPv6"
497}
498
499trap cleanup EXIT
500
501setup_prepare
502setup_wait
503
504tests_run
505
506exit $EXIT_STATUS