Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | // SPDX-License-Identifier: GPL-2.0 /* Copyright(c) 2017 Jesper Dangaard Brouer, Red Hat, Inc. */ static const char *__doc__= "XDP monitor tool, based on tracepoints\n"; static const char *__doc_err_only__= " NOTICE: Only tracking XDP redirect errors\n" " Enable redirect success stats via '-s/--stats'\n" " (which comes with a per packet processing overhead)\n"; #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <stdint.h> #include <string.h> #include <ctype.h> #include <unistd.h> #include <locale.h> #include <sys/resource.h> #include <getopt.h> #include <net/if.h> #include <time.h> #include <signal.h> #include <bpf/bpf.h> #include <bpf/libbpf.h> #include "bpf_util.h" #include "xdp_sample_user.h" #include "xdp_monitor.skel.h" static int mask = SAMPLE_REDIRECT_ERR_CNT | SAMPLE_CPUMAP_ENQUEUE_CNT | SAMPLE_CPUMAP_KTHREAD_CNT | SAMPLE_EXCEPTION_CNT | SAMPLE_DEVMAP_XMIT_CNT | SAMPLE_DEVMAP_XMIT_CNT_MULTI; DEFINE_SAMPLE_INIT(xdp_monitor); static const struct option long_options[] = { { "help", no_argument, NULL, 'h' }, { "stats", no_argument, NULL, 's' }, { "interval", required_argument, NULL, 'i' }, { "verbose", no_argument, NULL, 'v' }, {} }; int main(int argc, char **argv) { unsigned long interval = 2; int ret = EXIT_FAIL_OPTION; struct xdp_monitor *skel; bool errors_only = true; int longindex = 0, opt; bool error = true; /* Parse commands line args */ while ((opt = getopt_long(argc, argv, "si:vh", long_options, &longindex)) != -1) { switch (opt) { case 's': errors_only = false; mask |= SAMPLE_REDIRECT_CNT; break; case 'i': interval = strtoul(optarg, NULL, 0); break; case 'v': sample_switch_mode(); break; case 'h': error = false; default: sample_usage(argv, long_options, __doc__, mask, error); return ret; } } skel = xdp_monitor__open(); if (!skel) { fprintf(stderr, "Failed to xdp_monitor__open: %s\n", strerror(errno)); ret = EXIT_FAIL_BPF; goto end; } ret = sample_init_pre_load(skel); if (ret < 0) { fprintf(stderr, "Failed to sample_init_pre_load: %s\n", strerror(-ret)); ret = EXIT_FAIL_BPF; goto end_destroy; } ret = xdp_monitor__load(skel); if (ret < 0) { fprintf(stderr, "Failed to xdp_monitor__load: %s\n", strerror(errno)); ret = EXIT_FAIL_BPF; goto end_destroy; } ret = sample_init(skel, mask); if (ret < 0) { fprintf(stderr, "Failed to initialize sample: %s\n", strerror(-ret)); ret = EXIT_FAIL_BPF; goto end_destroy; } if (errors_only) printf("%s", __doc_err_only__); ret = sample_run(interval, NULL, NULL); if (ret < 0) { fprintf(stderr, "Failed during sample run: %s\n", strerror(-ret)); ret = EXIT_FAIL; goto end_destroy; } ret = EXIT_OK; end_destroy: xdp_monitor__destroy(skel); end: sample_exit(ret); } |