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