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