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
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170 readonly ksft_skip=4
0171
0172 readonly RDMSUFF="$(mktemp -u XXXXXXXX)"
0173 readonly VRF_TID=100
0174 readonly VRF_DEVNAME="vrf-${VRF_TID}"
0175 readonly RT2HS_DEVNAME="veth-t${VRF_TID}"
0176 readonly LOCALSID_TABLE_ID=90
0177 readonly IPv6_RT_NETWORK=fcf0:0
0178 readonly IPv6_HS_NETWORK=cafe
0179 readonly IPv4_HS_NETWORK=10.0.0
0180 readonly VPN_LOCATOR_SERVICE=fcff
0181 readonly END_FUNC=000e
0182 readonly DT46_FUNC=0d46
0183
0184 PING_TIMEOUT_SEC=4
0185 PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
0186
0187
0188
0189 ROUTERS=''
0190 HOSTS=''
0191
0192 SETUP_ERR=1
0193
0194 ret=${ksft_skip}
0195 nsuccess=0
0196 nfail=0
0197
0198 log_test()
0199 {
0200 local rc="$1"
0201 local expected="$2"
0202 local msg="$3"
0203
0204 if [ "${rc}" -eq "${expected}" ]; then
0205 nsuccess=$((nsuccess+1))
0206 printf "\n TEST: %-60s [ OK ]\n" "${msg}"
0207 else
0208 ret=1
0209 nfail=$((nfail+1))
0210 printf "\n TEST: %-60s [FAIL]\n" "${msg}"
0211 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
0212 echo
0213 echo "hit enter to continue, 'q' to quit"
0214 read a
0215 [ "$a" = "q" ] && exit 1
0216 fi
0217 fi
0218 }
0219
0220 print_log_test_results()
0221 {
0222 printf "\nTests passed: %3d\n" "${nsuccess}"
0223 printf "Tests failed: %3d\n" "${nfail}"
0224
0225
0226
0227
0228 if [ "${ret}" -ne 1 ]; then
0229 ret=0
0230 fi
0231 }
0232
0233 log_section()
0234 {
0235 echo
0236 echo "################################################################################"
0237 echo "TEST SECTION: $*"
0238 echo "################################################################################"
0239 }
0240
0241 test_command_or_ksft_skip()
0242 {
0243 local cmd="$1"
0244
0245 if [ ! -x "$(command -v "${cmd}")" ]; then
0246 echo "SKIP: Could not run test without \"${cmd}\" tool";
0247 exit "${ksft_skip}"
0248 fi
0249 }
0250
0251 get_nodename()
0252 {
0253 local name="$1"
0254
0255 echo "${name}-${RDMSUFF}"
0256 }
0257
0258 get_rtname()
0259 {
0260 local rtid="$1"
0261
0262 get_nodename "rt-${rtid}"
0263 }
0264
0265 get_hsname()
0266 {
0267 local hsid="$1"
0268
0269 get_nodename "hs-${hsid}"
0270 }
0271
0272 __create_namespace()
0273 {
0274 local name="$1"
0275
0276 ip netns add "${name}"
0277 }
0278
0279 create_router()
0280 {
0281 local rtid="$1"
0282 local nsname
0283
0284 nsname="$(get_rtname "${rtid}")"
0285
0286 __create_namespace "${nsname}"
0287 }
0288
0289 create_host()
0290 {
0291 local hsid="$1"
0292 local nsname
0293
0294 nsname="$(get_hsname "${hsid}")"
0295
0296 __create_namespace "${nsname}"
0297 }
0298
0299 cleanup()
0300 {
0301 local nsname
0302 local i
0303
0304
0305 for i in ${ROUTERS}; do
0306 nsname="$(get_rtname "${i}")"
0307
0308 ip netns del "${nsname}" &>/dev/null || true
0309 done
0310
0311
0312 for i in ${HOSTS}; do
0313 nsname="$(get_hsname "${i}")"
0314
0315 ip netns del "${nsname}" &>/dev/null || true
0316 done
0317
0318
0319
0320
0321 if [ "${SETUP_ERR}" -ne 0 ]; then
0322 echo "SKIP: Setting up the testing environment failed"
0323 exit "${ksft_skip}"
0324 fi
0325
0326 exit "${ret}"
0327 }
0328
0329 add_link_rt_pairs()
0330 {
0331 local rt="$1"
0332 local rt_neighs="$2"
0333 local neigh
0334 local nsname
0335 local neigh_nsname
0336
0337 nsname="$(get_rtname "${rt}")"
0338
0339 for neigh in ${rt_neighs}; do
0340 neigh_nsname="$(get_rtname "${neigh}")"
0341
0342 ip link add "veth-rt-${rt}-${neigh}" netns "${nsname}" \
0343 type veth peer name "veth-rt-${neigh}-${rt}" \
0344 netns "${neigh_nsname}"
0345 done
0346 }
0347
0348 get_network_prefix()
0349 {
0350 local rt="$1"
0351 local neigh="$2"
0352 local p="${rt}"
0353 local q="${neigh}"
0354
0355 if [ "${p}" -gt "${q}" ]; then
0356 p="${q}"; q="${rt}"
0357 fi
0358
0359 echo "${IPv6_RT_NETWORK}:${p}:${q}"
0360 }
0361
0362
0363 setup_rt_networking()
0364 {
0365 local rt="$1"
0366 local rt_neighs="$2"
0367 local nsname
0368 local net_prefix
0369 local devname
0370 local neigh
0371
0372 nsname="$(get_rtname "${rt}")"
0373
0374 for neigh in ${rt_neighs}; do
0375 devname="veth-rt-${rt}-${neigh}"
0376
0377 net_prefix="$(get_network_prefix "${rt}" "${neigh}")"
0378
0379 ip -netns "${nsname}" addr \
0380 add "${net_prefix}::${rt}/64" dev "${devname}" nodad
0381
0382 ip -netns "${nsname}" link set "${devname}" up
0383 done
0384
0385 ip -netns "${nsname}" link set lo up
0386
0387 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0
0388 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0
0389 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.forwarding=1
0390
0391 ip netns exec "${nsname}" sysctl -wq net.ipv4.conf.all.rp_filter=0
0392 ip netns exec "${nsname}" sysctl -wq net.ipv4.conf.default.rp_filter=0
0393 ip netns exec "${nsname}" sysctl -wq net.ipv4.ip_forward=1
0394 }
0395
0396
0397 setup_rt_local_sids()
0398 {
0399 local rt="$1"
0400 local rt_neighs="$2"
0401 local net_prefix
0402 local devname
0403 local nsname
0404 local neigh
0405
0406 nsname="$(get_rtname "${rt}")"
0407
0408 for neigh in ${rt_neighs}; do
0409 devname="veth-rt-${rt}-${neigh}"
0410
0411 net_prefix="$(get_network_prefix "${rt}" "${neigh}")"
0412
0413
0414 ip -netns "${nsname}" -6 route \
0415 add "${VPN_LOCATOR_SERVICE}:${neigh}::/32" \
0416 table "${LOCALSID_TABLE_ID}" \
0417 via "${net_prefix}::${neigh}" dev "${devname}"
0418 done
0419
0420
0421
0422 ip -netns "${nsname}" -6 route \
0423 add "${VPN_LOCATOR_SERVICE}:${rt}::${END_FUNC}" \
0424 table "${LOCALSID_TABLE_ID}" \
0425 encap seg6local action End dev "${VRF_DEVNAME}"
0426
0427
0428 ip -netns "${nsname}" -6 route \
0429 add "${VPN_LOCATOR_SERVICE}:${rt}::${DT46_FUNC}" \
0430 table "${LOCALSID_TABLE_ID}" \
0431 encap seg6local action End.DT46 vrftable "${VRF_TID}" \
0432 dev "${VRF_DEVNAME}"
0433
0434
0435
0436
0437 ip -netns "${nsname}" -6 rule \
0438 add to "${VPN_LOCATOR_SERVICE}::/16" \
0439 lookup "${LOCALSID_TABLE_ID}" prio 999
0440
0441
0442 ip -netns "${nsname}" -6 route \
0443 add unreachable default metric 4278198272 \
0444 vrf "${VRF_DEVNAME}"
0445
0446 ip -netns "${nsname}" -4 route \
0447 add unreachable default metric 4278198272 \
0448 vrf "${VRF_DEVNAME}"
0449 }
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460 __setup_rt_policy()
0461 {
0462 local dst="$1"
0463 local encap_rt="$2"
0464 local end_rts="$3"
0465 local dec_rt="$4"
0466 local mode="$5"
0467 local traffic="$6"
0468 local nsname
0469 local policy=''
0470 local n
0471
0472 nsname="$(get_rtname "${encap_rt}")"
0473
0474 for n in ${end_rts}; do
0475 policy="${policy}${VPN_LOCATOR_SERVICE}:${n}::${END_FUNC},"
0476 done
0477
0478 policy="${policy}${VPN_LOCATOR_SERVICE}:${dec_rt}::${DT46_FUNC}"
0479
0480
0481 if [ "${traffic}" -eq 6 ]; then
0482 ip -netns "${nsname}" -6 route \
0483 add "${IPv6_HS_NETWORK}::${dst}" vrf "${VRF_DEVNAME}" \
0484 encap seg6 mode "${mode}" segs "${policy}" \
0485 dev "${VRF_DEVNAME}"
0486
0487 ip -netns "${nsname}" -6 neigh \
0488 add proxy "${IPv6_HS_NETWORK}::${dst}" \
0489 dev "${RT2HS_DEVNAME}"
0490 else
0491
0492
0493 ip -netns "${nsname}" -4 route \
0494 add "${IPv4_HS_NETWORK}.${dst}" vrf "${VRF_DEVNAME}" \
0495 encap seg6 mode "${mode}" segs "${policy}" \
0496 dev "${VRF_DEVNAME}"
0497 fi
0498 }
0499
0500
0501 setup_rt_policy_ipv6()
0502 {
0503 __setup_rt_policy "$1" "$2" "$3" "$4" "$5" 6
0504 }
0505
0506
0507 setup_rt_policy_ipv4()
0508 {
0509 __setup_rt_policy "$1" "$2" "$3" "$4" "$5" 4
0510 }
0511
0512 setup_hs()
0513 {
0514 local hs="$1"
0515 local rt="$2"
0516 local hsname
0517 local rtname
0518
0519 hsname="$(get_hsname "${hs}")"
0520 rtname="$(get_rtname "${rt}")"
0521
0522 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0
0523 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0
0524
0525 ip -netns "${hsname}" link add veth0 type veth \
0526 peer name "${RT2HS_DEVNAME}" netns "${rtname}"
0527
0528 ip -netns "${hsname}" addr \
0529 add "${IPv6_HS_NETWORK}::${hs}/64" dev veth0 nodad
0530 ip -netns "${hsname}" addr add "${IPv4_HS_NETWORK}.${hs}/24" dev veth0
0531
0532 ip -netns "${hsname}" link set veth0 up
0533 ip -netns "${hsname}" link set lo up
0534
0535
0536
0537 ip -netns "${rtname}" link \
0538 add "${VRF_DEVNAME}" type vrf table "${VRF_TID}"
0539 ip -netns "${rtname}" link set "${VRF_DEVNAME}" up
0540
0541
0542
0543 ip -netns "${rtname}" link \
0544 set "${RT2HS_DEVNAME}" master "${VRF_DEVNAME}"
0545
0546 ip -netns "${rtname}" addr \
0547 add "${IPv6_HS_NETWORK}::254/64" dev "${RT2HS_DEVNAME}" nodad
0548 ip -netns "${rtname}" addr \
0549 add "${IPv4_HS_NETWORK}.254/24" dev "${RT2HS_DEVNAME}"
0550
0551 ip -netns "${rtname}" link set "${RT2HS_DEVNAME}" up
0552
0553 ip netns exec "${rtname}" \
0554 sysctl -wq net.ipv6.conf."${RT2HS_DEVNAME}".proxy_ndp=1
0555 ip netns exec "${rtname}" \
0556 sysctl -wq net.ipv4.conf."${RT2HS_DEVNAME}".proxy_arp=1
0557
0558
0559
0560 ip netns exec "${rtname}" \
0561 sysctl -wq net.ipv4.conf."${RT2HS_DEVNAME}".rp_filter=0
0562
0563 ip netns exec "${rtname}" sh -c "echo 1 > /proc/sys/net/vrf/strict_mode"
0564 }
0565
0566 setup()
0567 {
0568 local i
0569
0570
0571 ROUTERS="1 2 3 4"; readonly ROUTERS
0572 for i in ${ROUTERS}; do
0573 create_router "${i}"
0574 done
0575
0576
0577 HOSTS="1 2 3 4"; readonly HOSTS
0578 for i in ${HOSTS}; do
0579 create_host "${i}"
0580 done
0581
0582
0583 add_link_rt_pairs 1 "2 3 4"
0584 add_link_rt_pairs 2 "3 4"
0585 add_link_rt_pairs 3 "4"
0586
0587
0588
0589 setup_rt_networking 1 "2 3 4"
0590 setup_rt_networking 2 "1 3 4"
0591 setup_rt_networking 3 "1 2 4"
0592 setup_rt_networking 4 "1 2 3"
0593
0594
0595 setup_hs 1 1
0596 setup_hs 2 2
0597 setup_hs 3 3
0598 setup_hs 4 4
0599
0600
0601 setup_rt_local_sids 1 "2 3 4"
0602 setup_rt_local_sids 2 "1 3 4"
0603 setup_rt_local_sids 3 "1 2 4"
0604 setup_rt_local_sids 4 "1 2 3"
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618 setup_rt_policy_ipv6 2 1 "3 4" 2 encap.red
0619 setup_rt_policy_ipv6 1 2 "" 1 encap.red
0620
0621
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631 setup_rt_policy_ipv4 2 1 "" 2 encap.red
0632 setup_rt_policy_ipv4 1 2 "4 3" 1 encap.red
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645 setup_rt_policy_ipv6 4 3 "2" 4 encap.red
0646 setup_rt_policy_ipv6 3 4 "1" 3 encap.red
0647
0648
0649 SETUP_ERR=0
0650 }
0651
0652 check_rt_connectivity()
0653 {
0654 local rtsrc="$1"
0655 local rtdst="$2"
0656 local prefix
0657 local rtsrc_nsname
0658
0659 rtsrc_nsname="$(get_rtname "${rtsrc}")"
0660
0661 prefix="$(get_network_prefix "${rtsrc}" "${rtdst}")"
0662
0663 ip netns exec "${rtsrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
0664 "${prefix}::${rtdst}" >/dev/null 2>&1
0665 }
0666
0667 check_and_log_rt_connectivity()
0668 {
0669 local rtsrc="$1"
0670 local rtdst="$2"
0671
0672 check_rt_connectivity "${rtsrc}" "${rtdst}"
0673 log_test $? 0 "Routers connectivity: rt-${rtsrc} -> rt-${rtdst}"
0674 }
0675
0676 check_hs_ipv6_connectivity()
0677 {
0678 local hssrc="$1"
0679 local hsdst="$2"
0680 local hssrc_nsname
0681
0682 hssrc_nsname="$(get_hsname "${hssrc}")"
0683
0684 ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
0685 "${IPv6_HS_NETWORK}::${hsdst}" >/dev/null 2>&1
0686 }
0687
0688 check_hs_ipv4_connectivity()
0689 {
0690 local hssrc="$1"
0691 local hsdst="$2"
0692 local hssrc_nsname
0693
0694 hssrc_nsname="$(get_hsname "${hssrc}")"
0695
0696 ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
0697 "${IPv4_HS_NETWORK}.${hsdst}" >/dev/null 2>&1
0698 }
0699
0700 check_and_log_hs2gw_connectivity()
0701 {
0702 local hssrc="$1"
0703
0704 check_hs_ipv6_connectivity "${hssrc}" 254
0705 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> gw"
0706
0707 check_hs_ipv4_connectivity "${hssrc}" 254
0708 log_test $? 0 "IPv4 Hosts connectivity: hs-${hssrc} -> gw"
0709 }
0710
0711 check_and_log_hs_ipv6_connectivity()
0712 {
0713 local hssrc="$1"
0714 local hsdst="$2"
0715
0716 check_hs_ipv6_connectivity "${hssrc}" "${hsdst}"
0717 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}"
0718 }
0719
0720 check_and_log_hs_ipv4_connectivity()
0721 {
0722 local hssrc="$1"
0723 local hsdst="$2"
0724
0725 check_hs_ipv4_connectivity "${hssrc}" "${hsdst}"
0726 log_test $? 0 "IPv4 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}"
0727 }
0728
0729 check_and_log_hs_connectivity()
0730 {
0731 local hssrc="$1"
0732 local hsdst="$2"
0733
0734 check_and_log_hs_ipv4_connectivity "${hssrc}" "${hsdst}"
0735 check_and_log_hs_ipv6_connectivity "${hssrc}" "${hsdst}"
0736 }
0737
0738 check_and_log_hs_ipv6_isolation()
0739 {
0740 local hssrc="$1"
0741 local hsdst="$2"
0742
0743
0744 check_hs_ipv6_connectivity "${hssrc}" "${hsdst}"
0745 log_test $? 1 "IPv6 Hosts isolation: hs-${hssrc} -X-> hs-${hsdst}"
0746 }
0747
0748 check_and_log_hs_ipv4_isolation()
0749 {
0750 local hssrc="$1"
0751 local hsdst="$2"
0752
0753
0754 check_hs_ipv4_connectivity "${hssrc}" "${hsdst}"
0755 log_test $? 1 "IPv4 Hosts isolation: hs-${hssrc} -X-> hs-${hsdst}"
0756 }
0757
0758 check_and_log_hs_isolation()
0759 {
0760 local hssrc="$1"
0761 local hsdst="$2"
0762
0763 check_and_log_hs_ipv6_isolation "${hssrc}" "${hsdst}"
0764 check_and_log_hs_ipv4_isolation "${hssrc}" "${hsdst}"
0765 }
0766
0767 router_tests()
0768 {
0769 local i
0770 local j
0771
0772 log_section "IPv6 routers connectivity test"
0773
0774 for i in ${ROUTERS}; do
0775 for j in ${ROUTERS}; do
0776 if [ "${i}" -eq "${j}" ]; then
0777 continue
0778 fi
0779
0780 check_and_log_rt_connectivity "${i}" "${j}"
0781 done
0782 done
0783 }
0784
0785 host2gateway_tests()
0786 {
0787 local hs
0788
0789 log_section "IPv4/IPv6 connectivity test among hosts and gateways"
0790
0791 for hs in ${HOSTS}; do
0792 check_and_log_hs2gw_connectivity "${hs}"
0793 done
0794 }
0795
0796 host_vpn_tests()
0797 {
0798 log_section "SRv6 VPN connectivity test hosts (h1 <-> h2, IPv4/IPv6)"
0799
0800 check_and_log_hs_connectivity 1 2
0801 check_and_log_hs_connectivity 2 1
0802
0803 log_section "SRv6 VPN connectivity test hosts (h3 <-> h4, IPv6 only)"
0804
0805 check_and_log_hs_ipv6_connectivity 3 4
0806 check_and_log_hs_ipv6_connectivity 4 3
0807 }
0808
0809 host_vpn_isolation_tests()
0810 {
0811 local l1="1 2"
0812 local l2="3 4"
0813 local tmp
0814 local i
0815 local j
0816 local k
0817
0818 log_section "SRv6 VPN isolation test among hosts"
0819
0820 for k in 0 1; do
0821 for i in ${l1}; do
0822 for j in ${l2}; do
0823 check_and_log_hs_isolation "${i}" "${j}"
0824 done
0825 done
0826
0827
0828 tmp="${l1}"; l1="${l2}"; l2="${tmp}"
0829 done
0830
0831 log_section "SRv6 VPN isolation test among hosts (h2 <-> h4, IPv4 only)"
0832
0833 check_and_log_hs_ipv4_isolation 2 4
0834 check_and_log_hs_ipv4_isolation 4 2
0835 }
0836
0837 test_iproute2_supp_or_ksft_skip()
0838 {
0839 if ! ip route help 2>&1 | grep -qo "encap.red"; then
0840 echo "SKIP: Missing SRv6 encap.red support in iproute2"
0841 exit "${ksft_skip}"
0842 fi
0843 }
0844
0845 test_vrf_or_ksft_skip()
0846 {
0847 modprobe vrf &>/dev/null || true
0848 if [ ! -e /proc/sys/net/vrf/strict_mode ]; then
0849 echo "SKIP: vrf sysctl does not exist"
0850 exit "${ksft_skip}"
0851 fi
0852 }
0853
0854 if [ "$(id -u)" -ne 0 ]; then
0855 echo "SKIP: Need root privileges"
0856 exit "${ksft_skip}"
0857 fi
0858
0859
0860 test_command_or_ksft_skip ip
0861 test_command_or_ksft_skip ping
0862 test_command_or_ksft_skip sysctl
0863 test_command_or_ksft_skip grep
0864
0865 test_iproute2_supp_or_ksft_skip
0866 test_vrf_or_ksft_skip
0867
0868 set -e
0869 trap cleanup EXIT
0870
0871 setup
0872 set +e
0873
0874 router_tests
0875 host2gateway_tests
0876 host_vpn_tests
0877 host_vpn_isolation_tests
0878
0879 print_log_test_results