forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
3.4 KiB
159 lines
3.4 KiB
// 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 <sys/resource.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; |
|
}
|
|
|