18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci/**
48c2ecf20Sopenharmony_ci * ibumad BPF sample user side
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or
78c2ecf20Sopenharmony_ci * modify it under the terms of version 2 of the GNU General Public
88c2ecf20Sopenharmony_ci * License as published by the Free Software Foundation.
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * Copyright(c) 2018 Ira Weiny, Intel Corporation
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/bpf.h>
148c2ecf20Sopenharmony_ci#include <signal.h>
158c2ecf20Sopenharmony_ci#include <stdio.h>
168c2ecf20Sopenharmony_ci#include <stdlib.h>
178c2ecf20Sopenharmony_ci#include <string.h>
188c2ecf20Sopenharmony_ci#include <unistd.h>
198c2ecf20Sopenharmony_ci#include <sys/types.h>
208c2ecf20Sopenharmony_ci#include <limits.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include <sys/resource.h>
238c2ecf20Sopenharmony_ci#include <getopt.h>
248c2ecf20Sopenharmony_ci#include <net/if.h>
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#include "bpf_load.h"
278c2ecf20Sopenharmony_ci#include "bpf_util.h"
288c2ecf20Sopenharmony_ci#include <bpf/libbpf.h>
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic void dump_counts(int fd)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	__u32 key;
338c2ecf20Sopenharmony_ci	__u64 value;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	for (key = 0; key < 256; key++) {
368c2ecf20Sopenharmony_ci		if (bpf_map_lookup_elem(fd, &key, &value)) {
378c2ecf20Sopenharmony_ci			printf("failed to read key %u\n", key);
388c2ecf20Sopenharmony_ci			continue;
398c2ecf20Sopenharmony_ci		}
408c2ecf20Sopenharmony_ci		if (value)
418c2ecf20Sopenharmony_ci			printf("0x%02x : %llu\n", key, value);
428c2ecf20Sopenharmony_ci	}
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic void dump_all_counts(void)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	printf("Read 'Class : count'\n");
488c2ecf20Sopenharmony_ci	dump_counts(map_fd[0]);
498c2ecf20Sopenharmony_ci	printf("Write 'Class : count'\n");
508c2ecf20Sopenharmony_ci	dump_counts(map_fd[1]);
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistatic void dump_exit(int sig)
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	dump_all_counts();
568c2ecf20Sopenharmony_ci	exit(0);
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic const struct option long_options[] = {
608c2ecf20Sopenharmony_ci	{"help",      no_argument,       NULL, 'h'},
618c2ecf20Sopenharmony_ci	{"delay",     required_argument, NULL, 'd'},
628c2ecf20Sopenharmony_ci};
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_cistatic void usage(char *cmd)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	printf("eBPF test program to count packets from various IP addresses\n"
678c2ecf20Sopenharmony_ci		"Usage: %s <options>\n"
688c2ecf20Sopenharmony_ci		"       --help,   -h  this menu\n"
698c2ecf20Sopenharmony_ci		"       --delay,  -d  <delay>  wait <delay> sec between prints [1 - 1000000]\n"
708c2ecf20Sopenharmony_ci		, cmd
718c2ecf20Sopenharmony_ci		);
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ciint main(int argc, char **argv)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	unsigned long delay = 5;
778c2ecf20Sopenharmony_ci	int longindex = 0;
788c2ecf20Sopenharmony_ci	int opt;
798c2ecf20Sopenharmony_ci	char bpf_file[256];
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	/* Create the eBPF kernel code path name.
828c2ecf20Sopenharmony_ci	 * This follows the pattern of all of the other bpf samples
838c2ecf20Sopenharmony_ci	 */
848c2ecf20Sopenharmony_ci	snprintf(bpf_file, sizeof(bpf_file), "%s_kern.o", argv[0]);
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	/* Do one final dump when exiting */
878c2ecf20Sopenharmony_ci	signal(SIGINT, dump_exit);
888c2ecf20Sopenharmony_ci	signal(SIGTERM, dump_exit);
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	while ((opt = getopt_long(argc, argv, "hd:rSw",
918c2ecf20Sopenharmony_ci				  long_options, &longindex)) != -1) {
928c2ecf20Sopenharmony_ci		switch (opt) {
938c2ecf20Sopenharmony_ci		case 'd':
948c2ecf20Sopenharmony_ci			delay = strtoul(optarg, NULL, 0);
958c2ecf20Sopenharmony_ci			if (delay == ULONG_MAX || delay < 0 ||
968c2ecf20Sopenharmony_ci			    delay > 1000000) {
978c2ecf20Sopenharmony_ci				fprintf(stderr, "ERROR: invalid delay : %s\n",
988c2ecf20Sopenharmony_ci					optarg);
998c2ecf20Sopenharmony_ci				usage(argv[0]);
1008c2ecf20Sopenharmony_ci				return 1;
1018c2ecf20Sopenharmony_ci			}
1028c2ecf20Sopenharmony_ci			break;
1038c2ecf20Sopenharmony_ci		default:
1048c2ecf20Sopenharmony_ci		case 'h':
1058c2ecf20Sopenharmony_ci			usage(argv[0]);
1068c2ecf20Sopenharmony_ci			return 1;
1078c2ecf20Sopenharmony_ci		}
1088c2ecf20Sopenharmony_ci	}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	if (load_bpf_file(bpf_file)) {
1118c2ecf20Sopenharmony_ci		fprintf(stderr, "ERROR: failed to load eBPF from file : %s\n",
1128c2ecf20Sopenharmony_ci			bpf_file);
1138c2ecf20Sopenharmony_ci		return 1;
1148c2ecf20Sopenharmony_ci	}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	while (1) {
1178c2ecf20Sopenharmony_ci		sleep(delay);
1188c2ecf20Sopenharmony_ci		dump_all_counts();
1198c2ecf20Sopenharmony_ci	}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	return 0;
1228c2ecf20Sopenharmony_ci}
123