646 lines · bash
1#!/bin/bash2# SPDX-License-Identifier: GPL-2.03 4# End-to-end eBPF tunnel test suite5# The script tests BPF network tunnel implementation.6#7# Topology:8# ---------9# root namespace | at_ns0 namespace10# |11# ----------- | -----------12# | tnl dev | | | tnl dev | (overlay network)13# ----------- | -----------14# metadata-mode | native-mode15# with bpf |16# |17# ---------- | ----------18# | veth1 | --------- | veth0 | (underlay network)19# ---------- peer ----------20#21#22# Device Configuration23# --------------------24# Root namespace with metadata-mode tunnel + BPF25# Device names and addresses:26# veth1 IP: 172.16.1.200, IPv6: 00::22 (underlay)27# tunnel dev <type>11, ex: gre11, IPv4: 10.1.1.200, IPv6: 1::22 (overlay)28#29# Namespace at_ns0 with native tunnel30# Device names and addresses:31# veth0 IPv4: 172.16.1.100, IPv6: 00::11 (underlay)32# tunnel dev <type>00, ex: gre00, IPv4: 10.1.1.100, IPv6: 1::11 (overlay)33#34#35# End-to-end ping packet flow36# ---------------------------37# Most of the tests start by namespace creation, device configuration,38# then ping the underlay and overlay network. When doing 'ping 10.1.1.100'39# from root namespace, the following operations happen:40# 1) Route lookup shows 10.1.1.100/24 belongs to tnl dev, fwd to tnl dev.41# 2) Tnl device's egress BPF program is triggered and set the tunnel metadata,42# with remote_ip=172.16.1.100 and others.43# 3) Outer tunnel header is prepended and route the packet to veth1's egress44# 4) veth0's ingress queue receive the tunneled packet at namespace at_ns045# 5) Tunnel protocol handler, ex: vxlan_rcv, decap the packet46# 6) Forward the packet to the overlay tnl dev47 48BPF_FILE="test_tunnel_kern.bpf.o"49BPF_PIN_TUNNEL_DIR="/sys/fs/bpf/tc/tunnel"50PING_ARG="-c 3 -w 10 -q"51ret=052GREEN='\033[0;92m'53RED='\033[0;31m'54NC='\033[0m' # No Color55 56config_device()57{58 ip netns add at_ns059 ip link add veth0 type veth peer name veth160 ip link set veth0 netns at_ns061 ip netns exec at_ns0 ip addr add 172.16.1.100/24 dev veth062 ip netns exec at_ns0 ip link set dev veth0 up63 ip link set dev veth1 up mtu 150064 ip addr add dev veth1 172.16.1.200/2465}66 67add_gre_tunnel()68{69 tun_key=70 if [ -n "$1" ]; then71 tun_key="key $1"72 fi73 74 # at_ns0 namespace75 ip netns exec at_ns0 \76 ip link add dev $DEV_NS type $TYPE seq $tun_key \77 local 172.16.1.100 remote 172.16.1.20078 ip netns exec at_ns0 ip link set dev $DEV_NS up79 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/2480 81 # root namespace82 ip link add dev $DEV type $TYPE $tun_key external83 ip link set dev $DEV up84 ip addr add dev $DEV 10.1.1.200/2485}86 87add_ip6gretap_tunnel()88{89 90 # assign ipv6 address91 ip netns exec at_ns0 ip addr add ::11/96 dev veth092 ip netns exec at_ns0 ip link set dev veth0 up93 ip addr add dev veth1 ::22/9694 ip link set dev veth1 up95 96 # at_ns0 namespace97 ip netns exec at_ns0 \98 ip link add dev $DEV_NS type $TYPE seq flowlabel 0xbcdef key 2 \99 local ::11 remote ::22100 101 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24102 ip netns exec at_ns0 ip addr add dev $DEV_NS fc80::100/96103 ip netns exec at_ns0 ip link set dev $DEV_NS up104 105 # root namespace106 ip link add dev $DEV type $TYPE external107 ip addr add dev $DEV 10.1.1.200/24108 ip addr add dev $DEV fc80::200/24109 ip link set dev $DEV up110}111 112add_erspan_tunnel()113{114 # at_ns0 namespace115 if [ "$1" == "v1" ]; then116 ip netns exec at_ns0 \117 ip link add dev $DEV_NS type $TYPE seq key 2 \118 local 172.16.1.100 remote 172.16.1.200 \119 erspan_ver 1 erspan 123120 else121 ip netns exec at_ns0 \122 ip link add dev $DEV_NS type $TYPE seq key 2 \123 local 172.16.1.100 remote 172.16.1.200 \124 erspan_ver 2 erspan_dir egress erspan_hwid 3125 fi126 ip netns exec at_ns0 ip link set dev $DEV_NS up127 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24128 129 # root namespace130 ip link add dev $DEV type $TYPE external131 ip link set dev $DEV up132 ip addr add dev $DEV 10.1.1.200/24133}134 135add_ip6erspan_tunnel()136{137 138 # assign ipv6 address139 ip netns exec at_ns0 ip addr add ::11/96 dev veth0140 ip netns exec at_ns0 ip link set dev veth0 up141 ip addr add dev veth1 ::22/96142 ip link set dev veth1 up143 144 # at_ns0 namespace145 if [ "$1" == "v1" ]; then146 ip netns exec at_ns0 \147 ip link add dev $DEV_NS type $TYPE seq key 2 \148 local ::11 remote ::22 \149 erspan_ver 1 erspan 123150 else151 ip netns exec at_ns0 \152 ip link add dev $DEV_NS type $TYPE seq key 2 \153 local ::11 remote ::22 \154 erspan_ver 2 erspan_dir egress erspan_hwid 7155 fi156 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24157 ip netns exec at_ns0 ip link set dev $DEV_NS up158 159 # root namespace160 ip link add dev $DEV type $TYPE external161 ip addr add dev $DEV 10.1.1.200/24162 ip link set dev $DEV up163}164 165add_geneve_tunnel()166{167 # at_ns0 namespace168 ip netns exec at_ns0 \169 ip link add dev $DEV_NS type $TYPE \170 id 2 dstport 6081 remote 172.16.1.200171 ip netns exec at_ns0 ip link set dev $DEV_NS up172 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24173 174 # root namespace175 ip link add dev $DEV type $TYPE dstport 6081 external176 ip link set dev $DEV up177 ip addr add dev $DEV 10.1.1.200/24178}179 180add_ip6geneve_tunnel()181{182 ip netns exec at_ns0 ip addr add ::11/96 dev veth0183 ip netns exec at_ns0 ip link set dev veth0 up184 ip addr add dev veth1 ::22/96185 ip link set dev veth1 up186 187 # at_ns0 namespace188 ip netns exec at_ns0 \189 ip link add dev $DEV_NS type $TYPE id 22 \190 remote ::22 # geneve has no local option191 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24192 ip netns exec at_ns0 ip link set dev $DEV_NS up193 194 # root namespace195 ip link add dev $DEV type $TYPE external196 ip addr add dev $DEV 10.1.1.200/24197 ip link set dev $DEV up198}199 200add_ipip_tunnel()201{202 # at_ns0 namespace203 ip netns exec at_ns0 \204 ip link add dev $DEV_NS type $TYPE \205 local 172.16.1.100 remote 172.16.1.200206 ip netns exec at_ns0 ip link set dev $DEV_NS up207 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24208 209 # root namespace210 ip link add dev $DEV type $TYPE external211 ip link set dev $DEV up212 ip addr add dev $DEV 10.1.1.200/24213}214 215add_ip6tnl_tunnel()216{217 ip netns exec at_ns0 ip addr add ::11/96 dev veth0218 ip netns exec at_ns0 ip link set dev veth0 up219 ip addr add dev veth1 ::22/96220 ip link set dev veth1 up221 222 # at_ns0 namespace223 ip netns exec at_ns0 \224 ip link add dev $DEV_NS type $TYPE \225 local ::11 remote ::22226 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24227 ip netns exec at_ns0 ip addr add dev $DEV_NS 1::11/96228 ip netns exec at_ns0 ip link set dev $DEV_NS up229 230 # root namespace231 ip link add dev $DEV type $TYPE external232 ip addr add dev $DEV 10.1.1.200/24233 ip addr add dev $DEV 1::22/96234 ip link set dev $DEV up235}236 237test_gre()238{239 TYPE=gretap240 DEV_NS=gretap00241 DEV=gretap11242 ret=0243 244 check $TYPE245 config_device246 add_gre_tunnel 2247 attach_bpf $DEV gre_set_tunnel gre_get_tunnel248 ping $PING_ARG 10.1.1.100249 check_err $?250 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200251 check_err $?252 cleanup253 254 if [ $ret -ne 0 ]; then255 echo -e ${RED}"FAIL: $TYPE"${NC}256 return 1257 fi258 echo -e ${GREEN}"PASS: $TYPE"${NC}259}260 261test_gre_no_tunnel_key()262{263 TYPE=gre264 DEV_NS=gre00265 DEV=gre11266 ret=0267 268 check $TYPE269 config_device270 add_gre_tunnel271 attach_bpf $DEV gre_set_tunnel_no_key gre_get_tunnel272 ping $PING_ARG 10.1.1.100273 check_err $?274 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200275 check_err $?276 cleanup277 278 if [ $ret -ne 0 ]; then279 echo -e ${RED}"FAIL: $TYPE"${NC}280 return 1281 fi282 echo -e ${GREEN}"PASS: $TYPE"${NC}283}284 285test_ip6gre()286{287 TYPE=ip6gre288 DEV_NS=ip6gre00289 DEV=ip6gre11290 ret=0291 292 check $TYPE293 config_device294 # reuse the ip6gretap function295 add_ip6gretap_tunnel296 attach_bpf $DEV ip6gretap_set_tunnel ip6gretap_get_tunnel297 # underlay298 ping6 $PING_ARG ::11299 # overlay: ipv4 over ipv6300 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200301 ping $PING_ARG 10.1.1.100302 check_err $?303 # overlay: ipv6 over ipv6304 ip netns exec at_ns0 ping6 $PING_ARG fc80::200305 check_err $?306 cleanup307 308 if [ $ret -ne 0 ]; then309 echo -e ${RED}"FAIL: $TYPE"${NC}310 return 1311 fi312 echo -e ${GREEN}"PASS: $TYPE"${NC}313}314 315test_ip6gretap()316{317 TYPE=ip6gretap318 DEV_NS=ip6gretap00319 DEV=ip6gretap11320 ret=0321 322 check $TYPE323 config_device324 add_ip6gretap_tunnel325 attach_bpf $DEV ip6gretap_set_tunnel ip6gretap_get_tunnel326 # underlay327 ping6 $PING_ARG ::11328 # overlay: ipv4 over ipv6329 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200330 ping $PING_ARG 10.1.1.100331 check_err $?332 # overlay: ipv6 over ipv6333 ip netns exec at_ns0 ping6 $PING_ARG fc80::200334 check_err $?335 cleanup336 337 if [ $ret -ne 0 ]; then338 echo -e ${RED}"FAIL: $TYPE"${NC}339 return 1340 fi341 echo -e ${GREEN}"PASS: $TYPE"${NC}342}343 344test_erspan()345{346 TYPE=erspan347 DEV_NS=erspan00348 DEV=erspan11349 ret=0350 351 check $TYPE352 config_device353 add_erspan_tunnel $1354 attach_bpf $DEV erspan_set_tunnel erspan_get_tunnel355 ping $PING_ARG 10.1.1.100356 check_err $?357 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200358 check_err $?359 cleanup360 361 if [ $ret -ne 0 ]; then362 echo -e ${RED}"FAIL: $TYPE"${NC}363 return 1364 fi365 echo -e ${GREEN}"PASS: $TYPE"${NC}366}367 368test_ip6erspan()369{370 TYPE=ip6erspan371 DEV_NS=ip6erspan00372 DEV=ip6erspan11373 ret=0374 375 check $TYPE376 config_device377 add_ip6erspan_tunnel $1378 attach_bpf $DEV ip4ip6erspan_set_tunnel ip4ip6erspan_get_tunnel379 ping6 $PING_ARG ::11380 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200381 check_err $?382 cleanup383 384 if [ $ret -ne 0 ]; then385 echo -e ${RED}"FAIL: $TYPE"${NC}386 return 1387 fi388 echo -e ${GREEN}"PASS: $TYPE"${NC}389}390 391test_geneve()392{393 TYPE=geneve394 DEV_NS=geneve00395 DEV=geneve11396 ret=0397 398 check $TYPE399 config_device400 add_geneve_tunnel401 attach_bpf $DEV geneve_set_tunnel geneve_get_tunnel402 ping $PING_ARG 10.1.1.100403 check_err $?404 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200405 check_err $?406 cleanup407 408 if [ $ret -ne 0 ]; then409 echo -e ${RED}"FAIL: $TYPE"${NC}410 return 1411 fi412 echo -e ${GREEN}"PASS: $TYPE"${NC}413}414 415test_ip6geneve()416{417 TYPE=geneve418 DEV_NS=ip6geneve00419 DEV=ip6geneve11420 ret=0421 422 check $TYPE423 config_device424 add_ip6geneve_tunnel425 attach_bpf $DEV ip6geneve_set_tunnel ip6geneve_get_tunnel426 ping $PING_ARG 10.1.1.100427 check_err $?428 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200429 check_err $?430 cleanup431 432 if [ $ret -ne 0 ]; then433 echo -e ${RED}"FAIL: ip6$TYPE"${NC}434 return 1435 fi436 echo -e ${GREEN}"PASS: ip6$TYPE"${NC}437}438 439test_ipip()440{441 TYPE=ipip442 DEV_NS=ipip00443 DEV=ipip11444 ret=0445 446 check $TYPE447 config_device448 add_ipip_tunnel449 ip link set dev veth1 mtu 1500450 attach_bpf $DEV ipip_set_tunnel ipip_get_tunnel451 ping $PING_ARG 10.1.1.100452 check_err $?453 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200454 check_err $?455 cleanup456 457 if [ $ret -ne 0 ]; then458 echo -e ${RED}"FAIL: $TYPE"${NC}459 return 1460 fi461 echo -e ${GREEN}"PASS: $TYPE"${NC}462}463 464test_ipip6()465{466 TYPE=ip6tnl467 DEV_NS=ipip6tnl00468 DEV=ipip6tnl11469 ret=0470 471 check $TYPE472 config_device473 add_ip6tnl_tunnel474 ip link set dev veth1 mtu 1500475 attach_bpf $DEV ipip6_set_tunnel ipip6_get_tunnel476 # underlay477 ping6 $PING_ARG ::11478 # ip4 over ip6479 ping $PING_ARG 10.1.1.100480 check_err $?481 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200482 check_err $?483 cleanup484 485 if [ $ret -ne 0 ]; then486 echo -e ${RED}"FAIL: $TYPE"${NC}487 return 1488 fi489 echo -e ${GREEN}"PASS: $TYPE"${NC}490}491 492test_ip6ip6()493{494 TYPE=ip6tnl495 DEV_NS=ip6ip6tnl00496 DEV=ip6ip6tnl11497 ret=0498 499 check $TYPE500 config_device501 add_ip6tnl_tunnel502 ip link set dev veth1 mtu 1500503 attach_bpf $DEV ip6ip6_set_tunnel ip6ip6_get_tunnel504 # underlay505 ping6 $PING_ARG ::11506 # ip6 over ip6507 ping6 $PING_ARG 1::11508 check_err $?509 ip netns exec at_ns0 ping6 $PING_ARG 1::22510 check_err $?511 cleanup512 513 if [ $ret -ne 0 ]; then514 echo -e ${RED}"FAIL: ip6$TYPE"${NC}515 return 1516 fi517 echo -e ${GREEN}"PASS: ip6$TYPE"${NC}518}519 520attach_bpf()521{522 DEV=$1523 SET=$2524 GET=$3525 mkdir -p ${BPF_PIN_TUNNEL_DIR}526 bpftool prog loadall ${BPF_FILE} ${BPF_PIN_TUNNEL_DIR}/527 tc qdisc add dev $DEV clsact528 tc filter add dev $DEV egress bpf da object-pinned ${BPF_PIN_TUNNEL_DIR}/$SET529 tc filter add dev $DEV ingress bpf da object-pinned ${BPF_PIN_TUNNEL_DIR}/$GET530}531 532cleanup()533{534 rm -rf ${BPF_PIN_TUNNEL_DIR}535 536 ip netns delete at_ns0 2> /dev/null537 ip link del veth1 2> /dev/null538 ip link del ipip11 2> /dev/null539 ip link del ipip6tnl11 2> /dev/null540 ip link del ip6ip6tnl11 2> /dev/null541 ip link del gretap11 2> /dev/null542 ip link del gre11 2> /dev/null543 ip link del ip6gre11 2> /dev/null544 ip link del ip6gretap11 2> /dev/null545 ip link del geneve11 2> /dev/null546 ip link del ip6geneve11 2> /dev/null547 ip link del erspan11 2> /dev/null548 ip link del ip6erspan11 2> /dev/null549}550 551cleanup_exit()552{553 echo "CATCH SIGKILL or SIGINT, cleanup and exit"554 cleanup555 exit 0556}557 558check()559{560 ip link help 2>&1 | grep -q "\s$1\s"561 if [ $? -ne 0 ];then562 echo "SKIP $1: iproute2 not support"563 cleanup564 return 1565 fi566}567 568enable_debug()569{570 echo 'file ip_gre.c +p' > /sys/kernel/debug/dynamic_debug/control571 echo 'file ip6_gre.c +p' > /sys/kernel/debug/dynamic_debug/control572 echo 'file geneve.c +p' > /sys/kernel/debug/dynamic_debug/control573 echo 'file ipip.c +p' > /sys/kernel/debug/dynamic_debug/control574}575 576check_err()577{578 if [ $ret -eq 0 ]; then579 ret=$1580 fi581}582 583bpf_tunnel_test()584{585 local errors=0586 587 echo "Testing GRE tunnel..."588 test_gre589 errors=$(( $errors + $? ))590 591 echo "Testing GRE tunnel (without tunnel keys)..."592 test_gre_no_tunnel_key593 errors=$(( $errors + $? ))594 595 echo "Testing IP6GRE tunnel..."596 test_ip6gre597 errors=$(( $errors + $? ))598 599 echo "Testing IP6GRETAP tunnel..."600 test_ip6gretap601 errors=$(( $errors + $? ))602 603 echo "Testing ERSPAN tunnel..."604 test_erspan v2605 errors=$(( $errors + $? ))606 607 echo "Testing IP6ERSPAN tunnel..."608 test_ip6erspan v2609 errors=$(( $errors + $? ))610 611 echo "Testing GENEVE tunnel..."612 test_geneve613 errors=$(( $errors + $? ))614 615 echo "Testing IP6GENEVE tunnel..."616 test_ip6geneve617 errors=$(( $errors + $? ))618 619 echo "Testing IPIP tunnel..."620 test_ipip621 errors=$(( $errors + $? ))622 623 echo "Testing IPIP6 tunnel..."624 test_ipip6625 errors=$(( $errors + $? ))626 627 echo "Testing IP6IP6 tunnel..."628 test_ip6ip6629 errors=$(( $errors + $? ))630 631 return $errors632}633 634trap cleanup 0 3 6635trap cleanup_exit 2 9636 637cleanup638bpf_tunnel_test639 640if [ $? -ne 0 ]; then641 echo -e "$(basename $0): ${RED}FAIL${NC}"642 exit 1643fi644echo -e "$(basename $0): ${GREEN}PASS${NC}"645exit 0646