1 #!/bin/bash 2 # SPDX-License-Identifier: GPL-2.0 3 # 4 # author: Andrea Mayer <andrea.mayer@uniroma2.it> 5 # author: Paolo Lungaroni <paolo.lungaroni@uniroma2.it> 6 # 7 # This script is designed to test the support for "flavors" in the SRv6 End 8 # behavior. 9 # 10 # Flavors defined in RFC8986 [1] represent additional operations that can modify 11 # or extend the existing SRv6 End, End.X and End.T behaviors. For the sake of 12 # convenience, we report the list of flavors described in [1] hereafter: 13 # - Penultimate Segment Pop (PSP); 14 # - Ultimate Segment Pop (USP); 15 # - Ultimate Segment Decapsulation (USD). 16 # 17 # The End, End.X, and End.T behaviors can support these flavors either 18 # individually or in combinations. 19 # Currently in this selftest we consider only the PSP flavor for the SRv6 End 20 # behavior. However, it is possible to extend the script as soon as other 21 # flavors will be supported in the kernel. 22 # 23 # The purpose of the PSP flavor consists in instructing the penultimate node 24 # listed in the SRv6 policy to remove (i.e. pop) the outermost SRH from the IPv6 25 # header. 26 # A PSP enabled SRv6 End behavior instance processes the SRH by: 27 # - decrementing the Segment Left (SL) value from 1 to 0; 28 # - copying the last SID from the SID List into the IPv6 Destination Address 29 # (DA); 30 # - removing the SRH from the extension headers following the IPv6 header. 31 # 32 # Once the SRH is removed, the IPv6 packet is forwarded to the destination using 33 # the IPv6 DA updated during the PSP operation (i.e. the IPv6 DA corresponding 34 # to the last SID carried by the removed SRH). 35 # 36 # Although the PSP flavor can be set for any SRv6 End behavior instance on any 37 # SR node, it will be active only on such behaviors bound to a penultimate SID 38 # for a given SRv6 policy. 39 # SL=2 SL=1 SL=0 40 # | | | 41 # For example, given the SRv6 policy (SID List := <X, Y, Z>): 42 # - a PSP enabled SRv6 End behavior bound to SID Y will apply the PSP operation 43 # as Segment Left (SL) is 1, corresponding to the Penultimate Segment of the 44 # SID List; 45 # - a PSP enabled SRv6 End behavior bound to SID X will *NOT* apply the PSP 46 # operation as the Segment Left is 2. This behavior instance will apply the 47 # "standard" End packet processing, ignoring the configured PSP flavor at 48 # all. 49 # 50 # [1] RFC8986: https://datatracker.ietf.org/doc/html/rfc8986 51 # 52 # Network topology 53 # ================ 54 # 55 # The network topology used in this selftest is depicted hereafter, composed by 56 # two hosts (hs-1, hs-2) and four routers (rt-1, rt-2, rt-3, rt-4). 57 # Hosts hs-1 and hs-2 are connected to routers rt-1 and rt-2, respectively, 58 # allowing them to communicate with each other. 59 # Traffic exchanged between hs-1 and hs-2 can follow different network paths. 60 # The network operator, through specific SRv6 Policies can steer traffic to one 61 # path rather than another. In this selftest this is implemented as follows: 62 # 63 # i) The SRv6 H.Insert behavior applies SRv6 Policies on traffic received by 64 # connected hosts. It pushes the Segment Routing Header (SRH) after the 65 # IPv6 header. The SRH contains the SID List (i.e. SRv6 Policy) needed for 66 # steering traffic across the segments/waypoints specified in that list; 67 # 68 # ii) The SRv6 End behavior advances the active SID in the SID List carried by 69 # the SRH; 70 # 71 # iii) The PSP enabled SRv6 End behavior is used to remove the SRH when such 72 # behavior is configured on a node bound to the Penultimate Segment carried 73 # by the SID List. 74 # 75 # cafe::1 cafe::2 76 # +--------+ +--------+ 77 # | | | | 78 # | hs-1 | | hs-2 | 79 # | | | | 80 # +---+----+ +--- +---+ 81 # cafe::/64 | | cafe::/64 82 # | | 83 # +---+----+ +----+---+ 84 # | | fcf0:0:1:2::/64 | | 85 # | rt-1 +-------------------+ rt-2 | 86 # | | | | 87 # +---+----+ +----+---+ 88 # | . . | 89 # | fcf0:0:1:3::/64 . | 90 # | . . | 91 # | . . | 92 # fcf0:0:1:4::/64 | . | fcf0:0:2:3::/64 93 # | . . | 94 # | . . | 95 # | fcf0:0:2:4::/64 . | 96 # | . . | 97 # +---+----+ +----+---+ 98 # | | | | 99 # | rt-4 +-------------------+ rt-3 | 100 # | | fcf0:0:3:4::/64 | | 101 # +---+----+ +----+---+ 102 # 103 # Every fcf0:0:x:y::/64 network interconnects the SRv6 routers rt-x with rt-y in 104 # the IPv6 operator network. 105 # 106 # 107 # Local SID table 108 # =============== 109 # 110 # Each SRv6 router is configured with a Local SID table in which SIDs are 111 # stored. Considering the given SRv6 router rt-x, at least two SIDs are 112 # configured in the Local SID table: 113 # 114 # Local SID table for SRv6 router rt-x 115 # +---------------------------------------------------------------------+ 116 # |fcff:x::e is associated with the SRv6 End behavior | 117 # |fcff:x::ef1 is associated with the SRv6 End behavior with PSP flavor | 118 # +---------------------------------------------------------------------+ 119 # 120 # The fcff::/16 prefix is reserved by the operator for the SIDs. Reachability of 121 # SIDs is ensured by proper configuration of the IPv6 operator's network and 122 # SRv6 routers. 123 # 124 # 125 # SRv6 Policies 126 # ============= 127 # 128 # An SRv6 ingress router applies different SRv6 Policies to the traffic received 129 # from connected hosts on the basis of the destination addresses. 130 # In case of SRv6 H.Insert behavior, the SRv6 Policy enforcement consists of 131 # pushing the SRH (carrying a given SID List) after the existing IPv6 header. 132 # Note that in the inserting mode, there is no encapsulation at all. 133 # 134 # Before applying an SRv6 Policy using the SRv6 H.Insert behavior 135 # +------+---------+ 136 # | IPv6 | Payload | 137 # +------+---------+ 138 # 139 # After applying an SRv6 Policy using the SRv6 H.Insert behavior 140 # +------+-----+---------+ 141 # | IPv6 | SRH | Payload | 142 # +------+-----+---------+ 143 # 144 # Traffic from hs-1 to hs-2 145 # ------------------------- 146 # 147 # Packets generated from hs-1 and directed towards hs-2 are 148 # handled by rt-1 which applies the following SRv6 Policy: 149 # 150 # i.a) IPv6 traffic, SID List=fcff:3::e,fcff:4::ef1,fcff:2::ef1,cafe::2 151 # 152 # Router rt-1 is configured to enforce the Policy (i.a) through the SRv6 153 # H.Insert behavior which pushes the SRH after the existing IPv6 header. This 154 # Policy steers the traffic from hs-1 across rt-3, rt-4, rt-2 and finally to the 155 # destination hs-2. 156 # 157 # As the packet reaches the router rt-3, the SRv6 End behavior bound to SID 158 # fcff:3::e is triggered. The behavior updates the Segment Left (from SL=3 to 159 # SL=2) in the SRH, the IPv6 DA with fcff:4::ef1 and forwards the packet to the 160 # next router on the path, i.e. rt-4. 161 # 162 # When router rt-4 receives the packet, the PSP enabled SRv6 End behavior bound 163 # to SID fcff:4::ef1 is executed. Since the SL=2, the PSP operation is *NOT* 164 # kicked in and the behavior applies the default End processing: the Segment 165 # Left is decreased (from SL=2 to SL=1), the IPv6 DA is updated with the SID 166 # fcff:2::ef1 and the packet is forwarded to router rt-2. 167 # 168 # The PSP enabled SRv6 End behavior on rt-2 is associated with SID fcff:2::ef1 169 # and is executed as the packet is received. Because SL=1, the behavior applies 170 # the PSP processing on the packet as follows: i) SL is decreased, i.e. from 171 # SL=1 to SL=0; ii) last SID (cafe::2) is copied into the IPv6 DA; iii) the 172 # outermost SRH is removed from the extension headers following the IPv6 header. 173 # Once the PSP processing is completed, the packet is forwarded to the host hs-2 174 # (destination). 175 # 176 # Traffic from hs-2 to hs-1 177 # ------------------------- 178 # 179 # Packets generated from hs-2 and directed to hs-1 are handled by rt-2 which 180 # applies the following SRv6 Policy: 181 # 182 # i.b) IPv6 traffic, SID List=fcff:1::ef1,cafe::1 183 # 184 # Router rt-2 is configured to enforce the Policy (i.b) through the SRv6 185 # H.Insert behavior which pushes the SRH after the existing IPv6 header. This 186 # Policy steers the traffic from hs-2 across rt-1 and finally to the 187 # destination hs-1 188 # 189 # 190 # When the router rt-1 receives the packet, the PSP enabled SRv6 End behavior 191 # associated with the SID fcff:1::ef1 is triggered. Since the SL=1, 192 # the PSP operation takes place: i) the SL is decremented; ii) the IPv6 DA is 193 # set with the last SID; iii) the SRH is removed from the extension headers 194 # after the IPv6 header. At this point, the packet with IPv6 DA=cafe::1 is sent 195 # to the destination, i.e. hs-1. 196 197 # Kselftest framework requirement - SKIP code is 4. 198 readonly ksft_skip=4 199 200 readonly RDMSUFF="$(mktemp -u XXXXXXXX)" 201 readonly DUMMY_DEVNAME="dum0" 202 readonly RT2HS_DEVNAME="veth1" 203 readonly LOCALSID_TABLE_ID=90 204 readonly IPv6_RT_NETWORK=fcf0:0 205 readonly IPv6_HS_NETWORK=cafe 206 readonly IPv6_TESTS_ADDR=2001:db8::1 207 readonly LOCATOR_SERVICE=fcff 208 readonly END_FUNC=000e 209 readonly END_PSP_FUNC=0ef1 210 211 PING_TIMEOUT_SEC=4 212 PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no} 213 214 # IDs of routers and hosts are initialized during the setup of the testing 215 # network 216 ROUTERS='' 217 HOSTS='' 218 219 SETUP_ERR=1 220 221 ret=${ksft_skip} 222 nsuccess=0 223 nfail=0 224 225 log_test() 226 { 227 local rc="$1" 228 local expected="$2" 229 local msg="$3" 230 231 if [ "${rc}" -eq "${expected}" ]; then 232 nsuccess=$((nsuccess+1)) 233 printf "\n TEST: %-60s [ OK ]\n" "${msg}" 234 else 235 ret=1 236 nfail=$((nfail+1)) 237 printf "\n TEST: %-60s [FAIL]\n" "${msg}" 238 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then 239 echo 240 echo "hit enter to continue, 'q' to quit" 241 read a 242 [ "$a" = "q" ] && exit 1 243 fi 244 fi 245 } 246 247 print_log_test_results() 248 { 249 printf "\nTests passed: %3d\n" "${nsuccess}" 250 printf "Tests failed: %3d\n" "${nfail}" 251 252 # when a test fails, the value of 'ret' is set to 1 (error code). 253 # Conversely, when all tests are passed successfully, the 'ret' value 254 # is set to 0 (success code). 255 if [ "${ret}" -ne 1 ]; then 256 ret=0 257 fi 258 } 259 260 log_section() 261 { 262 echo 263 echo "################################################################################" 264 echo "TEST SECTION: $*" 265 echo "################################################################################" 266 } 267 268 test_command_or_ksft_skip() 269 { 270 local cmd="$1" 271 272 if [ ! -x "$(command -v "${cmd}")" ]; then 273 echo "SKIP: Could not run test without \"${cmd}\" tool"; 274 exit "${ksft_skip}" 275 fi 276 } 277 278 get_nodename() 279 { 280 local name="$1" 281 282 echo "${name}-${RDMSUFF}" 283 } 284 285 get_rtname() 286 { 287 local rtid="$1" 288 289 get_nodename "rt-${rtid}" 290 } 291 292 get_hsname() 293 { 294 local hsid="$1" 295 296 get_nodename "hs-${hsid}" 297 } 298 299 __create_namespace() 300 { 301 local name="$1" 302 303 ip netns add "${name}" 304 } 305 306 create_router() 307 { 308 local rtid="$1" 309 local nsname 310 311 nsname="$(get_rtname "${rtid}")" 312 313 __create_namespace "${nsname}" 314 } 315 316 create_host() 317 { 318 local hsid="$1" 319 local nsname 320 321 nsname="$(get_hsname "${hsid}")" 322 323 __create_namespace "${nsname}" 324 } 325 326 cleanup() 327 { 328 local nsname 329 local i 330 331 # destroy routers 332 for i in ${ROUTERS}; do 333 nsname="$(get_rtname "${i}")" 334 335 ip netns del "${nsname}" &>/dev/null || true 336 done 337 338 # destroy hosts 339 for i in ${HOSTS}; do 340 nsname="$(get_hsname "${i}")" 341 342 ip netns del "${nsname}" &>/dev/null || true 343 done 344 345 # check whether the setup phase was completed successfully or not. In 346 # case of an error during the setup phase of the testing environment, 347 # the selftest is considered as "skipped". 348 if [ "${SETUP_ERR}" -ne 0 ]; then 349 echo "SKIP: Setting up the testing environment failed" 350 exit "${ksft_skip}" 351 fi 352 353 exit "${ret}" 354 } 355 356 add_link_rt_pairs() 357 { 358 local rt="$1" 359 local rt_neighs="$2" 360 local neigh 361 local nsname 362 local neigh_nsname 363 364 nsname="$(get_rtname "${rt}")" 365 366 for neigh in ${rt_neighs}; do 367 neigh_nsname="$(get_rtname "${neigh}")" 368 369 ip link add "veth-rt-${rt}-${neigh}" netns "${nsname}" \ 370 type veth peer name "veth-rt-${neigh}-${rt}" \ 371 netns "${neigh_nsname}" 372 done 373 } 374 375 get_network_prefix() 376 { 377 local rt="$1" 378 local neigh="$2" 379 local p="${rt}" 380 local q="${neigh}" 381 382 if [ "${p}" -gt "${q}" ]; then 383 p="${q}"; q="${rt}" 384 fi 385 386 echo "${IPv6_RT_NETWORK}:${p}:${q}" 387 } 388 389 # Given the description of a router <id:op> as an input, the function returns 390 # the <id> token which represents the ID of the router. 391 # i.e. input: "12:psp" 392 # output: "12" 393 __get_srv6_rtcfg_id() 394 { 395 local element="$1" 396 397 echo "${element}" | cut -d':' -f1 398 } 399 400 # Given the description of a router <id:op> as an input, the function returns 401 # the <op> token which represents the operation (e.g. End behavior with or 402 # withouth flavors) configured for the node. 403 404 # Note that when the operation represents an End behavior with a list of 405 # flavors, the output is the ordered version of that list. 406 # i.e. input: "5:usp,psp,usd" 407 # output: "psp,usd,usp" 408 __get_srv6_rtcfg_op() 409 { 410 local element="$1" 411 412 # return the lexicographically ordered flavors 413 echo "${element}" | cut -d':' -f2 | sed 's/,/\n/g' | sort | \ 414 xargs | sed 's/ /,/g' 415 } 416 417 # Setup the basic networking for the routers 418 setup_rt_networking() 419 { 420 local rt="$1" 421 local rt_neighs="$2" 422 local nsname 423 local net_prefix 424 local devname 425 local neigh 426 427 nsname="$(get_rtname "${rt}")" 428 429 for neigh in ${rt_neighs}; do 430 devname="veth-rt-${rt}-${neigh}" 431 432 net_prefix="$(get_network_prefix "${rt}" "${neigh}")" 433 434 ip -netns "${nsname}" addr \ 435 add "${net_prefix}::${rt}/64" dev "${devname}" nodad 436 437 ip -netns "${nsname}" link set "${devname}" up 438 done 439 440 ip -netns "${nsname}" link set lo up 441 442 ip -netns "${nsname}" link add ${DUMMY_DEVNAME} type dummy 443 ip -netns "${nsname}" link set ${DUMMY_DEVNAME} up 444 445 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0 446 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0 447 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.forwarding=1 448 } 449 450 # Setup local SIDs for an SRv6 router 451 setup_rt_local_sids() 452 { 453 local rt="$1" 454 local rt_neighs="$2" 455 local net_prefix 456 local devname 457 local nsname 458 local neigh 459 460 nsname="$(get_rtname "${rt}")" 461 462 for neigh in ${rt_neighs}; do 463 devname="veth-rt-${rt}-${neigh}" 464 465 net_prefix="$(get_network_prefix "${rt}" "${neigh}")" 466 467 # set underlay network routes for SIDs reachability 468 ip -netns "${nsname}" -6 route \ 469 add "${LOCATOR_SERVICE}:${neigh}::/32" \ 470 table "${LOCALSID_TABLE_ID}" \ 471 via "${net_prefix}::${neigh}" dev "${devname}" 472 done 473 474 # Local End behavior (note that "dev" is a dummy interface chosen for 475 # the sake of simplicity). 476 ip -netns "${nsname}" -6 route \ 477 add "${LOCATOR_SERVICE}:${rt}::${END_FUNC}" \ 478 table "${LOCALSID_TABLE_ID}" \ 479 encap seg6local action End dev "${DUMMY_DEVNAME}" 480 481 482 # all SIDs start with a common locator. Routes and SRv6 Endpoint 483 # behavior instaces are grouped together in the 'localsid' table. 484 ip -netns "${nsname}" -6 rule \ 485 add to "${LOCATOR_SERVICE}::/16" \ 486 lookup "${LOCALSID_TABLE_ID}" prio 999 487 488 # set default routes to unreachable 489 ip -netns "${nsname}" -6 route \ 490 add unreachable default metric 4278198272 \ 491 dev "${DUMMY_DEVNAME}" 492 } 493 494 # This helper function builds and installs the SID List (i.e. SRv6 Policy) 495 # to be applied on incoming packets at the ingress node. Moreover, it 496 # configures the SRv6 nodes specified in the SID List to process the traffic 497 # according to the operations required by the Policy itself. 498 # args: 499 # $1 - destination host (i.e. cafe::x host) 500 # $2 - SRv6 router configured for enforcing the SRv6 Policy 501 # $3 - compact way to represent a list of SRv6 routers with their operations 502 # (i.e. behaviors) that each of them needs to perform. Every <nodeid:op> 503 # element constructs a SID that is associated with the behavior <op> on 504 # the <nodeid> node. The list of such elements forms an SRv6 Policy. 505 __setup_rt_policy() 506 { 507 local dst="$1" 508 local encap_rt="$2" 509 local policy_rts="$3" 510 local behavior_cfg 511 local in_nsname 512 local rt_nsname 513 local policy='' 514 local function 515 local fullsid 516 local op_type 517 local node 518 local n 519 520 in_nsname="$(get_rtname "${encap_rt}")" 521 522 for n in ${policy_rts}; do 523 node="$(__get_srv6_rtcfg_id "${n}")" 524 op_type="$(__get_srv6_rtcfg_op "${n}")" 525 rt_nsname="$(get_rtname "${node}")" 526 527 case "${op_type}" in 528 "noflv") 529 policy="${policy}${LOCATOR_SERVICE}:${node}::${END_FUNC}," 530 function="${END_FUNC}" 531 behavior_cfg="End" 532 ;; 533 534 "psp") 535 policy="${policy}${LOCATOR_SERVICE}:${node}::${END_PSP_FUNC}," 536 function="${END_PSP_FUNC}" 537 behavior_cfg="End flavors psp" 538 ;; 539 540 *) 541 break 542 ;; 543 esac 544 545 fullsid="${LOCATOR_SERVICE}:${node}::${function}" 546 547 # add SRv6 Endpoint behavior to the selected router 548 if ! ip -netns "${rt_nsname}" -6 route get "${fullsid}" \ 549 &>/dev/null; then 550 ip -netns "${rt_nsname}" -6 route \ 551 add "${fullsid}" \ 552 table "${LOCALSID_TABLE_ID}" \ 553 encap seg6local action ${behavior_cfg} \ 554 dev "${DUMMY_DEVNAME}" 555 fi 556 done 557 558 # we need to remove the trailing comma to avoid inserting an empty 559 # address (::0) in the SID List. 560 policy="${policy%,}" 561 562 # add SRv6 policy to incoming traffic sent by connected hosts 563 ip -netns "${in_nsname}" -6 route \ 564 add "${IPv6_HS_NETWORK}::${dst}" \ 565 encap seg6 mode inline segs "${policy}" \ 566 dev "${DUMMY_DEVNAME}" 567 568 ip -netns "${in_nsname}" -6 neigh \ 569 add proxy "${IPv6_HS_NETWORK}::${dst}" \ 570 dev "${RT2HS_DEVNAME}" 571 } 572 573 # see __setup_rt_policy 574 setup_rt_policy_ipv6() 575 { 576 __setup_rt_policy "$1" "$2" "$3" 577 } 578 579 setup_hs() 580 { 581 local hs="$1" 582 local rt="$2" 583 local hsname 584 local rtname 585 586 hsname="$(get_hsname "${hs}")" 587 rtname="$(get_rtname "${rt}")" 588 589 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0 590 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0 591 592 ip -netns "${hsname}" link add veth0 type veth \ 593 peer name "${RT2HS_DEVNAME}" netns "${rtname}" 594 595 ip -netns "${hsname}" addr \ 596 add "${IPv6_HS_NETWORK}::${hs}/64" dev veth0 nodad 597 598 ip -netns "${hsname}" link set veth0 up 599 ip -netns "${hsname}" link set lo up 600 601 ip -netns "${rtname}" addr \ 602 add "${IPv6_HS_NETWORK}::254/64" dev "${RT2HS_DEVNAME}" nodad 603 604 ip -netns "${rtname}" link set "${RT2HS_DEVNAME}" up 605 606 ip netns exec "${rtname}" \ 607 sysctl -wq net.ipv6.conf."${RT2HS_DEVNAME}".proxy_ndp=1 608 } 609 610 setup() 611 { 612 local i 613 614 # create routers 615 ROUTERS="1 2 3 4"; readonly ROUTERS 616 for i in ${ROUTERS}; do 617 create_router "${i}" 618 done 619 620 # create hosts 621 HOSTS="1 2"; readonly HOSTS 622 for i in ${HOSTS}; do 623 create_host "${i}" 624 done 625 626 # set up the links for connecting routers 627 add_link_rt_pairs 1 "2 3 4" 628 add_link_rt_pairs 2 "3 4" 629 add_link_rt_pairs 3 "4" 630 631 # set up the basic connectivity of routers and routes required for 632 # reachability of SIDs. 633 setup_rt_networking 1 "2 3 4" 634 setup_rt_networking 2 "1 3 4" 635 setup_rt_networking 3 "1 2 4" 636 setup_rt_networking 4 "1 2 3" 637 638 # set up the hosts connected to routers 639 setup_hs 1 1 640 setup_hs 2 2 641 642 # set up default SRv6 Endpoints (i.e. SRv6 End behavior) 643 setup_rt_local_sids 1 "2 3 4" 644 setup_rt_local_sids 2 "1 3 4" 645 setup_rt_local_sids 3 "1 2 4" 646 setup_rt_local_sids 4 "1 2 3" 647 648 # set up SRv6 policies 649 # create a connection between hosts hs-1 and hs-2. 650 # The path between hs-1 and hs-2 traverses SRv6 aware routers. 651 # For each direction two path are chosen: 652 # 653 # Direction hs-1 -> hs-2 (PSP flavor) 654 # - rt-1 (SRv6 H.Insert policy) 655 # - rt-3 (SRv6 End behavior) 656 # - rt-4 (SRv6 End flavor PSP with SL>1, acting as End behavior) 657 # - rt-2 (SRv6 End flavor PSP with SL=1) 658 # 659 # Direction hs-2 -> hs-1 (PSP flavor) 660 # - rt-2 (SRv6 H.Insert policy) 661 # - rt-1 (SRv6 End flavor PSP with SL=1) 662 setup_rt_policy_ipv6 2 1 "3:noflv 4:psp 2:psp" 663 setup_rt_policy_ipv6 1 2 "1:psp" 664 665 # testing environment was set up successfully 666 SETUP_ERR=0 667 } 668 669 check_rt_connectivity() 670 { 671 local rtsrc="$1" 672 local rtdst="$2" 673 local prefix 674 local rtsrc_nsname 675 676 rtsrc_nsname="$(get_rtname "${rtsrc}")" 677 678 prefix="$(get_network_prefix "${rtsrc}" "${rtdst}")" 679 680 ip netns exec "${rtsrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \ 681 "${prefix}::${rtdst}" >/dev/null 2>&1 682 } 683 684 check_and_log_rt_connectivity() 685 { 686 local rtsrc="$1" 687 local rtdst="$2" 688 689 check_rt_connectivity "${rtsrc}" "${rtdst}" 690 log_test $? 0 "Routers connectivity: rt-${rtsrc} -> rt-${rtdst}" 691 } 692 693 check_hs_ipv6_connectivity() 694 { 695 local hssrc="$1" 696 local hsdst="$2" 697 local hssrc_nsname 698 699 hssrc_nsname="$(get_hsname "${hssrc}")" 700 701 ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \ 702 "${IPv6_HS_NETWORK}::${hsdst}" >/dev/null 2>&1 703 } 704 705 check_and_log_hs2gw_connectivity() 706 { 707 local hssrc="$1" 708 709 check_hs_ipv6_connectivity "${hssrc}" 254 710 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> gw" 711 } 712 713 check_and_log_hs_ipv6_connectivity() 714 { 715 local hssrc="$1" 716 local hsdst="$2" 717 718 check_hs_ipv6_connectivity "${hssrc}" "${hsdst}" 719 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}" 720 } 721 722 check_and_log_hs_connectivity() 723 { 724 local hssrc="$1" 725 local hsdst="$2" 726 727 check_and_log_hs_ipv6_connectivity "${hssrc}" "${hsdst}" 728 } 729 730 router_tests() 731 { 732 local i 733 local j 734 735 log_section "IPv6 routers connectivity test" 736 737 for i in ${ROUTERS}; do 738 for j in ${ROUTERS}; do 739 if [ "${i}" -eq "${j}" ]; then 740 continue 741 fi 742 743 check_and_log_rt_connectivity "${i}" "${j}" 744 done 745 done 746 } 747 748 host2gateway_tests() 749 { 750 local hs 751 752 log_section "IPv6 connectivity test among hosts and gateways" 753 754 for hs in ${HOSTS}; do 755 check_and_log_hs2gw_connectivity "${hs}" 756 done 757 } 758 759 host_srv6_end_flv_psp_tests() 760 { 761 log_section "SRv6 connectivity test hosts (h1 <-> h2, PSP flavor)" 762 763 check_and_log_hs_connectivity 1 2 764 check_and_log_hs_connectivity 2 1 765 } 766 767 test_iproute2_supp_or_ksft_skip() 768 { 769 local flavor="$1" 770 771 if ! ip route help 2>&1 | grep -qo "${flavor}"; then 772 echo "SKIP: Missing SRv6 ${flavor} flavor support in iproute2" 773 exit "${ksft_skip}" 774 fi 775 } 776 777 test_kernel_supp_or_ksft_skip() 778 { 779 local flavor="$1" 780 local test_netns 781 782 test_netns="kflv-$(mktemp -u XXXXXXXX)" 783 784 if ! ip netns add "${test_netns}"; then 785 echo "SKIP: Cannot set up netns to test kernel support for flavors" 786 exit "${ksft_skip}" 787 fi 788 789 if ! ip -netns "${test_netns}" link \ 790 add "${DUMMY_DEVNAME}" type dummy; then 791 echo "SKIP: Cannot set up dummy dev to test kernel support for flavors" 792 793 ip netns del "${test_netns}" 794 exit "${ksft_skip}" 795 fi 796 797 if ! ip -netns "${test_netns}" link \ 798 set "${DUMMY_DEVNAME}" up; then 799 echo "SKIP: Cannot activate dummy dev to test kernel support for flavors" 800 801 ip netns del "${test_netns}" 802 exit "${ksft_skip}" 803 fi 804 805 if ! ip -netns "${test_netns}" -6 route \ 806 add "${IPv6_TESTS_ADDR}" encap seg6local \ 807 action End flavors "${flavor}" dev "${DUMMY_DEVNAME}"; then 808 echo "SKIP: ${flavor} flavor not supported in kernel" 809 810 ip netns del "${test_netns}" 811 exit "${ksft_skip}" 812 fi 813 814 ip netns del "${test_netns}" 815 } 816 817 test_dummy_dev_or_ksft_skip() 818 { 819 local test_netns 820 821 test_netns="dummy-$(mktemp -u XXXXXXXX)" 822 823 if ! ip netns add "${test_netns}"; then 824 echo "SKIP: Cannot set up netns for testing dummy dev support" 825 exit "${ksft_skip}" 826 fi 827 828 modprobe dummy &>/dev/null || true 829 if ! ip -netns "${test_netns}" link \ 830 add "${DUMMY_DEVNAME}" type dummy; then 831 echo "SKIP: dummy dev not supported" 832 833 ip netns del "${test_netns}" 834 exit "${ksft_skip}" 835 fi 836 837 ip netns del "${test_netns}" 838 } 839 840 if [ "$(id -u)" -ne 0 ]; then 841 echo "SKIP: Need root privileges" 842 exit "${ksft_skip}" 843 fi 844 845 # required programs to carry out this selftest 846 test_command_or_ksft_skip ip 847 test_command_or_ksft_skip ping 848 test_command_or_ksft_skip sysctl 849 test_command_or_ksft_skip grep 850 test_command_or_ksft_skip cut 851 test_command_or_ksft_skip sed 852 test_command_or_ksft_skip sort 853 test_command_or_ksft_skip xargs 854 855 test_dummy_dev_or_ksft_skip 856 test_iproute2_supp_or_ksft_skip psp 857 test_kernel_supp_or_ksft_skip psp 858 859 set -e 860 trap cleanup EXIT 861 862 setup 863 set +e 864 865 router_tests 866 host2gateway_tests 867 host_srv6_end_flv_psp_tests 868 869 print_log_test_results
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.