From: Justin Iurman <justin.iurman@gmail.com>
To: Andrea Mayer <andrea.mayer@uniroma2.it>, netdev@vger.kernel.org
Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, horms@kernel.org, dsahern@kernel.org,
david.lebrun@uclouvain.be, stefano.salsano@uniroma2.it,
paolo.lungaroni@uniroma2.it, nicolas.dichtel@6wind.com,
linux-kernel@vger.kernel.org, Shuah Khan <shuah@kernel.org>,
linux-kselftest@vger.kernel.org
Subject: Re: [PATCH net v2 2/2] selftests: seg6: add test for dst_cache isolation in seg6 lwtunnel
Date: Thu, 2 Apr 2026 20:35:12 +0200 [thread overview]
Message-ID: <d2b6a7fd-e09f-4e5d-838a-077ccecbd67f@gmail.com> (raw)
In-Reply-To: <20260401185755.29813-3-andrea.mayer@uniroma2.it>
On 4/1/26 20:57, Andrea Mayer wrote:
> Add a selftest that verifies the dst_cache in seg6 lwtunnel is not
> shared between the input (forwarding) and output (locally generated)
> paths.
>
> The test creates three namespaces (ns_src, ns_router, ns_dst)
> connected in a line. An SRv6 encap route on ns_router encapsulates
> traffic destined to cafe::1 with SID fc00::100. The SID is
> reachable only for forwarded traffic (from ns_src) via an ip rule
> matching the ingress interface (iif veth-r0 lookup 100), and
> blackholed in the main table.
>
> The test verifies that:
>
> 1. A packet generated locally on ns_router does not reach
> ns_dst with an empty cache, since the SID is blackholed;
> 2. A forwarded packet from ns_src populates the input cache
> from table 100 and reaches ns_dst;
> 3. A packet generated locally on ns_router still does not
> reach ns_dst after the input cache is populated,
> confirming the output path does not reuse the input
> cache entry.
>
> Both the forwarded and local packets are pinned to the same CPU
> with taskset, since dst_cache is per-cpu.
>
> Cc: Shuah Khan <shuah@kernel.org>
> Cc: linux-kselftest@vger.kernel.org
> Signed-off-by: Andrea Mayer <andrea.mayer@uniroma2.it>
> Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> ---
> Changes v1 -> v2:
> - fix SKIP message wording (Nicolas)
> ---
> tools/testing/selftests/net/Makefile | 1 +
> .../selftests/net/srv6_iptunnel_cache.sh | 177 ++++++++++++++++++
> 2 files changed, 178 insertions(+)
> create mode 100755 tools/testing/selftests/net/srv6_iptunnel_cache.sh
>
> diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
> index 605c54c0e8a3..c709523c99c6 100644
> --- a/tools/testing/selftests/net/Makefile
> +++ b/tools/testing/selftests/net/Makefile
> @@ -89,6 +89,7 @@ TEST_PROGS := \
> srv6_end_x_next_csid_l3vpn_test.sh \
> srv6_hencap_red_l3vpn_test.sh \
> srv6_hl2encap_red_l2vpn_test.sh \
> + srv6_iptunnel_cache.sh \
> stress_reuseport_listen.sh \
> tcp_fastopen_backup_key.sh \
> test_bpf.sh \
> diff --git a/tools/testing/selftests/net/srv6_iptunnel_cache.sh b/tools/testing/selftests/net/srv6_iptunnel_cache.sh
> new file mode 100755
> index 000000000000..1f3ebb930eb2
> --- /dev/null
> +++ b/tools/testing/selftests/net/srv6_iptunnel_cache.sh
> @@ -0,0 +1,177 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# author: Andrea Mayer <andrea.mayer@uniroma2.it>
> +
> +# This test verifies that the seg6 lwtunnel does not share the dst_cache
> +# between the input (forwarding) and output (locally generated) paths.
> +#
> +# A shared dst_cache allows a forwarded packet to populate the cache and a
> +# subsequent locally generated packet to silently reuse that entry, bypassing
> +# its own route lookup. To expose this, the SID is made reachable only for
> +# forwarded traffic (via an ip rule matching iif) and blackholed for everything
> +# else. A local ping on ns_router must always hit the blackhole;
> +# if it succeeds after a forwarded packet has populated the
> +# cache, the bug is confirmed.
> +#
> +# Both forwarded and local packets are pinned to the same CPU with taskset,
> +# since dst_cache is per-cpu.
> +#
> +#
> +# +--------------------+ +--------------------+
> +# | ns_src | | ns_dst |
> +# | | | |
> +# | veth-s0 | | veth-d0 |
> +# | fd00::1/64 | | fd01::2/64 |
> +# +-------|------------+ +----------|---------+
> +# | |
> +# | +--------------------+ |
> +# | | ns_router | |
> +# | | | |
> +# +----------->+ veth-r0 veth-r1 +<-------------+
> +# | fd00::2 fd01::1 |
> +# +--------------------+
> +#
> +#
> +# ns_router: encap (main table)
> +# +---------+---------------------------------------+
> +# | dst | action |
> +# +---------+---------------------------------------+
> +# | cafe::1 | encap seg6 mode encap segs fc00::100 |
> +# +---------+---------------------------------------+
> +#
> +# ns_router: post-encap SID resolution
> +# +-------+------------+----------------------------+
> +# | table | dst | action |
> +# +-------+------------+----------------------------+
> +# | 100 | fc00::100 | via fd01::2 dev veth-r1 |
> +# +-------+------------+----------------------------+
> +# | main | fc00::100 | blackhole |
> +# +-------+------------+----------------------------+
> +#
> +# ns_router: ip rule
> +# +------------------+------------------------------+
> +# | match | action |
> +# +------------------+------------------------------+
> +# | iif veth-r0 | lookup 100 |
> +# +------------------+------------------------------+
> +#
> +# ns_dst: SRv6 decap (main table)
> +# +--------------+----------------------------------+
> +# | SID | action |
> +# +--------------+----------------------------------+
> +# | fc00::100 | End.DT6 table 255 (local) |
> +# +--------------+----------------------------------+
> +
> +source lib.sh
> +
> +readonly SID="fc00::100"
> +readonly DEST="cafe::1"
> +
> +readonly SRC_MAC="02:00:00:00:00:01"
> +readonly RTR_R0_MAC="02:00:00:00:00:02"
> +readonly RTR_R1_MAC="02:00:00:00:00:03"
> +readonly DST_MAC="02:00:00:00:00:04"
> +
> +cleanup()
> +{
> + cleanup_ns "${NS_SRC}" "${NS_RTR}" "${NS_DST}"
> +}
> +
> +check_prerequisites()
> +{
> + if ! command -v taskset &>/dev/null; then
> + echo "SKIP: taskset not found"
> + exit "${ksft_skip}"
> + fi
> +}
> +
> +setup()
> +{
> + setup_ns NS_SRC NS_RTR NS_DST
> +
> + ip link add veth-s0 netns "${NS_SRC}" type veth \
> + peer name veth-r0 netns "${NS_RTR}"
> + ip link add veth-r1 netns "${NS_RTR}" type veth \
> + peer name veth-d0 netns "${NS_DST}"
> +
> + ip -n "${NS_SRC}" link set veth-s0 address "${SRC_MAC}"
> + ip -n "${NS_RTR}" link set veth-r0 address "${RTR_R0_MAC}"
> + ip -n "${NS_RTR}" link set veth-r1 address "${RTR_R1_MAC}"
> + ip -n "${NS_DST}" link set veth-d0 address "${DST_MAC}"
> +
> + # ns_src
> + ip -n "${NS_SRC}" link set veth-s0 up
> + ip -n "${NS_SRC}" addr add fd00::1/64 dev veth-s0 nodad
> + ip -n "${NS_SRC}" -6 route add "${DEST}"/128 via fd00::2
> +
> + # ns_router
> + ip -n "${NS_RTR}" link set veth-r0 up
> + ip -n "${NS_RTR}" addr add fd00::2/64 dev veth-r0 nodad
> + ip -n "${NS_RTR}" link set veth-r1 up
> + ip -n "${NS_RTR}" addr add fd01::1/64 dev veth-r1 nodad
> + ip netns exec "${NS_RTR}" sysctl -qw net.ipv6.conf.all.forwarding=1
> +
> + ip -n "${NS_RTR}" -6 route add "${DEST}"/128 \
> + encap seg6 mode encap segs "${SID}" dev veth-r0
> + ip -n "${NS_RTR}" -6 route add "${SID}"/128 table 100 \
> + via fd01::2 dev veth-r1
> + ip -n "${NS_RTR}" -6 route add blackhole "${SID}"/128
> + ip -n "${NS_RTR}" -6 rule add iif veth-r0 lookup 100
> +
> + # ns_dst
> + ip -n "${NS_DST}" link set veth-d0 up
> + ip -n "${NS_DST}" addr add fd01::2/64 dev veth-d0 nodad
> + ip -n "${NS_DST}" addr add "${DEST}"/128 dev lo nodad
> + ip -n "${NS_DST}" -6 route add "${SID}"/128 \
> + encap seg6local action End.DT6 table 255 dev veth-d0
> + ip -n "${NS_DST}" -6 route add fd00::/64 via fd01::1
> +
> + # static neighbors
> + ip -n "${NS_SRC}" -6 neigh add fd00::2 dev veth-s0 \
> + lladdr "${RTR_R0_MAC}" nud permanent
> + ip -n "${NS_RTR}" -6 neigh add fd00::1 dev veth-r0 \
> + lladdr "${SRC_MAC}" nud permanent
> + ip -n "${NS_RTR}" -6 neigh add fd01::2 dev veth-r1 \
> + lladdr "${DST_MAC}" nud permanent
> + ip -n "${NS_DST}" -6 neigh add fd01::1 dev veth-d0 \
> + lladdr "${RTR_R1_MAC}" nud permanent
> +}
> +
> +test_cache_isolation()
> +{
> + RET=0
> +
> + # local ping with empty cache: must fail (SID is blackholed)
> + if ip netns exec "${NS_RTR}" taskset -c 0 \
> + ping6 -c 1 -W 2 "${DEST}" &>/dev/null; then
> + echo "SKIP: local ping succeeded, topology broken"
> + exit "${ksft_skip}"
> + fi
> +
> + # forward from ns_src to populate the input cache
> + if ! ip netns exec "${NS_SRC}" taskset -c 0 \
> + ping6 -c 1 -W 2 "${DEST}" &>/dev/null; then
> + echo "SKIP: forwarded ping failed, topology broken"
> + exit "${ksft_skip}"
> + fi
> +
> + # local ping again: must still fail; if the output path reuses
> + # the input cache, it bypasses the blackhole and the ping succeeds
> + if ip netns exec "${NS_RTR}" taskset -c 0 \
> + ping6 -c 1 -W 2 "${DEST}" &>/dev/null; then
> + echo "FAIL: output path used dst cached by input path"
> + RET="${ksft_fail}"
> + else
> + echo "PASS: output path dst_cache is independent"
> + fi
> +
> + return "${RET}"
> +}
> +
We should check it runs as root here (e.g, required for netns creation).
if [ "$(id -u)" -ne 0 ]; then
echo "SKIP: Need root privileges"
exit "${ksft_skip}"
fi
Otherwise, LGTM:
Reviewed-by: Justin Iurman <justin.iurman@gmail.com>
> +trap cleanup EXIT
> +
> +check_prerequisites
> +setup
> +test_cache_isolation
> +exit "${RET}"
next prev parent reply other threads:[~2026-04-02 18:35 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-01 18:57 [PATCH net v2 0/2] seg6: fix dst_cache sharing in seg6 lwtunnel Andrea Mayer
2026-04-01 18:57 ` [PATCH net v2 1/2] seg6: separate dst_cache for input and output paths " Andrea Mayer
2026-04-02 18:30 ` Justin Iurman
2026-04-01 18:57 ` [PATCH net v2 2/2] selftests: seg6: add test for dst_cache isolation " Andrea Mayer
2026-04-02 18:35 ` Justin Iurman [this message]
2026-04-03 14:46 ` Andrea Mayer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d2b6a7fd-e09f-4e5d-838a-077ccecbd67f@gmail.com \
--to=justin.iurman@gmail.com \
--cc=andrea.mayer@uniroma2.it \
--cc=davem@davemloft.net \
--cc=david.lebrun@uclouvain.be \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=nicolas.dichtel@6wind.com \
--cc=pabeni@redhat.com \
--cc=paolo.lungaroni@uniroma2.it \
--cc=shuah@kernel.org \
--cc=stefano.salsano@uniroma2.it \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox