hc
2024-10-09 05e59e5fb0064c97a1c10921ecd549f2d4a58565
kernel/samples/bpf/xdp_tx_iptunnel_user.c
....@@ -1,8 +1,5 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /* Copyright (c) 2016 Facebook
2
- *
3
- * This program is free software; you can redistribute it and/or
4
- * modify it under the terms of version 2 of the GNU General Public
5
- * License as published by the Free Software Foundation.
63 */
74 #include <linux/bpf.h>
85 #include <linux/if_link.h>
....@@ -12,12 +9,13 @@
129 #include <stdio.h>
1310 #include <stdlib.h>
1411 #include <string.h>
12
+#include <net/if.h>
1513 #include <sys/resource.h>
1614 #include <arpa/inet.h>
1715 #include <netinet/ether.h>
1816 #include <unistd.h>
1917 #include <time.h>
20
-#include "bpf_load.h"
18
+#include <bpf/libbpf.h>
2119 #include <bpf/bpf.h>
2220 #include "bpf_util.h"
2321 #include "xdp_tx_iptunnel_common.h"
....@@ -25,12 +23,26 @@
2523 #define STATS_INTERVAL_S 2U
2624
2725 static int ifindex = -1;
28
-static __u32 xdp_flags = 0;
26
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
27
+static int rxcnt_map_fd;
28
+static __u32 prog_id;
2929
3030 static void int_exit(int sig)
3131 {
32
- if (ifindex > -1)
33
- bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
32
+ __u32 curr_prog_id = 0;
33
+
34
+ if (ifindex > -1) {
35
+ if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
36
+ printf("bpf_get_link_xdp_id failed\n");
37
+ exit(1);
38
+ }
39
+ if (prog_id == curr_prog_id)
40
+ bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
41
+ else if (!curr_prog_id)
42
+ printf("couldn't find a prog id on a given iface\n");
43
+ else
44
+ printf("program on interface changed, not removing\n");
45
+ }
3446 exit(0);
3547 }
3648
....@@ -53,7 +65,8 @@
5365 for (proto = 0; proto < nr_protos; proto++) {
5466 __u64 sum = 0;
5567
56
- assert(bpf_map_lookup_elem(map_fd[0], &proto, values) == 0);
68
+ assert(bpf_map_lookup_elem(rxcnt_map_fd, &proto,
69
+ values) == 0);
5770 for (i = 0; i < nr_cpus; i++)
5871 sum += (values[i] - prev[proto][i]);
5972
....@@ -71,7 +84,7 @@
7184 "in an IPv4/v6 header and XDP_TX it out. The dst <VIP:PORT>\n"
7285 "is used to select packets to encapsulate\n\n");
7386 printf("Usage: %s [...]\n", cmd);
74
- printf(" -i <ifindex> Interface Index\n");
87
+ printf(" -i <ifname|ifindex> Interface\n");
7588 printf(" -a <vip-service-address> IPv4 or IPv6\n");
7689 printf(" -p <vip-service-port> A port range (e.g. 433-444) is also allowed\n");
7790 printf(" -s <source-ip> Used in the IPTunnel header\n");
....@@ -81,6 +94,7 @@
8194 printf(" -P <IP-Protocol> Default is TCP\n");
8295 printf(" -S use skb-mode\n");
8396 printf(" -N enforce native mode\n");
97
+ printf(" -F Force loading the XDP prog\n");
8498 printf(" -h Display this help\n");
8599 }
86100
....@@ -138,16 +152,22 @@
138152
139153 int main(int argc, char **argv)
140154 {
141
- unsigned char opt_flags[256] = {};
142
- unsigned int kill_after_s = 0;
143
- const char *optstr = "i:a:p:s:d:m:T:P:SNh";
144
- int min_port = 0, max_port = 0;
145
- struct iptnl_info tnl = {};
155
+ struct bpf_prog_load_attr prog_load_attr = {
156
+ .prog_type = BPF_PROG_TYPE_XDP,
157
+ };
146158 struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
159
+ int min_port = 0, max_port = 0, vip2tnl_map_fd;
160
+ const char *optstr = "i:a:p:s:d:m:T:P:FSNh";
161
+ unsigned char opt_flags[256] = {};
162
+ struct bpf_prog_info info = {};
163
+ __u32 info_len = sizeof(info);
164
+ unsigned int kill_after_s = 0;
165
+ struct iptnl_info tnl = {};
166
+ struct bpf_object *obj;
147167 struct vip vip = {};
148168 char filename[256];
149
- int opt;
150
- int i;
169
+ int opt, prog_fd;
170
+ int i, err;
151171
152172 tnl.family = AF_UNSPEC;
153173 vip.protocol = IPPROTO_TCP;
....@@ -162,7 +182,9 @@
162182
163183 switch (opt) {
164184 case 'i':
165
- ifindex = atoi(optarg);
185
+ ifindex = if_nametoindex(optarg);
186
+ if (!ifindex)
187
+ ifindex = atoi(optarg);
166188 break;
167189 case 'a':
168190 vip.family = parse_ipstr(optarg, vip.daddr.v6);
....@@ -209,7 +231,10 @@
209231 xdp_flags |= XDP_FLAGS_SKB_MODE;
210232 break;
211233 case 'N':
212
- xdp_flags |= XDP_FLAGS_DRV_MODE;
234
+ /* default, set below */
235
+ break;
236
+ case 'F':
237
+ xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
213238 break;
214239 default:
215240 usage(argv[0]);
....@@ -217,6 +242,9 @@
217242 }
218243 opt_flags[opt] = 0;
219244 }
245
+
246
+ if (!(xdp_flags & XDP_FLAGS_SKB_MODE))
247
+ xdp_flags |= XDP_FLAGS_DRV_MODE;
220248
221249 for (i = 0; i < strlen(optstr); i++) {
222250 if (opt_flags[(unsigned int)optstr[i]]) {
....@@ -231,15 +259,26 @@
231259 return 1;
232260 }
233261
234
- snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
235
-
236
- if (load_bpf_file(filename)) {
237
- printf("%s", bpf_log_buf);
262
+ if (!ifindex) {
263
+ fprintf(stderr, "Invalid ifname\n");
238264 return 1;
239265 }
240266
241
- if (!prog_fd[0]) {
242
- printf("load_bpf_file: %s\n", strerror(errno));
267
+ snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
268
+ prog_load_attr.file = filename;
269
+
270
+ if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
271
+ return 1;
272
+
273
+ if (!prog_fd) {
274
+ printf("bpf_prog_load_xattr: %s\n", strerror(errno));
275
+ return 1;
276
+ }
277
+
278
+ rxcnt_map_fd = bpf_object__find_map_fd_by_name(obj, "rxcnt");
279
+ vip2tnl_map_fd = bpf_object__find_map_fd_by_name(obj, "vip2tnl");
280
+ if (vip2tnl_map_fd < 0 || rxcnt_map_fd < 0) {
281
+ printf("bpf_object__find_map_fd_by_name failed\n");
243282 return 1;
244283 }
245284
....@@ -248,17 +287,25 @@
248287
249288 while (min_port <= max_port) {
250289 vip.dport = htons(min_port++);
251
- if (bpf_map_update_elem(map_fd[1], &vip, &tnl, BPF_NOEXIST)) {
290
+ if (bpf_map_update_elem(vip2tnl_map_fd, &vip, &tnl,
291
+ BPF_NOEXIST)) {
252292 perror("bpf_map_update_elem(&vip2tnl)");
253293 return 1;
254294 }
255295 }
256296
257
- if (bpf_set_link_xdp_fd(ifindex, prog_fd[0], xdp_flags) < 0) {
297
+ if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) {
258298 printf("link set xdp fd failed\n");
259299 return 1;
260300 }
261301
302
+ err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
303
+ if (err) {
304
+ printf("can't get prog info - %s\n", strerror(errno));
305
+ return err;
306
+ }
307
+ prog_id = info.id;
308
+
262309 poll_stats(kill_after_s);
263310
264311 bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);