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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB /* * ibumad BPF sample user side * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. * * Copyright(c) 2018 Ira Weiny, Intel Corporation */ #include <linux/bpf.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <limits.h> #include <getopt.h> #include <net/if.h> #include <bpf/bpf.h> #include "bpf_util.h" #include <bpf/libbpf.h> static struct bpf_link *tp_links[3]; static struct bpf_object *obj; static int map_fd[2]; static int tp_cnt; static void dump_counts(int fd) { __u32 key; __u64 value; for (key = 0; key < 256; key++) { if (bpf_map_lookup_elem(fd, &key, &value)) { printf("failed to read key %u\n", key); continue; } if (value) printf("0x%02x : %llu\n", key, value); } } static void dump_all_counts(void) { printf("Read 'Class : count'\n"); dump_counts(map_fd[0]); printf("Write 'Class : count'\n"); dump_counts(map_fd[1]); } static void dump_exit(int sig) { dump_all_counts(); /* Detach tracepoints */ while (tp_cnt) bpf_link__destroy(tp_links[--tp_cnt]); bpf_object__close(obj); exit(0); } static const struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"delay", required_argument, NULL, 'd'}, }; static void usage(char *cmd) { printf("eBPF test program to count packets from various IP addresses\n" "Usage: %s <options>\n" " --help, -h this menu\n" " --delay, -d <delay> wait <delay> sec between prints [1 - 1000000]\n" , cmd ); } int main(int argc, char **argv) { struct bpf_program *prog; unsigned long delay = 5; char filename[256]; int longindex = 0; int opt, err = -1; while ((opt = getopt_long(argc, argv, "hd:rSw", long_options, &longindex)) != -1) { switch (opt) { case 'd': delay = strtoul(optarg, NULL, 0); if (delay == ULONG_MAX || delay < 0 || delay > 1000000) { fprintf(stderr, "ERROR: invalid delay : %s\n", optarg); usage(argv[0]); return 1; } break; default: case 'h': usage(argv[0]); return 1; } } /* Do one final dump when exiting */ signal(SIGINT, dump_exit); signal(SIGTERM, dump_exit); snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); obj = bpf_object__open_file(filename, NULL); if (libbpf_get_error(obj)) { fprintf(stderr, "ERROR: opening BPF object file failed\n"); return err; } /* load BPF program */ if (bpf_object__load(obj)) { fprintf(stderr, "ERROR: loading BPF object file failed\n"); goto cleanup; } map_fd[0] = bpf_object__find_map_fd_by_name(obj, "read_count"); map_fd[1] = bpf_object__find_map_fd_by_name(obj, "write_count"); if (map_fd[0] < 0 || map_fd[1] < 0) { fprintf(stderr, "ERROR: finding a map in obj file failed\n"); goto cleanup; } bpf_object__for_each_program(prog, obj) { tp_links[tp_cnt] = bpf_program__attach(prog); if (libbpf_get_error(tp_links[tp_cnt])) { fprintf(stderr, "ERROR: bpf_program__attach failed\n"); tp_links[tp_cnt] = NULL; goto cleanup; } tp_cnt++; } while (1) { sleep(delay); dump_all_counts(); } err = 0; cleanup: /* Detach tracepoints */ while (tp_cnt) bpf_link__destroy(tp_links[--tp_cnt]); bpf_object__close(obj); return err; } |