[go: up one dir, main page]

Skip to content

Commit

Permalink
Merge pull request iovisor#843 from shodoco/flag
Browse files Browse the repository at this point in the history
add support for bpf map flags
  • Loading branch information
4ast authored Dec 9, 2016
2 parents bb316bc + de11d07 commit a3ddcd5
Show file tree
Hide file tree
Showing 15 changed files with 81 additions and 21 deletions.
12 changes: 12 additions & 0 deletions src/cc/bpf_common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,18 @@ size_t bpf_table_max_entries_id(void *program, size_t id) {
return mod->table_max_entries(id);
}

int bpf_table_flags(void *program, const char *table_name) {
auto mod = static_cast<ebpf::BPFModule *>(program);
if (!mod) return -1;
return mod->table_flags(table_name);
}

int bpf_table_flags_id(void *program, size_t id) {
auto mod = static_cast<ebpf::BPFModule *>(program);
if (!mod) return -1;
return mod->table_flags(id);
}

const char * bpf_table_name(void *program, size_t id) {
auto mod = static_cast<ebpf::BPFModule *>(program);
if (!mod) return nullptr;
Expand Down
2 changes: 2 additions & 0 deletions src/cc/bpf_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ int bpf_table_type(void *program, const char *table_name);
int bpf_table_type_id(void *program, size_t id);
size_t bpf_table_max_entries(void *program, const char *table_name);
size_t bpf_table_max_entries_id(void *program, size_t id);
int bpf_table_flags(void *program, const char *table_name);
int bpf_table_flags_id(void *program, size_t id);
const char * bpf_table_name(void *program, size_t id);
const char * bpf_table_key_desc(void *program, const char *table_name);
const char * bpf_table_key_desc_id(void *program, size_t id);
Expand Down
9 changes: 9 additions & 0 deletions src/cc/bpf_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,15 @@ size_t BPFModule::table_max_entries(size_t id) const {
return (*tables_)[id].max_entries;
}

int BPFModule::table_flags(const string &name) const {
return table_flags(table_id(name));
}

int BPFModule::table_flags(size_t id) const {
if (id >= tables_->size()) return -1;
return (*tables_)[id].flags;
}

const char * BPFModule::table_name(size_t id) const {
if (id >= tables_->size()) return nullptr;
return (*tables_)[id].name.c_str();
Expand Down
2 changes: 2 additions & 0 deletions src/cc/bpf_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ class BPFModule {
int table_type(size_t id) const;
size_t table_max_entries(const std::string &name) const;
size_t table_max_entries(size_t id) const;
int table_flags(const std::string &name) const;
int table_flags(size_t id) const;
const char * table_key_desc(size_t id) const;
const char * table_key_desc(const std::string &name) const;
size_t table_key_size(size_t id) const;
Expand Down
8 changes: 6 additions & 2 deletions src/cc/export/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ R"********(
#define SEC(NAME) __attribute__((section(NAME), used))

// Changes to the macro require changes in BFrontendAction classes
#define BPF_TABLE(_table_type, _key_type, _leaf_type, _name, _max_entries) \
#define BPF_F_TABLE(_table_type, _key_type, _leaf_type, _name, _max_entries, _flags) \
struct _name##_table_t { \
_key_type key; \
_leaf_type leaf; \
Expand All @@ -50,9 +50,13 @@ struct _name##_table_t { \
void (*increment) (_key_type); \
int (*get_stackid) (void *, u64); \
_leaf_type data[_max_entries]; \
int flags; \
}; \
__attribute__((section("maps/" _table_type))) \
struct _name##_table_t _name
struct _name##_table_t _name = { .flags = (_flags) }

#define BPF_TABLE(_table_type, _key_type, _leaf_type, _name, _max_entries) \
BPF_F_TABLE(_table_type, _key_type, _leaf_type, _name, _max_entries, 0);

// define a table same as above but allow it to be referenced by other modules
#define BPF_TABLE_PUBLIC(_table_type, _key_type, _leaf_type, _name, _max_entries) \
Expand Down
3 changes: 2 additions & 1 deletion src/cc/frontends/b/codegen_llvm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1100,7 +1100,7 @@ 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_);
int map_fd = bpf_create_map(map_type, key->bit_width_ / 8, leaf->bit_width_ / 8, n->size_, 0);
if (map_fd >= 0)
table_fds_[n] = map_fd;
} else {
Expand Down Expand Up @@ -1244,6 +1244,7 @@ StatusTuple CodegenLLVM::visit(Node* root, vector<TableDesc> &tables) {
table.first->key_type_->bit_width_ >> 3,
table.first->leaf_type_->bit_width_ >> 3,
table.first->size_,
0,
"", "",
});
}
Expand Down
18 changes: 10 additions & 8 deletions src/cc/frontends/clang/b_frontend_action.cc
Original file line number Diff line number Diff line change
Expand Up @@ -599,13 +599,6 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
}
const RecordDecl *RD = R->getDecl()->getDefinition();

int major = 0, minor = 0;
struct utsname un;
if (uname(&un) == 0) {
// release format: <major>.<minor>.<revision>[-<othertag>]
sscanf(un.release, "%d.%d.", &major, &minor);
}

TableDesc table = {};
table.name = Decl->getName();

