507 lines · bash
1#!/bin/bash2# SPDX-License-Identifier: GPL-2.03 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=633source lib.sh34source tc_common.sh35 36require_command $MCD37require_command $MC_CLI38table_name=selftests39 40h1_create()41{42 simple_if_init $h1 198.51.100.2/28 2001:db8:1::2/6443 44 ip route add 198.51.100.16/28 vrf v$h1 nexthop via 198.51.100.145 ip route add 198.51.100.32/28 vrf v$h1 nexthop via 198.51.100.146 47 ip route add 2001:db8:2::/64 vrf v$h1 nexthop via 2001:db8:1::148 ip route add 2001:db8:3::/64 vrf v$h1 nexthop via 2001:db8:1::149 50 tc qdisc add dev $h1 ingress51}52 53h1_destroy()54{55 tc qdisc del dev $h1 ingress56 57 ip route del 2001:db8:3::/64 vrf v$h158 ip route del 2001:db8:2::/64 vrf v$h159 60 ip route del 198.51.100.32/28 vrf v$h161 ip route del 198.51.100.16/28 vrf v$h162 63 simple_if_fini $h1 198.51.100.2/28 2001:db8:1::2/6464}65 66h2_create()67{68 simple_if_init $h2 198.51.100.18/28 2001:db8:2::2/6469 70 ip route add 198.51.100.0/28 vrf v$h2 nexthop via 198.51.100.1771 ip route add 198.51.100.32/28 vrf v$h2 nexthop via 198.51.100.1772 73 ip route add 2001:db8:1::/64 vrf v$h2 nexthop via 2001:db8:2::174 ip route add 2001:db8:3::/64 vrf v$h2 nexthop via 2001:db8:2::175 76 tc qdisc add dev $h2 ingress77}78 79h2_destroy()80{81 tc qdisc del dev $h2 ingress82 83 ip route del 2001:db8:3::/64 vrf v$h284 ip route del 2001:db8:1::/64 vrf v$h285 86 ip route del 198.51.100.32/28 vrf v$h287 ip route del 198.51.100.0/28 vrf v$h288 89 simple_if_fini $h2 198.51.100.18/28 2001:db8:2::2/6490}91 92h3_create()93{94 simple_if_init $h3 198.51.100.34/28 2001:db8:3::2/6495 96 ip route add 198.51.100.0/28 vrf v$h3 nexthop via 198.51.100.3397 ip route add 198.51.100.16/28 vrf v$h3 nexthop via 198.51.100.3398 99 ip route add 2001:db8:1::/64 vrf v$h3 nexthop via 2001:db8:3::1100 ip route add 2001:db8:2::/64 vrf v$h3 nexthop via 2001:db8:3::1101 102 tc qdisc add dev $h3 ingress103}104 105h3_destroy()106{107 tc qdisc del dev $h3 ingress108 109 ip route del 2001:db8:2::/64 vrf v$h3110 ip route del 2001:db8:1::/64 vrf v$h3111 112 ip route del 198.51.100.16/28 vrf v$h3113 ip route del 198.51.100.0/28 vrf v$h3114 115 simple_if_fini $h3 198.51.100.34/28 2001:db8:3::2/64116}117 118router_create()119{120 ip link set dev $rp1 up121 ip link set dev $rp2 up122 ip link set dev $rp3 up123 124 ip address add 198.51.100.1/28 dev $rp1125 ip address add 198.51.100.17/28 dev $rp2126 ip address add 198.51.100.33/28 dev $rp3127 128 ip address add 2001:db8:1::1/64 dev $rp1129 ip address add 2001:db8:2::1/64 dev $rp2130 ip address add 2001:db8:3::1/64 dev $rp3131 132 tc qdisc add dev $rp3 ingress133}134 135router_destroy()136{137 tc qdisc del dev $rp3 ingress138 139 ip address del 2001:db8:3::1/64 dev $rp3140 ip address del 2001:db8:2::1/64 dev $rp2141 ip address del 2001:db8:1::1/64 dev $rp1142 143 ip address del 198.51.100.33/28 dev $rp3144 ip address del 198.51.100.17/28 dev $rp2145 ip address del 198.51.100.1/28 dev $rp1146 147 ip link set dev $rp3 down148 ip link set dev $rp2 down149 ip link set dev $rp1 down150}151 152start_mcd()153{154 SMCROUTEDIR="$(mktemp -d)"155 156 for ((i = 1; i <= $NUM_NETIFS; ++i)); do157 echo "phyint ${NETIFS[p$i]} enable" >> \158 $SMCROUTEDIR/$table_name.conf159 done160 161 $MCD -N -I $table_name -f $SMCROUTEDIR/$table_name.conf \162 -P $SMCROUTEDIR/$table_name.pid163}164 165kill_mcd()166{167 pkill $MCD168 rm -rf $SMCROUTEDIR169}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_mcd183 184 vrf_prepare185 186 h1_create187 h2_create188 h3_create189 190 router_create191 192 forwarding_enable193}194 195cleanup()196{197 pre_cleanup198 199 forwarding_restore200 201 router_destroy202 203 h3_destroy204 h2_destroy205 h1_destroy206 207 vrf_cleanup208 209 kill_mcd210}211 212create_mcast_sg()213{214 local if_name=$1; shift215 local s_addr=$1; shift216 local mcast=$1; shift217 local dest_ifs=${@}218 219 $MC_CLI -I $table_name add $if_name $s_addr $mcast $dest_ifs220}221 222delete_mcast_sg()223{224 local if_name=$1; shift225 local s_addr=$1; shift226 local mcast=$1; shift227 local dest_ifs=${@}228 229 $MC_CLI -I $table_name remove $if_name $s_addr $mcast $dest_ifs230}231 232mcast_v4()233{234 # Add two interfaces to an MC group, send a packet to the MC group and235 # verify packets are received on both. Then delete the route and verify236 # packets are no longer received.237 238 RET=0239 240 tc filter add dev $h2 ingress protocol ip pref 1 handle 122 flower \241 dst_ip 225.1.2.3 action drop242 tc filter add dev $h3 ingress protocol ip pref 1 handle 133 flower \243 dst_ip 225.1.2.3 action drop244 245 create_mcast_sg $rp1 198.51.100.2 225.1.2.3 $rp2 $rp3246 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 -q250 251 tc_check_packets "dev $h2 ingress" 122 5252 check_err $? "Multicast not received on first host"253 tc_check_packets "dev $h3 ingress" 133 5254 check_err $? "Multicast not received on second host"255 256 delete_mcast_sg $rp1 198.51.100.2 225.1.2.3 $rp2 $rp3257 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 -q260 261 tc_check_packets "dev $h2 ingress" 122 5262 check_err $? "Multicast received on host although deleted"263 tc_check_packets "dev $h3 ingress" 133 5264 check_err $? "Multicast received on second host although deleted"265 266 tc filter del dev $h3 ingress protocol ip pref 1 handle 133 flower267 tc filter del dev $h2 ingress protocol ip pref 1 handle 122 flower268 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 and275 # verify packets are received on both. Then delete the route and verify276 # packets are no longer received.277 278 RET=0279 280 tc filter add dev $h2 ingress protocol ipv6 pref 1 handle 122 flower \281 dst_ip ff0e::3 action drop282 tc filter add dev $h3 ingress protocol ipv6 pref 1 handle 133 flower \283 dst_ip ff0e::3 action drop284 285 create_mcast_sg $rp1 2001:db8:1::2 ff0e::3 $rp2 $rp3286 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 -q290 291 tc_check_packets "dev $h2 ingress" 122 5292 check_err $? "Multicast not received on first host"293 tc_check_packets "dev $h3 ingress" 133 5294 check_err $? "Multicast not received on second host"295 296 delete_mcast_sg $rp1 2001:db8:1::2 ff0e::3 $rp2 $rp3297 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 -q300 301 tc_check_packets "dev $h2 ingress" 122 5302 check_err $? "Multicast received on first host although deleted"303 tc_check_packets "dev $h3 ingress" 133 5304 check_err $? "Multicast received on second host although deleted"305 306 tc filter del dev $h3 ingress protocol ipv6 pref 1 handle 133 flower307 tc filter del dev $h2 ingress protocol ipv6 pref 1 handle 122 flower308 309 log_test "mcast IPv6"310}311 312rpf_v4()313{314 # Add a multicast route from first router port to the other two. Send315 # matching packets and test that both hosts receive them. Then, send316 # the same packets via the third router port and test that they do not317 # reach any host due to RPF check. A filter with 'skip_hw' is added to318 # test that devices capable of multicast routing offload trap those319 # packets. The filter is essentialy a NOP in other scenarios.320 321 RET=0322 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 drop325 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 drop327 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 drop329 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 pass331 332 create_mcast_sg $rp1 198.51.100.2 225.1.2.3 $rp2 $rp3333 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 -q337 338 tc_check_packets "dev $h2 ingress" 1 5339 check_err $? "Multicast not received on first host"340 tc_check_packets "dev $h3 ingress" 1 5341 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 -q346 347 tc_check_packets "dev $h1 ingress" 1 0348 check_err $? "Multicast received on first host when should not"349 tc_check_packets "dev $h2 ingress" 1 5350 check_err $? "Multicast received on second host when should not"351 tc_check_packets "dev $rp3 ingress" 1 5352 check_err $? "Packets not trapped due to RPF check"353 354 delete_mcast_sg $rp1 198.51.100.2 225.1.2.3 $rp2 $rp3355 356 tc filter del dev $rp3 ingress protocol ip pref 1 handle 1 flower357 tc filter del dev $h3 ingress protocol ip pref 1 handle 1 flower358 tc filter del dev $h2 ingress protocol ip pref 1 handle 1 flower359 tc filter del dev $h1 ingress protocol ip pref 1 handle 1 flower360 361 log_test "RPF IPv4"362}363 364rpf_v6()365{366 RET=0367 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 drop370 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 drop372 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 drop374 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 pass376 377 create_mcast_sg $rp1 2001:db8:1::2 ff0e::3 $rp2 $rp3378 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 -q382 383 tc_check_packets "dev $h2 ingress" 1 5384 check_err $? "Multicast not received on first host"385 tc_check_packets "dev $h3 ingress" 1 5386 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 -q391 392 tc_check_packets "dev $h1 ingress" 1 0393 check_err $? "Multicast received on first host when should not"394 tc_check_packets "dev $h2 ingress" 1 5395 check_err $? "Multicast received on second host when should not"396 tc_check_packets "dev $rp3 ingress" 1 5397 check_err $? "Packets not trapped due to RPF check"398 399 delete_mcast_sg $rp1 2001:db8:1::2 ff0e::3 $rp2 $rp3400 401 tc filter del dev $rp3 ingress protocol ipv6 pref 1 handle 1 flower402 tc filter del dev $h3 ingress protocol ipv6 pref 1 handle 1 flower403 tc filter del dev $h2 ingress protocol ipv6 pref 1 handle 1 flower404 tc filter del dev $h1 ingress protocol ipv6 pref 1 handle 1 flower405 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 an413 # IGMPMSG_NOCACHE notification. smcrouted will react to this414 # 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=0418 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 drop421 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 drop423 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 -q428 429 tc_check_packets "dev $h2 ingress" 1 0430 check_err $? "Multicast received on first host when should not"431 tc_check_packets "dev $h3 ingress" 1 0432 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 $rp3436 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 -q440 441 tc_check_packets "dev $h2 ingress" 1 1442 check_err $? "Multicast not received on first host"443 tc_check_packets "dev $h3 ingress" 1 1444 check_err $? "Multicast not received on second host"445 446 delete_mcast_sg $rp1 0.0.0.0 225.1.2.3 $rp2 $rp3447 448 tc filter del dev $h3 ingress protocol ip pref 1 handle 1 flower449 tc filter del dev $h2 ingress protocol ip pref 1 handle 1 flower450 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 an458 # MRT6MSG_NOCACHE notification. smcrouted will react to this459 # 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=0463 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 drop466 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 drop468 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 -q473 474 tc_check_packets "dev $h2 ingress" 1 0475 check_err $? "Multicast received on first host when should not"476 tc_check_packets "dev $h3 ingress" 1 0477 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 $rp3481 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 -q485 486 tc_check_packets "dev $h2 ingress" 1 1487 check_err $? "Multicast not received on first host"488 tc_check_packets "dev $h3 ingress" 1 1489 check_err $? "Multicast not received on second host"490 491 delete_mcast_sg $rp1 :: ff0e::3 $rp2 $rp3492 493 tc filter del dev $h3 ingress protocol ipv6 pref 1 handle 1 flower494 tc filter del dev $h2 ingress protocol ipv6 pref 1 handle 1 flower495 496 log_test "Unresolved queue IPv6"497}498 499trap cleanup EXIT500 501setup_prepare502setup_wait503 504tests_run505 506exit $EXIT_STATUS507