Merge branch 'selftests-bpf-migrate-test_xdp_redirect-sh-to-test_progs'

Bastien Curutchet says:

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

test_xdp_redirect.sh tests the XDP redirections done through
bpf_redirect().

These XDP redirections are already tested by prog_tests/xdp_do_redirect.c
but IMO it doesn't cover the exact same code path because
xdp_do_redirect.c uses bpf_prog_test_run_opts() to trigger redirections
of 'fake packets' while test_xdp_redirect.sh redirects packets coming
from the network. Also, the test_xdp_redirect.sh script tests the
redirections with both SKB and DRV modes while xdp_do_redirect.c only
tests the DRV mode.

The patch series adds two new test cases in prog_tests/xdp_do_redirect.c
to replace the test_xdp_redirect.sh script.
====================

Link: https://patch.msgid.link/20250110-xdp_redirect-v2-0-b8f3ae53e894@bootlin.com
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
This commit is contained in:
Martin KaFai Lau 2025-01-10 16:04:09 -08:00
commit be339ddf9e
5 changed files with 176 additions and 106 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 # Order correspond to 'make run_tests' order
TEST_PROGS := test_kmod.sh \ TEST_PROGS := test_kmod.sh \
test_xdp_redirect.sh \
test_xdp_redirect_multi.sh \ test_xdp_redirect_multi.sh \
test_xdp_meta.sh \ test_xdp_meta.sh \
test_tunnel.sh \ test_tunnel.sh \

View File

@ -11,6 +11,7 @@
#include <bpf/bpf_endian.h> #include <bpf/bpf_endian.h>
#include <uapi/linux/netdev.h> #include <uapi/linux/netdev.h>
#include "test_xdp_do_redirect.skel.h" #include "test_xdp_do_redirect.skel.h"
#include "xdp_dummy.skel.h"
struct udp_packet { struct udp_packet {
struct ethhdr eth; struct ethhdr eth;
@ -246,3 +247,166 @@ out:
SYS_NOFAIL("ip netns del testns"); SYS_NOFAIL("ip netns del testns");
test_xdp_do_redirect__destroy(skel); test_xdp_do_redirect__destroy(skel);
} }
#define NS_NB 3
#define NS0 "NS0"
#define NS1 "NS1"
#define NS2 "NS2"
#define IPV4_NETWORK "10.1.1"
#define VETH1_INDEX 111
#define VETH2_INDEX 222
struct test_data {
struct netns_obj *ns[NS_NB];
u32 xdp_flags;
};
static void cleanup(struct test_data *data)
{
int i;
for (i = 0; i < NS_NB; i++)
netns_free(data->ns[i]);
}
/**
* ping_setup -
* Create two veth peers and forward packets in-between using XDP
*
* ------------ ------------
* | NS1 | | NS2 |
* | veth0 | | veth0 |
* | 10.1.1.1 | | 10.1.1.2 |
* -----|------ ------|-----
* | |
* | |
* -----|-----------------------|-------
* | veth1 veth2 |
* | (id:111) (id:222) |
* | | | |
* | ----- xdp forwarding ----- |
* | |
* | NS0 |
* -------------------------------------
*/
static int ping_setup(struct test_data *data)
{
int i;
data->ns[0] = netns_new(NS0, false);
if (!ASSERT_OK_PTR(data->ns[0], "create ns"))
return -1;
for (i = 1; i < NS_NB; i++) {
char ns_name[4] = {};
snprintf(ns_name, 4, "NS%d", i);
data->ns[i] = netns_new(ns_name, false);
if (!ASSERT_OK_PTR(data->ns[i], "create ns"))
goto fail;
SYS(fail,
"ip -n %s link add veth%d index %d%d%d type veth peer name veth0 netns %s",
NS0, i, i, i, i, ns_name);
SYS(fail, "ip -n %s link set veth%d up", NS0, i);
SYS(fail, "ip -n %s addr add %s.%d/24 dev veth0", ns_name, IPV4_NETWORK, i);
SYS(fail, "ip -n %s link set veth0 up", ns_name);
}
return 0;
fail:
cleanup(data);
return -1;
}
static void ping_test(struct test_data *data)
{
struct test_xdp_do_redirect *skel = NULL;
struct xdp_dummy *skel_dummy = NULL;
struct nstoken *nstoken = NULL;
int i, ret;
skel_dummy = xdp_dummy__open_and_load();
if (!ASSERT_OK_PTR(skel_dummy, "open and load xdp_dummy skeleton"))
goto close;
for (i = 1; i < NS_NB; i++) {
char ns_name[4] = {};
snprintf(ns_name, 4, "NS%d", i);
nstoken = open_netns(ns_name);
if (!ASSERT_OK_PTR(nstoken, "open ns"))
goto close;
ret = bpf_xdp_attach(if_nametoindex("veth0"),
bpf_program__fd(skel_dummy->progs.xdp_dummy_prog),
data->xdp_flags, NULL);
if (!ASSERT_GE(ret, 0, "bpf_xdp_attach dummy_prog"))
goto close;
close_netns(nstoken);
nstoken = NULL;
}
skel = test_xdp_do_redirect__open_and_load();
if (!ASSERT_OK_PTR(skel, "open and load skeleton"))
goto close;
nstoken = open_netns(NS0);
if (!ASSERT_OK_PTR(nstoken, "open NS0"))
goto close;
ret = bpf_xdp_attach(VETH2_INDEX,
bpf_program__fd(skel->progs.xdp_redirect_to_111),
data->xdp_flags, NULL);
if (!ASSERT_GE(ret, 0, "bpf_xdp_attach"))
goto close;
ret = bpf_xdp_attach(VETH1_INDEX,
bpf_program__fd(skel->progs.xdp_redirect_to_222),
data->xdp_flags, NULL);
if (!ASSERT_GE(ret, 0, "bpf_xdp_attach"))
goto close;
close_netns(nstoken);
nstoken = NULL;
nstoken = open_netns(NS1);
if (!ASSERT_OK_PTR(nstoken, "open NS1"))
goto close;
SYS(close, "ping -c 1 %s.2 > /dev/null", IPV4_NETWORK);
close:
close_netns(nstoken);
xdp_dummy__destroy(skel_dummy);
test_xdp_do_redirect__destroy(skel);
}
static void xdp_redirect_ping(u32 xdp_flags)
{
struct test_data data = {};
if (ping_setup(&data) < 0)
return;
data.xdp_flags = xdp_flags;
ping_test(&data);
cleanup(&data);
}
void test_xdp_index_redirect(void)
{
if (test__start_subtest("noflag"))
xdp_redirect_ping(0);
if (test__start_subtest("drvflag"))
xdp_redirect_ping(XDP_FLAGS_DRV_MODE);
if (test__start_subtest("skbflag"))
xdp_redirect_ping(XDP_FLAGS_SKB_MODE);
}

