1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# author: Andrea Mayer <andrea.mayer@uniroma2.it> 5 6# This test verifies that the seg6 lwtunnel does not share the dst_cache 7# between the input (forwarding) and output (locally generated) paths. 8# 9# A shared dst_cache allows a forwarded packet to populate the cache and a 10# subsequent locally generated packet to silently reuse that entry, bypassing 11# its own route lookup. To expose this, the SID is made reachable only for 12# forwarded traffic (via an ip rule matching iif) and blackholed for everything 13# else. A local ping on ns_router must always hit the blackhole; 14# if it succeeds after a forwarded packet has populated the 15# cache, the bug is confirmed. 16# 17# Both forwarded and local packets are pinned to the same CPU with taskset, 18# since dst_cache is per-cpu. 19# 20# 21# +--------------------+ +--------------------+ 22# | ns_src | | ns_dst | 23# | | | | 24# | veth-s0 | | veth-d0 | 25# | fd00::1/64 | | fd01::2/64 | 26# +-------+------------+ +----------+---------+ 27# | | 28# | +--------------------+ | 29# | | ns_router | | 30# | | | | 31# +------------+ veth-r0 veth-r1 +--------------+ 32# | fd00::2 fd01::1 | 33# +--------------------+ 34# 35# 36# ns_router: encap (main table) 37# +---------+---------------------------------------+ 38# | dst | action | 39# +---------+---------------------------------------+ 40# | cafe::1 | encap seg6 mode encap segs fc00::100 | 41# +---------+---------------------------------------+ 42# 43# ns_router: post-encap SID resolution 44# +-------+------------+----------------------------+ 45# | table | dst | action | 46# +-------+------------+----------------------------+ 47# | 100 | fc00::100 | via fd01::2 dev veth-r1 | 48# +-------+------------+----------------------------+ 49# | main | fc00::100 | blackhole | 50# +-------+------------+----------------------------+ 51# 52# ns_router: ip rule 53# +------------------+------------------------------+ 54# | match | action | 55# +------------------+------------------------------+ 56# | iif veth-r0 | lookup 100 | 57# +------------------+------------------------------+ 58# 59# ns_dst: SRv6 decap (main table) 60# +--------------+----------------------------------+ 61# | SID | action | 62# +--------------+----------------------------------+ 63# | fc00::100 | End.DT6 table 255 (local) | 64# +--------------+----------------------------------+ 65 66source lib.sh 67 68readonly SID="fc00::100" 69readonly DEST="cafe::1" 70 71readonly SRC_MAC="02:00:00:00:00:01" 72readonly RTR_R0_MAC="02:00:00:00:00:02" 73readonly RTR_R1_MAC="02:00:00:00:00:03" 74readonly DST_MAC="02:00:00:00:00:04" 75 76cleanup() 77{ 78 cleanup_ns "${NS_SRC}" "${NS_RTR}" "${NS_DST}" 79} 80 81check_prerequisites() 82{ 83 if ! command -v ip &>/dev/null; then 84 echo "SKIP: ip tool not found" 85 exit "${ksft_skip}" 86 fi 87 88 if ! command -v ping &>/dev/null; then 89 echo "SKIP: ping not found" 90 exit "${ksft_skip}" 91 fi 92 93 if ! command -v sysctl &>/dev/null; then 94 echo "SKIP: sysctl not found" 95 exit "${ksft_skip}" 96 fi 97 98 if ! command -v taskset &>/dev/null; then 99 echo "SKIP: taskset not found" 100 exit "${ksft_skip}" 101 fi 102} 103 104setup() 105{ 106 setup_ns NS_SRC NS_RTR NS_DST 107 108 ip link add veth-s0 netns "${NS_SRC}" type veth \ 109 peer name veth-r0 netns "${NS_RTR}" 110 ip link add veth-r1 netns "${NS_RTR}" type veth \ 111 peer name veth-d0 netns "${NS_DST}" 112 113 ip -n "${NS_SRC}" link set veth-s0 address "${SRC_MAC}" 114 ip -n "${NS_RTR}" link set veth-r0 address "${RTR_R0_MAC}" 115 ip -n "${NS_RTR}" link set veth-r1 address "${RTR_R1_MAC}" 116 ip -n "${NS_DST}" link set veth-d0 address "${DST_MAC}" 117 118 # ns_src 119 ip -n "${NS_SRC}" link set veth-s0 up 120 ip -n "${NS_SRC}" addr add fd00::1/64 dev veth-s0 nodad 121 ip -n "${NS_SRC}" -6 route add "${DEST}"/128 via fd00::2 122 123 # ns_router 124 ip -n "${NS_RTR}" link set veth-r0 up 125 ip -n "${NS_RTR}" addr add fd00::2/64 dev veth-r0 nodad 126 ip -n "${NS_RTR}" link set veth-r1 up 127 ip -n "${NS_RTR}" addr add fd01::1/64 dev veth-r1 nodad 128 ip netns exec "${NS_RTR}" sysctl -qw net.ipv6.conf.all.forwarding=1 129 130 ip -n "${NS_RTR}" -6 route add "${DEST}"/128 \ 131 encap seg6 mode encap segs "${SID}" dev veth-r0 132 ip -n "${NS_RTR}" -6 route add "${SID}"/128 table 100 \ 133 via fd01::2 dev veth-r1 134 ip -n "${NS_RTR}" -6 route add blackhole "${SID}"/128 135 ip -n "${NS_RTR}" -6 rule add iif veth-r0 lookup 100 136 137 # ns_dst 138 ip -n "${NS_DST}" link set veth-d0 up 139 ip -n "${NS_DST}" addr add fd01::2/64 dev veth-d0 nodad 140 ip -n "${NS_DST}" addr add "${DEST}"/128 dev lo nodad 141 ip -n "${NS_DST}" -6 route add "${SID}"/128 \ 142 encap seg6local action End.DT6 table 255 dev veth-d0 143 ip -n "${NS_DST}" -6 route add fd00::/64 via fd01::1 144 145 # static neighbors 146 ip -n "${NS_SRC}" -6 neigh add fd00::2 dev veth-s0 \ 147 lladdr "${RTR_R0_MAC}" nud permanent 148 ip -n "${NS_RTR}" -6 neigh add fd00::1 dev veth-r0 \ 149 lladdr "${SRC_MAC}" nud permanent 150 ip -n "${NS_RTR}" -6 neigh add fd01::2 dev veth-r1 \ 151 lladdr "${DST_MAC}" nud permanent 152 ip -n "${NS_DST}" -6 neigh add fd01::1 dev veth-d0 \ 153 lladdr "${RTR_R1_MAC}" nud permanent 154} 155 156test_cache_isolation() 157{ 158 RET=0 159 160 # local ping with empty cache: must fail (SID is blackholed) 161 if ip netns exec "${NS_RTR}" taskset -c 0 \ 162 ping -c 1 -W 2 "${DEST}" &>/dev/null; then 163 echo "SKIP: local ping succeeded, topology broken" 164 exit "${ksft_skip}" 165 fi 166 167 # forward from ns_src to populate the input cache 168 if ! ip netns exec "${NS_SRC}" taskset -c 0 \ 169 ping -c 1 -W 2 "${DEST}" &>/dev/null; then 170 echo "SKIP: forwarded ping failed, topology broken" 171 exit "${ksft_skip}" 172 fi 173 174 # local ping again: must still fail; if the output path reuses 175 # the input cache, it bypasses the blackhole and the ping succeeds 176 if ip netns exec "${NS_RTR}" taskset -c 0 \ 177 ping -c 1 -W 2 "${DEST}" &>/dev/null; then 178 echo "FAIL: output path used dst cached by input path" 179 RET="${ksft_fail}" 180 else 181 echo "PASS: output path dst_cache is independent" 182 fi 183 184 return "${RET}" 185} 186 187if [ "$(id -u)" -ne 0 ]; then 188 echo "SKIP: Need root privileges" 189 exit "${ksft_skip}" 190fi 191 192trap cleanup EXIT 193 194check_prerequisites 195setup 196test_cache_isolation 197exit "${RET}" 198