18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <stdio.h> 38c2ecf20Sopenharmony_ci#include <assert.h> 48c2ecf20Sopenharmony_ci#include <bpf/bpf.h> 58c2ecf20Sopenharmony_ci#include <bpf/libbpf.h> 68c2ecf20Sopenharmony_ci#include "sock_example.h" 78c2ecf20Sopenharmony_ci#include <unistd.h> 88c2ecf20Sopenharmony_ci#include <arpa/inet.h> 98c2ecf20Sopenharmony_ci#include <sys/resource.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_cistruct flow_key_record { 128c2ecf20Sopenharmony_ci __be32 src; 138c2ecf20Sopenharmony_ci __be32 dst; 148c2ecf20Sopenharmony_ci union { 158c2ecf20Sopenharmony_ci __be32 ports; 168c2ecf20Sopenharmony_ci __be16 port16[2]; 178c2ecf20Sopenharmony_ci }; 188c2ecf20Sopenharmony_ci __u32 ip_proto; 198c2ecf20Sopenharmony_ci}; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistruct pair { 228c2ecf20Sopenharmony_ci __u64 packets; 238c2ecf20Sopenharmony_ci __u64 bytes; 248c2ecf20Sopenharmony_ci}; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ciint main(int argc, char **argv) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci int i, sock, key, fd, main_prog_fd, jmp_table_fd, hash_map_fd; 298c2ecf20Sopenharmony_ci struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; 308c2ecf20Sopenharmony_ci struct bpf_program *prog; 318c2ecf20Sopenharmony_ci struct bpf_object *obj; 328c2ecf20Sopenharmony_ci const char *section; 338c2ecf20Sopenharmony_ci char filename[256]; 348c2ecf20Sopenharmony_ci FILE *f; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 378c2ecf20Sopenharmony_ci setrlimit(RLIMIT_MEMLOCK, &r); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci obj = bpf_object__open_file(filename, NULL); 408c2ecf20Sopenharmony_ci if (libbpf_get_error(obj)) { 418c2ecf20Sopenharmony_ci fprintf(stderr, "ERROR: opening BPF object file failed\n"); 428c2ecf20Sopenharmony_ci return 0; 438c2ecf20Sopenharmony_ci } 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* load BPF program */ 468c2ecf20Sopenharmony_ci if (bpf_object__load(obj)) { 478c2ecf20Sopenharmony_ci fprintf(stderr, "ERROR: loading BPF object file failed\n"); 488c2ecf20Sopenharmony_ci goto cleanup; 498c2ecf20Sopenharmony_ci } 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci jmp_table_fd = bpf_object__find_map_fd_by_name(obj, "jmp_table"); 528c2ecf20Sopenharmony_ci hash_map_fd = bpf_object__find_map_fd_by_name(obj, "hash_map"); 538c2ecf20Sopenharmony_ci if (jmp_table_fd < 0 || hash_map_fd < 0) { 548c2ecf20Sopenharmony_ci fprintf(stderr, "ERROR: finding a map in obj file failed\n"); 558c2ecf20Sopenharmony_ci goto cleanup; 568c2ecf20Sopenharmony_ci } 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci bpf_object__for_each_program(prog, obj) { 598c2ecf20Sopenharmony_ci fd = bpf_program__fd(prog); 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci section = bpf_program__section_name(prog); 628c2ecf20Sopenharmony_ci if (sscanf(section, "socket/%d", &key) != 1) { 638c2ecf20Sopenharmony_ci fprintf(stderr, "ERROR: finding prog failed\n"); 648c2ecf20Sopenharmony_ci goto cleanup; 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci if (key == 0) 688c2ecf20Sopenharmony_ci main_prog_fd = fd; 698c2ecf20Sopenharmony_ci else 708c2ecf20Sopenharmony_ci bpf_map_update_elem(jmp_table_fd, &key, &fd, BPF_ANY); 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci sock = open_raw_sock("lo"); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci /* attach BPF program to socket */ 768c2ecf20Sopenharmony_ci assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &main_prog_fd, 778c2ecf20Sopenharmony_ci sizeof(__u32)) == 0); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci if (argc > 1) 808c2ecf20Sopenharmony_ci f = popen("ping -4 -c5 localhost", "r"); 818c2ecf20Sopenharmony_ci else 828c2ecf20Sopenharmony_ci f = popen("netperf -l 4 localhost", "r"); 838c2ecf20Sopenharmony_ci (void) f; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci for (i = 0; i < 5; i++) { 868c2ecf20Sopenharmony_ci struct flow_key_record key = {}, next_key; 878c2ecf20Sopenharmony_ci struct pair value; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci sleep(1); 908c2ecf20Sopenharmony_ci printf("IP src.port -> dst.port bytes packets\n"); 918c2ecf20Sopenharmony_ci while (bpf_map_get_next_key(hash_map_fd, &key, &next_key) == 0) { 928c2ecf20Sopenharmony_ci bpf_map_lookup_elem(hash_map_fd, &next_key, &value); 938c2ecf20Sopenharmony_ci printf("%s.%05d -> %s.%05d %12lld %12lld\n", 948c2ecf20Sopenharmony_ci inet_ntoa((struct in_addr){htonl(next_key.src)}), 958c2ecf20Sopenharmony_ci next_key.port16[0], 968c2ecf20Sopenharmony_ci inet_ntoa((struct in_addr){htonl(next_key.dst)}), 978c2ecf20Sopenharmony_ci next_key.port16[1], 988c2ecf20Sopenharmony_ci value.bytes, value.packets); 998c2ecf20Sopenharmony_ci key = next_key; 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cicleanup: 1048c2ecf20Sopenharmony_ci bpf_object__close(obj); 1058c2ecf20Sopenharmony_ci return 0; 1068c2ecf20Sopenharmony_ci} 107