Commit be339ddf authored by Martin KaFai Lau's avatar Martin KaFai Lau
Browse files

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: default avatarMartin KaFai Lau <martin.lau@kernel.org>
parents 95ad526e 3e99fa9f
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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_xdp_redirect.sh \
	test_xdp_redirect_multi.sh \
	test_xdp_meta.sh \
	test_tunnel.sh \
+164 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <bpf/bpf_endian.h>
#include <uapi/linux/netdev.h>
#include "test_xdp_do_redirect.skel.h"
#include "xdp_dummy.skel.h"

struct udp_packet {
	struct ethhdr eth;
@@ -246,3 +247,166 @@ void test_xdp_do_redirect(void)
	SYS_NOFAIL("ip netns del testns");
	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);
}
+12 −0
Original line number Diff line number Diff line
@@ -98,6 +98,18 @@ int xdp_count_pkts(struct xdp_md *xdp)
	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")
int tc_count_pkts(struct __sk_buff *skb)
{
+0 −26
Original line number Diff line number Diff line
/* 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";
+0 −79
Original line number Diff line number Diff line
#!/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