forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
samples: bpf: Add simple sample with CORE
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
1 parent
7dc8f75
commit b2523c2
Showing
3 changed files
with
197 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |