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" 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 409trap cleanup EXIT 410 411setup_prepare 412setup_wait 413 414tests_run 415 416exit $EXIT_STATUS 417