Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions headers/xdp/libxdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ typedef int (*libxdp_print_fn_t)(enum libxdp_print_level level,

libxdp_print_fn_t libxdp_set_print(libxdp_print_fn_t fn);

/* Probe and cache kernel feature support during single-threaded startup. */
void libxdp_cache_kernel_features(void);


struct xdp_program;
struct xdp_multiprog;
Expand Down
7 changes: 7 additions & 0 deletions lib/libxdp/README.org
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ well as reading and writing packets from these sockets.
Some of the functionality provided by libxdp depends on particular kernel
features; see the "Kernel feature compatibility" section below for details.

Applications that want to control when libbpf reports unsupported XDP feature
probes can call =libxdp_cache_kernel_features()= during single-threaded startup.
This probes and caches XDP frags and device-bound support, so later dispatcher
attachments reuse the results instead of repeating the probes. Call it with the
same privileges that will be used for later attachments, and before starting
threads that use libxdp.

** Using libxdp from an application

Basic usage of libxdp from an application is quite straight forward. The
Expand Down
7 changes: 7 additions & 0 deletions lib/libxdp/libxdp.3
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ well as reading and writing packets from these sockets.
.PP
Some of the functionality provided by libxdp depends on particular kernel
features; see the "Kernel feature compatibility" section below for details.
.PP
Applications that want to control when libbpf reports unsupported XDP feature
probes can call \fIlibxdp_cache_kernel_features()\fP during single-threaded startup.
This probes and caches XDP frags and device-bound support, so later dispatcher
attachments reuse the results instead of repeating the probes. Call it with the
same privileges that will be used for later attachments, and before starting
threads that use libxdp.
.SS "Using libxdp from an application"
.PP
Basic usage of libxdp from an application is quite straight forward. The
Expand Down
42 changes: 38 additions & 4 deletions lib/libxdp/libxdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,14 @@ static enum {
COMPAT_UNSUPPORTED
} kernel_compat = COMPAT_UNKNOWN;

/* Set by libxdp_cache_kernel_features() during single-threaded startup. */
static bool kernel_features_cached;
static bool cached_kernel_frags_support;
static bool cached_kernel_dev_bound;

static bool kernel_has_frags_support(void);
static bool kernel_has_dev_bound(void);

static int xdp_multiprog__attach(struct xdp_multiprog *old_mp,
struct xdp_multiprog *mp,
enum xdp_attach_mode mode);
Expand Down Expand Up @@ -1664,13 +1672,13 @@ struct xdp_program *xdp_program__clone(struct xdp_program *prog, unsigned int fl
}

#ifndef HAVE_LIBBPF_BPF_PROGRAM__FLAGS
static bool kernel_has_frags_support(void)
static bool probe_kernel_frags_support(void)
{
pr_debug("Can't support frags with old version of libbpf that doesn't support setting program flags.\n");
return false;
}

static bool kernel_has_dev_bound(void)
static bool probe_kernel_dev_bound(void)
{
pr_debug("Can't bind to device with old version of libbpf that doesn't support setting program flags.\n");
return false;
Expand Down Expand Up @@ -1723,12 +1731,12 @@ static bool kernel_has_bpf_flag(__u32 flag)
return ret;
}

static bool kernel_has_frags_support(void)
static bool probe_kernel_frags_support(void)
{
return kernel_has_bpf_flag(BPF_F_XDP_HAS_FRAGS);
}

static bool kernel_has_dev_bound(void)
static bool probe_kernel_dev_bound(void)
{
return kernel_has_bpf_flag(BPF_F_XDP_DEV_BOUND_ONLY);
}
Expand Down Expand Up @@ -1763,6 +1771,32 @@ static int xdp_program__set_xdp_dev_bound(struct xdp_program *prog,
}
#endif // HAVE_LIBBPF_BPF_PROGRAM__FLAGS

static bool kernel_has_frags_support(void)
{
return kernel_features_cached ? cached_kernel_frags_support :
probe_kernel_frags_support();
}

static bool kernel_has_dev_bound(void)
{
return kernel_features_cached ? cached_kernel_dev_bound :
probe_kernel_dev_bound();
}

/*
* Probe kernel features ahead of time so applications can choose when the
* libbpf diagnostics from unsupported features are emitted.
*/
void libxdp_cache_kernel_features(void)
{
if (kernel_features_cached)
return;

cached_kernel_frags_support = probe_kernel_frags_support();
cached_kernel_dev_bound = probe_kernel_dev_bound();
kernel_features_cached = true;
}

static int xdp_program__attach_single(struct xdp_program *prog, int ifindex,
enum xdp_attach_mode mode,
unsigned int flags)
Expand Down
4 changes: 4 additions & 0 deletions lib/libxdp/libxdp.map
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,7 @@ LIBXDP_1.5.0 {
LIBXDP_1.6.0 {
xdp_multiprog__xdp_dev_bound;
} LIBXDP_1.5.0;

LIBXDP_1.7.0 {
libxdp_cache_kernel_features;
} LIBXDP_1.6.0;
2 changes: 1 addition & 1 deletion lib/libxdp/tests/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)

USER_TARGETS := test_xsk_refcnt test_xdp_frags test_link_detach test_xsk_umem_flags test_xdp_devbound test_xsk_map_leak
USER_TARGETS := test_xsk_refcnt test_xdp_frags test_link_detach test_xsk_umem_flags test_xdp_devbound test_xsk_map_leak test_kernel_feature_cache
STATIC_LINK_TARGETS := check_kern_compat test_dispatcher_versions
BPF_TARGETS := xdp_dispatcher_v1 xdp_dispatcher_v2 xdp_pass
USER_LIBS := -lpthread
Expand Down
10 changes: 9 additions & 1 deletion lib/libxdp/tests/test-libxdp.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)

