Skip to content

Commit

Permalink
samples: bpf: Add simple sample with CORE
Browse files Browse the repository at this point in the history
Example checks if received metadata is generic, based on
the last 12 bytes of data_meta.

Example also showcases new CO-RE functionality and is able to
acquire BTF id and type id for both vmlinux and module types.

On the user side, xdp program is detached before termination
is executed, before that trace_pipe is printed for every packet.

Signed-off-by: Michal Swiatkowski <michal.swiatkowski@intel.com>
Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com>
  • Loading branch information
walking-machine committed Feb 4, 2022
1 parent 7dc8f75 commit b2523c2
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 2 deletions.
8 changes: 6 additions & 2 deletions samples/bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -409,17 +412,18 @@ $(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
xdp_redirect_map_multi.skel.h-deps := xdp_redirect_map_multi.bpf.o xdp_sample.bpf.o
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))
Expand Down
73 changes: 73 additions & 0 deletions samples/bpf/xdp_meta.bpf.c
Original file line number Diff line number Diff line change
@@ -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 <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_helpers.h>

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";
118 changes: 118 additions & 0 deletions samples/bpf/xdp_meta_user.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/resource.h>
#include <net/if.h>
#include <time.h>
#include <signal.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <linux/if_link.h>
#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;
}

0 comments on commit b2523c2

Please sign in to comment.