Commit 6d198a89 authored by Tushar Vyavahare's avatar Tushar Vyavahare Committed by Daniel Borkmann
Browse files

selftests/xsk: Add a test for shared umem feature



Add a new test for testing shared umem feature. This is accomplished by
adding a new XDP program and using the multiple sockets.

The new XDP program redirects the packets based on the destination MAC
address.

Signed-off-by: default avatarTushar Vyavahare <tushar.vyavahare@intel.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarMagnus Karlsson <magnus.karlsson@intel.com>
Link: https://lore.kernel.org/bpf/20230927135241.2287547-9-tushar.vyavahare@intel.com
parent fc2cb864
Loading
Loading
Loading
Loading
+19 −1
Original line number Diff line number Diff line
@@ -3,11 +3,12 @@

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <linux/if_ether.h>
#include "xsk_xdp_common.h"

struct {
	__uint(type, BPF_MAP_TYPE_XSKMAP);
	__uint(max_entries, 1);
	__uint(max_entries, 2);
	__uint(key_size, sizeof(int));
	__uint(value_size, sizeof(int));
} xsk SEC(".maps");
@@ -52,4 +53,21 @@ SEC("xdp.frags") int xsk_xdp_populate_metadata(struct xdp_md *xdp)
	return bpf_redirect_map(&xsk, 0, XDP_DROP);
}

SEC("xdp") int xsk_xdp_shared_umem(struct xdp_md *xdp)
{
	void *data = (void *)(long)xdp->data;
	void *data_end = (void *)(long)xdp->data_end;
	struct ethhdr *eth = data;

	if (eth + 1 > data_end)
		return XDP_DROP;

	/* Redirecting packets based on the destination MAC address */
	idx = ((unsigned int)(eth->h_dest[5])) / 2;
	if (idx > MAX_SOCKETS)
		return XDP_DROP;

	return bpf_redirect_map(&xsk, idx, XDP_DROP);
}

char _license[] SEC("license") = "GPL";
+2 −0
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@
#ifndef XSK_XDP_COMMON_H_
#define XSK_XDP_COMMON_H_

#define MAX_SOCKETS 2

struct xdp_info {
	__u64 count;
} __attribute__((aligned(32)));
+50 −5
Original line number Diff line number Diff line
@@ -651,7 +651,7 @@ static u32 pkt_get_buffer_len(struct xsk_umem_info *umem, u32 len)
	return ceil_u32(len, umem->frame_size) * umem->frame_size;
}

static struct pkt_stream *pkt_stream_generate(u32 nb_pkts, u32 pkt_len)
static struct pkt_stream *__pkt_stream_generate(u32 nb_pkts, u32 pkt_len, u32 nb_start, u32 nb_off)
{
	struct pkt_stream *pkt_stream;
	u32 i;
@@ -666,12 +666,17 @@ static struct pkt_stream *pkt_stream_generate(u32 nb_pkts, u32 pkt_len)
		struct pkt *pkt = &pkt_stream->pkts[i];

		pkt_set(pkt_stream, pkt, 0, pkt_len);
		pkt->pkt_nb = i;
		pkt->pkt_nb = nb_start + i * nb_off;
	}

	return pkt_stream;
}

static struct pkt_stream *pkt_stream_generate(u32 nb_pkts, u32 pkt_len)
{
	return __pkt_stream_generate(nb_pkts, pkt_len, 0, 1);
}

static struct pkt_stream *pkt_stream_clone(struct pkt_stream *pkt_stream)
{
	return pkt_stream_generate(pkt_stream->nb_pkts, pkt_stream->pkts[0].len);
@@ -721,6 +726,24 @@ static void pkt_stream_receive_half(struct test_spec *test)
	pkt_stream->nb_valid_entries /= 2;
}

