1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4ALL_TESTS="vlmc_control_test vlmc_querier_test vlmc_igmp_mld_version_test \ 5 vlmc_last_member_test vlmc_startup_query_test vlmc_membership_test \ 6 vlmc_querier_intvl_test vlmc_query_intvl_test vlmc_query_response_intvl_test \ 7 vlmc_router_port_test vlmc_filtering_test" 8NUM_NETIFS=4 9CHECK_TC="yes" 10TEST_GROUP="239.10.10.10" 11 12source lib.sh 13 14h1_create() 15{ 16 simple_if_init $h1 192.0.2.1/24 2001:db8:1::1/64 17 ip link add l $h1 $h1.10 up type vlan id 10 18} 19 20h1_destroy() 21{ 22 ip link del $h1.10 23 simple_if_fini $h1 192.0.2.1/24 2001:db8:1::1/64 24} 25 26h2_create() 27{ 28 simple_if_init $h2 192.0.2.2/24 2001:db8:1::2/64 29 ip link add l $h2 $h2.10 up type vlan id 10 30} 31 32h2_destroy() 33{ 34 ip link del $h2.10 35 simple_if_fini $h2 192.0.2.2/24 2001:db8:1::2/64 36} 37 38switch_create() 39{ 40 ip link add dev br0 type bridge mcast_snooping 1 mcast_querier 1 vlan_filtering 1 41 42 ip link set dev $swp1 master br0 43 ip link set dev $swp2 master br0 44 45 ip link set dev br0 up 46 ip link set dev $swp1 up 47 ip link set dev $swp2 up 48 49 tc qdisc add dev $swp1 clsact 50 tc qdisc add dev $swp2 clsact 51 52 bridge vlan add vid 10-11 dev $swp1 master 53 bridge vlan add vid 10-11 dev $swp2 master 54 55 ip link set dev br0 type bridge mcast_vlan_snooping 1 56 check_err $? "Could not enable global vlan multicast snooping" 57 log_test "Vlan multicast snooping enable" 58} 59 60switch_destroy() 61{ 62 ip link set dev $swp2 down 63 ip link set dev $swp1 down 64 65 ip link del dev br0 66} 67 68setup_prepare() 69{ 70 h1=${NETIFS[p1]} 71 swp1=${NETIFS[p2]} 72 73 swp2=${NETIFS[p3]} 74 h2=${NETIFS[p4]} 75 76 vrf_prepare 77 78 h1_create 79 h2_create 80 81 switch_create 82} 83 84cleanup() 85{ 86 pre_cleanup 87 88 switch_destroy 89 90 h2_destroy 91 h1_destroy 92 93 vrf_cleanup 94} 95 96vlmc_v2join_test() 97{ 98 local expect=$1 99 100 RET=0 101 ip address add dev $h2.10 $TEST_GROUP/32 autojoin 102 check_err $? "Could not join $TEST_GROUP" 103 104 sleep 5 105 bridge -j mdb show dev br0 | 106 jq -e ".[].mdb[] | select(.grp == \"$TEST_GROUP\" and .vid == 10)" &>/dev/null 107 if [ $expect -eq 0 ]; then 108 check_err $? "IGMPv2 report didn't create mdb entry for $TEST_GROUP" 109 else 110 check_fail $? "IGMPv2 report shouldn't have created mdb entry for $TEST_GROUP" 111 fi 112 113 # check if we need to cleanup 114 if [ $RET -eq 0 ]; then 115 ip address del dev $h2.10 $TEST_GROUP/32 2>&1 1>/dev/null 116 sleep 5 117 bridge -j mdb show dev br0 | 118 jq -e ".[].mdb[] | select(.grp == \"$TEST_GROUP\" and \ 119 .vid == 10)" &>/dev/null 120 check_fail $? "IGMPv2 leave didn't remove mdb entry for $TEST_GROUP" 121 fi 122} 123 124vlmc_control_test() 125{ 126 RET=0 127 local goutput=`bridge -j vlan global show` 128 echo -n $goutput | 129 jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null 130 check_err $? "Could not find vlan 10's global options" 131 log_test "Vlan global options existence" 132 133 RET=0 134 echo -n $goutput | 135 jq -e ".[].vlans[] | select(.vlan == 10 and .mcast_snooping == 1) " &>/dev/null 136 check_err $? "Wrong default mcast_snooping global option value" 137 log_test "Vlan mcast_snooping global option default value" 138 139 RET=0 140 vlmc_v2join_test 0 141 bridge vlan global set vid 10 dev br0 mcast_snooping 0 142 check_err $? "Could not disable multicast snooping in vlan 10" 143 vlmc_v2join_test 1 144 log_test "Vlan 10 multicast snooping control" 145} 146 147# setup for general query counting 148vlmc_query_cnt_xstats() 149{ 150 local type=$1 151 local version=$2 152 local dev=$3 153 154 ip -j link xstats type bridge_slave dev $dev | \ 155 jq -e ".[].multicast.${type}_queries.tx_v${version}" 156} 157 158vlmc_query_cnt_setup() 159{ 160 local type=$1 161 local dev=$2 162 163 if [[ $type == "igmp" ]]; then 164 tc filter add dev $dev egress pref 10 prot 802.1Q \ 165 flower vlan_id 10 vlan_ethtype ipv4 dst_ip 224.0.0.1 ip_proto 2 \ 166 action pass 167 else 168 tc filter add dev $dev egress pref 10 prot 802.1Q \ 169 flower vlan_id 10 vlan_ethtype ipv6 dst_ip ff02::1 ip_proto icmpv6 \ 170 action pass 171 fi 172 173 ip link set dev br0 type bridge mcast_stats_enabled 1 174} 175 176vlmc_query_cnt_cleanup() 177{ 178 local dev=$1 179 180 ip link set dev br0 type bridge mcast_stats_enabled 0 181 tc filter del dev $dev egress pref 10 182} 183 184vlmc_check_query() 185{ 186 local type=$1 187 local version=$2 188 local dev=$3 189 local expect=$4 190 local time=$5 191 local ret=0 192 193 vlmc_query_cnt_setup $type $dev 194 195 local pre_tx_xstats=$(vlmc_query_cnt_xstats $type $version $dev) 196 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier 1 197 ret=$? 198 if [[ $ret -eq 0 ]]; then 199 sleep $time 200 201 local tcstats=$(tc_rule_stats_get $dev 10 egress) 202 local post_tx_xstats=$(vlmc_query_cnt_xstats $type $version $dev) 203 204 if [[ $tcstats != $expect || \ 205 $(($post_tx_xstats-$pre_tx_xstats)) != $expect || \ 206 $tcstats != $(($post_tx_xstats-$pre_tx_xstats)) ]]; then 207 ret=1 208 fi 209 fi 210 211 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier 0 212 vlmc_query_cnt_cleanup $dev 213 214 return $ret 215} 216 217vlmc_querier_test() 218{ 219 RET=0 220 local goutput=`bridge -j vlan global show` 221 echo -n $goutput | 222 jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null 223 check_err $? "Could not find vlan 10's global options" 224 225 echo -n $goutput | 226 jq -e ".[].vlans[] | select(.vlan == 10 and .mcast_querier == 0) " &>/dev/null 227 check_err $? "Wrong default mcast_querier global vlan option value" 228 log_test "Vlan mcast_querier global option default value" 229 230 RET=0 231 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier 1 232 check_err $? "Could not enable querier in vlan 10" 233 log_test "Vlan 10 multicast querier enable" 234 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier 0 235 236 RET=0 237 vlmc_check_query igmp 2 $swp1 1 1 238 check_err $? "No vlan tagged IGMPv2 general query packets sent" 239 log_test "Vlan 10 tagged IGMPv2 general query sent" 240 241 RET=0 242 vlmc_check_query mld 1 $swp1 1 1 243 check_err $? "No vlan tagged MLD general query packets sent" 244 log_test "Vlan 10 tagged MLD general query sent" 245} 246 247vlmc_igmp_mld_version_test() 248{ 249 RET=0 250 local goutput=`bridge -j vlan global show` 251 echo -n $goutput | 252 jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null 253 check_err $? "Could not find vlan 10's global options" 254 255 echo -n $goutput | 256 jq -e ".[].vlans[] | select(.vlan == 10 and .mcast_igmp_version == 2) " &>/dev/null 257 check_err $? "Wrong default mcast_igmp_version global vlan option value" 258 log_test "Vlan mcast_igmp_version global option default value" 259 260 RET=0 261 echo -n $goutput | 262 jq -e ".[].vlans[] | select(.vlan == 10 and .mcast_mld_version == 1) " &>/dev/null 263 check_err $? "Wrong default mcast_mld_version global vlan option value" 264 log_test "Vlan mcast_mld_version global option default value" 265 266 RET=0 267 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version 3 268 check_err $? "Could not set mcast_igmp_version in vlan 10" 269 log_test "Vlan 10 mcast_igmp_version option changed to 3" 270 271 RET=0 272 vlmc_check_query igmp 3 $swp1 1 1 273 check_err $? "No vlan tagged IGMPv3 general query packets sent" 274 log_test "Vlan 10 tagged IGMPv3 general query sent" 275 276 RET=0 277 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 2 278 check_err $? "Could not set mcast_mld_version in vlan 10" 279 log_test "Vlan 10 mcast_mld_version option changed to 2" 280 281 RET=0 282 vlmc_check_query mld 2 $swp1 1 1 283 check_err $? "No vlan tagged MLDv2 general query packets sent" 284 log_test "Vlan 10 tagged MLDv2 general query sent" 285 286 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version 2 287 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 1 288} 289 290vlmc_last_member_test() 291{ 292 RET=0 293 local goutput=`bridge -j vlan global show` 294 echo -n $goutput | 295 jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null 296 check_err $? "Could not find vlan 10's global options" 297 298 echo -n $goutput | 299 jq -e ".[].vlans[] | select(.vlan == 10 and \ 300 .mcast_last_member_count == 2) " &>/dev/null 301 check_err $? "Wrong default mcast_last_member_count global vlan option value" 302 log_test "Vlan mcast_last_member_count global option default value" 303 304 RET=0 305 echo -n $goutput | 306 jq -e ".[].vlans[] | select(.vlan == 10 and \ 307 .mcast_last_member_interval == 100) " &>/dev/null 308 check_err $? "Wrong default mcast_last_member_interval global vlan option value" 309 log_test "Vlan mcast_last_member_interval global option default value" 310 311 RET=0 312 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_last_member_count 3 313 check_err $? "Could not set mcast_last_member_count in vlan 10" 314 log_test "Vlan 10 mcast_last_member_count option changed to 3" 315 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_last_member_count 2 316 317 RET=0 318 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_last_member_interval 200 319 check_err $? "Could not set mcast_last_member_interval in vlan 10" 320 log_test "Vlan 10 mcast_last_member_interval option changed to 200" 321 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_last_member_interval 100 322} 323 324vlmc_startup_query_test() 325{ 326 RET=0 327 local goutput=`bridge -j vlan global show` 328 echo -n $goutput | 329 jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null 330 check_err $? "Could not find vlan 10's global options" 331 332 echo -n $goutput | 333 jq -e ".[].vlans[] | select(.vlan == 10 and \ 334 .mcast_startup_query_interval == 3125) " &>/dev/null 335 check_err $? "Wrong default mcast_startup_query_interval global vlan option value" 336 log_test "Vlan mcast_startup_query_interval global option default value" 337 338 RET=0 339 echo -n $goutput | 340 jq -e ".[].vlans[] | select(.vlan == 10 and \ 341 .mcast_startup_query_count == 2) " &>/dev/null 342 check_err $? "Wrong default mcast_startup_query_count global vlan option value" 343 log_test "Vlan mcast_startup_query_count global option default value" 344 345 RET=0 346 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_interval 100 347 check_err $? "Could not set mcast_startup_query_interval in vlan 10" 348 vlmc_check_query igmp 2 $swp1 2 3 349 check_err $? "Wrong number of tagged IGMPv2 general queries sent" 350 log_test "Vlan 10 mcast_startup_query_interval option changed to 100" 351 352 RET=0 353 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_count 3 354 check_err $? "Could not set mcast_startup_query_count in vlan 10" 355 vlmc_check_query igmp 2 $swp1 3 4 356 check_err $? "Wrong number of tagged IGMPv2 general queries sent" 357 log_test "Vlan 10 mcast_startup_query_count option changed to 3" 358 359 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_interval 3125 360 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_count 2 361} 362 363vlmc_membership_test() 364{ 365 RET=0 366 local goutput=`bridge -j vlan global show` 367 echo -n $goutput | 368 jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null 369 check_err $? "Could not find vlan 10's global options" 370 371 echo -n $goutput | 372 jq -e ".[].vlans[] | select(.vlan == 10 and \ 373 .mcast_membership_interval == 26000) " &>/dev/null 374 check_err $? "Wrong default mcast_membership_interval global vlan option value" 375 log_test "Vlan mcast_membership_interval global option default value" 376 377 RET=0 378 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_membership_interval 200 379 check_err $? "Could not set mcast_membership_interval in vlan 10" 380 log_test "Vlan 10 mcast_membership_interval option changed to 200" 381 382 RET=0 383 vlmc_v2join_test 1 384 log_test "Vlan 10 mcast_membership_interval mdb entry expire" 385 386 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_membership_interval 26000 387} 388 389vlmc_querier_intvl_test() 390{ 391 RET=0 392 local goutput=`bridge -j vlan global show` 393 echo -n $goutput | 394 jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null 395 check_err $? "Could not find vlan 10's global options" 396 397 echo -n $goutput | 398 jq -e ".[].vlans[] | select(.vlan == 10 and \ 399 .mcast_querier_interval == 25500) " &>/dev/null 400 check_err $? "Wrong default mcast_querier_interval global vlan option value" 401 log_test "Vlan mcast_querier_interval global option default value" 402 403 RET=0 404 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier_interval 100 405 check_err $? "Could not set mcast_querier_interval in vlan 10" 406 log_test "Vlan 10 mcast_querier_interval option changed to 100" 407 408 RET=0 409 ip link add dev br1 type bridge mcast_snooping 1 mcast_querier 1 vlan_filtering 1 \ 410 mcast_vlan_snooping 1 411 bridge vlan add vid 10 dev br1 self pvid untagged 412 ip link set dev $h1 master br1 413 ip link set dev br1 up 414 bridge vlan add vid 10 dev $h1 master 415 bridge vlan global set vid 10 dev br1 mcast_snooping 1 mcast_querier 1 416 sleep 2 417 ip link del dev br1 418 ip addr replace 2001:db8:1::1/64 dev $h1 419 vlmc_check_query igmp 2 $swp1 1 1 420 check_err $? "Wrong number of IGMPv2 general queries after querier interval" 421 log_test "Vlan 10 mcast_querier_interval expire after outside query" 422 423 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier_interval 25500 424} 425 426vlmc_query_intvl_test() 427{ 428 RET=0 429 local goutput=`bridge -j vlan global show` 430 echo -n $goutput | 431 jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null 432 check_err $? "Could not find vlan 10's global options" 433 434 echo -n $goutput | 435 jq -e ".[].vlans[] | select(.vlan == 10 and \ 436 .mcast_query_interval == 12500) " &>/dev/null 437 check_err $? "Wrong default mcast_query_interval global vlan option value" 438 log_test "Vlan mcast_query_interval global option default value" 439 440 RET=0 441 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_count 0 442 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_interval 200 443 check_err $? "Could not set mcast_query_interval in vlan 10" 444 # 1 is sent immediately, then 2 more in the next 5 seconds 445 vlmc_check_query igmp 2 $swp1 3 5 446 check_err $? "Wrong number of tagged IGMPv2 general queries sent" 447 log_test "Vlan 10 mcast_query_interval option changed to 200" 448 449 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_count 2 450 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_interval 12500 451} 452 453vlmc_query_response_intvl_test() 454{ 455 RET=0 456 local goutput=`bridge -j vlan global show` 457 echo -n $goutput | 458 jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null 459 check_err $? "Could not find vlan 10's global options" 460 461 echo -n $goutput | 462 jq -e ".[].vlans[] | select(.vlan == 10 and \ 463 .mcast_query_response_interval == 1000) " &>/dev/null 464 check_err $? "Wrong default mcast_query_response_interval global vlan option value" 465 log_test "Vlan mcast_query_response_interval global option default value" 466 467 RET=0 468 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_response_interval 200 469 check_err $? "Could not set mcast_query_response_interval in vlan 10" 470 log_test "Vlan 10 mcast_query_response_interval option changed to 200" 471 472 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_response_interval 1000 473} 474 475vlmc_router_port_test() 476{ 477 RET=0 478 local goutput=`bridge -j -d vlan show` 479 echo -n $goutput | 480 jq -e ".[] | select(.ifname == \"$swp1\" and \ 481 .vlans[].vlan == 10)" &>/dev/null 482 check_err $? "Could not find port vlan 10's options" 483 484 echo -n $goutput | 485 jq -e ".[] | select(.ifname == \"$swp1\" and \ 486 .vlans[].vlan == 10 and \ 487 .vlans[].mcast_router == 1)" &>/dev/null 488 check_err $? "Wrong default port mcast_router option value" 489 log_test "Port vlan 10 option mcast_router default value" 490 491 RET=0 492 bridge vlan set vid 10 dev $swp1 mcast_router 2 493 check_err $? "Could not set port vlan 10's mcast_router option" 494 log_test "Port vlan 10 mcast_router option changed to 2" 495 496 RET=0 497 tc filter add dev $swp1 egress pref 10 prot 802.1Q \ 498 flower vlan_id 10 vlan_ethtype ipv4 dst_ip 239.1.1.1 ip_proto udp action pass 499 tc filter add dev $swp2 egress pref 10 prot 802.1Q \ 500 flower vlan_id 10 vlan_ethtype ipv4 dst_ip 239.1.1.1 ip_proto udp action pass 501 bridge vlan set vid 10 dev $swp2 mcast_router 0 502 # we need to enable querier and disable query response interval to 503 # make sure packets are flooded only to router ports 504 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier 1 \ 505 mcast_query_response_interval 0 506 bridge vlan add vid 10 dev br0 self 507 sleep 1 508 mausezahn br0 -Q 10 -c 10 -p 128 -b 01:00:5e:01:01:01 -B 239.1.1.1 \ 509 -t udp "dp=1024" &>/dev/null 510 local swp1_tcstats=$(tc_rule_stats_get $swp1 10 egress) 511 if [[ $swp1_tcstats != 10 ]]; then 512 check_err 1 "Wrong number of vlan 10 multicast packets flooded" 513 fi 514 local swp2_tcstats=$(tc_rule_stats_get $swp2 10 egress) 515 check_err $swp2_tcstats "Vlan 10 multicast packets flooded to non-router port" 516 log_test "Flood unknown vlan multicast packets to router port only" 517 518 tc filter del dev $swp2 egress pref 10 519 tc filter del dev $swp1 egress pref 10 520 bridge vlan del vid 10 dev br0 self 521 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_response_interval 1000 522 bridge vlan set vid 10 dev $swp2 mcast_router 1 523 bridge vlan set vid 10 dev $swp1 mcast_router 1 524} 525 526vlmc_filtering_test() 527{ 528 RET=0 529 ip link set dev br0 type bridge vlan_filtering 0 530 ip -j -d link show dev br0 | \ 531 jq -e "select(.[0].linkinfo.info_data.mcast_vlan_snooping == 1)" &>/dev/null 532 check_fail $? "Vlan filtering is disabled but multicast vlan snooping is still enabled" 533 log_test "Disable multicast vlan snooping when vlan filtering is disabled" 534} 535 536trap cleanup EXIT 537 538setup_prepare 539setup_wait 540 541tests_run 542 543exit $EXIT_STATUS 544