1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# Test VxLAN flooding. The device stores flood records in a singly linked list 5# where each record stores up to three IPv4 addresses of remote VTEPs. The test 6# verifies that packets are correctly flooded in various cases such as deletion 7# of a record in the middle of the list. 8# 9# +--------------------+ 10# | H1 (vrf) | 11# | + $h1 | 12# | | 203.0.113.1/24| 13# +----|---------------+ 14# | 15# +----|----------------------------------------------------------------------+ 16# | SW | | 17# | +--|--------------------------------------------------------------------+ | 18# | | + $swp1 BR0 (802.1d) | | 19# | | | | 20# | | + vxlan0 (vxlan) | | 21# | | local 198.51.100.1 | | 22# | | remote 198.51.100.{2..13} | | 23# | | id 10 dstport 4789 | | 24# | +-----------------------------------------------------------------------+ | 25# | | 26# | 198.51.100.0/24 via 192.0.2.2 | 27# | | 28# | + $rp1 | 29# | | 192.0.2.1/24 | 30# +----|----------------------------------------------------------------------+ 31# | 32# +----|--------------------------------------------------------+ 33# | | R2 (vrf) | 34# | + $rp2 | 35# | 192.0.2.2/24 | 36# | | 37# +-------------------------------------------------------------+ 38 39lib_dir=$(dirname $0)/../../../net/forwarding 40 41ALL_TESTS="flooding_test" 42NUM_NETIFS=4 43source $lib_dir/tc_common.sh 44source $lib_dir/lib.sh 45 46h1_create() 47{ 48 simple_if_init $h1 203.0.113.1/24 49} 50 51h1_destroy() 52{ 53 simple_if_fini $h1 203.0.113.1/24 54} 55 56switch_create() 57{ 58 # Make sure the bridge uses the MAC address of the local port and 59 # not that of the VxLAN's device 60 ip link add dev br0 type bridge mcast_snooping 0 61 ip link set dev br0 address $(mac_get $swp1) 62 63 ip link add name vxlan0 type vxlan id 10 nolearning noudpcsum \ 64 ttl 20 tos inherit local 198.51.100.1 dstport 4789 65 66 ip address add 198.51.100.1/32 dev lo 67 68 ip link set dev $swp1 master br0 69 ip link set dev vxlan0 master br0 70 71 ip link set dev br0 up 72 ip link set dev $swp1 up 73 ip link set dev vxlan0 up 74} 75 76switch_destroy() 77{ 78 ip link set dev vxlan0 down 79 ip link set dev $swp1 down 80 ip link set dev br0 down 81 82 ip link set dev vxlan0 nomaster 83 ip link set dev $swp1 nomaster 84 85 ip address del 198.51.100.1/32 dev lo 86 87 ip link del dev vxlan0 88 89 ip link del dev br0 90} 91 92router1_create() 93{ 94 # This router is in the default VRF, where the VxLAN device is 95 # performing the L3 lookup 96 ip link set dev $rp1 up 97 ip address add 192.0.2.1/24 dev $rp1 98 ip route add 198.51.100.0/24 via 192.0.2.2 99} 100 101router1_destroy() 102{ 103 ip route del 198.51.100.0/24 via 192.0.2.2 104 ip address del 192.0.2.1/24 dev $rp1 105 ip link set dev $rp1 down 106} 107 108router2_create() 109{ 110 # This router is not in the default VRF, so use simple_if_init() 111 simple_if_init $rp2 192.0.2.2/24 112} 113 114router2_destroy() 115{ 116 simple_if_fini $rp2 192.0.2.2/24 117} 118 119setup_prepare() 120{ 121 h1=${NETIFS[p1]} 122 swp1=${NETIFS[p2]} 123 124 rp1=${NETIFS[p3]} 125 rp2=${NETIFS[p4]} 126 127 vrf_prepare 128 129 h1_create 130 131 switch_create 132 133 router1_create 134 router2_create 135 136 forwarding_enable 137} 138 139cleanup() 140{ 141 pre_cleanup 142 143 forwarding_restore 144 145 router2_destroy 146 router1_destroy 147 148 switch_destroy 149 150 h1_destroy 151 152 vrf_cleanup 153} 154 155flooding_remotes_add() 156{ 157 local num_remotes=$1 158 local lsb 159 local i 160 161 for i in $(eval echo {1..$num_remotes}); do 162 lsb=$((i + 1)) 163 164 bridge fdb append 00:00:00:00:00:00 dev vxlan0 self \ 165 dst 198.51.100.$lsb 166 done 167} 168 169flooding_filters_add() 170{ 171 local num_remotes=$1 172 local lsb 173 local i 174 175 tc qdisc add dev $rp2 clsact 176 177 for i in $(eval echo {1..$num_remotes}); do 178 lsb=$((i + 1)) 179 180 tc filter add dev $rp2 ingress protocol ip pref $i handle $i \ 181 flower ip_proto udp dst_ip 198.51.100.$lsb \ 182 dst_port 4789 skip_sw action drop 183 done 184} 185 186flooding_filters_del() 187{ 188 local num_remotes=$1 189 local i 190 191 for i in $(eval echo {1..$num_remotes}); do 192 tc filter del dev $rp2 ingress protocol ip pref $i \ 193 handle $i flower 194 done 195 196 tc qdisc del dev $rp2 clsact 197} 198 199flooding_check_packets() 200{ 201 local packets=("$@") 202 local num_remotes=${#packets[@]} 203 local i 204 205 for i in $(eval echo {1..$num_remotes}); do 206 tc_check_packets "dev $rp2 ingress" $i ${packets[i - 1]} 207 check_err $? "remote $i - did not get expected number of packets" 208 done 209} 210 211flooding_test() 212{ 213 # Use 12 remote VTEPs that will be stored in 4 records. The array 214 # 'packets' will store how many packets are expected to be received 215 # by each remote VTEP at each stage of the test 216 declare -a packets=(1 1 1 1 1 1 1 1 1 1 1 1) 217 local num_remotes=12 218 219 RET=0 220 221 # Add FDB entries for remote VTEPs and corresponding tc filters on the 222 # ingress of the nexthop router. These filters will count how many 223 # packets were flooded to each remote VTEP 224 flooding_remotes_add $num_remotes 225 flooding_filters_add $num_remotes 226 227 # Send one packet and make sure it is flooded to all the remote VTEPs 228 $MZ $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1 229 flooding_check_packets "${packets[@]}" 230 log_test "flood after 1 packet" 231 232 # Delete the third record which corresponds to VTEPs with LSB 8..10 233 # and check that packet is flooded correctly when we remove a record 234 # from the middle of the list 235 RET=0 236 237 packets=(2 2 2 2 2 2 1 1 1 2 2 2) 238 bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 198.51.100.8 239 bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 198.51.100.9 240 bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 198.51.100.10 241 242 $MZ $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1 243 flooding_check_packets "${packets[@]}" 244 log_test "flood after 2 packets" 245 246 # Delete the first record and make sure the packet is flooded correctly 247 RET=0 248 249 packets=(2 2 2 3 3 3 1 1 1 3 3 3) 250 bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 198.51.100.2 251 bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 198.51.100.3 252 bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 198.51.100.4 253 254 $MZ $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1 255 flooding_check_packets "${packets[@]}" 256 log_test "flood after 3 packets" 257 258 # Delete the last record and make sure the packet is flooded correctly 259 RET=0 260 261 packets=(2 2 2 4 4 4 1 1 1 3 3 3) 262 bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 198.51.100.11 263 bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 198.51.100.12 264 bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 198.51.100.13 265 266 $MZ $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1 267 flooding_check_packets "${packets[@]}" 268 log_test "flood after 4 packets" 269 270 # Delete the last record, one entry at a time and make sure single 271 # entries are correctly removed 272 RET=0 273 274 packets=(2 2 2 4 5 5 1 1 1 3 3 3) 275 bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 198.51.100.5 276 277 $MZ $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1 278 flooding_check_packets "${packets[@]}" 279 log_test "flood after 5 packets" 280 281 RET=0 282 283 packets=(2 2 2 4 5 6 1 1 1 3 3 3) 284 bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 198.51.100.6 285 286 $MZ $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1 287 flooding_check_packets "${packets[@]}" 288 log_test "flood after 6 packets" 289 290 RET=0 291 292 packets=(2 2 2 4 5 6 1 1 1 3 3 3) 293 bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 198.51.100.7 294 295 $MZ $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1 296 flooding_check_packets "${packets[@]}" 297 log_test "flood after 7 packets" 298 299 flooding_filters_del $num_remotes 300} 301 302trap cleanup EXIT 303 304setup_prepare 305setup_wait 306 307tests_run 308 309exit $EXIT_STATUS 310