diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 38638845db9d74..5319949dbe85a4 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -59,6 +59,7 @@ tprogs-y += xdp_redirect_map_multi tprogs-y += xdp_redirect_map tprogs-y += xdp_redirect tprogs-y += xdp_monitor +tprogs-y += xdp_meta # Libbpf dependencies LIBBPF_SRC = $(TOOLS_PATH)/lib/bpf @@ -124,6 +125,7 @@ xdp_redirect_cpu-objs := xdp_redirect_cpu_user.o $(XDP_SAMPLE) xdp_redirect_map-objs := xdp_redirect_map_user.o $(XDP_SAMPLE) xdp_redirect-objs := xdp_redirect_user.o $(XDP_SAMPLE) xdp_monitor-objs := xdp_monitor_user.o $(XDP_SAMPLE) +xdp_meta-objs := xdp_meta_user.o # Tell kbuild to always build the programs always-y := $(tprogs-y) @@ -342,6 +344,7 @@ $(obj)/xdp_redirect_map_multi_user.o: $(obj)/xdp_redirect_map_multi.skel.h $(obj)/xdp_redirect_map_user.o: $(obj)/xdp_redirect_map.skel.h $(obj)/xdp_redirect_user.o: $(obj)/xdp_redirect.skel.h $(obj)/xdp_monitor_user.o: $(obj)/xdp_monitor.skel.h +$(obj)/xdp_meta_user.o: $(obj)/xdp_meta.skel.h $(obj)/tracex5_kern.o: $(obj)/syscall_nrs.h $(obj)/hbm_out_kern.o: $(src)/hbm.h $(src)/hbm_kern.h @@ -409,7 +412,8 @@ $(obj)/%.bpf.o: $(src)/%.bpf.c $(obj)/vmlinux.h $(src)/xdp_sample.bpf.h $(src)/x -c $(filter %.bpf.c,$^) -o $@ LINKED_SKELS := xdp_redirect_cpu.skel.h xdp_redirect_map_multi.skel.h \ - xdp_redirect_map.skel.h xdp_redirect.skel.h xdp_monitor.skel.h + xdp_redirect_map.skel.h xdp_redirect.skel.h xdp_monitor.skel.h \ + xdp_meta.skel.h clean-files += $(LINKED_SKELS) xdp_redirect_cpu.skel.h-deps := xdp_redirect_cpu.bpf.o xdp_sample.bpf.o @@ -417,9 +421,9 @@ xdp_redirect_map_multi.skel.h-deps := xdp_redirect_map_multi.bpf.o xdp_sample.bp xdp_redirect_map.skel.h-deps := xdp_redirect_map.bpf.o xdp_sample.bpf.o xdp_redirect.skel.h-deps := xdp_redirect.bpf.o xdp_sample.bpf.o xdp_monitor.skel.h-deps := xdp_monitor.bpf.o xdp_sample.bpf.o +xdp_meta.skel.h-deps := xdp_meta.bpf.o LINKED_BPF_SRCS := $(patsubst %.bpf.o,%.bpf.c,$(foreach skel,$(LINKED_SKELS),$($(skel)-deps))) - BPF_SRCS_LINKED := $(notdir $(wildcard $(src)/*.bpf.c)) BPF_OBJS_LINKED := $(patsubst %.bpf.c,$(obj)/%.bpf.o, $(BPF_SRCS_LINKED)) BPF_SKELS_LINKED := $(addprefix $(obj)/,$(LINKED_SKELS)) diff --git a/samples/bpf/xdp_meta.bpf.c b/samples/bpf/xdp_meta.bpf.c new file mode 100644 index 00000000000000..399d9c444e3840 --- /dev/null +++ b/samples/bpf/xdp_meta.bpf.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0 +/* This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + */ +#include "vmlinux.h" + +#include +#include +#include + +struct ice_aqc_generic___min { + __le32 param0; + __le32 param1; + __le32 addr_high; + __le32 addr_low; +}; + +SEC("xdp") +int xdp_meta_prog(struct xdp_md *ctx) +{ + struct xdp_meta_generic *data_meta = + (void *)(long)ctx->data_meta; + void *data = (void *)(long)ctx->data; + void *data_end = (void *)(long)ctx->data_end; + u32 type_id_meta, btf_id_meta, magic_meta; + u64 btf_id_libbpf, btf_id_ice; + struct ethhdr *eth = data; + u64 nh_off; + u16 rxcvid; + u32 hash; + + nh_off = sizeof(*eth); + if (data + nh_off > data_end) + return XDP_DROP; + + if (data_meta + 1 > data) { + bpf_printk("data_meta space is not sufficient for generic metadata, should be %ld, is %ld\n", + sizeof(struct xdp_meta_generic), (long)data - (long)data_meta); + return XDP_DROP; + } + + bpf_probe_read_kernel(&magic_meta, sizeof(magic_meta), (void *)data - 4); + if (magic_meta != XDP_META_GENERIC_MAGIC) { + bpf_printk("meta des not contain generic hints, based on received magic: 0x%x\n", + magic_meta); + return XDP_DROP; + } + + btf_id_libbpf = bpf_core_type_id_kernel(struct xdp_meta_generic); + bpf_probe_read_kernel(&type_id_meta, sizeof(type_id_meta), (void *)data - 8); + bpf_probe_read_kernel(&btf_id_meta, sizeof(btf_id_meta), (void *)data - 12); + + bpf_printk("id from libbpf %u (module BTF id: %u), id from hints metadata %u (module BTF id: %u)\n", + btf_id_libbpf & 0xFFFFFFFF, btf_id_libbpf >> 32, type_id_meta, btf_id_meta); + + if (btf_id_libbpf == ((u64)btf_id_meta << 32 | type_id_meta)) + bpf_printk("Received meta is generic\n"); + else + bpf_printk("Received meta type is unknown\n"); + + btf_id_ice = bpf_core_type_id_kernel(struct ice_aqc_generic___min); + bpf_printk("ice_aqc_generic type id %u, ice BTF id %u\n", + btf_id_ice & 0xFFFFFFFF, btf_id_ice >> 32); + + hash = BPF_CORE_READ(data_meta, rx_hash); + rxcvid = BPF_CORE_READ(data_meta, rx_vid); + bpf_printk("Metadata. Hash: 0x%x, VID: %d\n", hash, rxcvid); + + return XDP_PASS; +} + +char LICENSE[] SEC("license") = "GPL"; diff --git a/samples/bpf/xdp_meta_user.c b/samples/bpf/xdp_meta_user.c new file mode 100644 index 00000000000000..4551d9bafb9945 --- /dev/null +++ b/samples/bpf/xdp_meta_user.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xdp_meta.skel.h" + +#define DEBUGFS "/sys/kernel/debug/tracing/" + +static volatile bool xdp_meta_sample_running = true; + +static void xdp_meta_sample_stop(int signo) +{ + xdp_meta_sample_running = false; +} + +/* Had to change the standard read_trace_pipe from trace_helpers.h */ +static void xdp_meta_read_trace_pipe(void) +{ + int trace_fd; + + trace_fd = open(DEBUGFS "trace_pipe", O_RDONLY, 0); + if (trace_fd < 0) { + fprintf(stderr, "Could not open the trace_pipe\n"); + return; + } + + while (xdp_meta_sample_running) { + static char buf[4096]; + ssize_t sz; + + sz = read(trace_fd, buf, sizeof(buf) - 1); + if (sz > 0) { + buf[sz] = 0; + puts(buf); + } + } +} + +int main(int argc, char **argv) +{ + __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST | XDP_FLAGS_USE_METADATA; + __u32 prog_id, prog_fd, running_prog_id; + struct xdp_meta *skel; + int ifindex, ret = 1; + struct sigaction handle_ctrl_c; + + if (argc == optind) + return ret; + + ifindex = if_nametoindex(argv[optind]); + if (!ifindex) + ifindex = strtoul(argv[optind], NULL, 0); + if (!ifindex) { + fprintf(stderr, "Bad interface index or name\n"); + goto end; + } + + skel = xdp_meta__open(); + if (!skel) { + fprintf(stderr, "Failed to xdp_meta__open: %s\n", + strerror(errno)); + ret = 1; + goto end; + } + + ret = xdp_meta__load(skel); + if (ret < 0) { + fprintf(stderr, "Failed to xdp_meta__load: %s\n", strerror(errno)); + ret = 1; + goto end_destroy; + } + + ret = 1; + prog_fd = bpf_program__fd(skel->progs.xdp_meta_prog); + if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) { + fprintf(stderr, "Failed to set xdp link\n"); + goto end_destroy; + } + + if (bpf_get_link_xdp_id(ifindex, &prog_id, xdp_flags)) { + fprintf(stderr, "Failed to get XDP program id for ifindex\n"); + goto end_destroy; + } + + memset(&handle_ctrl_c, 0, sizeof(handle_ctrl_c)); + handle_ctrl_c.sa_handler = &xdp_meta_sample_stop; + sigaction(SIGINT, &handle_ctrl_c, NULL); + + xdp_meta_read_trace_pipe(); + + ret = 0; + + if (bpf_get_link_xdp_id(ifindex, &running_prog_id, xdp_flags) || + running_prog_id != prog_id) { + fprintf(stderr, + "Failed to get the running XDP program id or another program is running. Exit without detaching.\n"); + goto end_destroy; + } + + fprintf(stderr, "Detaching the program...\n"); + bpf_set_link_xdp_fd(ifindex, -1, 0); + +end_destroy: + xdp_meta__destroy(skel); +end: + return ret; +}