ALL_TESTS="test_link_so test_link_a test_old_dispatcher test_xdp_devbound test_xdp_frags test_xsk_prog_refcnt_bpffs test_xsk_prog_refcnt_legacy test_xsk_non_privileged test_link_detach test_xsk_umem_flags test_xsk_map_leak"
ALL_TESTS="test_link_so test_link_a test_kernel_feature_cache test_old_dispatcher test_xdp_devbound test_xdp_frags test_xsk_prog_refcnt_bpffs test_xsk_prog_refcnt_legacy test_xsk_non_privileged test_link_detach test_xsk_umem_flags test_xsk_map_leak"

TESTS_DIR=$(dirname "${BASH_SOURCE[0]}")

Expand All @@ -21,6 +21,7 @@ test_link_so()
int main(int argc, char **argv) {
(void) argc; (void) argv;
(void) xdp_program__open_file("filename", "section_name", NULL);
libxdp_cache_kernel_features();
return 0;
}
EOF
Expand All @@ -40,6 +41,7 @@ test_link_a()
int main(int argc, char **argv) {
(void) argc; (void) argv;
(void) xdp_program__open_file("filename", "section_name", NULL);
libxdp_cache_kernel_features();
return 0;
}
EOF
Expand All @@ -49,6 +51,12 @@ EOF
return $retval
}

test_kernel_feature_cache()
{
export LIBXDP_OBJECT_PATH="$TESTS_DIR/.."
check_run "$TESTS_DIR/test_kernel_feature_cache"
}

test_refcnt_once()
{
# We need multiple queues for this test
Expand Down
34 changes: 34 additions & 0 deletions lib/libxdp/tests/test_kernel_feature_cache.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
#include <xdp/libxdp.h>

static int debug_messages;

static int count_debug(enum libxdp_print_level level, const char *format,
va_list args)
{
(void)format;
(void)args;

if (level == LIBXDP_DEBUG)
debug_messages++;
return 0;
}

int main(void)
{
libxdp_print_fn_t old_print;
int first_probe_messages;

old_print = libxdp_set_print(count_debug);
libxdp_cache_kernel_features();
first_probe_messages = debug_messages;
if (!first_probe_messages)
return 1;

libxdp_cache_kernel_features();
if (debug_messages != first_probe_messages)
return 2;

libxdp_set_print(old_print);
return 0;
}