0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 readonly ksft_skip=4
0121
0122 readonly RDMSUFF="$(mktemp -u XXXXXXXX)"
0123 readonly DUMMY_DEVNAME="dum0"
0124 readonly RT2HS_DEVNAME="veth-hs"
0125 readonly HS_VETH_NAME="veth0"
0126 readonly LOCALSID_TABLE_ID=90
0127 readonly IPv6_RT_NETWORK=fcf0:0
0128 readonly IPv6_HS_NETWORK=cafe
0129 readonly IPv4_HS_NETWORK=10.0.0
0130 readonly VPN_LOCATOR_SERVICE=fcff
0131 readonly MAC_PREFIX=00:00:00:c0:01
0132 readonly END_FUNC=000e
0133 readonly DX2_FUNC=00d2
0134
0135 PING_TIMEOUT_SEC=4
0136 PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
0137
0138
0139
0140 ROUTERS=''
0141 HOSTS=''
0142
0143 SETUP_ERR=1
0144
0145 ret=${ksft_skip}
0146 nsuccess=0
0147 nfail=0
0148
0149 log_test()
0150 {
0151 local rc="$1"
0152 local expected="$2"
0153 local msg="$3"
0154
0155 if [ "${rc}" -eq "${expected}" ]; then
0156 nsuccess=$((nsuccess+1))
0157 printf "\n TEST: %-60s [ OK ]\n" "${msg}"
0158 else
0159 ret=1
0160 nfail=$((nfail+1))
0161 printf "\n TEST: %-60s [FAIL]\n" "${msg}"
0162 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
0163 echo
0164 echo "hit enter to continue, 'q' to quit"
0165 read a
0166 [ "$a" = "q" ] && exit 1
0167 fi
0168 fi
0169 }
0170
0171 print_log_test_results()
0172 {
0173 printf "\nTests passed: %3d\n" "${nsuccess}"
0174 printf "Tests failed: %3d\n" "${nfail}"
0175
0176
0177
0178
0179 if [ "${ret}" -ne 1 ]; then
0180 ret=0
0181 fi
0182 }
0183
0184 log_section()
0185 {
0186 echo
0187 echo "################################################################################"
0188 echo "TEST SECTION: $*"
0189 echo "################################################################################"
0190 }
0191
0192 test_command_or_ksft_skip()
0193 {
0194 local cmd="$1"
0195
0196 if [ ! -x "$(command -v "${cmd}")" ]; then
0197 echo "SKIP: Could not run test without \"${cmd}\" tool";
0198 exit "${ksft_skip}"
0199 fi
0200 }
0201
0202 get_nodename()
0203 {
0204 local name="$1"
0205
0206 echo "${name}-${RDMSUFF}"
0207 }
0208
0209 get_rtname()
0210 {
0211 local rtid="$1"
0212
0213 get_nodename "rt-${rtid}"
0214 }
0215
0216 get_hsname()
0217 {
0218 local hsid="$1"
0219
0220 get_nodename "hs-${hsid}"
0221 }
0222
0223 __create_namespace()
0224 {
0225 local name="$1"
0226
0227 ip netns add "${name}"
0228 }
0229
0230 create_router()
0231 {
0232 local rtid="$1"
0233 local nsname
0234
0235 nsname="$(get_rtname "${rtid}")"
0236
0237 __create_namespace "${nsname}"
0238 }
0239
0240 create_host()
0241 {
0242 local hsid="$1"
0243 local nsname
0244
0245 nsname="$(get_hsname "${hsid}")"
0246
0247 __create_namespace "${nsname}"
0248 }
0249
0250 cleanup()
0251 {
0252 local nsname
0253 local i
0254
0255
0256 for i in ${ROUTERS}; do
0257 nsname="$(get_rtname "${i}")"
0258
0259 ip netns del "${nsname}" &>/dev/null || true
0260 done
0261
0262
0263 for i in ${HOSTS}; do
0264 nsname="$(get_hsname "${i}")"
0265
0266 ip netns del "${nsname}" &>/dev/null || true
0267 done
0268
0269
0270
0271
0272 if [ "${SETUP_ERR}" -ne 0 ]; then
0273 echo "SKIP: Setting up the testing environment failed"
0274 exit "${ksft_skip}"
0275 fi
0276
0277 exit "${ret}"
0278 }
0279
0280 add_link_rt_pairs()
0281 {
0282 local rt="$1"
0283 local rt_neighs="$2"
0284 local neigh
0285 local nsname
0286 local neigh_nsname
0287
0288 nsname="$(get_rtname "${rt}")"
0289
0290 for neigh in ${rt_neighs}; do
0291 neigh_nsname="$(get_rtname "${neigh}")"
0292
0293 ip link add "veth-rt-${rt}-${neigh}" netns "${nsname}" \
0294 type veth peer name "veth-rt-${neigh}-${rt}" \
0295 netns "${neigh_nsname}"
0296 done
0297 }
0298
0299 get_network_prefix()
0300 {
0301 local rt="$1"
0302 local neigh="$2"
0303 local p="${rt}"
0304 local q="${neigh}"
0305
0306 if [ "${p}" -gt "${q}" ]; then
0307 p="${q}"; q="${rt}"
0308 fi
0309
0310 echo "${IPv6_RT_NETWORK}:${p}:${q}"
0311 }
0312
0313
0314 setup_rt_networking()
0315 {
0316 local rt="$1"
0317 local rt_neighs="$2"
0318 local nsname
0319 local net_prefix
0320 local devname
0321 local neigh
0322
0323 nsname="$(get_rtname "${rt}")"
0324
0325 for neigh in ${rt_neighs}; do
0326 devname="veth-rt-${rt}-${neigh}"
0327
0328 net_prefix="$(get_network_prefix "${rt}" "${neigh}")"
0329
0330 ip -netns "${nsname}" addr \
0331 add "${net_prefix}::${rt}/64" dev "${devname}" nodad
0332
0333 ip -netns "${nsname}" link set "${devname}" up
0334 done
0335
0336 ip -netns "${nsname}" link add "${DUMMY_DEVNAME}" type dummy
0337
0338 ip -netns "${nsname}" link set "${DUMMY_DEVNAME}" up
0339 ip -netns "${nsname}" link set lo up
0340
0341 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0
0342 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0
0343 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.forwarding=1
0344
0345 ip netns exec "${nsname}" sysctl -wq net.ipv4.conf.all.rp_filter=0
0346 ip netns exec "${nsname}" sysctl -wq net.ipv4.conf.default.rp_filter=0
0347 ip netns exec "${nsname}" sysctl -wq net.ipv4.ip_forward=1
0348 }
0349
0350
0351 setup_rt_local_sids()
0352 {
0353 local rt="$1"
0354 local rt_neighs="$2"
0355 local net_prefix
0356 local devname
0357 local nsname
0358 local neigh
0359
0360 nsname="$(get_rtname "${rt}")"
0361
0362 for neigh in ${rt_neighs}; do
0363 devname="veth-rt-${rt}-${neigh}"
0364
0365 net_prefix="$(get_network_prefix "${rt}" "${neigh}")"
0366
0367
0368 ip -netns "${nsname}" -6 route \
0369 add "${VPN_LOCATOR_SERVICE}:${neigh}::/32" \
0370 table "${LOCALSID_TABLE_ID}" \
0371 via "${net_prefix}::${neigh}" dev "${devname}"
0372 done
0373
0374
0375
0376 ip -netns "${nsname}" -6 route \
0377 add "${VPN_LOCATOR_SERVICE}:${rt}::${END_FUNC}" \
0378 table "${LOCALSID_TABLE_ID}" \
0379 encap seg6local action End dev "${DUMMY_DEVNAME}"
0380
0381
0382
0383
0384 ip -netns "${nsname}" -6 rule add \
0385 to "${VPN_LOCATOR_SERVICE}::/16" \
0386 lookup "${LOCALSID_TABLE_ID}" prio 999
0387 }
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398 __setup_rt_policy()
0399 {
0400 local dst="$1"
0401 local encap_rt="$2"
0402 local end_rts="$3"
0403 local dec_rt="$4"
0404 local mode="$5"
0405 local traffic="$6"
0406 local nsname
0407 local policy=''
0408 local n
0409
0410 nsname="$(get_rtname "${encap_rt}")"
0411
0412 for n in ${end_rts}; do
0413 policy="${policy}${VPN_LOCATOR_SERVICE}:${n}::${END_FUNC},"
0414 done
0415
0416 policy="${policy}${VPN_LOCATOR_SERVICE}:${dec_rt}::${DX2_FUNC}"
0417
0418
0419 if [ "${traffic}" -eq 6 ]; then
0420 ip -netns "${nsname}" -6 route \
0421 add "${IPv6_HS_NETWORK}::${dst}" \
0422 encap seg6 mode "${mode}" segs "${policy}" \
0423 dev dum0
0424 else
0425 ip -netns "${nsname}" -4 route \
0426 add "${IPv4_HS_NETWORK}.${dst}" \
0427 encap seg6 mode "${mode}" segs "${policy}" \
0428 dev dum0
0429 fi
0430 }
0431
0432
0433 setup_rt_policy_ipv6()
0434 {
0435 __setup_rt_policy "$1" "$2" "$3" "$4" "$5" 6
0436 }
0437
0438
0439 setup_rt_policy_ipv4()
0440 {
0441 __setup_rt_policy "$1" "$2" "$3" "$4" "$5" 4
0442 }
0443
0444 setup_decap()
0445 {
0446 local rt="$1"
0447 local nsname
0448
0449 nsname="$(get_rtname "${rt}")"
0450
0451
0452 ip -netns "${nsname}" -6 route \
0453 add "${VPN_LOCATOR_SERVICE}:${rt}::${DX2_FUNC}" \
0454 table "${LOCALSID_TABLE_ID}" \
0455 encap seg6local action End.DX2 oif "${RT2HS_DEVNAME}" \
0456 dev "${RT2HS_DEVNAME}"
0457 }
0458
0459 setup_hs()
0460 {
0461 local hs="$1"
0462 local rt="$2"
0463 local hsname
0464 local rtname
0465
0466 hsname="$(get_hsname "${hs}")"
0467 rtname="$(get_rtname "${rt}")"
0468
0469 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0
0470 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0
0471
0472 ip -netns "${hsname}" link add "${HS_VETH_NAME}" type veth \
0473 peer name "${RT2HS_DEVNAME}" netns "${rtname}"
0474
0475 ip -netns "${hsname}" addr add "${IPv6_HS_NETWORK}::${hs}/64" \
0476 dev "${HS_VETH_NAME}" nodad
0477 ip -netns "${hsname}" addr add "${IPv4_HS_NETWORK}.${hs}/24" \
0478 dev "${HS_VETH_NAME}"
0479
0480 ip -netns "${hsname}" link set "${HS_VETH_NAME}" up
0481 ip -netns "${hsname}" link set lo up
0482
0483 ip -netns "${rtname}" addr add "${IPv6_HS_NETWORK}::254/64" \
0484 dev "${RT2HS_DEVNAME}" nodad
0485 ip -netns "${rtname}" addr \
0486 add "${IPv4_HS_NETWORK}.254/24" dev "${RT2HS_DEVNAME}"
0487
0488 ip -netns "${rtname}" link set "${RT2HS_DEVNAME}" up
0489
0490
0491
0492 ip netns exec "${rtname}" \
0493 sysctl -wq net.ipv4.conf."${RT2HS_DEVNAME}".rp_filter=0
0494 }
0495
0496
0497
0498
0499
0500
0501
0502
0503 set_mac_address()
0504 {
0505 local nodename="$1"
0506 local nodeid="$2"
0507 local host="$3"
0508 local ifname="$4"
0509 local nsname
0510
0511 nsname=$(get_nodename "${nodename}")
0512
0513 ip -netns "${nsname}" link set dev "${ifname}" down
0514
0515 ip -netns "${nsname}" link set address "${MAC_PREFIX}:${nodeid}" \
0516 dev "${ifname}"
0517
0518
0519
0520 ip -netns "${nsname}" addr add "${IPv6_HS_NETWORK}::${host}/64" \
0521 dev "${ifname}" nodad
0522
0523 ip -netns "${nsname}" link set dev "${ifname}" up
0524 }
0525
0526 set_host_l2peer()
0527 {
0528 local hssrc="$1"
0529 local hsdst="$2"
0530 local ipprefix="$3"
0531 local proto="$4"
0532 local hssrc_name
0533 local ipaddr
0534
0535 hssrc_name="$(get_hsname "${hssrc}")"
0536
0537 if [ "${proto}" -eq 6 ]; then
0538 ipaddr="${ipprefix}::${hsdst}"
0539 else
0540 ipaddr="${ipprefix}.${hsdst}"
0541 fi
0542
0543 ip -netns "${hssrc_name}" route add "${ipaddr}" dev "${HS_VETH_NAME}"
0544
0545 ip -netns "${hssrc_name}" neigh \
0546 add "${ipaddr}" lladdr "${MAC_PREFIX}:${hsdst}" \
0547 dev "${HS_VETH_NAME}"
0548 }
0549
0550
0551
0552
0553
0554
0555
0556 setup_l2vpn()
0557 {
0558 local hssrc="$1"
0559 local end_rts="$2"
0560 local hsdst="$3"
0561 local rtsrc="${hssrc}"
0562 local rtdst="${hsdst}"
0563
0564
0565 set_mac_address "hs-${hssrc}" "${hssrc}" "${hssrc}" "${HS_VETH_NAME}"
0566 set_host_l2peer "${hssrc}" "${hsdst}" "${IPv6_HS_NETWORK}" 6
0567 set_host_l2peer "${hssrc}" "${hsdst}" "${IPv4_HS_NETWORK}" 4
0568
0569
0570
0571
0572
0573 set_mac_address "rt-${rtsrc}" "${hsdst}" 254 "${RT2HS_DEVNAME}"
0574
0575
0576 setup_rt_policy_ipv6 "${hsdst}" "${rtsrc}" "${end_rts}" "${rtdst}" \
0577 l2encap.red 6
0578 setup_rt_policy_ipv4 "${hsdst}" "${rtsrc}" "${end_rts}" "${rtdst}" \
0579 l2encap.red 4
0580
0581
0582 setup_decap "${rtsrc}"
0583 }
0584
0585 setup()
0586 {
0587 local i
0588
0589
0590 ROUTERS="1 2 3 4"; readonly ROUTERS
0591 for i in ${ROUTERS}; do
0592 create_router "${i}"
0593 done
0594
0595
0596 HOSTS="1 2"; readonly HOSTS
0597 for i in ${HOSTS}; do
0598 create_host "${i}"
0599 done
0600
0601
0602 add_link_rt_pairs 1 "2 3 4"
0603 add_link_rt_pairs 2 "3 4"
0604 add_link_rt_pairs 3 "4"
0605
0606
0607
0608 setup_rt_networking 1 "2 3 4"
0609 setup_rt_networking 2 "1 3 4"
0610 setup_rt_networking 3 "1 2 4"
0611 setup_rt_networking 4 "1 2 3"
0612
0613
0614 setup_hs 1 1
0615 setup_hs 2 2
0616
0617
0618 setup_rt_local_sids 1 "2 3 4"
0619 setup_rt_local_sids 2 "1 3 4"
0620 setup_rt_local_sids 3 "1 2 4"
0621 setup_rt_local_sids 4 "1 2 3"
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636 setup_l2vpn 1 "" 2
0637 setup_l2vpn 2 "4 3" 1
0638
0639
0640 SETUP_ERR=0
0641 }
0642
0643 check_rt_connectivity()
0644 {
0645 local rtsrc="$1"
0646 local rtdst="$2"
0647 local prefix
0648 local rtsrc_nsname
0649
0650 rtsrc_nsname="$(get_rtname "${rtsrc}")"
0651
0652 prefix="$(get_network_prefix "${rtsrc}" "${rtdst}")"
0653
0654 ip netns exec "${rtsrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
0655 "${prefix}::${rtdst}" >/dev/null 2>&1
0656 }
0657
0658 check_and_log_rt_connectivity()
0659 {
0660 local rtsrc="$1"
0661 local rtdst="$2"
0662
0663 check_rt_connectivity "${rtsrc}" "${rtdst}"
0664 log_test $? 0 "Routers connectivity: rt-${rtsrc} -> rt-${rtdst}"
0665 }
0666
0667 check_hs_ipv6_connectivity()
0668 {
0669 local hssrc="$1"
0670 local hsdst="$2"
0671 local hssrc_nsname
0672
0673 hssrc_nsname="$(get_hsname "${hssrc}")"
0674
0675 ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
0676 "${IPv6_HS_NETWORK}::${hsdst}" >/dev/null 2>&1
0677 }
0678
0679 check_hs_ipv4_connectivity()
0680 {
0681 local hssrc="$1"
0682 local hsdst="$2"
0683 local hssrc_nsname
0684
0685 hssrc_nsname="$(get_hsname "${hssrc}")"
0686
0687 ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
0688 "${IPv4_HS_NETWORK}.${hsdst}" >/dev/null 2>&1
0689 }
0690
0691 check_and_log_hs2gw_connectivity()
0692 {
0693 local hssrc="$1"
0694
0695 check_hs_ipv6_connectivity "${hssrc}" 254
0696 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> gw"
0697
0698 check_hs_ipv4_connectivity "${hssrc}" 254
0699 log_test $? 0 "IPv4 Hosts connectivity: hs-${hssrc} -> gw"
0700 }
0701
0702 check_and_log_hs_ipv6_connectivity()
0703 {
0704 local hssrc="$1"
0705 local hsdst="$2"
0706
0707 check_hs_ipv6_connectivity "${hssrc}" "${hsdst}"
0708 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}"
0709 }
0710
0711 check_and_log_hs_ipv4_connectivity()
0712 {
0713 local hssrc="$1"
0714 local hsdst="$2"
0715
0716 check_hs_ipv4_connectivity "${hssrc}" "${hsdst}"
0717 log_test $? 0 "IPv4 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}"
0718 }
0719
0720 check_and_log_hs_connectivity()
0721 {
0722 local hssrc="$1"
0723 local hsdst="$2"
0724
0725 check_and_log_hs_ipv4_connectivity "${hssrc}" "${hsdst}"
0726 check_and_log_hs_ipv6_connectivity "${hssrc}" "${hsdst}"
0727 }
0728
0729 router_tests()
0730 {
0731 local i
0732 local j
0733
0734 log_section "IPv6 routers connectivity test"
0735
0736 for i in ${ROUTERS}; do
0737 for j in ${ROUTERS}; do
0738 if [ "${i}" -eq "${j}" ]; then
0739 continue
0740 fi
0741
0742 check_and_log_rt_connectivity "${i}" "${j}"
0743 done
0744 done
0745 }
0746
0747 host2gateway_tests()
0748 {
0749 local hs
0750
0751 log_section "IPv4/IPv6 connectivity test among hosts and gateways"
0752
0753 for hs in ${HOSTS}; do
0754 check_and_log_hs2gw_connectivity "${hs}"
0755 done
0756 }
0757
0758 host_vpn_tests()
0759 {
0760 log_section "SRv6 L2 VPN connectivity test hosts (h1 <-> h2)"
0761
0762 check_and_log_hs_connectivity 1 2
0763 check_and_log_hs_connectivity 2 1
0764 }
0765
0766 test_dummy_dev_or_ksft_skip()
0767 {
0768 local test_netns
0769
0770 test_netns="dummy-$(mktemp -u XXXXXXXX)"
0771
0772 if ! ip netns add "${test_netns}"; then
0773 echo "SKIP: Cannot set up netns for testing dummy dev support"
0774 exit "${ksft_skip}"
0775 fi
0776
0777 modprobe dummy &>/dev/null || true
0778 if ! ip -netns "${test_netns}" link \
0779 add "${DUMMY_DEVNAME}" type dummy; then
0780 echo "SKIP: dummy dev not supported"
0781
0782 ip netns del "${test_netns}"
0783 exit "${ksft_skip}"
0784 fi
0785
0786 ip netns del "${test_netns}"
0787 }
0788
0789 test_iproute2_supp_or_ksft_skip()
0790 {
0791 if ! ip route help 2>&1 | grep -qo "l2encap.red"; then
0792 echo "SKIP: Missing SRv6 l2encap.red support in iproute2"
0793 exit "${ksft_skip}"
0794 fi
0795 }
0796
0797 if [ "$(id -u)" -ne 0 ]; then
0798 echo "SKIP: Need root privileges"
0799 exit "${ksft_skip}"
0800 fi
0801
0802
0803 test_command_or_ksft_skip ip
0804 test_command_or_ksft_skip ping
0805 test_command_or_ksft_skip sysctl
0806 test_command_or_ksft_skip grep
0807
0808 test_iproute2_supp_or_ksft_skip
0809 test_dummy_dev_or_ksft_skip
0810
0811 set -e
0812 trap cleanup EXIT
0813
0814 setup
0815 set +e
0816
0817 router_tests
0818 host2gateway_tests
0819 host_vpn_tests
0820
0821 print_log_test_results