Commit 9a321fd3 authored by Tushar Vyavahare's avatar Tushar Vyavahare Committed by Alexei Starovoitov

selftests/xsk: add xdp populate metadata test

Add a new test in copy-mode for testing the copying of metadata from the
buffer in kernel-space to user-space. This is accomplished by adding a
new XDP program and using the bss map to store a counter that is written
to the metadata field. This counter is incremented for every packet so
that the number becomes unique and should be the same as the payload. It
is store in the bss so the value can be reset between runs.

The XDP program populates the metadata and the userspace program checks
the value stored in the metadata field against the payload using the new
is_metadata_correct() function. To turn this verification on or off, add
a new parameter (use_metadata) to the ifobject structure.
Signed-off-by: default avatarTushar Vyavahare <tushar.vyavahare@intel.com>
Reviewed-by: default avatarMaciej Fijalkowski <maciej.fijalkowski@intel.com>
Link: https://lore.kernel.org/r/20230320102705.306187-1-tushar.vyavahare@intel.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 6a9f5cdb
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <linux/bpf.h> #include <linux/bpf.h>
#include <bpf/bpf_helpers.h> #include <bpf/bpf_helpers.h>
#include "xsk_xdp_metadata.h"
struct { struct {
__uint(type, BPF_MAP_TYPE_XSKMAP); __uint(type, BPF_MAP_TYPE_XSKMAP);
...@@ -12,6 +13,7 @@ struct { ...@@ -12,6 +13,7 @@ struct {
} xsk SEC(".maps"); } xsk SEC(".maps");
static unsigned int idx; static unsigned int idx;
int count = 0;
SEC("xdp") int xsk_def_prog(struct xdp_md *xdp) SEC("xdp") int xsk_def_prog(struct xdp_md *xdp)
{ {
...@@ -27,4 +29,27 @@ SEC("xdp") int xsk_xdp_drop(struct xdp_md *xdp) ...@@ -27,4 +29,27 @@ SEC("xdp") int xsk_xdp_drop(struct xdp_md *xdp)
return bpf_redirect_map(&xsk, 0, XDP_DROP); return bpf_redirect_map(&xsk, 0, XDP_DROP);
} }
SEC("xdp") int xsk_xdp_populate_metadata(struct xdp_md *xdp)
{
void *data, *data_meta;
struct xdp_info *meta;
int err;
/* Reserve enough for all custom metadata. */
err = bpf_xdp_adjust_meta(xdp, -(int)sizeof(struct xdp_info));
if (err)
return XDP_DROP;
data = (void *)(long)xdp->data;
data_meta = (void *)(long)xdp->data_meta;
if (data_meta + sizeof(struct xdp_info) > data)
return XDP_DROP;
meta = data_meta;
meta->count = count++;
return bpf_redirect_map(&xsk, 0, XDP_DROP);
}
char _license[] SEC("license") = "GPL"; char _license[] SEC("license") = "GPL";
/* SPDX-License-Identifier: GPL-2.0 */
struct xdp_info {
__u64 count;
} __attribute__((aligned(32)));
...@@ -103,6 +103,7 @@ ...@@ -103,6 +103,7 @@
#include <bpf/bpf.h> #include <bpf/bpf.h>
#include <linux/filter.h> #include <linux/filter.h>
#include "../kselftest.h" #include "../kselftest.h"
#include "xsk_xdp_metadata.h"
static const char *MAC1 = "\x00\x0A\x56\x9E\xEE\x62"; static const char *MAC1 = "\x00\x0A\x56\x9E\xEE\x62";
static const char *MAC2 = "\x00\x0A\x56\x9E\xEE\x61"; static const char *MAC2 = "\x00\x0A\x56\x9E\xEE\x61";
...@@ -464,6 +465,7 @@ static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx, ...@@ -464,6 +465,7 @@ static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx,
ifobj->use_fill_ring = true; ifobj->use_fill_ring = true;
ifobj->release_rx = true; ifobj->release_rx = true;
ifobj->validation_func = NULL; ifobj->validation_func = NULL;
ifobj->use_metadata = false;
if (i == 0) { if (i == 0) {
ifobj->rx_on = false; ifobj->rx_on = false;
...@@ -798,6 +800,20 @@ static bool is_offset_correct(struct xsk_umem_info *umem, struct pkt_stream *pkt ...@@ -798,6 +800,20 @@ static bool is_offset_correct(struct xsk_umem_info *umem, struct pkt_stream *pkt
return false; return false;
} }
static bool is_metadata_correct(struct pkt *pkt, void *buffer, u64 addr)
{
void *data = xsk_umem__get_data(buffer, addr);
struct xdp_info *meta = data - sizeof(struct xdp_info);
if (meta->count != pkt->payload) {
ksft_print_msg("[%s] expected meta_count [%d], got meta_count [%d]\n",
__func__, pkt->payload, meta->count);
return false;
}
return true;
}
static bool is_pkt_valid(struct pkt *pkt, void *buffer, u64 addr, u32 len) static bool is_pkt_valid(struct pkt *pkt, void *buffer, u64 addr, u32 len)
{ {
void *data = xsk_umem__get_data(buffer, addr); void *data = xsk_umem__get_data(buffer, addr);
...@@ -959,7 +975,8 @@ static int receive_pkts(struct test_spec *test, struct pollfd *fds) ...@@ -959,7 +975,8 @@ static int receive_pkts(struct test_spec *test, struct pollfd *fds)
addr = xsk_umem__add_offset_to_addr(addr); addr = xsk_umem__add_offset_to_addr(addr);
if (!is_pkt_valid(pkt, umem->buffer, addr, desc->len) || if (!is_pkt_valid(pkt, umem->buffer, addr, desc->len) ||
!is_offset_correct(umem, pkt_stream, addr, pkt->addr)) !is_offset_correct(umem, pkt_stream, addr, pkt->addr) ||
(ifobj->use_metadata && !is_metadata_correct(pkt, umem->buffer, addr)))
return TEST_FAILURE; return TEST_FAILURE;
if (ifobj->use_fill_ring) if (ifobj->use_fill_ring)
...@@ -1686,6 +1703,30 @@ static void testapp_xdp_drop(struct test_spec *test) ...@@ -1686,6 +1703,30 @@ static void testapp_xdp_drop(struct test_spec *test)
testapp_validate_traffic(test); testapp_validate_traffic(test);
} }
static void testapp_xdp_metadata_count(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;
struct bpf_map *data_map;
int count = 0;
int key = 0;
test_spec_set_name(test, "XDP_METADATA_COUNT");
test_spec_set_xdp_prog(test, skel_rx->progs.xsk_xdp_populate_metadata,
skel_tx->progs.xsk_xdp_populate_metadata,
skel_rx->maps.xsk, skel_tx->maps.xsk);
test->ifobj_rx->use_metadata = true;
data_map = bpf_object__find_map_by_name(skel_rx->obj, "xsk_xdp_.bss");
if (!data_map || !bpf_map__is_internal(data_map))
exit_with_error(ENOMEM);
if (bpf_map_update_elem(bpf_map__fd(data_map), &key, &count, BPF_ANY))
exit_with_error(errno);
testapp_validate_traffic(test);
}
static void testapp_poll_txq_tmout(struct test_spec *test) static void testapp_poll_txq_tmout(struct test_spec *test)
{ {
test_spec_set_name(test, "POLL_TXQ_FULL"); test_spec_set_name(test, "POLL_TXQ_FULL");
...@@ -1835,6 +1876,9 @@ static void run_pkt_test(struct test_spec *test, enum test_mode mode, enum test_ ...@@ -1835,6 +1876,9 @@ static void run_pkt_test(struct test_spec *test, enum test_mode mode, enum test_
case TEST_TYPE_XDP_DROP_HALF: case TEST_TYPE_XDP_DROP_HALF:
testapp_xdp_drop(test); testapp_xdp_drop(test);
break; break;
case TEST_TYPE_XDP_METADATA_COUNT:
testapp_xdp_metadata_count(test);
break;
default: default:
break; break;
} }
......
...@@ -88,6 +88,7 @@ enum test_type { ...@@ -88,6 +88,7 @@ enum test_type {
TEST_TYPE_STATS_FILL_EMPTY, TEST_TYPE_STATS_FILL_EMPTY,
TEST_TYPE_BPF_RES, TEST_TYPE_BPF_RES,
TEST_TYPE_XDP_DROP_HALF, TEST_TYPE_XDP_DROP_HALF,
TEST_TYPE_XDP_METADATA_COUNT,
TEST_TYPE_MAX TEST_TYPE_MAX
}; };
...@@ -158,6 +159,7 @@ struct ifobject { ...@@ -158,6 +159,7 @@ struct ifobject {
bool use_fill_ring; bool use_fill_ring;
bool release_rx; bool release_rx;
bool shared_umem; bool shared_umem;
bool use_metadata;
u8 dst_mac[ETH_ALEN]; u8 dst_mac[ETH_ALEN];
u8 src_mac[ETH_ALEN]; u8 src_mac[ETH_ALEN];
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment