Skip to content

Commit

Permalink
bpf: Add support for prog_name and map_name
Browse files Browse the repository at this point in the history
This patch adds support for prog_name and map_name.

For libbpf.{h,c}, the new functions, bpf_prog_load_name()
and bpf_create_map_name() is created to avoid breaking the
existing libbpf.{a,so} user.

libbcc.py is also modified accordingly to reflect the
availability of the new functions in libbpf.

clang/b_frontend_action.cc, b/codegen_llvm.cc and BPF.cc are
modified to take advantage of the prog and map name also.

Run the following tests in new and old kernel (old kernel
in the sense that it does not support the prog/map name):

1) tools/trace.py -K sys_clone
2) examples/cpp/HelloWorld

Here is the output of the bpf (BPF Snapshot) that
will be introduced in the later patch:
[root@arch-fb-vm1 bcc]# ./tools/biosnoop.py

[root@arch-fb-vm1 bcc]# ./build/introspection/bps
      BID TYPE                 UID  #MAPS LoadTime     NAME
      113 kprobe                 0      1 Oct20/13:11  trace_pid_start
      114 kprobe                 0      1 Oct20/13:11  trace_req_start
      115 kprobe                 0      3 Oct20/13:11  trace_req_compl

[root@arch-fb-vm1 bcc]# ./build/introspection/bps 113
      BID TYPE                 UID  #MAPS LoadTime     NAME
      113 kprobe                 0      1 Oct20/13:11  trace_pid_start

     MID TYPE            FLAGS         KeySz  ValueSz  MaxEnts NAME
     186 hash            0x0               8       20    10240 infobyreq

Signed-off-by: Martin KaFai Lau <[email protected]>
  • Loading branch information
iamkafai committed Oct 24, 2017
1 parent 3aa8bf4 commit df36816
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 16 deletions.
5 changes: 3 additions & 2 deletions src/cc/api/BPF.cc
Original file line number Diff line number Diff line change
Expand Up @@ -480,11 +480,12 @@ StatusTuple BPF::load_func(const std::string& func_name,
func_name.c_str());
size_t func_size = bpf_module_->function_size(func_name);

fd = bpf_prog_load(type, reinterpret_cast<struct bpf_insn*>(func_start),
fd = bpf_prog_load(type, func_name.c_str(),
reinterpret_cast<struct bpf_insn*>(func_start),
func_size, bpf_module_->license(),
bpf_module_->kern_version(), nullptr,
0 // BPFModule will handle error printing
);
);

if (fd < 0)
return StatusTuple(-1, "Failed to load %s: %d", func_name.c_str(), fd);
Expand Down
4 changes: 3 additions & 1 deletion src/cc/frontends/b/codegen_llvm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,9 @@ StatusTuple CodegenLLVM::visit_table_decl_stmt_node(TableDeclStmtNode *n) {
decl_gvar->setSection("maps");
tables_[n] = decl_gvar;

int map_fd = bpf_create_map(map_type, key->bit_width_ / 8, leaf->bit_width_ / 8, n->size_, 0);
int map_fd = bpf_create_map(map_type, n->id_->name_.c_str(),
key->bit_width_ / 8, leaf->bit_width_ / 8,
n->size_, 0);
if (map_fd >= 0)
table_fds_[n] = map_fd;
} else {
Expand Down
4 changes: 3 additions & 1 deletion src/cc/frontends/clang/b_frontend_action.cc
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,9 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
}

table.type = map_type;
table.fd = bpf_create_map(map_type, table.key_size, table.leaf_size, table.max_entries, table.flags);
table.fd = bpf_create_map(map_type, table.name.c_str(),
table.key_size, table.leaf_size,
table.max_entries, table.flags);
}
if (table.fd < 0) {
error(Decl->getLocStart(), "could not open bpf map: %0\nis %1 map type enabled in your kernel?") <<
Expand Down
25 changes: 22 additions & 3 deletions src/cc/libbpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,24 +73,36 @@
#define PERF_FLAG_FD_CLOEXEC (1UL << 3)
#endif

#define min(x, y) ((x) < (y) ? (x) : (y))

static int probe_perf_reader_page_cnt = 8;

static uint64_t ptr_to_u64(void *ptr)
{
return (uint64_t) (unsigned long) ptr;
}

int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int max_entries, int map_flags)
int bpf_create_map(enum bpf_map_type map_type, const char *name,
int key_size, int value_size,
int max_entries, int map_flags)
{
size_t name_len = name ? strlen(name) : 0;
union bpf_attr attr;
memset(&attr, 0, sizeof(attr));
attr.map_type = map_type;
attr.key_size = key_size;
attr.value_size = value_size;
attr.max_entries = max_entries;
attr.map_flags = map_flags;
memcpy(attr.map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1));

int ret = syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));

if (ret < 0 && name_len && (errno == E2BIG || errno == EINVAL)) {
memset(attr.map_name, 0, BPF_OBJ_NAME_LEN);
ret = syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
}

