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. ./lib.sh 110 111ERR=4 # Return 4 by default, which is the SKIP code for kselftest 112PING6="ping" 113PAUSE_ON_FAIL="no" 114 115# Exit the script after having removed the network namespaces it created 116exit_cleanup() 117{ 118 cleanup_all_ns 119 120 if [ "${ERR}" -eq 4 ]; then 121 echo "Error: Setting up the testing environment failed." >&2 122 fi 123 124 exit "${ERR}" 125} 126 127# Create the four network namespaces used by the script (NS0, NS1, NS2 and NS3) 128# 129# New namespaces are cleaned up manually in case of error, to ensure that only 130# namespaces created by this script are deleted. 131create_namespaces() 132{ 133 setup_ns NS0 NS1 NS2 NS3 || exit_cleanup 134} 135 136# Configure a network interface using a host route 137# 138# Parameters 139# 140# * $1: the netns the network interface resides in, 141# * $2: the network interface name, 142# * $3: the local IPv4 address to assign to this interface, 143# * $4: the IPv4 address of the remote network interface, 144# * $5: the local IPv6 address to assign to this interface, 145# * $6: the IPv6 address of the remote network interface. 146# 147iface_config() 148{ 149 local NS="${1}"; readonly NS 150 local DEV="${2}"; readonly DEV 151 local LOCAL_IP4="${3}"; readonly LOCAL_IP4 152 local PEER_IP4="${4}"; readonly PEER_IP4 153 local LOCAL_IP6="${5}"; readonly LOCAL_IP6 154 local PEER_IP6="${6}"; readonly PEER_IP6 155 156 ip -netns "${NS}" link set dev "${DEV}" up 157 ip -netns "${NS}" address add dev "${DEV}" "${LOCAL_IP4}" peer "${PEER_IP4}" 158 ip -netns "${NS}" address add dev "${DEV}" "${LOCAL_IP6}" peer "${PEER_IP6}" nodad 159} 160 161# Create base networking topology: 162# 163# * set up the loopback device in all network namespaces (NS0..NS3), 164# * set up a veth pair to connect each netns in sequence (NS0 with NS1, 165# NS1 with NS2, etc.), 166# * add and IPv4 and an IPv6 address on each veth interface, 167# * prepare the ingress qdiscs in the intermediate namespaces. 168# 169setup_underlay() 170{ 171 ip link add name veth01 netns "${NS0}" type veth peer name veth10 netns "${NS1}" 172 ip link add name veth12 netns "${NS1}" type veth peer name veth21 netns "${NS2}" 173 ip link add name veth23 netns "${NS2}" type veth peer name veth32 netns "${NS3}" 174 iface_config "${NS0}" veth01 192.0.2.10 192.0.2.11/32 2001:db8::10 2001:db8::11/128 175 iface_config "${NS1}" veth10 192.0.2.11 192.0.2.10/32 2001:db8::11 2001:db8::10/128 176 iface_config "${NS1}" veth12 192.0.2.21 192.0.2.22/32 2001:db8::21 2001:db8::22/128 177 iface_config "${NS2}" veth21 192.0.2.22 192.0.2.21/32 2001:db8::22 2001:db8::21/128 178 iface_config "${NS2}" veth23 192.0.2.32 192.0.2.33/32 2001:db8::32 2001:db8::33/128 179 iface_config "${NS3}" veth32 192.0.2.33 192.0.2.32/32 2001:db8::33 2001:db8::32/128 180 181 tc -netns "${NS1}" qdisc add dev veth10 ingress 182 tc -netns "${NS2}" qdisc add dev veth23 ingress 183} 184 185# Set up the IPv4, IPv6 and MPLS overlays. 186# 187# Configuration is similar for all protocols: 188# 189# * add an overlay IP address on the loopback interface of each edge 190# namespace, 191# * route these IP addresses via the intermediate namespaces (for the MPLS 192# tests, this is also where MPLS encapsulation is done), 193# * add routes for these IP addresses (or MPLS labels) in the intermediate 194# namespaces. 195# 196# The bareudp encapsulation isn't configured in setup_overlay_*(). That will be 197# done just before running the reachability tests. 198 199setup_overlay_ipv4() 200{ 201 # Add the overlay IP addresses and route them through the veth devices 202 ip -netns "${NS0}" address add 192.0.2.100/32 dev lo 203 ip -netns "${NS3}" address add 192.0.2.103/32 dev lo 204 ip -netns "${NS0}" route add 192.0.2.103/32 src 192.0.2.100 via 192.0.2.11 205 ip -netns "${NS3}" route add 192.0.2.100/32 src 192.0.2.103 via 192.0.2.32 206 207 # Route the overlay addresses in the intermediate namespaces 208 # (used after bareudp decapsulation) 209 ip netns exec "${NS1}" sysctl -qw net.ipv4.ip_forward=1 210 ip netns exec "${NS2}" sysctl -qw net.ipv4.ip_forward=1 211 ip -netns "${NS1}" route add 192.0.2.100/32 via 192.0.2.10 212 ip -netns "${NS2}" route add 192.0.2.103/32 via 192.0.2.33 213} 214 215setup_overlay_ipv6() 216{ 217 # Add the overlay IP addresses and route them through the veth devices 218 ip -netns "${NS0}" address add 2001:db8::100/128 dev lo 219 ip -netns "${NS3}" address add 2001:db8::103/128 dev lo 220 ip -netns "${NS0}" route add 2001:db8::103/128 src 2001:db8::100 via 2001:db8::11 221 ip -netns "${NS3}" route add 2001:db8::100/128 src 2001:db8::103 via 2001:db8::32 222 223 # Route the overlay addresses in the intermediate namespaces 224 # (used after bareudp decapsulation) 225 ip netns exec "${NS1}" sysctl -qw net.ipv6.conf.all.forwarding=1 226 ip netns exec "${NS2}" sysctl -qw net.ipv6.conf.all.forwarding=1 227 ip -netns "${NS1}" route add 2001:db8::100/128 via 2001:db8::10 228 ip -netns "${NS2}" route add 2001:db8::103/128 via 2001:db8::33 229} 230 231setup_overlay_mpls() 232{ 233 # Add specific overlay IP addresses, routed over MPLS 234 ip -netns "${NS0}" address add 2001:db8::200/128 dev lo 235 ip -netns "${NS3}" address add 2001:db8::203/128 dev lo 236 ip -netns "${NS0}" route add 2001:db8::203/128 src 2001:db8::200 encap mpls 203 via 2001:db8::11 237 ip -netns "${NS3}" route add 2001:db8::200/128 src 2001:db8::203 encap mpls 200 via 2001:db8::32 238 239 # Route the MPLS packets in the intermediate namespaces 240 # (used after bareudp decapsulation) 241 ip netns exec "${NS1}" sysctl -qw net.mpls.platform_labels=256 242 ip netns exec "${NS2}" sysctl -qw net.mpls.platform_labels=256 243 ip -netns "${NS1}" -family mpls route add 200 via inet6 2001:db8::10 244 ip -netns "${NS2}" -family mpls route add 203 via inet6 2001:db8::33 245} 246 247# Run "ping" from NS0 and print the result 248# 249# Parameters: 250# 251# * $1: the variant of ping to use (normally either "ping" or "ping6"), 252# * $2: the IP address to ping, 253# * $3: a human readable description of the purpose of the test. 254# 255# If the test fails and PAUSE_ON_FAIL is active, the user is given the 256# possibility to continue with the next test or to quit immediately. 257# 258ping_test_one() 259{ 260 local PING="$1"; readonly PING 261 local IP="$2"; readonly IP 262 local MSG="$3"; readonly MSG 263 local RET 264 265 printf "TEST: %-60s " "${MSG}" 266 267 set +e 268 ip netns exec "${NS0}" "${PING}" -w 5 -c 1 "${IP}" > /dev/null 2>&1 269 RET=$? 270 set -e 271 272 if [ "${RET}" -eq 0 ]; then 273 printf "[ OK ]\n" 274 else 275 ERR=1 276 printf "[FAIL]\n" 277 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then 278 printf "\nHit enter to continue, 'q' to quit\n" 279 read a 280 if [ "$a" = "q" ]; then 281 exit 1 282 fi 283 fi 284 fi 285} 286 287# Run reachability tests 288# 289# Parameters: 290# 291# * $1: human readable string describing the underlay protocol. 292# 293# $IPV4, $IPV6, $MPLS_UC and $MULTIPROTO are inherited from the calling 294# function. 295# 296ping_test() 297{ 298 local UNDERLAY="$1"; readonly UNDERLAY 299 local MODE 300 local MSG 301 302 if [ "${MULTIPROTO}" = "multiproto" ]; then 303 MODE=" (multiproto mode)" 304 else 305 MODE="" 306 fi 307 308 if [ $IPV4 ]; then 309 ping_test_one "ping" "192.0.2.103" "IPv4 packets over ${UNDERLAY}${MODE}" 310 fi 311 if [ $IPV6 ]; then 312 ping_test_one "${PING6}" "2001:db8::103" "IPv6 packets over ${UNDERLAY}${MODE}" 313 fi 314 if [ $MPLS_UC ]; then 315 ping_test_one "${PING6}" "2001:db8::203" "Unicast MPLS packets over ${UNDERLAY}${MODE}" 316 fi 317} 318 319# Set up a bareudp overlay and run reachability tests over IPv4 and IPv6 320# 321# Parameters: 322# 323# * $1: the packet type (protocol) to be handled by bareudp, 324# * $2: a flag to activate or deactivate bareudp's "multiproto" mode. 325# 326test_overlay() 327{ 328 local ETHERTYPE="$1"; readonly ETHERTYPE 329 local MULTIPROTO="$2"; readonly MULTIPROTO 330 local IPV4 331 local IPV6 332 local MPLS_UC 333 334 case "${ETHERTYPE}" in 335 "ipv4") 336 IPV4="ipv4" 337 if [ "${MULTIPROTO}" = "multiproto" ]; then 338 IPV6="ipv6" 339 else 340 IPV6="" 341 fi 342 MPLS_UC="" 343 ;; 344 "ipv6") 345 IPV6="ipv6" 346 IPV4="" 347 MPLS_UC="" 348 ;; 349 "mpls_uc") 350 MPLS_UC="mpls_uc" 351 IPV4="" 352 IPV6="" 353 ;; 354 *) 355 exit 1 356 ;; 357 esac 358 readonly IPV4 359 readonly IPV6 360 readonly MPLS_UC 361 362 # Create the bareudp devices in the intermediate namespaces 363 ip -netns "${NS1}" link add name bareudp_ns1 up type bareudp dstport 6635 ethertype "${ETHERTYPE}" "${MULTIPROTO}" 364 ip -netns "${NS2}" link add name bareudp_ns2 up type bareudp dstport 6635 ethertype "${ETHERTYPE}" "${MULTIPROTO}" 365 366 # IPv4 over UDPv4 367 if [ $IPV4 ]; then 368 # Encapsulation instructions for bareudp over IPv4 369 tc -netns "${NS1}" filter add dev veth10 ingress protocol ipv4 \ 370 flower dst_ip 192.0.2.103/32 \ 371 action tunnel_key set src_ip 192.0.2.21 dst_ip 192.0.2.22 id 0 \ 372 action mirred egress redirect dev bareudp_ns1 373 tc -netns "${NS2}" filter add dev veth23 ingress protocol ipv4 \ 374 flower dst_ip 192.0.2.100/32 \ 375 action tunnel_key set src_ip 192.0.2.22 dst_ip 192.0.2.21 id 0 \ 376 action mirred egress redirect dev bareudp_ns2 377 fi 378 379 # IPv6 over UDPv4 380 if [ $IPV6 ]; then 381 # Encapsulation instructions for bareudp over IPv4 382 tc -netns "${NS1}" filter add dev veth10 ingress protocol ipv6 \ 383 flower dst_ip 2001:db8::103/128 \ 384 action tunnel_key set src_ip 192.0.2.21 dst_ip 192.0.2.22 id 0 \ 385 action mirred egress redirect dev bareudp_ns1 386 tc -netns "${NS2}" filter add dev veth23 ingress protocol ipv6 \ 387 flower dst_ip 2001:db8::100/128 \ 388 action tunnel_key set src_ip 192.0.2.22 dst_ip 192.0.2.21 id 0 \ 389 action mirred egress redirect dev bareudp_ns2 390 fi 391 392 # MPLS (unicast) over UDPv4 393 if [ $MPLS_UC ]; then 394 ip netns exec "${NS1}" sysctl -qw net.mpls.conf.bareudp_ns1.input=1 395 ip netns exec "${NS2}" sysctl -qw net.mpls.conf.bareudp_ns2.input=1 396 397 # Encapsulation instructions for bareudp over IPv4 398 tc -netns "${NS1}" filter add dev veth10 ingress protocol mpls_uc \ 399 flower mpls_label 203 \ 400 action tunnel_key set src_ip 192.0.2.21 dst_ip 192.0.2.22 id 0 \ 401 action mirred egress redirect dev bareudp_ns1 402 tc -netns "${NS2}" filter add dev veth23 ingress protocol mpls_uc \ 403 flower mpls_label 200 \ 404 action tunnel_key set src_ip 192.0.2.22 dst_ip 192.0.2.21 id 0 \ 405 action mirred egress redirect dev bareudp_ns2 406 fi 407 408 # Test IPv4 underlay 409 ping_test "UDPv4" 410 411 # Cleanup bareudp encapsulation instructions, as they were specific to 412 # the IPv4 underlay, before setting up and testing the IPv6 underlay 413 tc -netns "${NS1}" filter delete dev veth10 ingress 414 tc -netns "${NS2}" filter delete dev veth23 ingress 415 416 # IPv4 over UDPv6 417 if [ $IPV4 ]; then 418 # New encapsulation instructions for bareudp over IPv6 419 tc -netns "${NS1}" filter add dev veth10 ingress protocol ipv4 \ 420 flower dst_ip 192.0.2.103/32 \ 421 action tunnel_key set src_ip 2001:db8::21 dst_ip 2001:db8::22 id 0 \ 422 action mirred egress redirect dev bareudp_ns1 423 tc -netns "${NS2}" filter add dev veth23 ingress protocol ipv4 \ 424 flower dst_ip 192.0.2.100/32 \ 425 action tunnel_key set src_ip 2001:db8::22 dst_ip 2001:db8::21 id 0 \ 426 action mirred egress redirect dev bareudp_ns2 427 fi 428 429 # IPv6 over UDPv6 430 if [ $IPV6 ]; then 431 # New encapsulation instructions for bareudp over IPv6 432 tc -netns "${NS1}" filter add dev veth10 ingress protocol ipv6 \ 433 flower dst_ip 2001:db8::103/128 \ 434 action tunnel_key set src_ip 2001:db8::21 dst_ip 2001:db8::22 id 0 \ 435 action mirred egress redirect dev bareudp_ns1 436 tc -netns "${NS2}" filter add dev veth23 ingress protocol ipv6 \ 437 flower dst_ip 2001:db8::100/128 \ 438 action tunnel_key set src_ip 2001:db8::22 dst_ip 2001:db8::21 id 0 \ 439 action mirred egress redirect dev bareudp_ns2 440 fi 441 442 # MPLS (unicast) over UDPv6 443 if [ $MPLS_UC ]; then 444 # New encapsulation instructions for bareudp over IPv6 445 tc -netns "${NS1}" filter add dev veth10 ingress protocol mpls_uc \ 446 flower mpls_label 203 \ 447 action tunnel_key set src_ip 2001:db8::21 dst_ip 2001:db8::22 id 0 \ 448 action mirred egress redirect dev bareudp_ns1 449 tc -netns "${NS2}" filter add dev veth23 ingress protocol mpls_uc \ 450 flower mpls_label 200 \ 451 action tunnel_key set src_ip 2001:db8::22 dst_ip 2001:db8::21 id 0 \ 452 action mirred egress redirect dev bareudp_ns2 453 fi 454 455 # Test IPv6 underlay 456 ping_test "UDPv6" 457 458 tc -netns "${NS1}" filter delete dev veth10 ingress 459 tc -netns "${NS2}" filter delete dev veth23 ingress 460 ip -netns "${NS1}" link delete bareudp_ns1 461 ip -netns "${NS2}" link delete bareudp_ns2 462} 463 464check_features() 465{ 466 ip link help 2>&1 | grep -q bareudp 467 if [ $? -ne 0 ]; then 468 echo "Missing bareudp support in iproute2" >&2 469 exit_cleanup 470 fi 471 472 # Use ping6 on systems where ping doesn't handle IPv6 473 ping -w 1 -c 1 ::1 > /dev/null 2>&1 || PING6="ping6" 474} 475 476usage() 477{ 478 echo "Usage: $0 [-p]" 479 exit 1 480} 481 482while getopts :p o 483do 484 case $o in 485 p) PAUSE_ON_FAIL="yes";; 486 *) usage;; 487 esac 488done 489 490check_features 491 492set -e 493trap exit_cleanup EXIT 494 495create_namespaces 496 497setup_underlay 498setup_overlay_ipv4 499setup_overlay_ipv6 500setup_overlay_mpls 501 502test_overlay ipv4 nomultiproto 503test_overlay ipv6 nomultiproto 504test_overlay ipv4 multiproto 505test_overlay mpls_uc nomultiproto 506 507if [ "${ERR}" -eq 1 ]; then 508 echo "Some tests failed." >&2 509else 510 ERR=0 511fi 512