[Devel] [PATCH hci-8.1 v4 2/3] selftests/bpf: xsk: take the fragment limit from the kernel's BTF
Konstantin Khorenko
khorenko at virtuozzo.com
Tue Oct 27 21:15:20 MSK 2026
From: Eva Kurchatova <eva.kurchatova at virtuozzo.com>
too_many_frags sends a packet with as many fragments as the kernel
takes, then one that goes past the limit, and expects only the first to
arrive. xskxceiver reads the limit from the max_skb_frags sysctl, which
has two problems:
- AF_XDP does not use the sysctl: xsk_build_skb() checks the
compile-time MAX_SKB_FRAGS. The sysctl only equals it by default, so
on a host where it is lowered the test expects the wrong limit.
- The sysctl exists in the initial network namespace only. A run in any
other namespace finds no file and falls back to 17, wrong for a kernel
built with another CONFIG_MAX_SKB_FRAGS.
Take the limit from the kernel's BTF as the element count of
skb_shared_info's frags array: it is MAX_SKB_FRAGS itself and readable
from any namespace. The sysctl stays as a fallback for a kernel without
BTF.
https://virtuozzo.atlassian.net/browse/VSTOR-150731
Feature: fix selftests
Signed-off-by: Eva Kurchatova <eva.kurchatova at virtuozzo.com>
Reviewed-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
tools/testing/selftests/bpf/xskxceiver.c | 39 +++++++++++++++++++++++++++++++-
1 file changed, 38 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/xskxceiver.c b/tools/testing/selftests/bpf/xskxceiver.c
index 11f047b8af752..a4a0b4e2516ca 100644
--- a/tools/testing/selftests/bpf/xskxceiver.c
+++ b/tools/testing/selftests/bpf/xskxceiver.c
@@ -103,6 +103,7 @@
#include "xsk.h"
#include "xskxceiver.h"
#include <bpf/bpf.h>
+#include <bpf/btf.h>
#include <linux/filter.h>
#include "../kselftest.h"
#include "xsk_xdp_common.h"
@@ -325,12 +326,48 @@ static bool ifobj_zc_avail(struct ifobject *ifobject)
return zc_avail;
}
+/* AF_XDP checks MAX_SKB_FRAGS, which the sysctl only follows by default */
+static unsigned int btf_max_skb_frags(void)
+{
+ unsigned int max_skb_frags = 0;
+ const struct btf_member *m;
+ const struct btf_type *t;
+ struct btf *btf;
+ int id, i;
+
+ btf = btf__load_vmlinux_btf();
+ if (!btf)
+ return 0;
+
+ id = btf__find_by_name_kind(btf, "skb_shared_info", BTF_KIND_STRUCT);
+ if (id < 0)
+ goto out;
+
+ t = btf__type_by_id(btf, id);
+ m = btf_members(t);
+ for (i = 0; i < btf_vlen(t); i++, m++) {
+ if (strcmp(btf__name_by_offset(btf, m->name_off), "frags"))
+ continue;
+ t = btf__type_by_id(btf, m->type);
+ if (btf_is_array(t))
+ max_skb_frags = btf_array(t)->nelems;
+ break;
+ }
+out:
+ btf__free(btf);
+ return max_skb_frags;
+}
+
#define MAX_SKB_FRAGS_PATH "/proc/sys/net/core/max_skb_frags"
static unsigned int get_max_skb_frags(void)
{
- unsigned int max_skb_frags = 0;
+ unsigned int max_skb_frags = btf_max_skb_frags();
FILE *file;
+ if (max_skb_frags)
+ return max_skb_frags;
+
+ ksft_print_msg("No MAX_SKB_FRAGS in the kernel's BTF, reading %s\n", MAX_SKB_FRAGS_PATH);
file = fopen(MAX_SKB_FRAGS_PATH, "r");
if (!file) {
ksft_print_msg("Error opening %s\n", MAX_SKB_FRAGS_PATH);
--
2.43.0
More information about the Devel
mailing list