hc
2024-10-16 50a212ec906f7524620675f0c57357691c26c81f
kernel/samples/bpf/xdp_router_ipv4_user.c
....@@ -1,8 +1,5 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /* Copyright (C) 2017 Cavium, Inc.
2
- *
3
- * This program is free software; you can redistribute it and/or modify it
4
- * under the terms of version 2 of the GNU General Public License
5
- * as published by the Free Software Foundation.
63 */
74 #include <linux/bpf.h>
85 #include <linux/netlink.h>
....@@ -15,7 +12,6 @@
1512 #include <string.h>
1613 #include <sys/socket.h>
1714 #include <unistd.h>
18
-#include "bpf_load.h"
1915 #include <bpf/bpf.h>
2016 #include <arpa/inet.h>
2117 #include <fcntl.h>
....@@ -25,32 +21,52 @@
2521 #include <sys/ioctl.h>
2622 #include <sys/syscall.h>
2723 #include "bpf_util.h"
24
+#include <bpf/libbpf.h>
25
+#include <sys/resource.h>
26
+#include <libgen.h>
2827
29
-int sock, sock_arp, flags = 0;
28
+int sock, sock_arp, flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
3029 static int total_ifindex;
31
-int *ifindex_list;
30
+static int *ifindex_list;
31
+static __u32 *prog_id_list;
3232 char buf[8192];
33
+static int lpm_map_fd;
34
+static int rxcnt_map_fd;
35
+static int arp_table_map_fd;
36
+static int exact_match_map_fd;
37
+static int tx_port_map_fd;
3338
3439 static int get_route_table(int rtm_family);
3540 static void int_exit(int sig)
3641 {
42
+ __u32 prog_id = 0;
3743 int i = 0;
3844
39
- for (i = 0; i < total_ifindex; i++)
40
- bpf_set_link_xdp_fd(ifindex_list[i], -1, flags);
45
+ for (i = 0; i < total_ifindex; i++) {
46
+ if (bpf_get_link_xdp_id(ifindex_list[i], &prog_id, flags)) {
47
+ printf("bpf_get_link_xdp_id on iface %d failed\n",
48
+ ifindex_list[i]);
49
+ exit(1);
50
+ }
51
+ if (prog_id_list[i] == prog_id)
52
+ bpf_set_link_xdp_fd(ifindex_list[i], -1, flags);
53
+ else if (!prog_id)
54
+ printf("couldn't find a prog id on iface %d\n",
55
+ ifindex_list[i]);
56
+ else
57
+ printf("program on iface %d changed, not removing\n",
58
+ ifindex_list[i]);
59
+ prog_id = 0;
60
+ }
4161 exit(0);
4262 }
4363
4464 static void close_and_exit(int sig)
4565 {
46
- int i = 0;
47
-
4866 close(sock);
4967 close(sock_arp);
5068
51
- for (i = 0; i < total_ifindex; i++)
52
- bpf_set_link_xdp_fd(ifindex_list[i], -1, flags);
53
- exit(0);
69
+ int_exit(0);
5470 }
5571
5672 /* Get the mac address of the interface given interface name */
....@@ -179,14 +195,10 @@
179195 route.iface_name = alloca(sizeof(char *) * IFNAMSIZ);
180196 route.iface_name = if_indextoname(route.iface, route.iface_name);
181197 route.mac = getmac(route.iface_name);
182
- if (route.mac == -1) {
183
- int i = 0;
184
-
185
- for (i = 0; i < total_ifindex; i++)
186
- bpf_set_link_xdp_fd(ifindex_list[i], -1, flags);
187
- exit(0);
188
- }
189
- assert(bpf_map_update_elem(map_fd[4], &route.iface, &route.iface, 0) == 0);
198
+ if (route.mac == -1)
199
+ int_exit(0);
200
+ assert(bpf_map_update_elem(tx_port_map_fd,
201
+ &route.iface, &route.iface, 0) == 0);
190202 if (rtm_family == AF_INET) {
191203 struct trie_value {
192204 __u8 prefix[4];
....@@ -207,11 +219,16 @@
207219 direct_entry.arp.dst = 0;
208220 if (route.dst_len == 32) {
209221 if (nh->nlmsg_type == RTM_DELROUTE) {
210
- assert(bpf_map_delete_elem(map_fd[3], &route.dst) == 0);
222
+ assert(bpf_map_delete_elem(exact_match_map_fd,
223
+ &route.dst) == 0);
211224 } else {
212
- if (bpf_map_lookup_elem(map_fd[2], &route.dst, &direct_entry.arp.mac) == 0)
225
+ if (bpf_map_lookup_elem(arp_table_map_fd,
226
+ &route.dst,
227
+ &direct_entry.arp.mac) == 0)
213228 direct_entry.arp.dst = route.dst;
214
- assert(bpf_map_update_elem(map_fd[3], &route.dst, &direct_entry, 0) == 0);
229
+ assert(bpf_map_update_elem(exact_match_map_fd,
230
+ &route.dst,
231
+ &direct_entry, 0) == 0);
215232 }
216233 }
217234 for (i = 0; i < 4; i++)
....@@ -225,7 +242,7 @@
225242 route.gw, route.dst_len,
226243 route.metric,
227244 route.iface_name);
228
- if (bpf_map_lookup_elem(map_fd[0], prefix_key,
245
+ if (bpf_map_lookup_elem(lpm_map_fd, prefix_key,
229246 prefix_value) < 0) {
230247 for (i = 0; i < 4; i++)
231248 prefix_value->prefix[i] = prefix_key->data[i];
....@@ -234,7 +251,7 @@
234251 prefix_value->gw = route.gw;
235252 prefix_value->metric = route.metric;
236253
237
- assert(bpf_map_update_elem(map_fd[0],
254
+ assert(bpf_map_update_elem(lpm_map_fd,
238255 prefix_key,
239256 prefix_value, 0
240257 ) == 0);
....@@ -247,7 +264,7 @@
247264 prefix_key->data[2],
248265 prefix_key->data[3],
249266 prefix_key->prefixlen);
250
- assert(bpf_map_delete_elem(map_fd[0],
267
+ assert(bpf_map_delete_elem(lpm_map_fd,
251268 prefix_key
252269 ) == 0);
253270 /* Rereading the route table to check if
....@@ -275,8 +292,7 @@
275292 prefix_value->ifindex = route.iface;
276293 prefix_value->gw = route.gw;
277294 prefix_value->metric = route.metric;
278
- assert(bpf_map_update_elem(
279
- map_fd[0],
295
+ assert(bpf_map_update_elem(lpm_map_fd,
280296 prefix_key,
281297 prefix_value,
282298 0) == 0);
....@@ -401,7 +417,8 @@
401417 arp_entry.mac = atol(mac);
402418 printf("%x\t\t%llx\n", arp_entry.dst, arp_entry.mac);
403419 if (ndm_family == AF_INET) {
404
- if (bpf_map_lookup_elem(map_fd[3], &arp_entry.dst,
420
+ if (bpf_map_lookup_elem(exact_match_map_fd,
421
+ &arp_entry.dst,
405422 &direct_entry) == 0) {
406423 if (nh->nlmsg_type == RTM_DELNEIGH) {
407424 direct_entry.arp.dst = 0;
....@@ -410,16 +427,17 @@
410427 direct_entry.arp.dst = arp_entry.dst;
411428 direct_entry.arp.mac = arp_entry.mac;
412429 }
413
- assert(bpf_map_update_elem(map_fd[3],
430
+ assert(bpf_map_update_elem(exact_match_map_fd,
414431 &arp_entry.dst,
415432 &direct_entry, 0
416433 ) == 0);
417434 memset(&direct_entry, 0, sizeof(direct_entry));
418435 }
419436 if (nh->nlmsg_type == RTM_DELNEIGH) {
420
- assert(bpf_map_delete_elem(map_fd[2], &arp_entry.dst) == 0);
437
+ assert(bpf_map_delete_elem(arp_table_map_fd,
438
+ &arp_entry.dst) == 0);
421439 } else if (nh->nlmsg_type == RTM_NEWNEIGH) {
422
- assert(bpf_map_update_elem(map_fd[2],
440
+ assert(bpf_map_update_elem(arp_table_map_fd,
423441 &arp_entry.dst,
424442 &arp_entry.mac, 0
425443 ) == 0);
....@@ -553,7 +571,8 @@
553571 for (key = 0; key < nr_keys; key++) {
554572 __u64 sum = 0;
555573
556
- assert(bpf_map_lookup_elem(map_fd[1], &key, values) == 0);
574
+ assert(bpf_map_lookup_elem(rxcnt_map_fd,
575
+ &key, values) == 0);
557576 for (i = 0; i < nr_cpus; i++)
558577 sum += (values[i] - prev[key][i]);
559578 if (sum)
....@@ -594,36 +613,90 @@
594613 return ret;
595614 }
596615
616
+static void usage(const char *prog)
617
+{
618
+ fprintf(stderr,
619
+ "%s: %s [OPTS] interface name list\n\n"
620
+ "OPTS:\n"
621
+ " -S use skb-mode\n"
622
+ " -F force loading prog\n",
623
+ __func__, prog);
624
+}
625
+
597626 int main(int ac, char **argv)
598627 {
628
+ struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
629
+ struct bpf_prog_load_attr prog_load_attr = {
630
+ .prog_type = BPF_PROG_TYPE_XDP,
631
+ };
632
+ struct bpf_prog_info info = {};
633
+ __u32 info_len = sizeof(info);
634
+ const char *optstr = "SF";
635
+ struct bpf_object *obj;
599636 char filename[256];
600637 char **ifname_list;
601
- int i = 1;
638
+ int prog_fd, opt;
639
+ int err, i = 1;
602640
603641 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
604
- if (ac < 2) {
605
- printf("usage: %s [-S] Interface name list\n", argv[0]);
642
+ prog_load_attr.file = filename;
643
+
644
+ total_ifindex = ac - 1;
645
+ ifname_list = (argv + 1);
646
+
647
+ while ((opt = getopt(ac, argv, optstr)) != -1) {
648
+ switch (opt) {
649
+ case 'S':
650
+ flags |= XDP_FLAGS_SKB_MODE;
651
+ total_ifindex--;
652
+ ifname_list++;
653
+ break;
654
+ case 'F':
655
+ flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
656
+ total_ifindex--;
657
+ ifname_list++;
658
+ break;
659
+ default:
660
+ usage(basename(argv[0]));
661
+ return 1;
662
+ }
663
+ }
664
+
665
+ if (!(flags & XDP_FLAGS_SKB_MODE))
666
+ flags |= XDP_FLAGS_DRV_MODE;
667
+
668
+ if (optind == ac) {
669
+ usage(basename(argv[0]));
606670 return 1;
607671 }
608
- if (!strcmp(argv[1], "-S")) {
609
- flags = XDP_FLAGS_SKB_MODE;
610
- total_ifindex = ac - 2;
611
- ifname_list = (argv + 2);
612
- } else {
613
- flags = 0;
614
- total_ifindex = ac - 1;
615
- ifname_list = (argv + 1);
616
- }
617
- if (load_bpf_file(filename)) {
618
- printf("%s", bpf_log_buf);
672
+
673
+ if (setrlimit(RLIMIT_MEMLOCK, &r)) {
674
+ perror("setrlimit(RLIMIT_MEMLOCK)");
619675 return 1;
620676 }
677
+
678
+ if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
679
+ return 1;
680
+
621681 printf("\n**************loading bpf file*********************\n\n\n");
622
- if (!prog_fd[0]) {
623
- printf("load_bpf_file: %s\n", strerror(errno));
682
+ if (!prog_fd) {
683
+ printf("bpf_prog_load_xattr: %s\n", strerror(errno));
624684 return 1;
625685 }
626
- ifindex_list = (int *)malloc(total_ifindex * sizeof(int *));
686
+
687
+ lpm_map_fd = bpf_object__find_map_fd_by_name(obj, "lpm_map");
688
+ rxcnt_map_fd = bpf_object__find_map_fd_by_name(obj, "rxcnt");
689
+ arp_table_map_fd = bpf_object__find_map_fd_by_name(obj, "arp_table");
690
+ exact_match_map_fd = bpf_object__find_map_fd_by_name(obj,
691
+ "exact_match");
692
+ tx_port_map_fd = bpf_object__find_map_fd_by_name(obj, "tx_port");
693
+ if (lpm_map_fd < 0 || rxcnt_map_fd < 0 || arp_table_map_fd < 0 ||
694
+ exact_match_map_fd < 0 || tx_port_map_fd < 0) {
695
+ printf("bpf_object__find_map_fd_by_name failed\n");
696
+ return 1;
697
+ }
698
+
699
+ ifindex_list = (int *)calloc(total_ifindex, sizeof(int *));
627700 for (i = 0; i < total_ifindex; i++) {
628701 ifindex_list[i] = if_nametoindex(ifname_list[i]);
629702 if (!ifindex_list[i]) {
....@@ -632,8 +705,9 @@
632705 return 1;
633706 }
634707 }
708
+ prog_id_list = (__u32 *)calloc(total_ifindex, sizeof(__u32 *));
635709 for (i = 0; i < total_ifindex; i++) {
636
- if (bpf_set_link_xdp_fd(ifindex_list[i], prog_fd[0], flags) < 0) {
710
+ if (bpf_set_link_xdp_fd(ifindex_list[i], prog_fd, flags) < 0) {
637711 printf("link set xdp fd failed\n");
638712 int recovery_index = i;
639713
....@@ -642,6 +716,13 @@
642716
643717 return 1;
644718 }
719
+ err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
720
+ if (err) {
721
+ printf("can't get prog info - %s\n", strerror(errno));
722
+ return err;
723
+ }
724
+ prog_id_list[i] = info.id;
725
+ memset(&info, 0, sizeof(info));
645726 printf("Attached to %d\n", ifindex_list[i]);
646727 }
647728 signal(SIGINT, int_exit);