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