linux/samples/bpf/libbpf.c
<<
>>
Prefs
   1/* eBPF mini library */
   2#include <stdlib.h>
   3#include <stdio.h>
   4#include <linux/unistd.h>
   5#include <unistd.h>
   6#include <string.h>
   7#include <linux/netlink.h>
   8#include <linux/bpf.h>
   9#include <errno.h>
  10#include <net/ethernet.h>
  11#include <net/if.h>
  12#include <linux/if_packet.h>
  13#include <arpa/inet.h>
  14#include "libbpf.h"
  15
  16static __u64 ptr_to_u64(void *ptr)
  17{
  18        return (__u64) (unsigned long) ptr;
  19}
  20
  21int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
  22                   int max_entries, int map_flags)
  23{
  24        union bpf_attr attr = {
  25                .map_type = map_type,
  26                .key_size = key_size,
  27                .value_size = value_size,
  28                .max_entries = max_entries,
  29                .map_flags = map_flags,
  30        };
  31
  32        return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
  33}
  34
  35int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags)
  36{
  37        union bpf_attr attr = {
  38                .map_fd = fd,
  39                .key = ptr_to_u64(key),
  40                .value = ptr_to_u64(value),
  41                .flags = flags,
  42        };
  43
  44        return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
  45}
  46
  47int bpf_lookup_elem(int fd, void *key, void *value)
  48{
  49        union bpf_attr attr = {
  50                .map_fd = fd,
  51                .key = ptr_to_u64(key),
  52                .value = ptr_to_u64(value),
  53        };
  54
  55        return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
  56}
  57
  58int bpf_delete_elem(int fd, void *key)
  59{
  60        union bpf_attr attr = {
  61                .map_fd = fd,
  62                .key = ptr_to_u64(key),
  63        };
  64
  65        return syscall(__NR_bpf, BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
  66}
  67
  68int bpf_get_next_key(int fd, void *key, void *next_key)
  69{
  70        union bpf_attr attr = {
  71                .map_fd = fd,
  72                .key = ptr_to_u64(key),
  73                .next_key = ptr_to_u64(next_key),
  74        };
  75
  76        return syscall(__NR_bpf, BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
  77}
  78
  79#define ROUND_UP(x, n) (((x) + (n) - 1u) & ~((n) - 1u))
  80
  81char bpf_log_buf[LOG_BUF_SIZE];
  82
  83int bpf_prog_load(enum bpf_prog_type prog_type,
  84                  const struct bpf_insn *insns, int prog_len,
  85                  const char *license, int kern_version)
  86{
  87        union bpf_attr attr = {
  88                .prog_type = prog_type,
  89                .insns = ptr_to_u64((void *) insns),
  90                .insn_cnt = prog_len / sizeof(struct bpf_insn),
  91                .license = ptr_to_u64((void *) license),
  92                .log_buf = ptr_to_u64(bpf_log_buf),
  93                .log_size = LOG_BUF_SIZE,
  94                .log_level = 1,
  95        };
  96
  97        /* assign one field outside of struct init to make sure any
  98         * padding is zero initialized
  99         */
 100        attr.kern_version = kern_version;
 101
 102        bpf_log_buf[0] = 0;
 103
 104        return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
 105}
 106
 107int bpf_obj_pin(int fd, const char *pathname)
 108{
 109        union bpf_attr attr = {
 110                .pathname       = ptr_to_u64((void *)pathname),
 111                .bpf_fd         = fd,
 112        };
 113
 114        return syscall(__NR_bpf, BPF_OBJ_PIN, &attr, sizeof(attr));
 115}
 116
 117int bpf_obj_get(const char *pathname)
 118{
 119        union bpf_attr attr = {
 120                .pathname       = ptr_to_u64((void *)pathname),
 121        };
 122
 123        return syscall(__NR_bpf, BPF_OBJ_GET, &attr, sizeof(attr));
 124}
 125
 126int open_raw_sock(const char *name)
 127{
 128        struct sockaddr_ll sll;
 129        int sock;
 130
 131        sock = socket(PF_PACKET, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, htons(ETH_P_ALL));
 132        if (sock < 0) {
 133                printf("cannot create raw socket\n");
 134                return -1;
 135        }
 136
 137        memset(&sll, 0, sizeof(sll));
 138        sll.sll_family = AF_PACKET;
 139        sll.sll_ifindex = if_nametoindex(name);
 140        sll.sll_protocol = htons(ETH_P_ALL);
 141        if (bind(sock, (struct sockaddr *)&sll, sizeof(sll)) < 0) {
 142                printf("bind to %s: %s\n", name, strerror(errno));
 143                close(sock);
 144                return -1;
 145        }
 146
 147        return sock;
 148}
 149
 150int perf_event_open(struct perf_event_attr *attr, int pid, int cpu,
 151                    int group_fd, unsigned long flags)
 152{
 153        return syscall(__NR_perf_event_open, attr, pid, cpu,
 154                       group_fd, flags);
 155}
 156