1 #include <stdio.h> 2 #include <assert.h> 3 #include <linux/bpf.h> 4 #include "libbpf.h" 5 #include "bpf_load.h" 6 #include "sock_example.h" 7 #include <unistd.h> 8 #include <arpa/inet.h> 9 #include <sys/resource.h> 10 11 #define PARSE_IP 3 12 #define PARSE_IP_PROG_FD (prog_fd[0]) 13 #define PROG_ARRAY_FD (map_fd[0]) 14 15 struct bpf_flow_keys { 16 __be32 src; 17 __be32 dst; 18 union { 19 __be32 ports; 20 __be16 port16[2]; 21 }; 22 __u32 ip_proto; 23 }; 24 25 struct pair { 26 __u64 packets; 27 __u64 bytes; 28 }; 29 30 int main(int argc, char **argv) 31 { 32 struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; 33 char filename[256]; 34 FILE *f; 35 int i, sock, err, id, key = PARSE_IP; 36 struct bpf_prog_info info = {}; 37 uint32_t info_len = sizeof(info); 38 39 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 40 setrlimit(RLIMIT_MEMLOCK, &r); 41 42 if (load_bpf_file(filename)) { 43 printf("%s", bpf_log_buf); 44 return 1; 45 } 46 47 /* Test fd array lookup which returns the id of the bpf_prog */ 48 err = bpf_obj_get_info_by_fd(PARSE_IP_PROG_FD, &info, &info_len); 49 assert(!err); 50 err = bpf_map_lookup_elem(PROG_ARRAY_FD, &key, &id); 51 assert(!err); 52 assert(id == info.id); 53 54 sock = open_raw_sock("lo"); 55 56 assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd[4], 57 sizeof(__u32)) == 0); 58 59 if (argc > 1) 60 f = popen("ping -c5 localhost", "r"); 61 else 62 f = popen("netperf -l 4 localhost", "r"); 63 (void) f; 64 65 for (i = 0; i < 5; i++) { 66 struct bpf_flow_keys key = {}, next_key; 67 struct pair value; 68 69 sleep(1); 70 printf("IP src.port -> dst.port bytes packets\n"); 71 while (bpf_map_get_next_key(map_fd[2], &key, &next_key) == 0) { 72 bpf_map_lookup_elem(map_fd[2], &next_key, &value); 73 printf("%s.%05d -> %s.%05d %12lld %12lld\n", 74 inet_ntoa((struct in_addr){htonl(next_key.src)}), 75 next_key.port16[0], 76 inet_ntoa((struct in_addr){htonl(next_key.dst)}), 77 next_key.port16[1], 78 value.bytes, value.packets); 79 key = next_key; 80 } 81 } 82 return 0; 83 } 84