0001
0002
0003 static const char *__doc__=
0004 "XDP monitor tool, based on tracepoints\n";
0005
0006 static const char *__doc_err_only__=
0007 " NOTICE: Only tracking XDP redirect errors\n"
0008 " Enable redirect success stats via '-s/--stats'\n"
0009 " (which comes with a per packet processing overhead)\n";
0010
0011 #include <errno.h>
0012 #include <stdio.h>
0013 #include <stdlib.h>
0014 #include <stdbool.h>
0015 #include <stdint.h>
0016 #include <string.h>
0017 #include <ctype.h>
0018 #include <unistd.h>
0019 #include <locale.h>
0020 #include <getopt.h>
0021 #include <net/if.h>
0022 #include <time.h>
0023 #include <signal.h>
0024 #include <bpf/bpf.h>
0025 #include <bpf/libbpf.h>
0026 #include "bpf_util.h"
0027 #include "xdp_sample_user.h"
0028 #include "xdp_monitor.skel.h"
0029
0030 static int mask = SAMPLE_REDIRECT_ERR_CNT | SAMPLE_CPUMAP_ENQUEUE_CNT |
0031 SAMPLE_CPUMAP_KTHREAD_CNT | SAMPLE_EXCEPTION_CNT |
0032 SAMPLE_DEVMAP_XMIT_CNT | SAMPLE_DEVMAP_XMIT_CNT_MULTI;
0033
0034 DEFINE_SAMPLE_INIT(xdp_monitor);
0035
0036 static const struct option long_options[] = {
0037 { "help", no_argument, NULL, 'h' },
0038 { "stats", no_argument, NULL, 's' },
0039 { "interval", required_argument, NULL, 'i' },
0040 { "verbose", no_argument, NULL, 'v' },
0041 {}
0042 };
0043
0044 int main(int argc, char **argv)
0045 {
0046 unsigned long interval = 2;
0047 int ret = EXIT_FAIL_OPTION;
0048 struct xdp_monitor *skel;
0049 bool errors_only = true;
0050 int longindex = 0, opt;
0051 bool error = true;
0052
0053
0054 while ((opt = getopt_long(argc, argv, "si:vh",
0055 long_options, &longindex)) != -1) {
0056 switch (opt) {
0057 case 's':
0058 errors_only = false;
0059 mask |= SAMPLE_REDIRECT_CNT;
0060 break;
0061 case 'i':
0062 interval = strtoul(optarg, NULL, 0);
0063 break;
0064 case 'v':
0065 sample_switch_mode();
0066 break;
0067 case 'h':
0068 error = false;
0069 default:
0070 sample_usage(argv, long_options, __doc__, mask, error);
0071 return ret;
0072 }
0073 }
0074
0075 skel = xdp_monitor__open();
0076 if (!skel) {
0077 fprintf(stderr, "Failed to xdp_monitor__open: %s\n",
0078 strerror(errno));
0079 ret = EXIT_FAIL_BPF;
0080 goto end;
0081 }
0082
0083 ret = sample_init_pre_load(skel);
0084 if (ret < 0) {
0085 fprintf(stderr, "Failed to sample_init_pre_load: %s\n", strerror(-ret));
0086 ret = EXIT_FAIL_BPF;
0087 goto end_destroy;
0088 }
0089
0090 ret = xdp_monitor__load(skel);
0091 if (ret < 0) {
0092 fprintf(stderr, "Failed to xdp_monitor__load: %s\n", strerror(errno));
0093 ret = EXIT_FAIL_BPF;
0094 goto end_destroy;
0095 }
0096
0097 ret = sample_init(skel, mask);
0098 if (ret < 0) {
0099 fprintf(stderr, "Failed to initialize sample: %s\n", strerror(-ret));
0100 ret = EXIT_FAIL_BPF;
0101 goto end_destroy;
0102 }
0103
0104 if (errors_only)
0105 printf("%s", __doc_err_only__);
0106
0107 ret = sample_run(interval, NULL, NULL);
0108 if (ret < 0) {
0109 fprintf(stderr, "Failed during sample run: %s\n", strerror(-ret));
0110 ret = EXIT_FAIL;
0111 goto end_destroy;
0112 }
0113 ret = EXIT_OK;
0114 end_destroy:
0115 xdp_monitor__destroy(skel);
0116 end:
0117 sample_exit(ret);
0118 }