static void pkt_stream_even_odd_sequence(struct test_spec *test)
{
	struct pkt_stream *pkt_stream;
	u32 i;

	for (i = 0; i < test->nb_sockets; i++) {
		pkt_stream = test->ifobj_tx->xsk_arr[i].pkt_stream;
		pkt_stream = __pkt_stream_generate(pkt_stream->nb_pkts / 2,
						   pkt_stream->pkts[0].len, i, 2);
		test->ifobj_tx->xsk_arr[i].pkt_stream = pkt_stream;

		pkt_stream = test->ifobj_rx->xsk_arr[i].pkt_stream;
		pkt_stream = __pkt_stream_generate(pkt_stream->nb_pkts / 2,
						   pkt_stream->pkts[0].len, i, 2);
		test->ifobj_rx->xsk_arr[i].pkt_stream = pkt_stream;
	}
}

static u64 pkt_get_addr(struct pkt *pkt, struct xsk_umem_info *umem)
{
	if (!pkt->valid)
@@ -1584,6 +1607,7 @@ static void thread_common_ops(struct test_spec *test, struct ifobject *ifobject)
	LIBBPF_OPTS(bpf_xdp_query_opts, opts);
	void *bufs;
	int ret;
	u32 i;

	if (ifobject->umem->unaligned_mode)
		mmap_flags |= MAP_HUGETLB | MAP_HUGE_2MB;
@@ -1608,10 +1632,13 @@ static void thread_common_ops(struct test_spec *test, struct ifobject *ifobject)

	xsk_populate_fill_ring(ifobject->umem, ifobject->xsk->pkt_stream, ifobject->use_fill_ring);

	ret = xsk_update_xskmap(ifobject->xskmap, ifobject->xsk->xsk, 0);
	for (i = 0; i < test->nb_sockets; i++) {
		ifobject->xsk = &ifobject->xsk_arr[i];
		ret = xsk_update_xskmap(ifobject->xskmap, ifobject->xsk->xsk, i);
		if (ret)
			exit_with_error(errno);
	}
}

static void *worker_testapp_validate_tx(void *arg)
{
@@ -2111,6 +2138,23 @@ static int testapp_xdp_metadata_copy(struct test_spec *test)
	return testapp_validate_traffic(test);
}

static int testapp_xdp_shared_umem(struct test_spec *test)
{
	struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs;
	struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs;

	test->total_steps = 1;
	test->nb_sockets = 2;

	test_spec_set_xdp_prog(test, skel_rx->progs.xsk_xdp_shared_umem,
			       skel_tx->progs.xsk_xdp_shared_umem,
			       skel_rx->maps.xsk, skel_tx->maps.xsk);

	pkt_stream_even_odd_sequence(test);

	return testapp_validate_traffic(test);
}

static int testapp_poll_txq_tmout(struct test_spec *test)
{
	test->ifobj_tx->use_poll = true;
@@ -2412,6 +2456,7 @@ static const struct test_spec tests[] = {
	{.name = "STAT_FILL_EMPTY", .test_func = testapp_stats_fill_empty},
	{.name = "XDP_PROG_CLEANUP", .test_func = testapp_xdp_prog_cleanup},
	{.name = "XDP_DROP_HALF", .test_func = testapp_xdp_drop},
	{.name = "XDP_SHARED_UMEM", .test_func = testapp_xdp_shared_umem},
	{.name = "XDP_METADATA_COPY", .test_func = testapp_xdp_metadata},
	{.name = "XDP_METADATA_COPY_MULTI_BUFF", .test_func = testapp_xdp_metadata_mb},
	{.name = "SEND_RECEIVE_9K_PACKETS", .test_func = testapp_send_receive_mb},
+1 −1
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <limits.h>

#include "xsk_xdp_progs.skel.h"
#include "xsk_xdp_common.h"

#ifndef SOL_XDP
#define SOL_XDP 283
@@ -35,7 +36,6 @@
#define TEST_SKIP 2
#define MAX_INTERFACES 2
#define MAX_INTERFACE_NAME_CHARS 16
#define MAX_SOCKETS 2
#define MAX_TEST_NAME_SIZE 48
#define MAX_TEARDOWN_ITER 10
#define PKT_HDR_SIZE (sizeof(struct ethhdr) + 2) /* Just to align the data in the packet */