hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
kernel/samples/bpf/xdp_monitor_user.c
....@@ -26,12 +26,37 @@
2626 #include <net/if.h>
2727 #include <time.h>
2828
29
+#include <signal.h>
2930 #include <bpf/bpf.h>
30
-#include "bpf_load.h"
31
+#include <bpf/libbpf.h>
3132 #include "bpf_util.h"
3233
34
+enum map_type {
35
+ REDIRECT_ERR_CNT,
36
+ EXCEPTION_CNT,
37
+ CPUMAP_ENQUEUE_CNT,
38
+ CPUMAP_KTHREAD_CNT,
39
+ DEVMAP_XMIT_CNT,
40
+};
41
+
42
+static const char *const map_type_strings[] = {
43
+ [REDIRECT_ERR_CNT] = "redirect_err_cnt",
44
+ [EXCEPTION_CNT] = "exception_cnt",
45
+ [CPUMAP_ENQUEUE_CNT] = "cpumap_enqueue_cnt",
46
+ [CPUMAP_KTHREAD_CNT] = "cpumap_kthread_cnt",
47
+ [DEVMAP_XMIT_CNT] = "devmap_xmit_cnt",
48
+};
49
+
50
+#define NUM_MAP 5
51
+#define NUM_TP 8
52
+
53
+static int tp_cnt;
54
+static int map_cnt;
3355 static int verbose = 1;
3456 static bool debug = false;
57
+struct bpf_map *map_data[NUM_MAP] = {};
58
+struct bpf_link *tp_links[NUM_TP] = {};
59
+struct bpf_object *obj;
3560
3661 static const struct option long_options[] = {
3762 {"help", no_argument, NULL, 'h' },
....@@ -40,6 +65,16 @@
4065 {"sec", required_argument, NULL, 's' },
4166 {0, 0, NULL, 0 }
4267 };
68
+
69
+static void int_exit(int sig)
70
+{
71
+ /* Detach tracepoints */
72
+ while (tp_cnt)
73
+ bpf_link__destroy(tp_links[--tp_cnt]);
74
+
75
+ bpf_object__close(obj);
76
+ exit(0);
77
+}
4378
4479 /* C standard specifies two constants, EXIT_SUCCESS(0) and EXIT_FAILURE(1) */
4580 #define EXIT_FAIL_MEM 5
....@@ -483,23 +518,23 @@
483518 * this can happen by someone running perf-record -e
484519 */
485520
486
- fd = map_data[0].fd; /* map0: redirect_err_cnt */
521
+ fd = bpf_map__fd(map_data[REDIRECT_ERR_CNT]);
487522 for (i = 0; i < REDIR_RES_MAX; i++)
488523 map_collect_record_u64(fd, i, &rec->xdp_redirect[i]);
489524
490
- fd = map_data[1].fd; /* map1: exception_cnt */
525
+ fd = bpf_map__fd(map_data[EXCEPTION_CNT]);
491526 for (i = 0; i < XDP_ACTION_MAX; i++) {
492527 map_collect_record_u64(fd, i, &rec->xdp_exception[i]);
493528 }
494529
495
- fd = map_data[2].fd; /* map2: cpumap_enqueue_cnt */
530
+ fd = bpf_map__fd(map_data[CPUMAP_ENQUEUE_CNT]);
496531 for (i = 0; i < MAX_CPUS; i++)
497532 map_collect_record(fd, i, &rec->xdp_cpumap_enqueue[i]);
498533
499
- fd = map_data[3].fd; /* map3: cpumap_kthread_cnt */
534
+ fd = bpf_map__fd(map_data[CPUMAP_KTHREAD_CNT]);
500535 map_collect_record(fd, 0, &rec->xdp_cpumap_kthread);
501536
502
- fd = map_data[4].fd; /* map4: devmap_xmit_cnt */
537
+ fd = bpf_map__fd(map_data[DEVMAP_XMIT_CNT]);
503538 map_collect_record(fd, 0, &rec->xdp_devmap_xmit);
504539
505540 return true;
....@@ -509,11 +544,8 @@
509544 {
510545 unsigned int nr_cpus = bpf_num_possible_cpus();
511546 void *array;
512
- size_t size;
513547
514
- size = record_size * nr_cpus;
515
- array = malloc(size);
516
- memset(array, 0, size);
548
+ array = calloc(nr_cpus, record_size);
517549 if (!array) {
518550 fprintf(stderr, "Mem alloc error (nr_cpus:%u)\n", nr_cpus);
519551 exit(EXIT_FAIL_MEM);
....@@ -528,8 +560,7 @@
528560 int i;
529561
530562 /* Alloc main stats_record structure */
531
- rec = malloc(sizeof(*rec));
532
- memset(rec, 0, sizeof(*rec));
563
+ rec = calloc(1, sizeof(*rec));
533564 if (!rec) {
534565 fprintf(stderr, "Mem alloc error\n");
535566 exit(EXIT_FAIL_MEM);
....@@ -602,8 +633,8 @@
602633
603634 /* TODO Need more advanced stats on error types */
604635 if (verbose) {
605
- printf(" - Stats map0: %s\n", map_data[0].name);
606
- printf(" - Stats map1: %s\n", map_data[1].name);
636
+ printf(" - Stats map0: %s\n", bpf_map__name(map_data[0]));
637
+ printf(" - Stats map1: %s\n", bpf_map__name(map_data[1]));
607638 printf("\n");
608639 }
609640 fflush(stdout);
....@@ -622,43 +653,50 @@
622653
623654 static void print_bpf_prog_info(void)
624655 {
625
- int i;
656
+ struct bpf_program *prog;
657
+ struct bpf_map *map;
658
+ int i = 0;
626659
627660 /* Prog info */
628
- printf("Loaded BPF prog have %d bpf program(s)\n", prog_cnt);
629
- for (i = 0; i < prog_cnt; i++) {
630
- printf(" - prog_fd[%d] = fd(%d)\n", i, prog_fd[i]);
661
+ printf("Loaded BPF prog have %d bpf program(s)\n", tp_cnt);
662
+ bpf_object__for_each_program(prog, obj) {
663
+ printf(" - prog_fd[%d] = fd(%d)\n", i, bpf_program__fd(prog));
664
+ i++;
631665 }
632666
667
+ i = 0;
633668 /* Maps info */
634
- printf("Loaded BPF prog have %d map(s)\n", map_data_count);
635
- for (i = 0; i < map_data_count; i++) {
636
- char *name = map_data[i].name;
637
- int fd = map_data[i].fd;
669
+ printf("Loaded BPF prog have %d map(s)\n", map_cnt);
670
+ bpf_object__for_each_map(map, obj) {
671
+ const char *name = bpf_map__name(map);
672
+ int fd = bpf_map__fd(map);
638673
639674 printf(" - map_data[%d] = fd(%d) name:%s\n", i, fd, name);
675
+ i++;
640676 }
641677
642678 /* Event info */
643
- printf("Searching for (max:%d) event file descriptor(s)\n", prog_cnt);
644
- for (i = 0; i < prog_cnt; i++) {
645
- if (event_fd[i] != -1)
646
- printf(" - event_fd[%d] = fd(%d)\n", i, event_fd[i]);
679
+ printf("Searching for (max:%d) event file descriptor(s)\n", tp_cnt);
680
+ for (i = 0; i < tp_cnt; i++) {
681
+ int fd = bpf_link__fd(tp_links[i]);
682
+
683
+ if (fd != -1)
684
+ printf(" - event_fd[%d] = fd(%d)\n", i, fd);
647685 }
648686 }
649687
650688 int main(int argc, char **argv)
651689 {
652690 struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
691
+ struct bpf_program *prog;
653692 int longindex = 0, opt;
654
- int ret = EXIT_SUCCESS;
655
- char bpf_obj_file[256];
693
+ int ret = EXIT_FAILURE;
694
+ enum map_type type;
695
+ char filename[256];
656696
657697 /* Default settings: */
658698 bool errors_only = true;
659699 int interval = 2;
660
-
661
- snprintf(bpf_obj_file, sizeof(bpf_obj_file), "%s_kern.o", argv[0]);
662700
663701 /* Parse commands line args */
664702 while ((opt = getopt_long(argc, argv, "hDSs:",
....@@ -676,40 +714,79 @@
676714 case 'h':
677715 default:
678716 usage(argv);
679
- return EXIT_FAILURE;
717
+ return ret;
680718 }
681719 }
682720
721
+ snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
683722 if (setrlimit(RLIMIT_MEMLOCK, &r)) {
684723 perror("setrlimit(RLIMIT_MEMLOCK)");
685
- return EXIT_FAILURE;
724
+ return ret;
686725 }
687726
688
- if (load_bpf_file(bpf_obj_file)) {
689
- printf("ERROR - bpf_log_buf: %s", bpf_log_buf);
690
- return EXIT_FAILURE;
727
+ /* Remove tracepoint program when program is interrupted or killed */
728
+ signal(SIGINT, int_exit);
729
+ signal(SIGTERM, int_exit);
730
+
731
+ obj = bpf_object__open_file(filename, NULL);
732
+ if (libbpf_get_error(obj)) {
733
+ printf("ERROR: opening BPF object file failed\n");
734
+ obj = NULL;
735
+ goto cleanup;
691736 }
692
- if (!prog_fd[0]) {
693
- printf("ERROR - load_bpf_file: %s\n", strerror(errno));
694
- return EXIT_FAILURE;
737
+
738
+ /* load BPF program */
739
+ if (bpf_object__load(obj)) {
740
+ printf("ERROR: loading BPF object file failed\n");
741
+ goto cleanup;
742
+ }
743
+
744
+ for (type = 0; type < NUM_MAP; type++) {
745
+ map_data[type] =
746
+ bpf_object__find_map_by_name(obj, map_type_strings[type]);
747
+
748
+ if (libbpf_get_error(map_data[type])) {
749
+ printf("ERROR: finding a map in obj file failed\n");
750
+ goto cleanup;
751
+ }
752
+ map_cnt++;
753
+ }
754
+
755
+ bpf_object__for_each_program(prog, obj) {
756
+ tp_links[tp_cnt] = bpf_program__attach(prog);
757
+ if (libbpf_get_error(tp_links[tp_cnt])) {
758
+ printf("ERROR: bpf_program__attach failed\n");
759
+ tp_links[tp_cnt] = NULL;
760
+ goto cleanup;
761
+ }
762
+ tp_cnt++;
695763 }
696764
697765 if (debug) {
698766 print_bpf_prog_info();
699767 }
700768
701
- /* Unload/stop tracepoint event by closing fd's */
769
+ /* Unload/stop tracepoint event by closing bpf_link's */
702770 if (errors_only) {
703
- /* The prog_fd[i] and event_fd[i] depend on the
704
- * order the functions was defined in _kern.c
771
+ /* The bpf_link[i] depend on the order of
772
+ * the functions was defined in _kern.c
705773 */
706
- close(event_fd[2]); /* tracepoint/xdp/xdp_redirect */
707
- close(prog_fd[2]); /* func: trace_xdp_redirect */
708
- close(event_fd[3]); /* tracepoint/xdp/xdp_redirect_map */
709
- close(prog_fd[3]); /* func: trace_xdp_redirect_map */
774
+ bpf_link__destroy(tp_links[2]); /* tracepoint/xdp/xdp_redirect */
775
+ tp_links[2] = NULL;
776
+
777
+ bpf_link__destroy(tp_links[3]); /* tracepoint/xdp/xdp_redirect_map */
778
+ tp_links[3] = NULL;
710779 }
711780
712781 stats_poll(interval, errors_only);
713782
783
+ ret = EXIT_SUCCESS;
784
+
785
+cleanup:
786
+ /* Detach tracepoints */
787
+ while (tp_cnt)
788
+ bpf_link__destroy(tp_links[--tp_cnt]);
789
+
790
+ bpf_object__close(obj);
714791 return ret;
715792 }