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 48 BPF_FILE="test_tunnel_kern.bpf.o" 49 BPF_PIN_TUNNEL_DIR="/sys/fs/bpf/tc/tunnel" 50 PING_ARG="-c 3 -w 10 -q" 51 ret=0 52 GREEN='\033[0;92m' 53 RED='\033[0;31m' 54 NC='\033[0m' # No Color 55 56 config_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 67 add_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 87 add_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 112 add_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 135 add_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 165 add_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 180 add_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 200 add_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 215 add_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 237 test_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 261 test_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 285 test_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 315 test_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 344 test_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 368 test_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 391 test_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 415 test_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 439 test_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 464 test_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 492 test_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 520 attach_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 532 cleanup() 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 551 cleanup_exit() 552 { 553 echo "CATCH SIGKILL or SIGINT, cleanup and exit" 554 cleanup 555 exit 0 556 } 557 558 check() 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 568 enable_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 576 check_err() 577 { 578 if [ $ret -eq 0 ]; then 579 ret=$1 580 fi 581 } 582 583 bpf_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 634 trap cleanup 0 3 6 635 trap cleanup_exit 2 9 636 637 cleanup 638 bpf_tunnel_test 639 640 if [ $? -ne 0 ]; then 641 echo -e "$(basename $0): ${RED}FAIL${NC}" 642 exit 1 643 fi 644 echo -e "$(basename $0): ${GREEN}PASS${NC}" 645 exit 0
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.