Merge branch 'selftests-bpf-move-test_lwt_seg6local-to-test_progs'

Bastien Curutchet says:

====================
This patch series continues the work to migrate the script tests into
prog_tests.

test_lwt_seg6local.sh tests some bpf_lwt_* helpers. It contains only one
test that uses a network topology quite different than the ones that
can be found in others prog_tests/lwt_*.c files so I add a new
prog_tests/lwt_seg6local.c file.

While working on the migration I noticed that some routes present in the
script weren't needed so PATCH 1 deletes them and then PATCH 2 migrates
the test into the test_progs framework.
====================

Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Link: https://patch.msgid.link/20250307-seg6local-v1-0-990fff8f180d@bootlin.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Alexei Starovoitov
2025-03-08 01:22:20 -08:00
3 changed files with 176 additions and 157 deletions

View File

@@ -100,7 +100,6 @@ TEST_FILES = xsk_prereqs.sh $(wildcard progs/btf_dump_test_case_*.c)
# Order correspond to 'make run_tests' order
TEST_PROGS := test_kmod.sh \
test_lwt_seg6local.sh \
test_lirc_mode2.sh \
test_xdp_vlan_mode_generic.sh \
test_xdp_vlan_mode_native.sh \

View File

@@ -0,0 +1,176 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Connects 6 network namespaces through veths.
* Each NS may have different IPv6 global scope addresses :
*
* NS1 NS2 NS3 NS4 NS5 NS6
* lo veth1 <-> veth2 veth3 <-> veth4 veth5 <-> veth6 lo veth7 <-> veth8 veth9 <-> veth10 lo
* fb00 ::1 ::12 ::21 ::34 ::43 ::56 ::65 ::78 ::87 ::910 ::109 ::6
* fd00 ::4
* fc42 ::1
*
* All IPv6 packets going to fb00::/16 through NS2 will be encapsulated in a
* IPv6 header with a Segment Routing Header, with segments :
* fd00::1 -> fd00::2 -> fd00::3 -> fd00::4
*
* 3 fd00::/16 IPv6 addresses are binded to seg6local End.BPF actions :
* - fd00::1 : add a TLV, change the flags and apply a End.X action to fc42::1
* - fd00::2 : remove the TLV, change the flags, add a tag
* - fd00::3 : apply an End.T action to fd00::4, through routing table 117
*
* fd00::4 is a simple Segment Routing node decapsulating the inner IPv6 packet.
* Each End.BPF action will validate the operations applied on the SRH by the
* previous BPF program in the chain, otherwise the packet is dropped.
*
* An UDP datagram is sent from fb00::1 to fb00::6. The test succeeds if this
* datagram can be read on NS6 when binding to fb00::6.
*/
#include "network_helpers.h"
#include "test_progs.h"
#define NETNS_BASE "lwt-seg6local-"
#define BPF_FILE "test_lwt_seg6local.bpf.o"
static void cleanup(void)
{
int ns;
for (ns = 1; ns < 7; ns++)
SYS_NOFAIL("ip netns del %s%d", NETNS_BASE, ns);
}
static int setup(void)
{
int ns;
for (ns = 1; ns < 7; ns++)
SYS(fail, "ip netns add %s%d", NETNS_BASE, ns);
SYS(fail, "ip -n %s6 link set dev lo up", NETNS_BASE);
for (ns = 1; ns < 6; ns++) {
int local_id = ns * 2 - 1;
int peer_id = ns * 2;
int next_ns = ns + 1;
SYS(fail, "ip -n %s%d link add veth%d type veth peer name veth%d netns %s%d",
NETNS_BASE, ns, local_id, peer_id, NETNS_BASE, next_ns);
SYS(fail, "ip -n %s%d link set dev veth%d up", NETNS_BASE, ns, local_id);
SYS(fail, "ip -n %s%d link set dev veth%d up", NETNS_BASE, next_ns, peer_id);
/* All link scope addresses to veths */
SYS(fail, "ip -n %s%d -6 addr add fb00::%d%d/16 dev veth%d scope link",
NETNS_BASE, ns, local_id, peer_id, local_id);
SYS(fail, "ip -n %s%d -6 addr add fb00::%d%d/16 dev veth%d scope link",
NETNS_BASE, next_ns, peer_id, local_id, peer_id);
}
SYS(fail, "ip -n %s5 -6 route add fb00::109 table 117 dev veth9 scope link", NETNS_BASE);
SYS(fail, "ip -n %s1 -6 addr add fb00::1/16 dev lo", NETNS_BASE);
SYS(fail, "ip -n %s1 -6 route add fb00::6 dev veth1 via fb00::21", NETNS_BASE);
SYS(fail, "ip -n %s2 -6 route add fb00::6 encap bpf in obj %s sec encap_srh dev veth2",
NETNS_BASE, BPF_FILE);
SYS(fail, "ip -n %s2 -6 route add fd00::1 dev veth3 via fb00::43 scope link", NETNS_BASE);
SYS(fail, "ip -n %s3 -6 route add fc42::1 dev veth5 via fb00::65", NETNS_BASE);
SYS(fail,
"ip -n %s3 -6 route add fd00::1 encap seg6local action End.BPF endpoint obj %s sec add_egr_x dev veth4",
NETNS_BASE, BPF_FILE);
SYS(fail,
"ip -n %s4 -6 route add fd00::2 encap seg6local action End.BPF endpoint obj %s sec pop_egr dev veth6",
NETNS_BASE, BPF_FILE);
SYS(fail, "ip -n %s4 -6 addr add fc42::1 dev lo", NETNS_BASE);
SYS(fail, "ip -n %s4 -6 route add fd00::3 dev veth7 via fb00::87", NETNS_BASE);
SYS(fail, "ip -n %s5 -6 route add fd00::4 table 117 dev veth9 via fb00::109", NETNS_BASE);
SYS(fail,
"ip -n %s5 -6 route add fd00::3 encap seg6local action End.BPF endpoint obj %s sec inspect_t dev veth8",
NETNS_BASE, BPF_FILE);
SYS(fail, "ip -n %s6 -6 addr add fb00::6/16 dev lo", NETNS_BASE);
SYS(fail, "ip -n %s6 -6 addr add fd00::4/16 dev lo", NETNS_BASE);
for (ns = 1; ns < 6; ns++)
SYS(fail, "ip netns exec %s%d sysctl -wq net.ipv6.conf.all.forwarding=1",
NETNS_BASE, ns);
SYS(fail, "ip netns exec %s6 sysctl -wq net.ipv6.conf.all.seg6_enabled=1", NETNS_BASE);
SYS(fail, "ip netns exec %s6 sysctl -wq net.ipv6.conf.lo.seg6_enabled=1", NETNS_BASE);
SYS(fail, "ip netns exec %s6 sysctl -wq net.ipv6.conf.veth10.seg6_enabled=1", NETNS_BASE);
return 0;
fail:
return -1;
}
#define SERVER_PORT 7330
#define CLIENT_PORT 2121
void test_lwt_seg6local(void)
{
struct sockaddr_in6 server_addr = {};
const char *ns1 = NETNS_BASE "1";
const char *ns6 = NETNS_BASE "6";
struct nstoken *nstoken = NULL;
const char *foobar = "foobar";
ssize_t bytes;
int sfd, cfd;
char buf[7];
if (!ASSERT_OK(setup(), "setup"))
goto out;
nstoken = open_netns(ns6);
if (!ASSERT_OK_PTR(nstoken, "open ns6"))
goto out;
sfd = start_server_str(AF_INET6, SOCK_DGRAM, "fb00::6", SERVER_PORT, NULL);
if (!ASSERT_OK_FD(sfd, "start server"))
goto close_netns;
close_netns(nstoken);
nstoken = open_netns(ns1);
if (!ASSERT_OK_PTR(nstoken, "open ns1"))
goto close_server;
cfd = start_server_str(AF_INET6, SOCK_DGRAM, "fb00::1", CLIENT_PORT, NULL);
if (!ASSERT_OK_FD(cfd, "start client"))
goto close_server;
close_netns(nstoken);
nstoken = NULL;
/* Send a packet larger than MTU */
server_addr.sin6_family = AF_INET6;
server_addr.sin6_port = htons(SERVER_PORT);
if (!ASSERT_EQ(inet_pton(AF_INET6, "fb00::6", &server_addr.sin6_addr), 1,
"build target addr"))
goto close_client;
bytes = sendto(cfd, foobar, sizeof(foobar), 0,
(struct sockaddr *)&server_addr, sizeof(server_addr));
if (!ASSERT_EQ(bytes, sizeof(foobar), "send packet"))
goto close_client;
/* Verify we received all expected bytes */
bytes = read(sfd, buf, sizeof(buf));
if (!ASSERT_EQ(bytes, sizeof(buf), "receive packet"))
goto close_client;
ASSERT_STREQ(buf, foobar, "check udp packet");
close_client:
close(cfd);
close_server:
close(sfd);
close_netns:
close_netns(nstoken);
out:
cleanup();
}

