Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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}"