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 109ERR=4 # Return 4 by default, which is the SKIP code for kselftest 110PING6="ping" 111PAUSE_ON_FAIL="no" 112 113readonly NS0=$(mktemp -u ns0-XXXXXXXX) 114readonly NS1=$(mktemp -u ns1-XXXXXXXX) 115readonly NS2=$(mktemp -u ns2-XXXXXXXX) 116readonly 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# 124exit_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. 141create_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# 151exit_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# 167iface_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# 189setup_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 223setup_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 239setup_overlay_ipv6() 240{ 241 # Add the overlay IP addresses and route them through the veth devices 242 ip -netns "${NS0}" address add 2001:db8::100/128 dev lo 243 ip -netns "${NS3}" address add 2001:db8::103/128 dev lo 244 ip -netns "${NS0}" route add 2001:db8::103/128 src 2001:db8::100 via 2001:db8::11 245 ip -netns "${NS3}" route add 2001:db8::100/128 src 2001:db8::103 via 2001:db8::32 246 247 # Route the overlay addresses in the intermediate namespaces 248 # (used after bareudp decapsulation) 249 ip netns exec "${NS1}" sysctl -qw net.ipv6.conf.all.forwarding=1 250 ip netns exec "${NS2}" sysctl -qw net.ipv6.conf.all.forwarding=1 251 ip -netns "${NS1}" route add 2001:db8::100/128 via 2001:db8::10 252 ip -netns "${NS2}" route add 2001:db8::103/128 via 2001:db8::33 253} 254 255setup_overlay_mpls() 256{ 257 # Add specific overlay IP addresses, routed over MPLS 258 ip -netns "${NS0}" address add 2001:db8::200/128 dev lo 259 ip -netns "${NS3}" address add 2001:db8::203/128 dev lo 260 ip -netns "${NS0}" route add 2001:db8::203/128 src 2001:db8::200 encap mpls 203 via 2001:db8::11 261 ip -netns "${NS3}" route add 2001:db8::200/128 src 2001:db8::203 encap mpls 200 via 2001:db8::32 262 263 # Route the MPLS packets in the intermediate namespaces 264 # (used after bareudp decapsulation) 265 ip netns exec "${NS1}" sysctl -qw net.mpls.platform_labels=256 266 ip netns exec "${NS2}" sysctl -qw net.mpls.platform_labels=256 267 ip -netns "${NS1}" -family mpls route add 200 via inet6 2001:db8::10 268 ip -netns "${NS2}" -family mpls route add 203 via inet6 2001:db8::33 269} 270 271# Run "ping" from NS0 and print the result 272# 273# Parameters: 274# 275# * $1: the variant of ping to use (normally either "ping" or "ping6"), 276# * $2: the IP address to ping, 277# * $3: a human readable description of the purpose of the test. 278# 279# If the test fails and PAUSE_ON_FAIL is active, the user is given the 280# possibility to continue with the next test or to quit immediately. 281# 282ping_test_one() 283{ 284 local PING="$1"; readonly PING 285 local IP="$2"; readonly IP 286 local MSG="$3"; readonly MSG 287 local RET 288 289 printf "TEST: %-60s " "${MSG}" 290 291 set +e 292 ip netns exec "${NS0}" "${PING}" -w 5 -c 1 "${IP}" > /dev/null 2>&1 293 RET=$? 294 set -e 295 296 if [ "${RET}" -eq 0 ]; then 297 printf "[ OK ]\n" 298 else 299 ERR=1 300 printf "[FAIL]\n" 301 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then 302 printf "\nHit enter to continue, 'q' to quit\n" 303 read a 304 if [ "$a" = "q" ]; then 305 exit 1 306 fi 307 fi 308 fi 309} 310 311# Run reachability tests 312# 313# Parameters: 314# 315# * $1: human readable string describing the underlay protocol. 316# 317# $IPV4, $IPV6, $MPLS_UC and $MULTIPROTO are inherited from the calling 318# function. 319# 320ping_test() 321{ 322 local UNDERLAY="$1"; readonly UNDERLAY 323 local MODE 324 local MSG 325 326 if [ "${MULTIPROTO}" = "multiproto" ]; then 327 MODE=" (multiproto mode)" 328 else 329 MODE="" 330 fi 331 332 if [ $IPV4 ]; then 333 ping_test_one "ping" "192.0.2.103" "IPv4 packets over ${UNDERLAY}${MODE}" 334 fi 335 if [ $IPV6 ]; then 336 ping_test_one "${PING6}" "2001:db8::103" "IPv6 packets over ${UNDERLAY}${MODE}" 337 fi 338 if [ $MPLS_UC ]; then 339 ping_test_one "${PING6}" "2001:db8::203" "Unicast MPLS packets over ${UNDERLAY}${MODE}" 340 fi 341} 342 343# Set up a bareudp overlay and run reachability tests over IPv4 and IPv6 344# 345# Parameters: 346# 347# * $1: the packet type (protocol) to be handled by bareudp, 348# * $2: a flag to activate or deactivate bareudp's "multiproto" mode. 349# 350test_overlay() 351{ 352 local ETHERTYPE="$1"; readonly ETHERTYPE 353 local MULTIPROTO="$2"; readonly MULTIPROTO 354 local IPV4 355 local IPV6 356 local MPLS_UC 357 358 case "${ETHERTYPE}" in 359 "ipv4") 360 IPV4="ipv4" 361 if [ "${MULTIPROTO}" = "multiproto" ]; then 362 IPV6="ipv6" 363 else 364 IPV6="" 365 fi 366 MPLS_UC="" 367 ;; 368 "ipv6") 369 IPV6="ipv6" 370 IPV4="" 371 MPLS_UC="" 372 ;; 373 "mpls_uc") 374 MPLS_UC="mpls_uc" 375 IPV4="" 376 IPV6="" 377 ;; 378 *) 379 exit 1 380 ;; 381 esac 382 readonly IPV4 383 readonly IPV6 384 readonly MPLS_UC 385 386 # Create the bareudp devices in the intermediate namespaces 387 ip -netns "${NS1}" link add name bareudp_ns1 up type bareudp dstport 6635 ethertype "${ETHERTYPE}" "${MULTIPROTO}" 388 ip -netns "${NS2}" link add name bareudp_ns2 up type bareudp dstport 6635 ethertype "${ETHERTYPE}" "${MULTIPROTO}" 389 390 # IPv4 over UDPv4 391 if [ $IPV4 ]; then 392 # Encapsulation instructions for bareudp over IPv4 393 tc -netns "${NS1}" filter add dev veth10 ingress protocol ipv4 \ 394 flower dst_ip 192.0.2.103/32 \ 395 action tunnel_key set src_ip 192.0.2.21 dst_ip 192.0.2.22 id 0 \ 396 action mirred egress redirect dev bareudp_ns1 397 tc -netns "${NS2}" filter add dev veth23 ingress protocol ipv4 \ 398 flower dst_ip 192.0.2.100/32 \ 399 action tunnel_key set src_ip 192.0.2.22 dst_ip 192.0.2.21 id 0 \ 400 action mirred egress redirect dev bareudp_ns2 401 fi 402 403 # IPv6 over UDPv4 404 if [ $IPV6 ]; then 405 # Encapsulation instructions for bareudp over IPv4 406 tc -netns "${NS1}" filter add dev veth10 ingress protocol ipv6 \ 407 flower dst_ip 2001:db8::103/128 \ 408 action tunnel_key set src_ip 192.0.2.21 dst_ip 192.0.2.22 id 0 \ 409 action mirred egress redirect dev bareudp_ns1 410 tc -netns "${NS2}" filter add dev veth23 ingress protocol ipv6 \ 411 flower dst_ip 2001:db8::100/128 \ 412 action tunnel_key set src_ip 192.0.2.22 dst_ip 192.0.2.21 id 0 \ 413 action mirred egress redirect dev bareudp_ns2 414 fi 415 416 # MPLS (unicast) over UDPv4 417 if [ $MPLS_UC ]; then 418 ip netns exec "${NS1}" sysctl -qw net.mpls.conf.bareudp_ns1.input=1 419 ip netns exec "${NS2}" sysctl -qw net.mpls.conf.bareudp_ns2.input=1 420 421 # Encapsulation instructions for bareudp over IPv4 422 tc -netns "${NS1}" filter add dev veth10 ingress protocol mpls_uc \ 423 flower mpls_label 203 \ 424 action tunnel_key set src_ip 192.0.2.21 dst_ip 192.0.2.22 id 0 \ 425 action mirred egress redirect dev bareudp_ns1 426 tc -netns "${NS2}" filter add dev veth23 ingress protocol mpls_uc \ 427 flower mpls_label 200 \ 428 action tunnel_key set src_ip 192.0.2.22 dst_ip 192.0.2.21 id 0 \ 429 action mirred egress redirect dev bareudp_ns2 430 fi 431 432 # Test IPv4 underlay 433 ping_test "UDPv4" 434 435 # Cleanup bareudp encapsulation instructions, as they were specific to 436 # the IPv4 underlay, before setting up and testing the IPv6 underlay 437 tc -netns "${NS1}" filter delete dev veth10 ingress 438 tc -netns "${NS2}" filter delete dev veth23 ingress 439 440 # IPv4 over UDPv6 441 if [ $IPV4 ]; then 442 # New encapsulation instructions for bareudp over IPv6 443 tc -netns "${NS1}" filter add dev veth10 ingress protocol ipv4 \ 444 flower dst_ip 192.0.2.103/32 \ 445 action tunnel_key set src_ip 2001:db8::21 dst_ip 2001:db8::22 id 0 \ 446 action mirred egress redirect dev bareudp_ns1 447 tc -netns "${NS2}" filter add dev veth23 ingress protocol ipv4 \ 448 flower dst_ip 192.0.2.100/32 \ 449 action tunnel_key set src_ip 2001:db8::22 dst_ip 2001:db8::21 id 0 \ 450 action mirred egress redirect dev bareudp_ns2 451 fi 452 453 # IPv6 over UDPv6 454 if [ $IPV6 ]; then 455 # New encapsulation instructions for bareudp over IPv6 456 tc -netns "${NS1}" filter add dev veth10 ingress protocol ipv6 \ 457 flower dst_ip 2001:db8::103/128 \ 458 action tunnel_key set src_ip 2001:db8::21 dst_ip 2001:db8::22 id 0 \ 459 action mirred egress redirect dev bareudp_ns1 460 tc -netns "${NS2}" filter add dev veth23 ingress protocol ipv6 \ 461 flower dst_ip 2001:db8::100/128 \ 462 action tunnel_key set src_ip 2001:db8::22 dst_ip 2001:db8::21 id 0 \ 463 action mirred egress redirect dev bareudp_ns2 464 fi 465 466 # MPLS (unicast) over UDPv6 467 if [ $MPLS_UC ]; then 468 # New encapsulation instructions for bareudp over IPv6 469 tc -netns "${NS1}" filter add dev veth10 ingress protocol mpls_uc \ 470 flower mpls_label 203 \ 471 action tunnel_key set src_ip 2001:db8::21 dst_ip 2001:db8::22 id 0 \ 472 action mirred egress redirect dev bareudp_ns1 473 tc -netns "${NS2}" filter add dev veth23 ingress protocol mpls_uc \ 474 flower mpls_label 200 \ 475 action tunnel_key set src_ip 2001:db8::22 dst_ip 2001:db8::21 id 0 \ 476 action mirred egress redirect dev bareudp_ns2 477 fi 478 479 # Test IPv6 underlay 480 ping_test "UDPv6" 481 482 tc -netns "${NS1}" filter delete dev veth10 ingress 483 tc -netns "${NS2}" filter delete dev veth23 ingress 484 ip -netns "${NS1}" link delete bareudp_ns1 485 ip -netns "${NS2}" link delete bareudp_ns2 486} 487 488check_features() 489{ 490 ip link help 2>&1 | grep -q bareudp 491 if [ $? -ne 0 ]; then 492 echo "Missing bareudp support in iproute2" >&2 493 exit_cleanup 494 fi 495 496 # Use ping6 on systems where ping doesn't handle IPv6 497 ping -w 1 -c 1 ::1 > /dev/null 2>&1 || PING6="ping6" 498} 499 500usage() 501{ 502 echo "Usage: $0 [-p]" 503 exit 1 504} 505 506while getopts :p o 507do 508 case $o in 509 p) PAUSE_ON_FAIL="yes";; 510 *) usage;; 511 esac 512done 513 514check_features 515 516# Create namespaces before setting up the exit trap. 517# Otherwise, exit_cleanup_all() could delete namespaces that were not created 518# by this script. 519create_namespaces 520 521set -e 522trap exit_cleanup_all EXIT 523 524setup_underlay 525setup_overlay_ipv4 526setup_overlay_ipv6 527setup_overlay_mpls 528 529test_overlay ipv4 nomultiproto 530test_overlay ipv6 nomultiproto 531test_overlay ipv4 multiproto 532test_overlay mpls_uc nomultiproto 533 534if [ "${ERR}" -eq 1 ]; then 535 echo "Some tests failed." >&2 536else 537 ERR=0 538fi 539