Commit df36816a authored by Martin KaFai Lau's avatar Martin KaFai Lau

bpf: Add support for prog_name and map_name

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: default avatarMartin KaFai Lau <kafai@fb.com>
parent 3aa8bf4c
......@@ -480,7 +480,8 @@ 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
......
......@@ -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 {
......
......@@ -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?") <<
......
......@@ -73,6 +73,8 @@
#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)
......@@ -80,8 +82,11 @@ 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;
......@@ -89,8 +94,15 @@ int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int
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
......@@ -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;
......@@ -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)
......@@ -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()
......
......@@ -29,15 +29,16 @@ 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,
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);
......
......@@ -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),
......
......@@ -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);
......
......@@ -324,6 +324,7 @@ class BPF(object):
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),
......
......@@ -83,8 +83,8 @@ lib.bpf_open_raw_sock.argtypes = [ct.c_char_p]
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))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment