2 # SPDX-License-Identifier: GPL-2.0
4 # This test is for checking the VXLAN vni filtering api and
6 # It simulates two hypervisors running two VMs each using four network
7 # six namespaces: two for the HVs, four for the VMs. Each VM is
8 # connected to a separate bridge. The VM's use overlapping vlans and
9 # hence the separate bridge domain. Each vxlan device is a collect
10 # metadata device with vni filtering and hence has the ability to
11 # terminate configured vni's only.
13 # +--------------------------------+ +------------------------------------+
14 # | vm-11 netns | | vm-21 netns |
16 # |+------------+ +-------------+ | |+-------------+ +----------------+ |
17 # ||veth-11.10 | |veth-11.20 | | ||veth-21.10 | | veth-21.20 | |
18 # ||10.0.10.11/24 |10.0.20.11/24| | ||10.0.10.21/24| | 10.0.20.21/24 | |
19 # |+------|-----+ +|------------+ | |+-----------|-+ +---|------------+ |
21 # | | | | | +------------+ |
22 # | +------------+ | | | veth-21 | |
23 # | | veth-11 | | | | | |
24 # | | | | | +-----|------+ |
25 # | +-----|------+ | | | |
27 # +------------|-------------------+ +---------------|--------------------+
28 # +------------|-----------------------------------------|-------------------+
29 # | +-----|------+ +-----|------+ |
30 # | |vethhv-11 | |vethhv-21 | |
31 # | +----|-------+ +-----|------+ |
32 # | +---|---+ +---|--+ |
34 # | +---|---+ +---|--+ |
35 # | +---|----+ +---|--+ |
36 # | | vxlan1| |vxlan2| |
37 # | +--|-----+ +--|---+ |
39 # | | +---------------------+ | |
41 # | +---------|172.16.0.1/24 -----------+ |
42 # | |2002:fee1::1/64 | |
43 # | hv-1 netns +--------|------------+ |
44 # +-----------------------------|--------------------------------------------+
46 # +-----------------------------|--------------------------------------------+
47 # | hv-2 netns +--------|-------------+ |
49 # | +------| 172.16.0.2/24 |---+ |
50 # | | | 2002:fee1::2/64 | | |
52 # | | +----------------------+ | - |
54 # | +-|-------+ +--------|-+ |
55 # | | vxlan1 | | vxlan2 | |
56 # | +----|----+ +---|------+ |
60 # | +-----|-------+ +----|-------+ |
61 # | | vethhv-12 | |vethhv-22 | |
62 # | +------|------+ +-------|----+ |
63 # +-----------------|----------------------------|---------------------------+
65 # +-----------------|-----------------+ +--------|---------------------------+
66 # | +-------|---+ | | +--|---------+ |
67 # | | veth-12 | | | |veth-22 | |
68 # | +-|--------|+ | | +--|--------|+ |
70 # |+----------|--+ +---|-----------+ | |+-------|-----+ +|---------------+ |
71 # ||veth-12.10 | |veth-12.20 | | ||veth-22.10 | |veth-22.20 | |
72 # ||10.0.10.12/24| |10.0.20.12/24 | | ||10.0.10.22/24| |10.0.20.22/24 | |
73 # |+-------------+ +---------------+ | |+-------------+ +----------------+ |
76 # | vm-12 netns | |vm-22 netns |
77 # +-----------------------------------+ +------------------------------------+
80 # This test tests the new vxlan vnifiltering api
83 # Kselftest framework requirement - SKIP code is 4.
86 # all tests in this script. Can be overridden with -t option
89 vxlan_vnifilter_datapath
90 vxlan_vnifilter_datapath_pervni
91 vxlan_vnifilter_datapath_mgroup
92 vxlan_vnifilter_datapath_mgroup_pervni
93 vxlan_vnifilter_metadata_and_traditional_mix
99 which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
107 if [ ${rc} -eq ${expected} ]; then
108 printf " TEST: %-60s [ OK ]\n" "${msg}"
109 nsuccess=$((nsuccess+1))
113 printf " TEST: %-60s [FAIL]\n" "${msg}"
114 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
116 echo "hit enter to continue, 'q' to quit"
118 [ "$a" = "q" ] && exit 1
122 if [ "${PAUSE}" = "yes" ]; then
124 echo "hit enter to continue, 'q' to quit"
126 [ "$a" = "q" ] && exit 1
134 local stderr="2>/dev/null"
136 if [ "$VERBOSE" = "1" ]; then
137 printf "COMMAND: $cmd\n"
141 out=$(eval $cmd $stderr)
143 if [ "$VERBOSE" = "1" -a -n "$out" ]; then
150 check_hv_connectivity() {
151 ip netns exec hv-1 ping -c 1 -W 1 $1 &>/dev/null
153 ip netns exec hv-1 ping -c 1 -W 1 $2 &>/dev/null
158 check_vm_connectivity() {
159 run_cmd "ip netns exec vm-11 ping -c 1 -W 1 10.0.10.12"
160 log_test $? 0 "VM connectivity over $1 (ipv4 default rdst)"
162 run_cmd "ip netns exec vm-21 ping -c 1 -W 1 10.0.10.22"
163 log_test $? 0 "VM connectivity over $1 (ipv6 default rdst)"
167 ip link del veth-hv-1 2>/dev/null || true
168 ip link del vethhv-11 vethhv-12 vethhv-21 vethhv-22 2>/dev/null || true
170 for ns in hv-1 hv-2 vm-11 vm-21 vm-12 vm-22 vm-31 vm-32; do
171 ip netns del $ns 2>/dev/null || true
177 setup-hv-networking() {
185 ip link set veth-hv-$hv netns hv-$hv
186 ip -netns hv-$hv link set veth-hv-$hv name veth0
187 ip -netns hv-$hv addr add $local1/$mask1 dev veth0
188 ip -netns hv-$hv addr add $local2/$mask2 dev veth0
189 ip -netns hv-$hv link set veth0 up
192 # Setups a "VM" simulated by a netns an a veth pair
193 # example: setup-vm <hvid> <vmid> <brid> <VATTRS> <mcast_for_bum>
194 # VATTRS = comma separated "<vlan>-<v[46]>-<localip>-<remoteip>-<VTYPE>-<vxlandstport>"
195 # VTYPE = vxlan device type. "default = traditional device, metadata = metadata device
196 # vnifilter = vnifiltering device,
197 # vnifilterg = vnifiltering device with per vni group/remote"
200 # 10-v4-172.16.0.1-239.1.1.100-vnifilterg,20-v4-172.16.0.1-239.1.1.100-vnifilterg 1
211 ip -netns hv-$hvid link add br$brid type bridge vlan_filtering 1 vlan_default_pvid 0 \
213 ip -netns hv-$hvid link set br$brid up
215 # create vm namespace and interfaces and connect to hypervisor
217 ip netns add vm-$vmid
218 hvvethif="vethhv-$vmid"
219 vmvethif="veth-$vmid"
220 ip link add $hvvethif type veth peer name $vmvethif
221 ip link set $hvvethif netns hv-$hvid
222 ip link set $vmvethif netns vm-$vmid
223 ip -netns hv-$hvid link set $hvvethif up
224 ip -netns vm-$vmid link set $vmvethif up
225 ip -netns hv-$hvid link set $hvvethif master br$brid
227 # configure VM vlan/vni filtering on hypervisor
228 for vmap in $(echo $vattrs | cut -d "," -f1- --output-delimiter=' ')
230 local vid=$(echo $vmap | awk -F'-' '{print ($1)}')
231 local family=$(echo $vmap | awk -F'-' '{print ($2)}')
232 local localip=$(echo $vmap | awk -F'-' '{print ($3)}')
233 local group=$(echo $vmap | awk -F'-' '{print ($4)}')
234 local vtype=$(echo $vmap | awk -F'-' '{print ($5)}')
235 local port=$(echo $vmap | awk -F'-' '{print ($6)}')
237 ip -netns vm-$vmid link add name $vmvethif.$vid link $vmvethif type vlan id $vid
238 ip -netns vm-$vmid addr add 10.0.$vid.$vmid/24 dev $vmvethif.$vid
239 ip -netns vm-$vmid link set $vmvethif.$vid up
242 vxlandev="vxlan$brid"
245 if [[ -n $vtype && $vtype == "metadata" ]]; then
246 vxlandevflags="$vxlandevflags external"
247 elif [[ -n $vtype && $vtype == "vnifilter" || $vtype == "vnifilterg" ]]; then
248 vxlandevflags="$vxlandevflags external vnifilter"
251 vxlandevflags="$vxlandevflags id $tid"
255 if [[ -n $vtype && $vtype != "vnifilterg" ]]; then
256 if [[ -n "$group" && "$group" != "null" ]]; then
257 if [ $mcast -eq 1 ]; then
258 vxlandevflags="$vxlandevflags group $group"
260 vxlandevflags="$vxlandevflags remote $group"
265 if [[ -n "$port" && "$port" != "default" ]]; then
266 vxlandevflags="$vxlandevflags dstport $port"
269 # create vxlan device
270 if [ "$vxlandev" != "$lastvxlandev" ]; then
271 ip -netns hv-$hvid link add $vxlandev type vxlan local $localip $vxlandevflags dev veth0 2>/dev/null
272 ip -netns hv-$hvid link set $vxlandev master br$brid
273 ip -netns hv-$hvid link set $vxlandev up
274 lastvxlandev=$vxlandev
278 bridge -netns hv-$hvid vlan add vid $vid dev $hvvethif
279 bridge -netns hv-$hvid vlan add vid $vid pvid dev $vxlandev
281 # Add bridge vni filter for tx
282 if [[ -n $vtype && $vtype == "metadata" || $vtype == "vnifilter" || $vtype == "vnifilterg" ]]; then
283 bridge -netns hv-$hvid link set dev $vxlandev vlan_tunnel on
284 bridge -netns hv-$hvid vlan add dev $vxlandev vid $vid tunnel_info id $tid
287 if [[ -n $vtype && $vtype == "metadata" ]]; then
288 bridge -netns hv-$hvid fdb add 00:00:00:00:00:00 dev $vxlandev \
289 src_vni $tid vni $tid dst $group self
290 elif [[ -n $vtype && $vtype == "vnifilter" ]]; then
291 # Add per vni rx filter with 'bridge vni' api
292 bridge -netns hv-$hvid vni add dev $vxlandev vni $tid
293 elif [[ -n $vtype && $vtype == "vnifilterg" ]]; then
294 # Add per vni group config with 'bridge vni' api
295 if [ -n "$group" ]; then
296 if [ "$family" == "v4" ]; then
297 if [ $mcast -eq 1 ]; then
298 bridge -netns hv-$hvid vni add dev $vxlandev vni $tid group $group
300 bridge -netns hv-$hvid vni add dev $vxlandev vni $tid remote $group
303 if [ $mcast -eq 1 ]; then
304 bridge -netns hv-$hvid vni add dev $vxlandev vni $tid group6 $group
306 bridge -netns hv-$hvid vni add dev $vxlandev vni $tid remote6 $group
314 setup_vnifilter_api()
316 ip link add veth-host type veth peer name veth-testns
318 ip link set veth-testns netns testns
321 cleanup_vnifilter_api()
323 ip link del veth-host 2>/dev/null || true
324 ip netns del testns 2>/dev/null || true
327 # tests vxlan filtering api
328 vxlan_vnifilter_api()
330 hv1addr1="172.16.0.1"
331 hv2addr1="172.16.0.2"
332 hv1addr2="2002:fee1::1"
333 hv2addr2="2002:fee1::2"
337 cleanup_vnifilter_api &>/dev/null
341 # create non-vnifiltering traditional vni device
342 run_cmd "ip -netns testns link add vxlan100 type vxlan id 100 local $localip dev veth-testns dstport 4789"
343 log_test $? 0 "Create traditional vxlan device"
345 # create vni filtering device
346 run_cmd "ip -netns testns link add vxlan-ext1 type vxlan vnifilter local $localip dev veth-testns dstport 4789"
347 log_test $? 1 "Cannot create vnifilter device without external flag"
349 run_cmd "ip -netns testns link add vxlan-ext1 type vxlan external vnifilter local $localip dev veth-testns dstport 4789"
350 log_test $? 0 "Creating external vxlan device with vnifilter flag"
352 run_cmd "bridge -netns testns vni add dev vxlan-ext1 vni 100"
353 log_test $? 0 "Cannot set in-use vni id on vnifiltering device"
355 run_cmd "bridge -netns testns vni add dev vxlan-ext1 vni 200"
356 log_test $? 0 "Set new vni id on vnifiltering device"
358 run_cmd "ip -netns testns link add vxlan-ext2 type vxlan external vnifilter local $localip dev veth-testns dstport 4789"
359 log_test $? 0 "Create second external vxlan device with vnifilter flag"
361 run_cmd "bridge -netns testns vni add dev vxlan-ext2 vni 200"
362 log_test $? 255 "Cannot set in-use vni id on vnifiltering device"
364 run_cmd "bridge -netns testns vni add dev vxlan-ext2 vni 300"
365 log_test $? 0 "Set new vni id on vnifiltering device"
367 # check in bridge vni show
368 run_cmd "bridge -netns testns vni add dev vxlan-ext2 vni 300"
369 log_test $? 0 "Update vni id on vnifiltering device"
371 run_cmd "bridge -netns testns vni add dev vxlan-ext2 vni 400"
372 log_test $? 0 "Add new vni id on vnifiltering device"
374 # add multicast group per vni
375 run_cmd "bridge -netns testns vni add dev vxlan-ext1 vni 200 group $group"
376 log_test $? 0 "Set multicast group on existing vni"
378 # add multicast group per vni
379 run_cmd "bridge -netns testns vni add dev vxlan-ext2 vni 300 group $group"
380 log_test $? 0 "Set multicast group on existing vni"
382 # set vnifilter on an existing external vxlan device
383 run_cmd "ip -netns testns link set dev vxlan-ext1 type vxlan external vnifilter"
384 log_test $? 2 "Cannot set vnifilter flag on a device"
386 # change vxlan vnifilter flag
387 run_cmd "ip -netns testns link set dev vxlan-ext1 type vxlan external novnifilter"
388 log_test $? 2 "Cannot unset vnifilter flag on a device"
391 # Sanity test vnifilter datapath
392 # vnifilter vnis inherit BUM group from
394 vxlan_vnifilter_datapath()
396 hv1addr1="172.16.0.1"
397 hv2addr1="172.16.0.2"
398 hv1addr2="2002:fee1::1"
399 hv2addr2="2002:fee1::2"
401 ip link add veth-hv-1 type veth peer name veth-hv-2
402 setup-hv-networking 1 $hv1addr1 24 $hv1addr2 64 $hv2addr1 $hv2addr2
403 setup-hv-networking 2 $hv2addr1 24 $hv2addr2 64 $hv1addr1 $hv1addr2
405 check_hv_connectivity hv2addr1 hv2addr2
407 setup-vm 1 11 1 10-v4-$hv1addr1-$hv2addr1-vnifilter,20-v4-$hv1addr1-$hv2addr1-vnifilter 0
408 setup-vm 1 21 2 10-v6-$hv1addr2-$hv2addr2-vnifilter,20-v6-$hv1addr2-$hv2addr2-vnifilter 0
410 setup-vm 2 12 1 10-v4-$hv2addr1-$hv1addr1-vnifilter,20-v4-$hv2addr1-$hv1addr1-vnifilter 0
411 setup-vm 2 22 2 10-v6-$hv2addr2-$hv1addr2-vnifilter,20-v6-$hv2addr2-$hv1addr2-vnifilter 0
413 check_vm_connectivity "vnifiltering vxlan"
416 # Sanity test vnifilter datapath
417 # with vnifilter per vni configured BUM
419 vxlan_vnifilter_datapath_pervni()
421 hv1addr1="172.16.0.1"
422 hv2addr1="172.16.0.2"
423 hv1addr2="2002:fee1::1"
424 hv2addr2="2002:fee1::2"
426 ip link add veth-hv-1 type veth peer name veth-hv-2
427 setup-hv-networking 1 $hv1addr1 24 $hv1addr2 64
428 setup-hv-networking 2 $hv2addr1 24 $hv2addr2 64
430 check_hv_connectivity hv2addr1 hv2addr2
432 setup-vm 1 11 1 10-v4-$hv1addr1-$hv2addr1-vnifilterg,20-v4-$hv1addr1-$hv2addr1-vnifilterg 0
433 setup-vm 1 21 2 10-v6-$hv1addr2-$hv2addr2-vnifilterg,20-v6-$hv1addr2-$hv2addr2-vnifilterg 0
435 setup-vm 2 12 1 10-v4-$hv2addr1-$hv1addr1-vnifilterg,20-v4-$hv2addr1-$hv1addr1-vnifilterg 0
436 setup-vm 2 22 2 10-v6-$hv2addr2-$hv1addr2-vnifilterg,20-v6-$hv2addr2-$hv1addr2-vnifilterg 0
438 check_vm_connectivity "vnifiltering vxlan pervni remote"
442 vxlan_vnifilter_datapath_mgroup()
444 hv1addr1="172.16.0.1"
445 hv2addr1="172.16.0.2"
446 hv1addr2="2002:fee1::1"
447 hv2addr2="2002:fee1::2"
451 ip link add veth-hv-1 type veth peer name veth-hv-2
452 setup-hv-networking 1 $hv1addr1 24 $hv1addr2 64
453 setup-hv-networking 2 $hv2addr1 24 $hv2addr2 64
455 check_hv_connectivity hv2addr1 hv2addr2
457 setup-vm 1 11 1 10-v4-$hv1addr1-$group-vnifilter,20-v4-$hv1addr1-$group-vnifilter 1
458 setup-vm 1 21 2 "10-v6-$hv1addr2-$group6-vnifilter,20-v6-$hv1addr2-$group6-vnifilter" 1
460 setup-vm 2 12 1 10-v4-$hv2addr1-$group-vnifilter,20-v4-$hv2addr1-$group-vnifilter 1
461 setup-vm 2 22 2 10-v6-$hv2addr2-$group6-vnifilter,20-v6-$hv2addr2-$group6-vnifilter 1
463 check_vm_connectivity "vnifiltering vxlan mgroup"
466 vxlan_vnifilter_datapath_mgroup_pervni()
468 hv1addr1="172.16.0.1"
469 hv2addr1="172.16.0.2"
470 hv1addr2="2002:fee1::1"
471 hv2addr2="2002:fee1::2"
475 ip link add veth-hv-1 type veth peer name veth-hv-2
476 setup-hv-networking 1 $hv1addr1 24 $hv1addr2 64
477 setup-hv-networking 2 $hv2addr1 24 $hv2addr2 64
479 check_hv_connectivity hv2addr1 hv2addr2
481 setup-vm 1 11 1 10-v4-$hv1addr1-$group-vnifilterg,20-v4-$hv1addr1-$group-vnifilterg 1
482 setup-vm 1 21 2 10-v6-$hv1addr2-$group6-vnifilterg,20-v6-$hv1addr2-$group6-vnifilterg 1
484 setup-vm 2 12 1 10-v4-$hv2addr1-$group-vnifilterg,20-v4-$hv2addr1-$group-vnifilterg 1
485 setup-vm 2 22 2 10-v6-$hv2addr2-$group6-vnifilterg,20-v6-$hv2addr2-$group6-vnifilterg 1
487 check_vm_connectivity "vnifiltering vxlan pervni mgroup"
490 vxlan_vnifilter_metadata_and_traditional_mix()
492 hv1addr1="172.16.0.1"
493 hv2addr1="172.16.0.2"
494 hv1addr2="2002:fee1::1"
495 hv2addr2="2002:fee1::2"
497 ip link add veth-hv-1 type veth peer name veth-hv-2
498 setup-hv-networking 1 $hv1addr1 24 $hv1addr2 64
499 setup-hv-networking 2 $hv2addr1 24 $hv2addr2 64
501 check_hv_connectivity hv2addr1 hv2addr2
503 setup-vm 1 11 1 10-v4-$hv1addr1-$hv2addr1-vnifilter,20-v4-$hv1addr1-$hv2addr1-vnifilter 0
504 setup-vm 1 21 2 10-v6-$hv1addr2-$hv2addr2-vnifilter,20-v6-$hv1addr2-$hv2addr2-vnifilter 0
505 setup-vm 1 31 3 30-v4-$hv1addr1-$hv2addr1-default-4790,40-v6-$hv1addr2-$hv2addr2-default-4790,50-v4-$hv1addr1-$hv2addr1-metadata-4791 0
508 setup-vm 2 12 1 10-v4-$hv2addr1-$hv1addr1-vnifilter,20-v4-$hv2addr1-$hv1addr1-vnifilter 0
509 setup-vm 2 22 2 10-v6-$hv2addr2-$hv1addr2-vnifilter,20-v6-$hv2addr2-$hv1addr2-vnifilter 0
510 setup-vm 2 32 3 30-v4-$hv2addr1-$hv1addr1-default-4790,40-v6-$hv2addr2-$hv1addr2-default-4790,50-v4-$hv2addr1-$hv1addr1-metadata-4791 0
512 check_vm_connectivity "vnifiltering vxlan pervni remote mix"
514 # check VM connectivity over traditional/non-vxlan filtering vxlan devices
515 run_cmd "ip netns exec vm-31 ping -c 1 -W 1 10.0.30.32"
516 log_test $? 0 "VM connectivity over traditional vxlan (ipv4 default rdst)"
518 run_cmd "ip netns exec vm-31 ping -c 1 -W 1 10.0.40.32"
519 log_test $? 0 "VM connectivity over traditional vxlan (ipv6 default rdst)"
521 run_cmd "ip netns exec vm-31 ping -c 1 -W 1 10.0.50.32"
522 log_test $? 0 "VM connectivity over metadata nonfiltering vxlan (ipv4 default rdst)"
525 while getopts :t:pP46hv o
529 p) PAUSE_ON_FAIL=yes;;
531 v) VERBOSE=$(($VERBOSE + 1));;
537 # make sure we don't pause twice
538 [ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
540 if [ "$(id -u)" -ne 0 ];then
541 echo "SKIP: Need root privileges"
545 if [ ! -x "$(command -v ip)" ]; then
546 echo "SKIP: Could not run test without ip tool"
550 ip link help vxlan 2>&1 | grep -q "vnifilter"
551 if [ $? -ne 0 ]; then
552 echo "SKIP: iproute2 too old, missing vxlan dev vnifilter setting"
557 bridge vni help 2>&1 | grep -q "Usage: bridge vni"
558 if [ $? -ne 0 ]; then
559 echo "SKIP: iproute2 bridge lacks vxlan vnifiltering support"
569 none) setup; exit 0;;
574 if [ "$TESTS" != "none" ]; then
575 printf "\nTests passed: %3d\n" ${nsuccess}
576 printf "Tests failed: %3d\n" ${nfail}