1 #!/bin/sh 2 # SPDX-License-Identifier: GPL-2.0 3 4 # Test various bareudp tunnel configurations. 5 # 6 # The bareudp module allows to tunnel network protocols like IP or MPLS over 7 # UDP, without adding any intermediate header. This scripts tests several 8 # configurations of bareudp (using IPv4 or IPv6 as underlay and transporting 9 # IPv4, IPv6 or MPLS packets on the overlay). 10 # 11 # Network topology: 12 # 13 # * A chain of 4 network namespaces, connected with veth pairs. Each veth 14 # is assigned an IPv4 and an IPv6 address. A host-route allows a veth to 15 # join its peer. 16 # 17 # * NS0 and NS3 are at the extremities of the chain. They have additional 18 # IPv4 and IPv6 addresses on their loopback device. Routes are added in NS0 19 # and NS3, so that they can communicate using these overlay IP addresses. 20 # For IPv4 and IPv6 reachability tests, the route simply sets the peer's 21 # veth address as gateway. For MPLS reachability tests, an MPLS header is 22 # also pushed before the IP header. 23 # 24 # * NS1 and NS2 are the intermediate namespaces. They use a bareudp device to 25 # encapsulate the traffic into UDP. 26 # 27 # +-----------------------------------------------------------------------+ 28 # | NS0 | 29 # | | 30 # | lo: | 31 # | * IPv4 address: 192.0.2.100/32 | 32 # | * IPv6 address: 2001:db8::100/128 | 33 # | * IPv6 address: 2001:db8::200/128 | 34 # | * IPv4 route: 192.0.2.103/32 reachable via 192.0.2.11 | 35 # | * IPv6 route: 2001:db8::103/128 reachable via 2001:db8::11 | 36 # | * IPv6 route: 2001:db8::203/128 reachable via 2001:db8::11 | 37 # | (encapsulated with MPLS label 203) | 38 # | | 39 # | veth01: | 40 # | ^ * IPv4 address: 192.0.2.10, peer 192.0.2.11/32 | 41 # | | * IPv6 address: 2001:db8::10, peer 2001:db8::11/128 | 42 # | | | 43 # +---+-------------------------------------------------------------------+ 44 # | 45 # | Traffic type: IP or MPLS (depending on test) 46 # | 47 # +---+-------------------------------------------------------------------+ 48 # | | NS1 | 49 # | | | 50 # | v | 51 # | veth10: | 52 # | * IPv4 address: 192.0.2.11, peer 192.0.2.10/32 | 53 # | * IPv6 address: 2001:db8::11, peer 2001:db8::10/128 | 54 # | | 55 # | bareudp_ns1: | 56 # | * Encapsulate IP or MPLS packets received on veth10 into UDP | 57 # | and send the resulting packets through veth12. | 58 # | * Decapsulate bareudp packets (either IP or MPLS, over UDP) | 59 # | received on veth12 and send the inner packets through veth10. | 60 # | | 61 # | veth12: | 62 # | ^ * IPv4 address: 192.0.2.21, peer 192.0.2.22/32 | 63 # | | * IPv6 address: 2001:db8::21, peer 2001:db8::22/128 | 64 # | | | 65 # +---+-------------------------------------------------------------------+ 66 # | 67 # | Traffic type: IP or MPLS (depending on test), over UDP 68 # | 69 # +---+-------------------------------------------------------------------+ 70 # | | NS2 | 71 # | | | 72 # | v | 73 # | veth21: | 74 # | * IPv4 address: 192.0.2.22, peer 192.0.2.21/32 | 75 # | * IPv6 address: 2001:db8::22, peer 2001:db8::21/128 | 76 # | | 77 # | bareudp_ns2: | 78 # | * Decapsulate bareudp packets (either IP or MPLS, over UDP) | 79 # | received on veth21 and send the inner packets through veth23. | 80 # | * Encapsulate IP or MPLS packets received on veth23 into UDP | 81 # | and send the resulting packets through veth21. | 82 # | | 83 # | veth23: | 84 # | ^ * IPv4 address: 192.0.2.32, peer 192.0.2.33/32 | 85 # | | * IPv6 address: 2001:db8::32, peer 2001:db8::33/128 | 86 # | | | 87 # +---+-------------------------------------------------------------------+ 88 # | 89 # | Traffic type: IP or MPLS (depending on test) 90 # | 91 # +---+-------------------------------------------------------------------+ 92 # | | NS3 | 93 # | v | 94 # | veth32: | 95 # | * IPv4 address: 192.0.2.33, peer 192.0.2.32/32 | 96 # | * IPv6 address: 2001:db8::33, peer 2001:db8::32/128 | 97 # | | 98 # | lo: | 99 # | * IPv4 address: 192.0.2.103/32 | 100 # | * IPv6 address: 2001:db8::103/128 | 101 # | * IPv6 address: 2001:db8::203/128 | 102 # | * IPv4 route: 192.0.2.100/32 reachable via 192.0.2.32 | 103 # | * IPv6 route: 2001:db8::100/128 reachable via 2001:db8::32 | 104 # | * IPv6 route: 2001:db8::200/128 reachable via 2001:db8::32 | 105 # | (encapsulated with MPLS label 200) | 106 # | | 107 # +-----------------------------------------------------------------------+ 108 109 ERR=4 # Return 4 by default, which is the SKIP code for kselftest 110 PING6="ping" 111 PAUSE_ON_FAIL="no" 112 113 readonly NS0=$(mktemp -u ns0-XXXXXXXX) 114 readonly NS1=$(mktemp -u ns1-XXXXXXXX) 115 readonly NS2=$(mktemp -u ns2-XXXXXXXX) 116 readonly NS3=$(mktemp -u ns3-XXXXXXXX) 117 118 # Exit the script after having removed the network namespaces it created 119 # 120 # Parameters: 121 # 122 # * The list of network namespaces to delete before exiting. 123 # 124 exit_cleanup() 125 { 126 for ns in "$@"; do 127 ip netns delete "${ns}" 2>/dev/null || true 128 done 129 130 if [ "${ERR}" -eq 4 ]; then 131 echo "Error: Setting up the testing environment failed." >&2 132 fi 133 134 exit "${ERR}" 135 } 136 137 # Create the four network namespaces used by the script (NS0, NS1, NS2 and NS3) 138 # 139 # New namespaces are cleaned up manually in case of error, to ensure that only 140 # namespaces created by this script are deleted. 141 create_namespaces() 142 { 143 ip netns add "${NS0}" || exit_cleanup 144 ip netns add "${NS1}" || exit_cleanup "${NS0}" 145 ip netns add "${NS2}" || exit_cleanup "${NS0}" "${NS1}" 146 ip netns add "${NS3}" || exit_cleanup "${NS0}" "${NS1}" "${NS2}" 147 } 148 149 # The trap function handler 150 # 151 exit_cleanup_all() 152 { 153 exit_cleanup "${NS0}" "${NS1}" "${NS2}" "${NS3}" 154 } 155 156 # Configure a network interface using a host route 157 # 158 # Parameters 159 # 160 # * $1: the netns the network interface resides in, 161 # * $2: the network interface name, 162 # * $3: the local IPv4 address to assign to this interface, 163 # * $4: the IPv4 address of the remote network interface, 164 # * $5: the local IPv6 address to assign to this interface, 165 # * $6: the IPv6 address of the remote network interface. 166 # 167 iface_config() 168 { 169 local NS="${1}"; readonly NS 170 local DEV="${2}"; readonly DEV 171 local LOCAL_IP4="${3}"; readonly LOCAL_IP4 172 local PEER_IP4="${4}"; readonly PEER_IP4 173 local LOCAL_IP6="${5}"; readonly LOCAL_IP6 174 local PEER_IP6="${6}"; readonly PEER_IP6 175 176 ip -netns "${NS}" link set dev "${DEV}" up 177 ip -netns "${NS}" address add dev "${DEV}" "${LOCAL_IP4}" peer "${PEER_IP4}" 178 ip -netns "${NS}" address add dev "${DEV}" "${LOCAL_IP6}" peer "${PEER_IP6}" nodad 179 } 180 181 # Create base networking topology: 182 # 183 # * set up the loopback device in all network namespaces (NS0..NS3), 184 # * set up a veth pair to connect each netns in sequence (NS0 with NS1, 185 # NS1 with NS2, etc.), 186 # * add and IPv4 and an IPv6 address on each veth interface, 187 # * prepare the ingress qdiscs in the intermediate namespaces. 188 # 189 setup_underlay() 190 { 191 for ns in "${NS0}" "${NS1}" "${NS2}" "${NS3}"; do 192 ip -netns "${ns}" link set dev lo up 193 done; 194 195 ip link add name veth01 netns "${NS0}" type veth peer name veth10 netns "${NS1}" 196 ip link add name veth12 netns "${NS1}" type veth peer name veth21 netns "${NS2}" 197 ip link add name veth23 netns "${NS2}" type veth peer name veth32 netns "${NS3}" 198 iface_config "${NS0}" veth01 192.0.2.10 192.0.2.11/32 2001:db8::10 2001:db8::11/128 199 iface_config "${NS1}" veth10 192.0.2.11 192.0.2.10/32 2001:db8::11 2001:db8::10/128 200 iface_config "${NS1}" veth12 192.0.2.21 192.0.2.22/32 2001:db8::21 2001:db8::22/128 201 iface_config "${NS2}" veth21 192.0.2.22 192.0.2.21/32 2001:db8::22 2001:db8::21/128 202 iface_config "${NS2}" veth23 192.0.2.32 192.0.2.33/32 2001:db8::32 2001:db8::33/128 203 iface_config "${NS3}" veth32 192.0.2.33 192.0.2.32/32 2001:db8::33 2001:db8::32/128 204 205 tc -netns "${NS1}" qdisc add dev veth10 ingress 206 tc -netns "${NS2}" qdisc add dev veth23 ingress 207 } 208 209 # Set up the IPv4, IPv6 and MPLS overlays. 210 # 211 # Configuration is similar for all protocols: 212 # 213 # * add an overlay IP address on the loopback interface of each edge 214 # namespace, 215 # * route these IP addresses via the intermediate namespaces (for the MPLS 216 # tests, this is also where MPLS encapsulation is done), 217 # * add routes for these IP addresses (or MPLS labels) in the intermediate 218 # namespaces. 219 # 220 # The bareudp encapsulation isn't configured in setup_overlay_*(). That will be 221 # done just before running the reachability tests. 222 223 setup_overlay_ipv4() 224 { 225 # Add the overlay IP addresses and route them through the veth devices 226 ip -netns "${NS0}" address add 192.0.2.100/32 dev lo 227 ip -netns "${NS3}" address add 192.0.2.103/32 dev lo 228 ip -netns "${NS0}" route add 192.0.2.103/32 src 192.0.2.100 via 192.0.2.11 229 ip -netns "${NS3}" route add 192.0.2.100/32 src 192.0.2.103 via 192.0.2.32 230 231 # Route the overlay addresses in the intermediate namespaces 232 # (used after bareudp decapsulation) 233 ip netns exec "${NS1}" sysctl -qw net.ipv4.ip_forward=1 234 ip netns exec "${NS2}" sysctl -qw net.ipv4.ip_forward=1 235 ip -netns "${NS1}" route add 192.0.2.100/32 via 192.0.2.10 236 ip -netns "${NS2}" route add 192.0.2.103/32 via 192.0.2.33 237 238 # The intermediate namespaces don't have routes for the reverse path, 239 # as it will be handled by tc. So we need to ensure that rp_filter is 240 # not going to block the traffic. 241 ip netns exec "${NS1}" sysctl -qw net.ipv4.conf.all.rp_filter=0 242 ip netns exec "${NS2}" sysctl -qw net.ipv4.conf.all.rp_filter=0 243 ip netns exec "${NS1}" sysctl -qw net.ipv4.conf.default.rp_filter=0 244 ip netns exec "${NS2}" sysctl -qw net.ipv4.conf.default.rp_filter=0 245 } 246 247 setup_overlay_ipv6() 248 { 249 # Add the overlay IP addresses and route them through the veth devices 250 ip -netns "${NS0}" address add 2001:db8::100/128 dev lo 251 ip -netns "${NS3}" address add 2001:db8::103/128 dev lo 252 ip -netns "${NS0}" route add 2001:db8::103/128 src 2001:db8::100 via 2001:db8::11 253 ip -netns "${NS3}" route add 2001:db8::100/128 src 2001:db8::103 via 2001:db8::32 254 255 # Route the overlay addresses in the intermediate namespaces 256 # (used after bareudp decapsulation) 257 ip netns exec "${NS1}" sysctl -qw net.ipv6.conf.all.forwarding=1 258 ip netns exec "${NS2}" sysctl -qw net.ipv6.conf.all.forwarding=1 259 ip -netns "${NS1}" route add 2001:db8::100/128 via 2001:db8::10 260 ip -netns "${NS2}" route add 2001:db8::103/128 via 2001:db8::33 261 } 262 263 setup_overlay_mpls() 264 { 265 # Add specific overlay IP addresses, routed over MPLS 266 ip -netns "${NS0}" address add 2001:db8::200/128 dev lo 267 ip -netns "${NS3}" address add 2001:db8::203/128 dev lo 268 ip -netns "${NS0}" route add 2001:db8::203/128 src 2001:db8::200 encap mpls 203 via 2001:db8::11 269 ip -netns "${NS3}" route add 2001:db8::200/128 src 2001:db8::203 encap mpls 200 via 2001:db8::32 270 271 # Route the MPLS packets in the intermediate namespaces 272 # (used after bareudp decapsulation) 273 ip netns exec "${NS1}" sysctl -qw net.mpls.platform_labels=256 274 ip netns exec "${NS2}" sysctl -qw net.mpls.platform_labels=256 275 ip -netns "${NS1}" -family mpls route add 200 via inet6 2001:db8::10 276 ip -netns "${NS2}" -family mpls route add 203 via inet6 2001:db8::33 277 } 278 279 # Run "ping" from NS0 and print the result 280 # 281 # Parameters: 282 # 283 # * $1: the variant of ping to use (normally either "ping" or "ping6"), 284 # * $2: the IP address to ping, 285 # * $3: a human readable description of the purpose of the test. 286 # 287 # If the test fails and PAUSE_ON_FAIL is active, the user is given the 288 # possibility to continue with the next test or to quit immediately. 289 # 290 ping_test_one() 291 { 292 local PING="$1"; readonly PING 293 local IP="$2"; readonly IP 294 local MSG="$3"; readonly MSG 295 local RET 296 297 printf "TEST: %-60s " "${MSG}" 298 299 set +e 300 ip netns exec "${NS0}" "${PING}" -w 5 -c 1 "${IP}" > /dev/null 2>&1 301 RET=$? 302 set -e 303 304 if [ "${RET}" -eq 0 ]; then 305 printf "[ OK ]\n" 306 else 307 ERR=1 308 printf "[FAIL]\n" 309 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then 310 printf "\nHit enter to continue, 'q' to quit\n" 311 read a 312 if [ "$a" = "q" ]; then 313 exit 1 314 fi 315 fi 316 fi 317 } 318 319 # Run reachability tests 320 # 321 # Parameters: 322 # 323 # * $1: human readable string describing the underlay protocol. 324 # 325 # $IPV4, $IPV6, $MPLS_UC and $MULTIPROTO are inherited from the calling 326 # function. 327 # 328 ping_test() 329 { 330 local UNDERLAY="$1"; readonly UNDERLAY 331 local MODE 332 local MSG 333 334 if [ "${MULTIPROTO}" = "multiproto" ]; then 335 MODE=" (multiproto mode)" 336 else 337 MODE="" 338 fi 339 340 if [ $IPV4 ]; then 341 ping_test_one "ping" "192.0.2.103" "IPv4 packets over ${UNDERLAY}${MODE}" 342 fi 343 if [ $IPV6 ]; then 344 ping_test_one "${PING6}" "2001:db8::103" "IPv6 packets over ${UNDERLAY}${MODE}" 345 fi 346 if [ $MPLS_UC ]; then 347 ping_test_one "${PING6}" "2001:db8::203" "Unicast MPLS packets over ${UNDERLAY}${MODE}" 348 fi 349 } 350 351 # Set up a bareudp overlay and run reachability tests over IPv4 and IPv6 352 # 353 # Parameters: 354 # 355 # * $1: the packet type (protocol) to be handled by bareudp, 356 # * $2: a flag to activate or deactivate bareudp's "multiproto" mode. 357 # 358 test_overlay() 359 { 360 local ETHERTYPE="$1"; readonly ETHERTYPE 361 local MULTIPROTO="$2"; readonly MULTIPROTO 362 local IPV4 363 local IPV6 364 local MPLS_UC 365 366 case "${ETHERTYPE}" in 367 "ipv4") 368 IPV4="ipv4" 369 if [ "${MULTIPROTO}" = "multiproto" ]; then 370 IPV6="ipv6" 371 else 372 IPV6="" 373 fi 374 MPLS_UC="" 375 ;; 376 "ipv6") 377 IPV6="ipv6" 378 IPV4="" 379 MPLS_UC="" 380 ;; 381 "mpls_uc") 382 MPLS_UC="mpls_uc" 383 IPV4="" 384 IPV6="" 385 ;; 386 *) 387 exit 1 388 ;; 389 esac 390 readonly IPV4 391 readonly IPV6 392 readonly MPLS_UC 393 394 # Create the bareudp devices in the intermediate namespaces 395 ip -netns "${NS1}" link add name bareudp_ns1 up type bareudp dstport 6635 ethertype "${ETHERTYPE}" "${MULTIPROTO}" 396 ip -netns "${NS2}" link add name bareudp_ns2 up type bareudp dstport 6635 ethertype "${ETHERTYPE}" "${MULTIPROTO}" 397 398 # IPv4 over UDPv4 399 if [ $IPV4 ]; then 400 # Encapsulation instructions for bareudp over IPv4 401 tc -netns "${NS1}" filter add dev veth10 ingress protocol ipv4 \ 402 flower dst_ip 192.0.2.103/32 \ 403 action tunnel_key set src_ip 192.0.2.21 dst_ip 192.0.2.22 id 0 \ 404 action mirred egress redirect dev bareudp_ns1 405 tc -netns "${NS2}" filter add dev veth23 ingress protocol ipv4 \ 406 flower dst_ip 192.0.2.100/32 \ 407 action tunnel_key set src_ip 192.0.2.22 dst_ip 192.0.2.21 id 0 \ 408 action mirred egress redirect dev bareudp_ns2 409 fi 410 411 # IPv6 over UDPv4 412 if [ $IPV6 ]; then 413 # Encapsulation instructions for bareudp over IPv4 414 tc -netns "${NS1}" filter add dev veth10 ingress protocol ipv6 \ 415 flower dst_ip 2001:db8::103/128 \ 416 action tunnel_key set src_ip 192.0.2.21 dst_ip 192.0.2.22 id 0 \ 417 action mirred egress redirect dev bareudp_ns1 418 tc -netns "${NS2}" filter add dev veth23 ingress protocol ipv6 \ 419 flower dst_ip 2001:db8::100/128 \ 420 action tunnel_key set src_ip 192.0.2.22 dst_ip 192.0.2.21 id 0 \ 421 action mirred egress redirect dev bareudp_ns2 422 fi 423 424 # MPLS (unicast) over UDPv4 425 if [ $MPLS_UC ]; then 426 ip netns exec "${NS1}" sysctl -qw net.mpls.conf.bareudp_ns1.input=1 427 ip netns exec "${NS2}" sysctl -qw net.mpls.conf.bareudp_ns2.input=1 428 429 # Encapsulation instructions for bareudp over IPv4 430 tc -netns "${NS1}" filter add dev veth10 ingress protocol mpls_uc \ 431 flower mpls_label 203 \ 432 action tunnel_key set src_ip 192.0.2.21 dst_ip 192.0.2.22 id 0 \ 433 action mirred egress redirect dev bareudp_ns1 434 tc -netns "${NS2}" filter add dev veth23 ingress protocol mpls_uc \ 435 flower mpls_label 200 \ 436 action tunnel_key set src_ip 192.0.2.22 dst_ip 192.0.2.21 id 0 \ 437 action mirred egress redirect dev bareudp_ns2 438 fi 439 440 # Test IPv4 underlay 441 ping_test "UDPv4" 442 443 # Cleanup bareudp encapsulation instructions, as they were specific to 444 # the IPv4 underlay, before setting up and testing the IPv6 underlay 445 tc -netns "${NS1}" filter delete dev veth10 ingress 446 tc -netns "${NS2}" filter delete dev veth23 ingress 447 448 # IPv4 over UDPv6 449 if [ $IPV4 ]; then 450 # New encapsulation instructions for bareudp over IPv6 451 tc -netns "${NS1}" filter add dev veth10 ingress protocol ipv4 \ 452 flower dst_ip 192.0.2.103/32 \ 453 action tunnel_key set src_ip 2001:db8::21 dst_ip 2001:db8::22 id 0 \ 454 action mirred egress redirect dev bareudp_ns1 455 tc -netns "${NS2}" filter add dev veth23 ingress protocol ipv4 \ 456 flower dst_ip 192.0.2.100/32 \ 457 action tunnel_key set src_ip 2001:db8::22 dst_ip 2001:db8::21 id 0 \ 458 action mirred egress redirect dev bareudp_ns2 459 fi 460 461 # IPv6 over UDPv6 462 if [ $IPV6 ]; then 463 # New encapsulation instructions for bareudp over IPv6 464 tc -netns "${NS1}" filter add dev veth10 ingress protocol ipv6 \ 465 flower dst_ip 2001:db8::103/128 \ 466 action tunnel_key set src_ip 2001:db8::21 dst_ip 2001:db8::22 id 0 \ 467 action mirred egress redirect dev bareudp_ns1 468 tc -netns "${NS2}" filter add dev veth23 ingress protocol ipv6 \ 469 flower dst_ip 2001:db8::100/128 \ 470 action tunnel_key set src_ip 2001:db8::22 dst_ip 2001:db8::21 id 0 \ 471 action mirred egress redirect dev bareudp_ns2 472 fi 473 474 # MPLS (unicast) over UDPv6 475 if [ $MPLS_UC ]; then 476 # New encapsulation instructions for bareudp over IPv6 477 tc -netns "${NS1}" filter add dev veth10 ingress protocol mpls_uc \ 478 flower mpls_label 203 \ 479 action tunnel_key set src_ip 2001:db8::21 dst_ip 2001:db8::22 id 0 \ 480 action mirred egress redirect dev bareudp_ns1 481 tc -netns "${NS2}" filter add dev veth23 ingress protocol mpls_uc \ 482 flower mpls_label 200 \ 483 action tunnel_key set src_ip 2001:db8::22 dst_ip 2001:db8::21 id 0 \ 484 action mirred egress redirect dev bareudp_ns2 485 fi 486 487 # Test IPv6 underlay 488 ping_test "UDPv6" 489 490 tc -netns "${NS1}" filter delete dev veth10 ingress 491 tc -netns "${NS2}" filter delete dev veth23 ingress 492 ip -netns "${NS1}" link delete bareudp_ns1 493 ip -netns "${NS2}" link delete bareudp_ns2 494 } 495 496 check_features() 497 { 498 ip link help 2>&1 | grep -q bareudp 499 if [ $? -ne 0 ]; then 500 echo "Missing bareudp support in iproute2" >&2 501 exit_cleanup 502 fi 503 504 # Use ping6 on systems where ping doesn't handle IPv6 505 ping -w 1 -c 1 ::1 > /dev/null 2>&1 || PING6="ping6" 506 } 507 508 usage() 509 { 510 echo "Usage: $0 [-p]" 511 exit 1 512 } 513 514 while getopts :p o 515 do 516 case $o in 517 p) PAUSE_ON_FAIL="yes";; 518 *) usage;; 519 esac 520 done 521 522 check_features 523 524 # Create namespaces before setting up the exit trap. 525 # Otherwise, exit_cleanup_all() could delete namespaces that were not created 526 # by this script. 527 create_namespaces 528 529 set -e 530 trap exit_cleanup_all EXIT 531 532 setup_underlay 533 setup_overlay_ipv4 534 setup_overlay_ipv6 535 setup_overlay_mpls 536 537 test_overlay ipv4 nomultiproto 538 test_overlay ipv6 nomultiproto 539 test_overlay ipv4 multiproto 540 test_overlay mpls_uc nomultiproto 541 542 if [ "${ERR}" -eq 1 ]; then 543 echo "Some tests failed." >&2 544 else 545 ERR=0 546 fi
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.