View File

@@ -1,156 +0,0 @@
#!/bin/bash
# Connects 6 network namespaces through veths.
# Each NS may have different IPv6 global scope addresses :
# NS1 ---- NS2 ---- NS3 ---- NS4 ---- NS5 ---- NS6
# fb00::1 fd00::1 fd00::2 fd00::3 fb00::6
# fc42::1 fd00::4
#
# All IPv6 packets going to fb00::/16 through NS2 will be encapsulated in a
# IPv6 header with a Segment Routing Header, with segments :
# fd00::1 -> fd00::2 -> fd00::3 -> fd00::4
#
# 3 fd00::/16 IPv6 addresses are binded to seg6local End.BPF actions :
# - fd00::1 : add a TLV, change the flags and apply a End.X action to fc42::1
# - fd00::2 : remove the TLV, change the flags, add a tag
# - fd00::3 : apply an End.T action to fd00::4, through routing table 117
#
# fd00::4 is a simple Segment Routing node decapsulating the inner IPv6 packet.
# Each End.BPF action will validate the operations applied on the SRH by the
# previous BPF program in the chain, otherwise the packet is dropped.
#
# An UDP datagram is sent from fb00::1 to fb00::6. The test succeeds if this
# datagram can be read on NS6 when binding to fb00::6.
# Kselftest framework requirement - SKIP code is 4.
ksft_skip=4
BPF_FILE="test_lwt_seg6local.bpf.o"
readonly NS1="ns1-$(mktemp -u XXXXXX)"
readonly NS2="ns2-$(mktemp -u XXXXXX)"
readonly NS3="ns3-$(mktemp -u XXXXXX)"
readonly NS4="ns4-$(mktemp -u XXXXXX)"
readonly NS5="ns5-$(mktemp -u XXXXXX)"
readonly NS6="ns6-$(mktemp -u XXXXXX)"
msg="skip all tests:"
if [ $UID != 0 ]; then
echo $msg please run this as root >&2
exit $ksft_skip
fi
TMP_FILE="/tmp/selftest_lwt_seg6local.txt"
cleanup()
{
if [ "$?" = "0" ]; then
echo "selftests: test_lwt_seg6local [PASS]";
else
echo "selftests: test_lwt_seg6local [FAILED]";
fi
set +e
ip netns del ${NS1} 2> /dev/null
ip netns del ${NS2} 2> /dev/null
ip netns del ${NS3} 2> /dev/null
ip netns del ${NS4} 2> /dev/null
ip netns del ${NS5} 2> /dev/null
ip netns del ${NS6} 2> /dev/null
rm -f $TMP_FILE
}
set -e
ip netns add ${NS1}
ip netns add ${NS2}
ip netns add ${NS3}
ip netns add ${NS4}
ip netns add ${NS5}
ip netns add ${NS6}
trap cleanup 0 2 3 6 9
ip link add veth1 type veth peer name veth2
ip link add veth3 type veth peer name veth4
ip link add veth5 type veth peer name veth6
ip link add veth7 type veth peer name veth8
ip link add veth9 type veth peer name veth10
ip link set veth1 netns ${NS1}
ip link set veth2 netns ${NS2}
ip link set veth3 netns ${NS2}
ip link set veth4 netns ${NS3}
ip link set veth5 netns ${NS3}
ip link set veth6 netns ${NS4}
ip link set veth7 netns ${NS4}
ip link set veth8 netns ${NS5}
ip link set veth9 netns ${NS5}
ip link set veth10 netns ${NS6}
ip netns exec ${NS1} ip link set dev veth1 up
ip netns exec ${NS2} ip link set dev veth2 up
ip netns exec ${NS2} ip link set dev veth3 up
ip netns exec ${NS3} ip link set dev veth4 up
ip netns exec ${NS3} ip link set dev veth5 up
ip netns exec ${NS4} ip link set dev veth6 up
ip netns exec ${NS4} ip link set dev veth7 up
ip netns exec ${NS5} ip link set dev veth8 up
ip netns exec ${NS5} ip link set dev veth9 up
ip netns exec ${NS6} ip link set dev veth10 up
ip netns exec ${NS6} ip link set dev lo up
# All link scope addresses and routes required between veths
ip netns exec ${NS1} ip -6 addr add fb00::12/16 dev veth1 scope link
ip netns exec ${NS1} ip -6 route add fb00::21 dev veth1 scope link
ip netns exec ${NS2} ip -6 addr add fb00::21/16 dev veth2 scope link
ip netns exec ${NS2} ip -6 addr add fb00::34/16 dev veth3 scope link
ip netns exec ${NS2} ip -6 route add fb00::43 dev veth3 scope link
ip netns exec ${NS3} ip -6 route add fb00::65 dev veth5 scope link
ip netns exec ${NS3} ip -6 addr add fb00::43/16 dev veth4 scope link
ip netns exec ${NS3} ip -6 addr add fb00::56/16 dev veth5 scope link
ip netns exec ${NS4} ip -6 addr add fb00::65/16 dev veth6 scope link
ip netns exec ${NS4} ip -6 addr add fb00::78/16 dev veth7 scope link
ip netns exec ${NS4} ip -6 route add fb00::87 dev veth7 scope link
ip netns exec ${NS5} ip -6 addr add fb00::87/16 dev veth8 scope link
ip netns exec ${NS5} ip -6 addr add fb00::910/16 dev veth9 scope link
ip netns exec ${NS5} ip -6 route add fb00::109 dev veth9 scope link
ip netns exec ${NS5} ip -6 route add fb00::109 table 117 dev veth9 scope link
ip netns exec ${NS6} ip -6 addr add fb00::109/16 dev veth10 scope link
ip netns exec ${NS1} ip -6 addr add fb00::1/16 dev lo
ip netns exec ${NS1} ip -6 route add fb00::6 dev veth1 via fb00::21
ip netns exec ${NS2} ip -6 route add fb00::6 encap bpf in obj ${BPF_FILE} sec encap_srh dev veth2
ip netns exec ${NS2} ip -6 route add fd00::1 dev veth3 via fb00::43 scope link
ip netns exec ${NS3} ip -6 route add fc42::1 dev veth5 via fb00::65
ip netns exec ${NS3} ip -6 route add fd00::1 encap seg6local action End.BPF endpoint obj ${BPF_FILE} sec add_egr_x dev veth4
ip netns exec ${NS4} ip -6 route add fd00::2 encap seg6local action End.BPF endpoint obj ${BPF_FILE} sec pop_egr dev veth6
ip netns exec ${NS4} ip -6 addr add fc42::1 dev lo
ip netns exec ${NS4} ip -6 route add fd00::3 dev veth7 via fb00::87
ip netns exec ${NS5} ip -6 route add fd00::4 table 117 dev veth9 via fb00::109
ip netns exec ${NS5} ip -6 route add fd00::3 encap seg6local action End.BPF endpoint obj ${BPF_FILE} sec inspect_t dev veth8
ip netns exec ${NS6} ip -6 addr add fb00::6/16 dev lo
ip netns exec ${NS6} ip -6 addr add fd00::4/16 dev lo
ip netns exec ${NS1} sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
ip netns exec ${NS2} sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
ip netns exec ${NS3} sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
ip netns exec ${NS4} sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
ip netns exec ${NS5} sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
ip netns exec ${NS6} sysctl net.ipv6.conf.all.seg6_enabled=1 > /dev/null
ip netns exec ${NS6} sysctl net.ipv6.conf.lo.seg6_enabled=1 > /dev/null
ip netns exec ${NS6} sysctl net.ipv6.conf.veth10.seg6_enabled=1 > /dev/null
ip netns exec ${NS6} nc -l -6 -u -d 7330 > $TMP_FILE &
ip netns exec ${NS1} bash -c "echo 'foobar' | nc -w0 -6 -u -p 2121 -s fb00::1 fb00::6 7330"
sleep 5 # wait enough time to ensure the UDP datagram arrived to the last segment
kill -TERM $!
if [[ $(< $TMP_FILE) != "foobar" ]]; then
exit 1
fi
exit 0