^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <assert.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <bpf/bpf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <bpf/libbpf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "sock_example.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <arpa/inet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <sys/resource.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) struct flow_key_record {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) __be32 src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) __be32 dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) __be32 ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) __be16 port16[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) __u32 ip_proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct pair {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) __u64 packets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) __u64 bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) int main(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) int i, sock, key, fd, main_prog_fd, jmp_table_fd, hash_map_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct bpf_program *prog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct bpf_object *obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) const char *section;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) char filename[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) FILE *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) setrlimit(RLIMIT_MEMLOCK, &r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) obj = bpf_object__open_file(filename, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (libbpf_get_error(obj)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) fprintf(stderr, "ERROR: opening BPF object file failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* load BPF program */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (bpf_object__load(obj)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) fprintf(stderr, "ERROR: loading BPF object file failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) jmp_table_fd = bpf_object__find_map_fd_by_name(obj, "jmp_table");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) hash_map_fd = bpf_object__find_map_fd_by_name(obj, "hash_map");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (jmp_table_fd < 0 || hash_map_fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) fprintf(stderr, "ERROR: finding a map in obj file failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) bpf_object__for_each_program(prog, obj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) fd = bpf_program__fd(prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) section = bpf_program__section_name(prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (sscanf(section, "socket/%d", &key) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) fprintf(stderr, "ERROR: finding prog failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (key == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) main_prog_fd = fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) bpf_map_update_elem(jmp_table_fd, &key, &fd, BPF_ANY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) sock = open_raw_sock("lo");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* attach BPF program to socket */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &main_prog_fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) sizeof(__u32)) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (argc > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) f = popen("ping -4 -c5 localhost", "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) f = popen("netperf -l 4 localhost", "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) (void) f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) for (i = 0; i < 5; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct flow_key_record key = {}, next_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct pair value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) sleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) printf("IP src.port -> dst.port bytes packets\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) while (bpf_map_get_next_key(hash_map_fd, &key, &next_key) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) bpf_map_lookup_elem(hash_map_fd, &next_key, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) printf("%s.%05d -> %s.%05d %12lld %12lld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) inet_ntoa((struct in_addr){htonl(next_key.src)}),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) next_key.port16[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) inet_ntoa((struct in_addr){htonl(next_key.dst)}),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) next_key.port16[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) value.bytes, value.packets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) key = next_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) bpf_object__close(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }