xref: /linux/samples/bpf/ibumad_user.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
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