View File

@ -98,6 +98,18 @@ int xdp_count_pkts(struct xdp_md *xdp)
return XDP_DROP; return XDP_DROP;
} }
SEC("xdp")
int xdp_redirect_to_111(struct xdp_md *xdp)
{
return bpf_redirect(111, 0);
}
SEC("xdp")
int xdp_redirect_to_222(struct xdp_md *xdp)
{
return bpf_redirect(222, 0);
}
SEC("tc") SEC("tc")
int tc_count_pkts(struct __sk_buff *skb) int tc_count_pkts(struct __sk_buff *skb)
{ {

View File

@ -1,26 +0,0 @@
/* Copyright (c) 2017 VMware
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
SEC("redirect_to_111")
int xdp_redirect_to_111(struct xdp_md *xdp)
{
return bpf_redirect(111, 0);
}
SEC("redirect_to_222")
int xdp_redirect_to_222(struct xdp_md *xdp)
{
return bpf_redirect(222, 0);
}
char _license[] SEC("license") = "GPL";

View File

@ -1,79 +0,0 @@
#!/bin/bash
# Create 2 namespaces with two veth peers, and
# forward packets in-between using generic XDP
#
# NS1(veth11) NS2(veth22)
# | |
# | |
# (veth1, ------ (veth2,
# id:111) id:222)
# | xdp forwarding |
# ------------------
readonly NS1="ns1-$(mktemp -u XXXXXX)"
readonly NS2="ns2-$(mktemp -u XXXXXX)"
ret=0
setup()
{
local xdpmode=$1
ip netns add ${NS1}
ip netns add ${NS2}
ip link add veth1 index 111 type veth peer name veth11 netns ${NS1}
ip link add veth2 index 222 type veth peer name veth22 netns ${NS2}
ip link set veth1 up
ip link set veth2 up
ip -n ${NS1} link set dev veth11 up
ip -n ${NS2} link set dev veth22 up
ip -n ${NS1} addr add 10.1.1.11/24 dev veth11
ip -n ${NS2} addr add 10.1.1.22/24 dev veth22
}
cleanup()
{
ip link del veth1 2> /dev/null
ip link del veth2 2> /dev/null
ip netns del ${NS1} 2> /dev/null
ip netns del ${NS2} 2> /dev/null
}
test_xdp_redirect()
{
local xdpmode=$1
setup
ip link set dev veth1 $xdpmode off &> /dev/null
if [ $? -ne 0 ];then
echo "selftests: test_xdp_redirect $xdpmode [SKIP]"
return 0
fi
ip -n ${NS1} link set veth11 $xdpmode obj xdp_dummy.bpf.o sec xdp &> /dev/null
ip -n ${NS2} link set veth22 $xdpmode obj xdp_dummy.bpf.o sec xdp &> /dev/null
ip link set dev veth1 $xdpmode obj test_xdp_redirect.bpf.o sec redirect_to_222 &> /dev/null
ip link set dev veth2 $xdpmode obj test_xdp_redirect.bpf.o sec redirect_to_111 &> /dev/null
if ip netns exec ${NS1} ping -c 1 10.1.1.22 &> /dev/null &&
ip netns exec ${NS2} ping -c 1 10.1.1.11 &> /dev/null; then
echo "selftests: test_xdp_redirect $xdpmode [PASS]";
else
ret=1
echo "selftests: test_xdp_redirect $xdpmode [FAILED]";
fi
cleanup
}
set -e
trap cleanup 2 3 6 9
test_xdp_redirect xdpgeneric
test_xdp_redirect xdpdrv
exit $ret