hc
2024-10-09 05e59e5fb0064c97a1c10921ecd549f2d4a58565
kernel/samples/bpf/xdp_sample_pkts_user.c
....@@ -10,42 +10,68 @@
1010 #include <sys/sysinfo.h>
1111 #include <sys/ioctl.h>
1212 #include <signal.h>
13
-#include <libbpf.h>
13
+#include <bpf/libbpf.h>
1414 #include <bpf/bpf.h>
15
+#include <sys/resource.h>
16
+#include <libgen.h>
17
+#include <linux/if_link.h>
1518
1619 #include "perf-sys.h"
17
-#include "trace_helpers.h"
1820
19
-#define MAX_CPUS 128
20
-static int pmu_fds[MAX_CPUS], if_idx;
21
-static struct perf_event_mmap_page *headers[MAX_CPUS];
21
+static int if_idx;
2222 static char *if_name;
23
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
24
+static __u32 prog_id;
25
+static struct perf_buffer *pb = NULL;
2326
2427 static int do_attach(int idx, int fd, const char *name)
2528 {
29
+ struct bpf_prog_info info = {};
30
+ __u32 info_len = sizeof(info);
2631 int err;
2732
28
- err = bpf_set_link_xdp_fd(idx, fd, 0);
29
- if (err < 0)
33
+ err = bpf_set_link_xdp_fd(idx, fd, xdp_flags);
34
+ if (err < 0) {
3035 printf("ERROR: failed to attach program to %s\n", name);
36
+ return err;
37
+ }
38
+
39
+ err = bpf_obj_get_info_by_fd(fd, &info, &info_len);
40
+ if (err) {
41
+ printf("can't get prog info - %s\n", strerror(errno));
42
+ return err;
43
+ }
44
+ prog_id = info.id;
3145
3246 return err;
3347 }
3448
3549 static int do_detach(int idx, const char *name)
3650 {
37
- int err;
51
+ __u32 curr_prog_id = 0;
52
+ int err = 0;
3853
39
- err = bpf_set_link_xdp_fd(idx, -1, 0);
40
- if (err < 0)
41
- printf("ERROR: failed to detach program from %s\n", name);
54
+ err = bpf_get_link_xdp_id(idx, &curr_prog_id, xdp_flags);
55
+ if (err) {
56
+ printf("bpf_get_link_xdp_id failed\n");
57
+ return err;
58
+ }
59
+ if (prog_id == curr_prog_id) {
60
+ err = bpf_set_link_xdp_fd(idx, -1, xdp_flags);
61
+ if (err < 0)
62
+ printf("ERROR: failed to detach prog from %s\n", name);
63
+ } else if (!curr_prog_id) {
64
+ printf("couldn't find a prog id on a %s\n", name);
65
+ } else {
66
+ printf("program on interface changed, not removing\n");
67
+ }
4268
4369 return err;
4470 }
4571
4672 #define SAMPLE_SIZE 64
4773
48
-static int print_bpf_output(void *data, int size)
74
+static void print_bpf_output(void *ctx, int cpu, void *data, __u32 size)
4975 {
5076 struct {
5177 __u16 cookie;
....@@ -55,68 +81,72 @@
5581 int i;
5682
5783 if (e->cookie != 0xdead) {
58
- printf("BUG cookie %x sized %d\n",
59
- e->cookie, size);
60
- return LIBBPF_PERF_EVENT_ERROR;
84
+ printf("BUG cookie %x sized %d\n", e->cookie, size);
85
+ return;
6186 }
6287
6388 printf("Pkt len: %-5d bytes. Ethernet hdr: ", e->pkt_len);
6489 for (i = 0; i < 14 && i < e->pkt_len; i++)
6590 printf("%02x ", e->pkt_data[i]);
6691 printf("\n");
67
-
68
- return LIBBPF_PERF_EVENT_CONT;
69
-}
70
-
71
-static void test_bpf_perf_event(int map_fd, int num)
72
-{
73
- struct perf_event_attr attr = {
74
- .sample_type = PERF_SAMPLE_RAW,
75
- .type = PERF_TYPE_SOFTWARE,
76
- .config = PERF_COUNT_SW_BPF_OUTPUT,
77
- .wakeup_events = 1, /* get an fd notification for every event */
78
- };
79
- int i;
80
-
81
- for (i = 0; i < num; i++) {
82
- int key = i;
83
-
84
- pmu_fds[i] = sys_perf_event_open(&attr, -1/*pid*/, i/*cpu*/,
85
- -1/*group_fd*/, 0);
86
-
87
- assert(pmu_fds[i] >= 0);
88
- assert(bpf_map_update_elem(map_fd, &key,
89
- &pmu_fds[i], BPF_ANY) == 0);
90
- ioctl(pmu_fds[i], PERF_EVENT_IOC_ENABLE, 0);
91
- }
9292 }
9393
9494 static void sig_handler(int signo)
9595 {
9696 do_detach(if_idx, if_name);
97
+ perf_buffer__free(pb);
9798 exit(0);
99
+}
100
+
101
+static void usage(const char *prog)
102
+{
103
+ fprintf(stderr,
104
+ "%s: %s [OPTS] <ifname|ifindex>\n\n"
105
+ "OPTS:\n"
106
+ " -F force loading prog\n",
107
+ __func__, prog);
98108 }
99109
100110 int main(int argc, char **argv)
101111 {
112
+ struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
102113 struct bpf_prog_load_attr prog_load_attr = {
103114 .prog_type = BPF_PROG_TYPE_XDP,
104115 };
116
+ struct perf_buffer_opts pb_opts = {};
117
+ const char *optstr = "FS";
118
+ int prog_fd, map_fd, opt;
105119 struct bpf_object *obj;
106120 struct bpf_map *map;
107
- int prog_fd, map_fd;
108121 char filename[256];
109
- int ret, err, i;
110
- int numcpus;
122
+ int ret, err;
111123
112
- if (argc < 2) {
113
- printf("Usage: %s <ifname>\n", argv[0]);
124
+ while ((opt = getopt(argc, argv, optstr)) != -1) {
125
+ switch (opt) {
126
+ case 'F':
127
+ xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
128
+ break;
129
+ case 'S':
130
+ xdp_flags |= XDP_FLAGS_SKB_MODE;
131
+ break;
132
+ default:
133
+ usage(basename(argv[0]));
134
+ return 1;
135
+ }
136
+ }
137
+
138
+ if (!(xdp_flags & XDP_FLAGS_SKB_MODE))
139
+ xdp_flags |= XDP_FLAGS_DRV_MODE;
140
+
141
+ if (optind == argc) {
142
+ usage(basename(argv[0]));
114143 return 1;
115144 }
116145
117
- numcpus = get_nprocs();
118
- if (numcpus > MAX_CPUS)
119
- numcpus = MAX_CPUS;
146
+ if (setrlimit(RLIMIT_MEMLOCK, &r)) {
147
+ perror("setrlimit(RLIMIT_MEMLOCK)");
148
+ return 1;
149
+ }
120150
121151 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
122152 prog_load_attr.file = filename;
....@@ -125,7 +155,7 @@
125155 return 1;
126156
127157 if (!prog_fd) {
128
- printf("load_bpf_file: %s\n", strerror(errno));
158
+ printf("bpf_prog_load_xattr: %s\n", strerror(errno));
129159 return 1;
130160 }
131161
....@@ -136,16 +166,16 @@
136166 }
137167 map_fd = bpf_map__fd(map);
138168
139
- if_idx = if_nametoindex(argv[1]);
169
+ if_idx = if_nametoindex(argv[optind]);
140170 if (!if_idx)
141
- if_idx = strtoul(argv[1], NULL, 0);
171
+ if_idx = strtoul(argv[optind], NULL, 0);
142172
143173 if (!if_idx) {
144174 fprintf(stderr, "Invalid ifname\n");
145175 return 1;
146176 }
147
- if_name = argv[1];
148
- err = do_attach(if_idx, prog_fd, argv[1]);
177
+ if_name = argv[optind];
178
+ err = do_attach(if_idx, prog_fd, if_name);
149179 if (err)
150180 return err;
151181
....@@ -156,14 +186,17 @@
156186 return 1;
157187 }
158188
159
- test_bpf_perf_event(map_fd, numcpus);
189
+ pb_opts.sample_cb = print_bpf_output;
190
+ pb = perf_buffer__new(map_fd, 8, &pb_opts);
191
+ err = libbpf_get_error(pb);
192
+ if (err) {
193
+ perror("perf_buffer setup failed");
194
+ return 1;
195
+ }
160196
161
- for (i = 0; i < numcpus; i++)
162
- if (perf_event_mmap_header(pmu_fds[i], &headers[i]) < 0)
163
- return 1;
197
+ while ((ret = perf_buffer__poll(pb, 1000)) >= 0) {
198
+ }
164199
165
- ret = perf_event_poller_multi(pmu_fds, headers, numcpus,
166
- print_bpf_output);
167200 kill(0, SIGINT);
168201 return ret;
169202 }