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