1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright Leon Hwang */ |
3 | |
4 | #include <linux/bpf.h> |
5 | #include <bpf/bpf_helpers.h> |
6 | |
7 | #define ERRMSG_LEN 64 |
8 | |
9 | struct xdp_errmsg { |
10 | char msg[ERRMSG_LEN]; |
11 | }; |
12 | |
13 | struct { |
14 | __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); |
15 | __type(key, int); |
16 | __type(value, int); |
17 | } xdp_errmsg_pb SEC(".maps" ); |
18 | |
19 | struct xdp_attach_error_ctx { |
20 | unsigned long unused; |
21 | |
22 | /* |
23 | * bpf does not support tracepoint __data_loc directly. |
24 | * |
25 | * Actually, this field is a 32 bit integer whose value encodes |
26 | * information on where to find the actual data. The first 2 bytes is |
27 | * the size of the data. The last 2 bytes is the offset from the start |
28 | * of the tracepoint struct where the data begins. |
29 | * -- https://github.com/iovisor/bpftrace/pull/1542 |
30 | */ |
31 | __u32 msg; // __data_loc char[] msg; |
32 | }; |
33 | |
34 | /* |
35 | * Catch the error message at the tracepoint. |
36 | */ |
37 | |
38 | SEC("tp/xdp/bpf_xdp_link_attach_failed" ) |
39 | int tp__xdp__bpf_xdp_link_attach_failed(struct xdp_attach_error_ctx *ctx) |
40 | { |
41 | char *msg = (void *)(__u64) ((void *) ctx + (__u16) ctx->msg); |
42 | struct xdp_errmsg errmsg = {}; |
43 | |
44 | bpf_probe_read_kernel_str(&errmsg.msg, ERRMSG_LEN, msg); |
45 | bpf_perf_event_output(ctx, &xdp_errmsg_pb, BPF_F_CURRENT_CPU, &errmsg, |
46 | ERRMSG_LEN); |
47 | return 0; |
48 | } |
49 | |
50 | /* |
51 | * Reuse the XDP program in xdp_dummy.c. |
52 | */ |
53 | |
54 | char LICENSE[] SEC("license" ) = "GPL" ; |
55 | |