1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4# End-to-end eBPF tunnel test suite 5# The script tests BPF network tunnel implementation. 6# 7# Topology: 8# --------- 9# root namespace | at_ns0 namespace 10# | 11# ----------- | ----------- 12# | tnl dev | | | tnl dev | (overlay network) 13# ----------- | ----------- 14# metadata-mode | native-mode 15# with bpf | 16# | 17# ---------- | ---------- 18# | veth1 | --------- | veth0 | (underlay network) 19# ---------- peer ---------- 20# 21# 22# Device Configuration 23# -------------------- 24# Root namespace with metadata-mode tunnel + BPF 25# 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 tunnel 30# 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 flow 36# --------------------------- 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 egress 44# 4) veth0's ingress queue receive the tunneled packet at namespace at_ns0 45# 5) Tunnel protocol handler, ex: vxlan_rcv, decap the packet 46# 6) Forward the packet to the overlay tnl dev 47 48BPF_FILE="test_tunnel_kern.bpf.o" 49BPF_PIN_TUNNEL_DIR="/sys/fs/bpf/tc/tunnel" 50PING_ARG="-c 3 -w 10 -q" 51ret=0 52GREEN='\033[0;92m' 53RED='\033[0;31m' 54NC='\033[0m' # No Color 55 56config_device() 57{ 58 ip netns add at_ns0 59 ip link add veth0 type veth peer name veth1 60 ip link set veth0 netns at_ns0 61 ip netns exec at_ns0 ip addr add 172.16.1.100/24 dev veth0 62 ip netns exec at_ns0 ip link set dev veth0 up 63 ip link set dev veth1 up mtu 1500 64 ip addr add dev veth1 172.16.1.200/24 65} 66 67add_gre_tunnel() 68{ 69 tun_key= 70 if [ -n "$1" ]; then 71 tun_key="key $1" 72 fi 73 74 # at_ns0 namespace 75 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.200 78 ip netns exec at_ns0 ip link set dev $DEV_NS up 79 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 80 81 # root namespace 82 ip link add dev $DEV type $TYPE $tun_key external 83 ip link set dev $DEV up 84 ip addr add dev $DEV 10.1.1.200/24 85} 86 87add_ip6gretap_tunnel() 88{ 89 90 # assign ipv6 address 91 ip netns exec at_ns0 ip addr add ::11/96 dev veth0 92 ip netns exec at_ns0 ip link set dev veth0 up 93 ip addr add dev veth1 ::22/96 94 ip link set dev veth1 up 95 96 # at_ns0 namespace 97 ip netns exec at_ns0 \ 98 ip link add dev $DEV_NS type $TYPE seq flowlabel 0xbcdef key 2 \ 99 local ::11 remote ::22 100 101 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 102 ip netns exec at_ns0 ip addr add dev $DEV_NS fc80::100/96 103 ip netns exec at_ns0 ip link set dev $DEV_NS up 104 105 # root namespace 106 ip link add dev $DEV type $TYPE external 107 ip addr add dev $DEV 10.1.1.200/24 108 ip addr add dev $DEV fc80::200/24 109 ip link set dev $DEV up 110} 111 112add_erspan_tunnel() 113{ 114 # at_ns0 namespace 115 if [ "$1" == "v1" ]; then 116 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 123 120 else 121 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 3 125 fi 126 ip netns exec at_ns0 ip link set dev $DEV_NS up 127 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 128 129 # root namespace 130 ip link add dev $DEV type $TYPE external 131 ip link set dev $DEV up 132 ip addr add dev $DEV 10.1.1.200/24 133} 134 135add_ip6erspan_tunnel() 136{ 137 138 # assign ipv6 address 139 ip netns exec at_ns0 ip addr add ::11/96 dev veth0 140 ip netns exec at_ns0 ip link set dev veth0 up 141 ip addr add dev veth1 ::22/96 142 ip link set dev veth1 up 143 144 # at_ns0 namespace 145 if [ "$1" == "v1" ]; then 146 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 123 150 else 151 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 7 155 fi 156 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 157 ip netns exec at_ns0 ip link set dev $DEV_NS up 158 159 # root namespace 160 ip link add dev $DEV type $TYPE external 161 ip addr add dev $DEV 10.1.1.200/24 162 ip link set dev $DEV up 163} 164 165add_geneve_tunnel() 166{ 167 # at_ns0 namespace 168 ip netns exec at_ns0 \ 169 ip link add dev $DEV_NS type $TYPE \ 170 id 2 dstport 6081 remote 172.16.1.200 171 ip netns exec at_ns0 ip link set dev $DEV_NS up 172 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 173 174 # root namespace 175 ip link add dev $DEV type $TYPE dstport 6081 external 176 ip link set dev $DEV up 177 ip addr add dev $DEV 10.1.1.200/24 178} 179 180add_ip6geneve_tunnel() 181{ 182 ip netns exec at_ns0 ip addr add ::11/96 dev veth0 183 ip netns exec at_ns0 ip link set dev veth0 up 184 ip addr add dev veth1 ::22/96 185 ip link set dev veth1 up 186 187 # at_ns0 namespace 188 ip netns exec at_ns0 \ 189 ip link add dev $DEV_NS type $TYPE id 22 \ 190 remote ::22 # geneve has no local option 191 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 192 ip netns exec at_ns0 ip link set dev $DEV_NS up 193 194 # root namespace 195 ip link add dev $DEV type $TYPE external 196 ip addr add dev $DEV 10.1.1.200/24 197 ip link set dev $DEV up 198} 199 200add_ipip_tunnel() 201{ 202 # at_ns0 namespace 203 ip netns exec at_ns0 \ 204 ip link add dev $DEV_NS type $TYPE \ 205 local 172.16.1.100 remote 172.16.1.200 206 ip netns exec at_ns0 ip link set dev $DEV_NS up 207 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 208 209 # root namespace 210 ip link add dev $DEV type $TYPE external 211 ip link set dev $DEV up 212 ip addr add dev $DEV 10.1.1.200/24 213} 214 215add_ip6tnl_tunnel() 216{ 217 ip netns exec at_ns0 ip addr add ::11/96 dev veth0 218 ip netns exec at_ns0 ip link set dev veth0 up 219 ip addr add dev veth1 ::22/96 220 ip link set dev veth1 up 221 222 # at_ns0 namespace 223 ip netns exec at_ns0 \ 224 ip link add dev $DEV_NS type $TYPE \ 225 local ::11 remote ::22 226 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 227 ip netns exec at_ns0 ip addr add dev $DEV_NS 1::11/96 228 ip netns exec at_ns0 ip link set dev $DEV_NS up 229 230 # root namespace 231 ip link add dev $DEV type $TYPE external 232 ip addr add dev $DEV 10.1.1.200/24 233 ip addr add dev $DEV 1::22/96 234 ip link set dev $DEV up 235} 236 237test_gre() 238{ 239 TYPE=gretap 240 DEV_NS=gretap00 241 DEV=gretap11 242 ret=0 243 244 check $TYPE 245 config_device 246 add_gre_tunnel 2 247 attach_bpf $DEV gre_set_tunnel gre_get_tunnel 248 ping $PING_ARG 10.1.1.100 249 check_err $? 250 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200 251 check_err $? 252 cleanup 253 254 if [ $ret -ne 0 ]; then 255 echo -e ${RED}"FAIL: $TYPE"${NC} 256 return 1 257 fi 258 echo -e ${GREEN}"PASS: $TYPE"${NC} 259} 260 261test_gre_no_tunnel_key() 262{ 263 TYPE=gre 264 DEV_NS=gre00 265 DEV=gre11 266 ret=0 267 268 check $TYPE 269 config_device 270 add_gre_tunnel 271 attach_bpf $DEV gre_set_tunnel_no_key gre_get_tunnel 272 ping $PING_ARG 10.1.1.100 273 check_err $? 274 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200 275 check_err $? 276 cleanup 277 278 if [ $ret -ne 0 ]; then 279 echo -e ${RED}"FAIL: $TYPE"${NC} 280 return 1 281 fi 282 echo -e ${GREEN}"PASS: $TYPE"${NC} 283} 284 285test_ip6gre() 286{ 287 TYPE=ip6gre 288 DEV_NS=ip6gre00 289 DEV=ip6gre11 290 ret=0 291 292 check $TYPE 293 config_device 294 # reuse the ip6gretap function 295 add_ip6gretap_tunnel 296 attach_bpf $DEV ip6gretap_set_tunnel ip6gretap_get_tunnel 297 # underlay 298 ping6 $PING_ARG ::11 299 # overlay: ipv4 over ipv6 300 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200 301 ping $PING_ARG 10.1.1.100 302 check_err $? 303 # overlay: ipv6 over ipv6 304 ip netns exec at_ns0 ping6 $PING_ARG fc80::200 305 check_err $? 306 cleanup 307 308 if [ $ret -ne 0 ]; then 309 echo -e ${RED}"FAIL: $TYPE"${NC} 310 return 1 311 fi 312 echo -e ${GREEN}"PASS: $TYPE"${NC} 313} 314 315test_ip6gretap() 316{ 317 TYPE=ip6gretap 318 DEV_NS=ip6gretap00 319 DEV=ip6gretap11 320 ret=0 321 322 check $TYPE 323 config_device 324 add_ip6gretap_tunnel 325 attach_bpf $DEV ip6gretap_set_tunnel ip6gretap_get_tunnel 326 # underlay 327 ping6 $PING_ARG ::11 328 # overlay: ipv4 over ipv6 329 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200 330 ping $PING_ARG 10.1.1.100 331 check_err $? 332 # overlay: ipv6 over ipv6 333 ip netns exec at_ns0 ping6 $PING_ARG fc80::200 334 check_err $? 335 cleanup 336 337 if [ $ret -ne 0 ]; then 338 echo -e ${RED}"FAIL: $TYPE"${NC} 339 return 1 340 fi 341 echo -e ${GREEN}"PASS: $TYPE"${NC} 342} 343 344test_erspan() 345{ 346 TYPE=erspan 347 DEV_NS=erspan00 348 DEV=erspan11 349 ret=0 350 351 check $TYPE 352 config_device 353 add_erspan_tunnel $1 354 attach_bpf $DEV erspan_set_tunnel erspan_get_tunnel 355 ping $PING_ARG 10.1.1.100 356 check_err $? 357 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200 358 check_err $? 359 cleanup 360 361 if [ $ret -ne 0 ]; then 362 echo -e ${RED}"FAIL: $TYPE"${NC} 363 return 1 364 fi 365 echo -e ${GREEN}"PASS: $TYPE"${NC} 366} 367 368test_ip6erspan() 369{ 370 TYPE=ip6erspan 371 DEV_NS=ip6erspan00 372 DEV=ip6erspan11 373 ret=0 374 375 check $TYPE 376 config_device 377 add_ip6erspan_tunnel $1 378 attach_bpf $DEV ip4ip6erspan_set_tunnel ip4ip6erspan_get_tunnel 379 ping6 $PING_ARG ::11 380 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200 381 check_err $? 382 cleanup 383 384 if [ $ret -ne 0 ]; then 385 echo -e ${RED}"FAIL: $TYPE"${NC} 386 return 1 387 fi 388 echo -e ${GREEN}"PASS: $TYPE"${NC} 389} 390 391test_geneve() 392{ 393 TYPE=geneve 394 DEV_NS=geneve00 395 DEV=geneve11 396 ret=0 397 398 check $TYPE 399 config_device 400 add_geneve_tunnel 401 attach_bpf $DEV geneve_set_tunnel geneve_get_tunnel 402 ping $PING_ARG 10.1.1.100 403 check_err $? 404 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200 405 check_err $? 406 cleanup 407 408 if [ $ret -ne 0 ]; then 409 echo -e ${RED}"FAIL: $TYPE"${NC} 410 return 1 411 fi 412 echo -e ${GREEN}"PASS: $TYPE"${NC} 413} 414 415test_ip6geneve() 416{ 417 TYPE=geneve 418 DEV_NS=ip6geneve00 419 DEV=ip6geneve11 420 ret=0 421 422 check $TYPE 423 config_device 424 add_ip6geneve_tunnel 425 attach_bpf $DEV ip6geneve_set_tunnel ip6geneve_get_tunnel 426 ping $PING_ARG 10.1.1.100 427 check_err $? 428 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200 429 check_err $? 430 cleanup 431 432 if [ $ret -ne 0 ]; then 433 echo -e ${RED}"FAIL: ip6$TYPE"${NC} 434 return 1 435 fi 436 echo -e ${GREEN}"PASS: ip6$TYPE"${NC} 437} 438 439test_ipip() 440{ 441 TYPE=ipip 442 DEV_NS=ipip00 443 DEV=ipip11 444 ret=0 445 446 check $TYPE 447 config_device 448 add_ipip_tunnel 449 ip link set dev veth1 mtu 1500 450 attach_bpf $DEV ipip_set_tunnel ipip_get_tunnel 451 ping $PING_ARG 10.1.1.100 452 check_err $? 453 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200 454 check_err $? 455 cleanup 456 457 if [ $ret -ne 0 ]; then 458 echo -e ${RED}"FAIL: $TYPE"${NC} 459 return 1 460 fi 461 echo -e ${GREEN}"PASS: $TYPE"${NC} 462} 463 464test_ipip6() 465{ 466 TYPE=ip6tnl 467 DEV_NS=ipip6tnl00 468 DEV=ipip6tnl11 469 ret=0 470 471 check $TYPE 472 config_device 473 add_ip6tnl_tunnel 474 ip link set dev veth1 mtu 1500 475 attach_bpf $DEV ipip6_set_tunnel ipip6_get_tunnel 476 # underlay 477 ping6 $PING_ARG ::11 478 # ip4 over ip6 479 ping $PING_ARG 10.1.1.100 480 check_err $? 481 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200 482 check_err $? 483 cleanup 484 485 if [ $ret -ne 0 ]; then 486 echo -e ${RED}"FAIL: $TYPE"${NC} 487 return 1 488 fi 489 echo -e ${GREEN}"PASS: $TYPE"${NC} 490} 491 492test_ip6ip6() 493{ 494 TYPE=ip6tnl 495 DEV_NS=ip6ip6tnl00 496 DEV=ip6ip6tnl11 497 ret=0 498 499 check $TYPE 500 config_device 501 add_ip6tnl_tunnel 502 ip link set dev veth1 mtu 1500 503 attach_bpf $DEV ip6ip6_set_tunnel ip6ip6_get_tunnel 504 # underlay 505 ping6 $PING_ARG ::11 506 # ip6 over ip6 507 ping6 $PING_ARG 1::11 508 check_err $? 509 ip netns exec at_ns0 ping6 $PING_ARG 1::22 510 check_err $? 511 cleanup 512 513 if [ $ret -ne 0 ]; then 514 echo -e ${RED}"FAIL: ip6$TYPE"${NC} 515 return 1 516 fi 517 echo -e ${GREEN}"PASS: ip6$TYPE"${NC} 518} 519 520attach_bpf() 521{ 522 DEV=$1 523 SET=$2 524 GET=$3 525 mkdir -p ${BPF_PIN_TUNNEL_DIR} 526 bpftool prog loadall ${BPF_FILE} ${BPF_PIN_TUNNEL_DIR}/ 527 tc qdisc add dev $DEV clsact 528 tc filter add dev $DEV egress bpf da object-pinned ${BPF_PIN_TUNNEL_DIR}/$SET 529 tc filter add dev $DEV ingress bpf da object-pinned ${BPF_PIN_TUNNEL_DIR}/$GET 530} 531 532cleanup() 533{ 534 rm -rf ${BPF_PIN_TUNNEL_DIR} 535 536 ip netns delete at_ns0 2> /dev/null 537 ip link del veth1 2> /dev/null 538 ip link del ipip11 2> /dev/null 539 ip link del ipip6tnl11 2> /dev/null 540 ip link del ip6ip6tnl11 2> /dev/null 541 ip link del gretap11 2> /dev/null 542 ip link del gre11 2> /dev/null 543 ip link del ip6gre11 2> /dev/null 544 ip link del ip6gretap11 2> /dev/null 545 ip link del geneve11 2> /dev/null 546 ip link del ip6geneve11 2> /dev/null 547 ip link del erspan11 2> /dev/null 548 ip link del ip6erspan11 2> /dev/null 549} 550 551cleanup_exit() 552{ 553 echo "CATCH SIGKILL or SIGINT, cleanup and exit" 554 cleanup 555 exit 0 556} 557 558check() 559{ 560 ip link help 2>&1 | grep -q "\s$1\s" 561 if [ $? -ne 0 ];then 562 echo "SKIP $1: iproute2 not support" 563 cleanup 564 return 1 565 fi 566} 567 568enable_debug() 569{ 570 echo 'file ip_gre.c +p' > /sys/kernel/debug/dynamic_debug/control 571 echo 'file ip6_gre.c +p' > /sys/kernel/debug/dynamic_debug/control 572 echo 'file geneve.c +p' > /sys/kernel/debug/dynamic_debug/control 573 echo 'file ipip.c +p' > /sys/kernel/debug/dynamic_debug/control 574} 575 576check_err() 577{ 578 if [ $ret -eq 0 ]; then 579 ret=$1 580 fi 581} 582 583bpf_tunnel_test() 584{ 585 local errors=0 586 587 echo "Testing GRE tunnel..." 588 test_gre 589 errors=$(( $errors + $? )) 590 591 echo "Testing GRE tunnel (without tunnel keys)..." 592 test_gre_no_tunnel_key 593 errors=$(( $errors + $? )) 594 595 echo "Testing IP6GRE tunnel..." 596 test_ip6gre 597 errors=$(( $errors + $? )) 598 599 echo "Testing IP6GRETAP tunnel..." 600 test_ip6gretap 601 errors=$(( $errors + $? )) 602 603 echo "Testing ERSPAN tunnel..." 604 test_erspan v2 605 errors=$(( $errors + $? )) 606 607 echo "Testing IP6ERSPAN tunnel..." 608 test_ip6erspan v2 609 errors=$(( $errors + $? )) 610 611 echo "Testing GENEVE tunnel..." 612 test_geneve 613 errors=$(( $errors + $? )) 614 615 echo "Testing IP6GENEVE tunnel..." 616 test_ip6geneve 617 errors=$(( $errors + $? )) 618 619 echo "Testing IPIP tunnel..." 620 test_ipip 621 errors=$(( $errors + $? )) 622 623 echo "Testing IPIP6 tunnel..." 624 test_ipip6 625 errors=$(( $errors + $? )) 626 627 echo "Testing IP6IP6 tunnel..." 628 test_ip6ip6 629 errors=$(( $errors + $? )) 630 631 return $errors 632} 633 634trap cleanup 0 3 6 635trap cleanup_exit 2 9 636 637cleanup 638bpf_tunnel_test 639 640if [ $? -ne 0 ]; then 641 echo -e "$(basename $0): ${RED}FAIL${NC}" 642 exit 1 643fi 644echo -e "$(basename $0): ${GREEN}PASS${NC}" 645exit 0 646