linux/tools/lib/bpf/bpf.c
<<
>>
Prefs
   1/*
   2 * common eBPF ELF operations.
   3 *
   4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
   5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
   6 * Copyright (C) 2015 Huawei Inc.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU Lesser General Public
  10 * License as published by the Free Software Foundation;
  11 * version 2.1 of the License (not later!)
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU Lesser General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU Lesser General Public
  19 * License along with this program; if not,  see <http://www.gnu.org/licenses>
  20 */
  21
  22#include <stdlib.h>
  23#include <memory.h>
  24#include <unistd.h>
  25#include <asm/unistd.h>
  26#include <linux/bpf.h>
  27#include "bpf.h"
  28
  29/*
  30 * When building perf, unistd.h is overridden. __NR_bpf is
  31 * required to be defined explicitly.
  32 */
  33#ifndef __NR_bpf
  34# if defined(__i386__)
  35#  define __NR_bpf 357
  36# elif defined(__x86_64__)
  37#  define __NR_bpf 321
  38# elif defined(__aarch64__)
  39#  define __NR_bpf 280
  40# elif defined(__sparc__)
  41#  define __NR_bpf 349
  42# elif defined(__s390__)
  43#  define __NR_bpf 351
  44# else
  45#  error __NR_bpf not defined. libbpf does not support your arch.
  46# endif
  47#endif
  48
  49static inline __u64 ptr_to_u64(const void *ptr)
  50{
  51        return (__u64) (unsigned long) ptr;
  52}
  53
  54static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
  55                          unsigned int size)
  56{
  57        return syscall(__NR_bpf, cmd, attr, size);
  58}
  59
  60int bpf_create_map_node(enum bpf_map_type map_type, int key_size,
  61                        int value_size, int max_entries, __u32 map_flags,
  62                        int node)
  63{
  64        union bpf_attr attr;
  65
  66        memset(&attr, '\0', sizeof(attr));
  67
  68        attr.map_type = map_type;
  69        attr.key_size = key_size;
  70        attr.value_size = value_size;
  71        attr.max_entries = max_entries;
  72        attr.map_flags = map_flags;
  73        if (node >= 0) {
  74                attr.map_flags |= BPF_F_NUMA_NODE;
  75                attr.numa_node = node;
  76        }
  77
  78        return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
  79}
  80
  81int bpf_create_map(enum bpf_map_type map_type, int key_size,
  82                   int value_size, int max_entries, __u32 map_flags)
  83{
  84        return bpf_create_map_node(map_type, key_size, value_size,
  85                                   max_entries, map_flags, -1);
  86}
  87
  88int bpf_create_map_in_map_node(enum bpf_map_type map_type, int key_size,
  89                               int inner_map_fd, int max_entries,
  90                               __u32 map_flags, int node)
  91{
  92        union bpf_attr attr;
  93
  94        memset(&attr, '\0', sizeof(attr));
  95
  96        attr.map_type = map_type;
  97        attr.key_size = key_size;
  98        attr.value_size = 4;
  99        attr.inner_map_fd = inner_map_fd;
 100        attr.max_entries = max_entries;
 101        attr.map_flags = map_flags;
 102        if (node >= 0) {
 103                attr.map_flags |= BPF_F_NUMA_NODE;
 104                attr.numa_node = node;
 105        }
 106
 107        return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
 108}
 109
 110int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size,
 111                          int inner_map_fd, int max_entries, __u32 map_flags)
 112{
 113        return bpf_create_map_in_map_node(map_type, key_size, inner_map_fd,
 114                                          max_entries, map_flags, -1);
 115}
 116
 117int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
 118                     size_t insns_cnt, const char *license,
 119                     __u32 kern_version, char *log_buf, size_t log_buf_sz)
 120{
 121        int fd;
 122        union bpf_attr attr;
 123
 124        bzero(&attr, sizeof(attr));
 125        attr.prog_type = type;
 126        attr.insn_cnt = (__u32)insns_cnt;
 127        attr.insns = ptr_to_u64(insns);
 128        attr.license = ptr_to_u64(license);
 129        attr.log_buf = ptr_to_u64(NULL);
 130        attr.log_size = 0;
 131        attr.log_level = 0;
 132        attr.kern_version = kern_version;
 133
 134        fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
 135        if (fd >= 0 || !log_buf || !log_buf_sz)
 136                return fd;
 137
 138        /* Try again with log */
 139        attr.log_buf = ptr_to_u64(log_buf);
 140        attr.log_size = log_buf_sz;
 141        attr.log_level = 1;
 142        log_buf[0] = 0;
 143        return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
 144}
 145
 146int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
 147                       size_t insns_cnt, int strict_alignment,
 148                       const char *license, __u32 kern_version,
 149                       char *log_buf, size_t log_buf_sz, int log_level)
 150{
 151        union bpf_attr attr;
 152
 153        bzero(&attr, sizeof(attr));
 154        attr.prog_type = type;
 155        attr.insn_cnt = (__u32)insns_cnt;
 156        attr.insns = ptr_to_u64(insns);
 157        attr.license = ptr_to_u64(license);
 158        attr.log_buf = ptr_to_u64(log_buf);
 159        attr.log_size = log_buf_sz;
 160        attr.log_level = log_level;
 161        log_buf[0] = 0;
 162        attr.kern_version = kern_version;
 163        attr.prog_flags = strict_alignment ? BPF_F_STRICT_ALIGNMENT : 0;
 164
 165        return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
 166}
 167
 168int bpf_map_update_elem(int fd, const void *key, const void *value,
 169                        __u64 flags)
 170{
 171        union bpf_attr attr;
 172
 173        bzero(&attr, sizeof(attr));
 174        attr.map_fd = fd;
 175        attr.key = ptr_to_u64(key);
 176        attr.value = ptr_to_u64(value);
 177        attr.flags = flags;
 178
 179        return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
 180}
 181
 182int bpf_map_lookup_elem(int fd, const void *key, void *value)
 183{
 184        union bpf_attr attr;
 185
 186        bzero(&attr, sizeof(attr));
 187        attr.map_fd = fd;
 188        attr.key = ptr_to_u64(key);
 189        attr.value = ptr_to_u64(value);
 190
 191        return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
 192}
 193
 194int bpf_map_delete_elem(int fd, const void *key)
 195{
 196        union bpf_attr attr;
 197
 198        bzero(&attr, sizeof(attr));
 199        attr.map_fd = fd;
 200        attr.key = ptr_to_u64(key);
 201
 202        return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
 203}
 204
 205int bpf_map_get_next_key(int fd, const void *key, void *next_key)
 206{
 207        union bpf_attr attr;
 208
 209        bzero(&attr, sizeof(attr));
 210        attr.map_fd = fd;
 211        attr.key = ptr_to_u64(key);
 212        attr.next_key = ptr_to_u64(next_key);
 213
 214        return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
 215}
 216
 217int bpf_obj_pin(int fd, const char *pathname)
 218{
 219        union bpf_attr attr;
 220
 221        bzero(&attr, sizeof(attr));
 222        attr.pathname = ptr_to_u64((void *)pathname);
 223        attr.bpf_fd = fd;
 224
 225        return sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr));
 226}
 227
 228int bpf_obj_get(const char *pathname)
 229{
 230        union bpf_attr attr;
 231
 232        bzero(&attr, sizeof(attr));
 233        attr.pathname = ptr_to_u64((void *)pathname);
 234
 235        return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
 236}
 237
 238int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type,
 239                    unsigned int flags)
 240{
 241        union bpf_attr attr;
 242
 243        bzero(&attr, sizeof(attr));
 244        attr.target_fd     = target_fd;
 245        attr.attach_bpf_fd = prog_fd;
 246        attr.attach_type   = type;
 247        attr.attach_flags  = flags;
 248
 249        return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
 250}
 251
 252int bpf_prog_detach(int target_fd, enum bpf_attach_type type)
 253{
 254        union bpf_attr attr;
 255
 256        bzero(&attr, sizeof(attr));
 257        attr.target_fd   = target_fd;
 258        attr.attach_type = type;
 259
 260        return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
 261}
 262
 263int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size,
 264                      void *data_out, __u32 *size_out, __u32 *retval,
 265                      __u32 *duration)
 266{
 267        union bpf_attr attr;
 268        int ret;
 269
 270        bzero(&attr, sizeof(attr));
 271        attr.test.prog_fd = prog_fd;
 272        attr.test.data_in = ptr_to_u64(data);
 273        attr.test.data_out = ptr_to_u64(data_out);
 274        attr.test.data_size_in = size;
 275        attr.test.repeat = repeat;
 276
 277        ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr));
 278        if (size_out)
 279                *size_out = attr.test.data_size_out;
 280        if (retval)
 281                *retval = attr.test.retval;
 282        if (duration)
 283                *duration = attr.test.duration;
 284        return ret;
 285}
 286
 287int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id)
 288{
 289        union bpf_attr attr;
 290        int err;
 291
 292        bzero(&attr, sizeof(attr));
 293        attr.start_id = start_id;
 294
 295        err = sys_bpf(BPF_PROG_GET_NEXT_ID, &attr, sizeof(attr));
 296        if (!err)
 297                *next_id = attr.next_id;
 298
 299        return err;
 300}
 301
 302int bpf_map_get_next_id(__u32 start_id, __u32 *next_id)
 303{
 304        union bpf_attr attr;
 305        int err;
 306
 307        bzero(&attr, sizeof(attr));
 308        attr.start_id = start_id;
 309
 310        err = sys_bpf(BPF_MAP_GET_NEXT_ID, &attr, sizeof(attr));
 311        if (!err)
 312                *next_id = attr.next_id;
 313
 314        return err;
 315}
 316
 317int bpf_prog_get_fd_by_id(__u32 id)
 318{
 319        union bpf_attr attr;
 320
 321        bzero(&attr, sizeof(attr));
 322        attr.prog_id = id;
 323
 324        return sys_bpf(BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr));
 325}
 326
 327int bpf_map_get_fd_by_id(__u32 id)
 328{
 329        union bpf_attr attr;
 330
 331        bzero(&attr, sizeof(attr));
 332        attr.map_id = id;
 333
 334        return sys_bpf(BPF_MAP_GET_FD_BY_ID, &attr, sizeof(attr));
 335}
 336
 337int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len)
 338{
 339        union bpf_attr attr;
 340        int err;
 341
 342        bzero(&attr, sizeof(attr));
 343        attr.info.bpf_fd = prog_fd;
 344        attr.info.info_len = *info_len;
 345        attr.info.info = ptr_to_u64(info);
 346
 347        err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr));
 348        if (!err)
 349                *info_len = attr.info.info_len;
 350
 351        return err;
 352}
 353