10ac01febSIra Weiny // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
20ac01febSIra Weiny
3*4ce7d68bSAditya Srivastava /*
40ac01febSIra Weiny * ibumad BPF sample user side
50ac01febSIra Weiny *
60ac01febSIra Weiny * This program is free software; you can redistribute it and/or
70ac01febSIra Weiny * modify it under the terms of version 2 of the GNU General Public
80ac01febSIra Weiny * License as published by the Free Software Foundation.
90ac01febSIra Weiny *
100ac01febSIra Weiny * Copyright(c) 2018 Ira Weiny, Intel Corporation
110ac01febSIra Weiny */
120ac01febSIra Weiny
130ac01febSIra Weiny #include <linux/bpf.h>
140ac01febSIra Weiny #include <signal.h>
150ac01febSIra Weiny #include <stdio.h>
160ac01febSIra Weiny #include <stdlib.h>
170ac01febSIra Weiny #include <string.h>
180ac01febSIra Weiny #include <unistd.h>
190ac01febSIra Weiny #include <sys/types.h>
200ac01febSIra Weiny #include <limits.h>
210ac01febSIra Weiny
220ac01febSIra Weiny #include <getopt.h>
230ac01febSIra Weiny #include <net/if.h>
240ac01febSIra Weiny
25763af200SDaniel T. Lee #include <bpf/bpf.h>
260ac01febSIra Weiny #include "bpf_util.h"
277cf245a3SToke Høiland-Jørgensen #include <bpf/libbpf.h>
280ac01febSIra Weiny
29763af200SDaniel T. Lee static struct bpf_link *tp_links[3];
30763af200SDaniel T. Lee static struct bpf_object *obj;
31763af200SDaniel T. Lee static int map_fd[2];
32763af200SDaniel T. Lee static int tp_cnt;
33763af200SDaniel T. Lee
dump_counts(int fd)340ac01febSIra Weiny static void dump_counts(int fd)
350ac01febSIra Weiny {
360ac01febSIra Weiny __u32 key;
370ac01febSIra Weiny __u64 value;
380ac01febSIra Weiny
390ac01febSIra Weiny for (key = 0; key < 256; key++) {
400ac01febSIra Weiny if (bpf_map_lookup_elem(fd, &key, &value)) {
410ac01febSIra Weiny printf("failed to read key %u\n", key);
420ac01febSIra Weiny continue;
430ac01febSIra Weiny }
440ac01febSIra Weiny if (value)
450ac01febSIra Weiny printf("0x%02x : %llu\n", key, value);
460ac01febSIra Weiny }
470ac01febSIra Weiny }
480ac01febSIra Weiny
dump_all_counts(void)490ac01febSIra Weiny static void dump_all_counts(void)
500ac01febSIra Weiny {
510ac01febSIra Weiny printf("Read 'Class : count'\n");
520ac01febSIra Weiny dump_counts(map_fd[0]);
530ac01febSIra Weiny printf("Write 'Class : count'\n");
540ac01febSIra Weiny dump_counts(map_fd[1]);
550ac01febSIra Weiny }
560ac01febSIra Weiny
dump_exit(int sig)570ac01febSIra Weiny static void dump_exit(int sig)
580ac01febSIra Weiny {
590ac01febSIra Weiny dump_all_counts();
60763af200SDaniel T. Lee /* Detach tracepoints */
61763af200SDaniel T. Lee while (tp_cnt)
62763af200SDaniel T. Lee bpf_link__destroy(tp_links[--tp_cnt]);
63763af200SDaniel T. Lee
64763af200SDaniel T. Lee bpf_object__close(obj);
650ac01febSIra Weiny exit(0);
660ac01febSIra Weiny }
670ac01febSIra Weiny
680ac01febSIra Weiny static const struct option long_options[] = {
690ac01febSIra Weiny {"help", no_argument, NULL, 'h'},
700ac01febSIra Weiny {"delay", required_argument, NULL, 'd'},
710ac01febSIra Weiny };
720ac01febSIra Weiny
usage(char * cmd)730ac01febSIra Weiny static void usage(char *cmd)
740ac01febSIra Weiny {
750ac01febSIra Weiny printf("eBPF test program to count packets from various IP addresses\n"
760ac01febSIra Weiny "Usage: %s <options>\n"
770ac01febSIra Weiny " --help, -h this menu\n"
780ac01febSIra Weiny " --delay, -d <delay> wait <delay> sec between prints [1 - 1000000]\n"
790ac01febSIra Weiny , cmd
800ac01febSIra Weiny );
810ac01febSIra Weiny }
820ac01febSIra Weiny
main(int argc,char ** argv)830ac01febSIra Weiny int main(int argc, char **argv)
840ac01febSIra Weiny {
85763af200SDaniel T. Lee struct bpf_program *prog;
860ac01febSIra Weiny unsigned long delay = 5;
87763af200SDaniel T. Lee char filename[256];
880ac01febSIra Weiny int longindex = 0;
89763af200SDaniel T. Lee int opt, err = -1;
900ac01febSIra Weiny
910ac01febSIra Weiny while ((opt = getopt_long(argc, argv, "hd:rSw",
920ac01febSIra Weiny long_options, &longindex)) != -1) {
930ac01febSIra Weiny switch (opt) {
940ac01febSIra Weiny case 'd':
950ac01febSIra Weiny delay = strtoul(optarg, NULL, 0);
960ac01febSIra Weiny if (delay == ULONG_MAX || delay < 0 ||
970ac01febSIra Weiny delay > 1000000) {
980ac01febSIra Weiny fprintf(stderr, "ERROR: invalid delay : %s\n",
990ac01febSIra Weiny optarg);
1000ac01febSIra Weiny usage(argv[0]);
1010ac01febSIra Weiny return 1;
1020ac01febSIra Weiny }
1030ac01febSIra Weiny break;
1040ac01febSIra Weiny default:
1050ac01febSIra Weiny case 'h':
1060ac01febSIra Weiny usage(argv[0]);
1070ac01febSIra Weiny return 1;
1080ac01febSIra Weiny }
1090ac01febSIra Weiny }
1100ac01febSIra Weiny
111763af200SDaniel T. Lee /* Do one final dump when exiting */
112763af200SDaniel T. Lee signal(SIGINT, dump_exit);
113763af200SDaniel T. Lee signal(SIGTERM, dump_exit);
114763af200SDaniel T. Lee
115763af200SDaniel T. Lee snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
116763af200SDaniel T. Lee obj = bpf_object__open_file(filename, NULL);
117763af200SDaniel T. Lee if (libbpf_get_error(obj)) {
118763af200SDaniel T. Lee fprintf(stderr, "ERROR: opening BPF object file failed\n");
119763af200SDaniel T. Lee return err;
120763af200SDaniel T. Lee }
121763af200SDaniel T. Lee
122763af200SDaniel T. Lee /* load BPF program */
123763af200SDaniel T. Lee if (bpf_object__load(obj)) {
124763af200SDaniel T. Lee fprintf(stderr, "ERROR: loading BPF object file failed\n");
125763af200SDaniel T. Lee goto cleanup;
126763af200SDaniel T. Lee }
127763af200SDaniel T. Lee
128763af200SDaniel T. Lee map_fd[0] = bpf_object__find_map_fd_by_name(obj, "read_count");
129763af200SDaniel T. Lee map_fd[1] = bpf_object__find_map_fd_by_name(obj, "write_count");
130763af200SDaniel T. Lee if (map_fd[0] < 0 || map_fd[1] < 0) {
131763af200SDaniel T. Lee fprintf(stderr, "ERROR: finding a map in obj file failed\n");
132763af200SDaniel T. Lee goto cleanup;
133763af200SDaniel T. Lee }
134763af200SDaniel T. Lee
135763af200SDaniel T. Lee bpf_object__for_each_program(prog, obj) {
136763af200SDaniel T. Lee tp_links[tp_cnt] = bpf_program__attach(prog);
137763af200SDaniel T. Lee if (libbpf_get_error(tp_links[tp_cnt])) {
138763af200SDaniel T. Lee fprintf(stderr, "ERROR: bpf_program__attach failed\n");
139763af200SDaniel T. Lee tp_links[tp_cnt] = NULL;
140763af200SDaniel T. Lee goto cleanup;
141763af200SDaniel T. Lee }
142763af200SDaniel T. Lee tp_cnt++;
1430ac01febSIra Weiny }
1440ac01febSIra Weiny
1450ac01febSIra Weiny while (1) {
1460ac01febSIra Weiny sleep(delay);
1470ac01febSIra Weiny dump_all_counts();
1480ac01febSIra Weiny }
149763af200SDaniel T. Lee err = 0;
1500ac01febSIra Weiny
151763af200SDaniel T. Lee cleanup:
152763af200SDaniel T. Lee /* Detach tracepoints */
153763af200SDaniel T. Lee while (tp_cnt)
154763af200SDaniel T. Lee bpf_link__destroy(tp_links[--tp_cnt]);
155763af200SDaniel T. Lee
156763af200SDaniel T. Lee bpf_object__close(obj);
157763af200SDaniel T. Lee return err;
1580ac01febSIra Weiny }
159