if (ret < 0 && errno == EPERM) {
// see note below about the rationale for this retry

Expand Down Expand Up @@ -329,11 +341,12 @@ int bpf_prog_get_tag(int fd, unsigned long long *ptag)
return 0;
}

int bpf_prog_load(enum bpf_prog_type prog_type,
int bpf_prog_load(enum bpf_prog_type prog_type, const char *name,
const struct bpf_insn *insns, int prog_len,
const char *license, unsigned kern_version,
char *log_buf, unsigned log_buf_size)
{
size_t name_len = name ? strlen(name) : 0;
union bpf_attr attr;
char *bpf_log_buffer = NULL;
unsigned buffer_size = 0;
Expand All @@ -347,6 +360,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
attr.log_buf = ptr_to_u64(log_buf);
attr.log_size = log_buf_size;
attr.log_level = log_buf ? 1 : 0;
memcpy(attr.prog_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1));

attr.kern_version = kern_version;
if (log_buf)
Expand All @@ -356,13 +370,18 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
ret = -1;
errno = EINVAL;
fprintf(stderr,
"bpf: %s. Program too large (%d insns), at most %d insns\n\n",
"bpf: %s. Program too large (%u insns), at most %d insns\n\n",
strerror(errno), attr.insn_cnt, BPF_MAXINSNS);
return ret;
}

ret = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));

if (ret < 0 && name_len && (errno == E2BIG || errno == EINVAL)) {
memset(attr.prog_name, 0, BPF_OBJ_NAME_LEN);
ret = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
}

if (ret < 0 && errno == EPERM) {
// When EPERM is returned, two reasons are possible:
// 1. user has no permissions for bpf()
Expand Down
13 changes: 7 additions & 6 deletions src/cc/libbpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,19 @@ enum bpf_probe_attach_type {
BPF_PROBE_RETURN
};

int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
int max_entries, int map_flags);
int bpf_create_map(enum bpf_map_type map_type, const char *name,
int key_size, int value_size, int max_entries,
int map_flags);
int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_first_key(int fd, void *key, size_t key_size);
int bpf_get_next_key(int fd, void *key, void *next_key);

int bpf_prog_load(enum bpf_prog_type prog_type,
const struct bpf_insn *insns, int insn_len,
const char *license, unsigned kern_version,
char *log_buf, unsigned log_buf_size);
int bpf_prog_load(enum bpf_prog_type prog_type, const char *name,
const struct bpf_insn *insns, int insn_len,
const char *license, unsigned kern_version,
char *log_buf, unsigned log_buf_size);
int bpf_attach_socket(int sockfd, int progfd);

/* create RAW socket and bind to interface 'name' */
Expand Down
1 change: 1 addition & 0 deletions src/lua/bcc/bpf.lua
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ function Bpf:load_func(fn_name, prog_type)
"unknown program: "..fn_name)

local fd = libbcc.bpf_prog_load(prog_type,
fn_name,
libbcc.bpf_function_start(self.module, fn_name),
libbcc.bpf_function_size(self.module, fn_name),
libbcc.bpf_module_license(self.module),
Expand Down
3 changes: 2 additions & 1 deletion src/lua/bcc/libbcc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);

int bpf_prog_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns, int insn_len,
int bpf_prog_load(enum bpf_prog_type prog_type, const char *name,
const struct bpf_insn *insns, int insn_len,
const char *license, unsigned kern_version, char *log_buf, unsigned log_buf_size);
int bpf_attach_socket(int sockfd, int progfd);

Expand Down
1 change: 1 addition & 0 deletions src/python/bcc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ def load_func(self, func_name, prog_type):
while True:
log_buf = ct.create_string_buffer(buffer_len) if self.debug else None
fd = lib.bpf_prog_load(prog_type,
func_name.encode("ascii"),
lib.bpf_function_start(self.module, func_name.encode("ascii")),
lib.bpf_function_size(self.module, func_name.encode("ascii")),
lib.bpf_module_license(self.module),
Expand Down
4 changes: 2 additions & 2 deletions src/python/bcc/libbcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@
lib.bpf_attach_socket.restype = ct.c_int
lib.bpf_attach_socket.argtypes = [ct.c_int, ct.c_int]
lib.bpf_prog_load.restype = ct.c_int
lib.bpf_prog_load.argtypes = [ct.c_int, ct.c_void_p, ct.c_size_t,
ct.c_char_p, ct.c_uint, ct.c_char_p, ct.c_uint]
lib.bpf_prog_load.argtypes = [ct.c_int, ct.c_char_p, ct.c_void_p,
ct.c_size_t, ct.c_char_p, ct.c_uint, ct.c_char_p, ct.c_uint]
lib.bpf_attach_kprobe.restype = ct.c_void_p
_CB_TYPE = ct.CFUNCTYPE(None, ct.py_object, ct.c_int,
ct.c_ulonglong, ct.POINTER(ct.c_ulonglong))
Expand Down

0 comments on commit df36816

Please sign in to comment.