Expand All @@ -630,9 +623,18 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
visitor.TraverseType(F->getType());
} else if (F->getName() == "data") {
table.max_entries = sz / table.leaf_size;
} else if (F->getName() == "flags") {
unsigned idx = F->getFieldIndex();
if (auto I = dyn_cast_or_null<InitListExpr>(Decl->getInit())) {
llvm::APSInt res;
if (I->getInit(idx)->EvaluateAsInt(res, C)) {
table.flags = res.getExtValue();
}
}
}
++i;
}

bool is_extern = false;
bpf_map_type map_type = BPF_MAP_TYPE_UNSPEC;
if (A->getName() == "maps/hash") {
Expand Down Expand Up @@ -695,7 +697,7 @@ 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.fd = bpf_create_map(map_type, 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
5 changes: 0 additions & 5 deletions src/cc/frontends/clang/loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@ namespace ebpf {

struct TableDesc;

namespace cc {
class Parser;
class CodegenLLVM;
}

class ClangLoader {
public:
explicit ClangLoader(llvm::LLVMContext *ctx, unsigned flags);
Expand Down
7 changes: 4 additions & 3 deletions src/cc/libbpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,15 @@ static __u64 ptr_to_u64(void *ptr)
return (__u64) (unsigned long) ptr;
}

int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int max_entries)
int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int max_entries, int map_flags)
{
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;

int ret = syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
if (ret < 0 && errno == EPERM) {
Expand Down Expand Up @@ -171,7 +172,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
}

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 Expand Up @@ -221,7 +222,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type,

fprintf(stderr, "bpf: %s\n%s\n", strerror(errno), bpf_log_buffer);

free(bpf_log_buffer);
free(bpf_log_buffer);
}
return ret;
}
Expand Down
2 changes: 1 addition & 1 deletion src/cc/libbpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ extern "C" {
#endif

int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
int max_entries);
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);
Expand Down
1 change: 1 addition & 0 deletions src/cc/table_desc.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct TableDesc {
size_t key_size; // sizes are in bytes
size_t leaf_size;
size_t max_entries;
int flags;
std::string key_desc;
std::string leaf_desc;
llvm::Function *key_sscanf;
Expand Down
4 changes: 3 additions & 1 deletion src/lua/bcc/libbcc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ enum bpf_prog_type {
BPF_PROG_TYPE_SCHED_ACT,
};

int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int max_entries);
int bpf_create_map(enum bpf_map_type map_type, 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);
Expand Down Expand Up @@ -72,6 +72,8 @@ int bpf_table_type(void *program, const char *table_name);
int bpf_table_type_id(void *program, size_t id);
size_t bpf_table_max_entries(void *program, const char *table_name);
size_t bpf_table_max_entries_id(void *program, size_t id);
int bpf_table_flags(void *program, const char *table_name);
int bpf_table_flags_id(void *program, size_t id);
const char * bpf_table_name(void *program, size_t id);
const char * bpf_table_key_desc(void *program, const char *table_name);
const char * bpf_table_key_desc_id(void *program, size_t id);
Expand Down
2 changes: 2 additions & 0 deletions src/python/bcc/libbcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
lib.bpf_table_type_id.argtypes = [ct.c_void_p, ct.c_ulonglong]
lib.bpf_table_max_entries_id.restype = ct.c_ulonglong
lib.bpf_table_max_entries_id.argtypes = [ct.c_void_p, ct.c_ulonglong]
lib.bpf_table_flags_id.restype = ct.c_int
lib.bpf_table_flags_id.argtypes = [ct.c_void_p, ct.c_ulonglong]
lib.bpf_table_key_desc.restype = ct.c_char_p
lib.bpf_table_key_desc.argtypes = [ct.c_void_p, ct.c_char_p]
lib.bpf_table_leaf_desc.restype = ct.c_char_p
Expand Down
1 change: 1 addition & 0 deletions src/python/bcc/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ def __init__(self, bpf, map_id, map_fd, keytype, leaftype):
self.Key = keytype
self.Leaf = leaftype
self.ttype = lib.bpf_table_type_id(self.bpf.module, self.map_id)
self.flags = lib.bpf_table_flags_id(self.bpf.module, self.map_id)
self._cbs = {}

def key_sprintf(self, key):
Expand Down
26 changes: 26 additions & 0 deletions tests/python/test_flags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env python
# Copyright (c) PLUMgrid, Inc.
# Licensed under the Apache License, Version 2.0 (the "License")

import unittest
from bcc import BPF

class TestLru(unittest.TestCase):
def test_lru_map_flags(self):
test_prog1 = """
BPF_F_TABLE("lru_hash", int, u64, lru, 1024, BPF_F_NO_COMMON_LRU);
"""
b = BPF(text=test_prog1)
t = b["lru"]
self.assertEqual(t.flags, 2);

def test_hash_map_flags(self):
test_prog1 = """
BPF_F_TABLE("hash", int, u64, hash, 1024, BPF_F_NO_PREALLOC);
"""
b = BPF(text=test_prog1)
t = b["hash"]
self.assertEqual(t.flags, 1);

if __name__ == "__main__":
unittest.main()

0 comments on commit a3ddcd5

Please sign in to comment.