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