xdp-project / xdp-tools

Utilities and example programs for use with XDP
Other
661 stars 144 forks source link

xdp-loader seems unable to pin internal .data map? #419

Closed vincentmli closed 7 months ago

vincentmli commented 7 months ago

Hi @tohojo

I have fork of xdp-tools, based on that, I added a few xdp program in my fork repo, for example this xdp-udp (https://github.com/vincentmli/xdp-tools/blob/vli-xdp-synproxy/xdp-udp/xdp_udp.bpf.c#L54) has global variable ratelimit, when I ran command

xdp-loader load red0 -P 90 -p /sys/fs/bpf/xdp-udp -n xdp_udp /usr/lib/bpf/xdp_udp.bpf.o to pin bpf map to /sys/fs/bpf/xdp-udp directory, but the .data map is not pinned under that directory, other maps are pinned

[root@firebee ~]# ls -l /sys/fs/bpf/xdp-udp/
total 0
-rw------- 1 root root 0 Apr 19 09:58 udp_exclude_v4_prefixes
-rw------- 1 root root 0 Apr 19 09:58 udp_rate_table

here is the internal map name for the .data map from bpftool output

bpftool map | grep -A2 'xdp_udp.data'
202: array  name xdp_udp.data  flags 0x0
    key 4B  value 4B  max_entries 1  memlock 328B
    btf_id 323

in my fork of xdp-tools repo, the xdp-loader had this revert Revert "xdp-loader: Only load the BPF program we need from object files", so I can load xdp program with tail calls, that revert seems should not affect the pin map feature.

vincentmli commented 7 months ago

I did another test with a simple xdp_pass program with xdp-loader from upstream xdp-tools repo

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <xdp/xdp_helpers.h>

struct {
        __uint(priority, 10);
        __uint(XDP_PASS, 1);
} XDP_RUN_CONFIG(xdp_pass);

static volatile unsigned int ratelimit = 1000;

SEC("xdp")
int xdp_pass(struct xdp_md *ctx)
{
   bpf_printk("ratelimit %d \n",ratelimit);

    return XDP_PASS;
}

char _license[] SEC("license") = "GPL";

load the program

./xdp-loader/xdp-loader load -m skb lo -p /sys/fs/bpf/xdp-pass ./lib/testing/xdp_pass.o

 ls -l /sys/fs/bpf/xdp-pass
ls: cannot access '/sys/fs/bpf/xdp-pass': No such file or directory

bpftool shows the map

 bpftool map | grep -A2 'xdp_pass.data'
92: array  name xdp_pass.data  flags 0x0
    key 4B  value 4B  max_entries 1  memlock 4096B
    btf_id 223

it looks xdp-loader can't pin the internal .data map, I wonder if this is not supported in kernel, not xdp-loader issue.

vincentmli commented 7 months ago

it looks libbpf does not take the pin_root_path for global data map, Is it intended to not expose global data map to bpf fs ?

https://github.com/libbpf/libbpf/blob/master/src/libbpf.c#L2977-L2993

static int bpf_object__init_maps(struct bpf_object *obj,
                                 const struct bpf_object_open_opts *opts)
{
        const char *pin_root_path;
        bool strict;
        int err = 0;

        strict = !OPTS_GET(opts, relaxed_maps, false);
        pin_root_path = OPTS_GET(opts, pin_root_path, NULL);

        err = bpf_object__init_user_btf_maps(obj, strict, pin_root_path);
        err = err ?: bpf_object__init_global_data_maps(obj);
        err = err ?: bpf_object__init_kconfig_map(obj);
        err = err ?: bpf_object_init_struct_ops(obj);

        return err;
}
vincentmli commented 7 months ago

fyi, bpftool can update global .data map directly by iterate through map ids to get the global data map fd, no need to expose global data map to bpf fs

tohojo commented 7 months ago

Vincent Li @.***> writes:

it looks libbpf does not take the pin_root_path for global data map, Is it intended to not expose global data map to bpf fs ?

Yeah, pretty sure the .data map is considered internal and thus not really supposed to be exposed that way...