Commit de11d07d authored by Huapeng Zhou's avatar Huapeng Zhou

add support for bpf map flags

parent 3ce6d839
...@@ -146,6 +146,18 @@ size_t bpf_table_max_entries_id(void *program, size_t id) { ...@@ -146,6 +146,18 @@ size_t bpf_table_max_entries_id(void *program, size_t id) {
return mod->table_max_entries(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) { const char * bpf_table_name(void *program, size_t id) {
auto mod = static_cast<ebpf::BPFModule *>(program); auto mod = static_cast<ebpf::BPFModule *>(program);
if (!mod) return nullptr; if (!mod) return nullptr;
......
...@@ -44,6 +44,8 @@ int bpf_table_type(void *program, const char *table_name); ...@@ -44,6 +44,8 @@ int bpf_table_type(void *program, const char *table_name);
int bpf_table_type_id(void *program, size_t id); 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(void *program, const char *table_name);
size_t bpf_table_max_entries_id(void *program, size_t id); 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_name(void *program, size_t id);
const char * bpf_table_key_desc(void *program, const char *table_name); const char * bpf_table_key_desc(void *program, const char *table_name);
const char * bpf_table_key_desc_id(void *program, size_t id); const char * bpf_table_key_desc_id(void *program, size_t id);
......
...@@ -542,6 +542,15 @@ size_t BPFModule::table_max_entries(size_t id) const { ...@@ -542,6 +542,15 @@ size_t BPFModule::table_max_entries(size_t id) const {
return (*tables_)[id].max_entries; 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 { const char * BPFModule::table_name(size_t id) const {
if (id >= tables_->size()) return nullptr; if (id >= tables_->size()) return nullptr;
return (*tables_)[id].name.c_str(); return (*tables_)[id].name.c_str();
......
...@@ -72,6 +72,8 @@ class BPFModule { ...@@ -72,6 +72,8 @@ class BPFModule {
int table_type(size_t id) const; int table_type(size_t id) const;
size_t table_max_entries(const std::string &name) const; size_t table_max_entries(const std::string &name) const;
size_t table_max_entries(size_t id) 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(size_t id) const;
const char * table_key_desc(const std::string &name) const; const char * table_key_desc(const std::string &name) const;
size_t table_key_size(size_t id) const; size_t table_key_size(size_t id) const;
......
...@@ -38,7 +38,7 @@ R"********( ...@@ -38,7 +38,7 @@ R"********(
#define SEC(NAME) __attribute__((section(NAME), used)) #define SEC(NAME) __attribute__((section(NAME), used))
// Changes to the macro require changes in BFrontendAction classes // 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 { \ struct _name##_table_t { \
_key_type key; \ _key_type key; \
_leaf_type leaf; \ _leaf_type leaf; \
...@@ -50,9 +50,13 @@ struct _name##_table_t { \ ...@@ -50,9 +50,13 @@ struct _name##_table_t { \
void (*increment) (_key_type); \ void (*increment) (_key_type); \
int (*get_stackid) (void *, u64); \ int (*get_stackid) (void *, u64); \
_leaf_type data[_max_entries]; \ _leaf_type data[_max_entries]; \
int flags; \
}; \ }; \
__attribute__((section("maps/" _table_type))) \ __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 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) \ #define BPF_TABLE_PUBLIC(_table_type, _key_type, _leaf_type, _name, _max_entries) \
......
...@@ -1100,7 +1100,7 @@ StatusTuple CodegenLLVM::visit_table_decl_stmt_node(TableDeclStmtNode *n) { ...@@ -1100,7 +1100,7 @@ StatusTuple CodegenLLVM::visit_table_decl_stmt_node(TableDeclStmtNode *n) {
decl_gvar->setSection("maps"); decl_gvar->setSection("maps");
tables_[n] = decl_gvar; 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) if (map_fd >= 0)
table_fds_[n] = map_fd; table_fds_[n] = map_fd;
} else { } else {
...@@ -1244,6 +1244,7 @@ StatusTuple CodegenLLVM::visit(Node* root, vector<TableDesc> &tables) { ...@@ -1244,6 +1244,7 @@ StatusTuple CodegenLLVM::visit(Node* root, vector<TableDesc> &tables) {
table.first->key_type_->bit_width_ >> 3, table.first->key_type_->bit_width_ >> 3,
table.first->leaf_type_->bit_width_ >> 3, table.first->leaf_type_->bit_width_ >> 3,
table.first->size_, table.first->size_,
0,
"", "", "", "",
}); });
} }
......
...@@ -599,13 +599,6 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) { ...@@ -599,13 +599,6 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
} }
const RecordDecl *RD = R->getDecl()->getDefinition(); 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 = {}; TableDesc table = {};
table.name = Decl->getName(); table.name = Decl->getName();
...@@ -630,9 +623,18 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) { ...@@ -630,9 +623,18 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
visitor.TraverseType(F->getType()); visitor.TraverseType(F->getType());
} else if (F->getName() == "data") { } else if (F->getName() == "data") {
table.max_entries = sz / table.leaf_size; 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; ++i;
} }
bool is_extern = false; bool is_extern = false;
bpf_map_type map_type = BPF_MAP_TYPE_UNSPEC; bpf_map_type map_type = BPF_MAP_TYPE_UNSPEC;
if (A->getName() == "maps/hash") { if (A->getName() == "maps/hash") {
...@@ -695,7 +697,7 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) { ...@@ -695,7 +697,7 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
} }
table.type = map_type; 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) { if (table.fd < 0) {
error(Decl->getLocStart(), "could not open bpf map: %0\nis %1 map type enabled in your kernel?") << error(Decl->getLocStart(), "could not open bpf map: %0\nis %1 map type enabled in your kernel?") <<
......
...@@ -30,11 +30,6 @@ namespace ebpf { ...@@ -30,11 +30,6 @@ namespace ebpf {
struct TableDesc; struct TableDesc;
namespace cc {
class Parser;
class CodegenLLVM;
}
class ClangLoader { class ClangLoader {
public: public:
explicit ClangLoader(llvm::LLVMContext *ctx, unsigned flags); explicit ClangLoader(llvm::LLVMContext *ctx, unsigned flags);
......
...@@ -68,7 +68,7 @@ static __u64 ptr_to_u64(void *ptr) ...@@ -68,7 +68,7 @@ static __u64 ptr_to_u64(void *ptr)
return (__u64) (unsigned long) 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; union bpf_attr attr;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
...@@ -76,6 +76,7 @@ int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int ...@@ -76,6 +76,7 @@ int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int
attr.key_size = key_size; attr.key_size = key_size;
attr.value_size = value_size; attr.value_size = value_size;
attr.max_entries = max_entries; attr.max_entries = max_entries;
attr.map_flags = map_flags;
int ret = syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr)); int ret = syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
if (ret < 0 && errno == EPERM) { if (ret < 0 && errno == EPERM) {
...@@ -171,7 +172,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type, ...@@ -171,7 +172,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
} }
ret = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); ret = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
if (ret < 0 && errno == EPERM) { if (ret < 0 && errno == EPERM) {
// When EPERM is returned, two reasons are possible: // When EPERM is returned, two reasons are possible:
// 1. user has no permissions for bpf() // 1. user has no permissions for bpf()
...@@ -221,7 +222,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type, ...@@ -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); fprintf(stderr, "bpf: %s\n%s\n", strerror(errno), bpf_log_buffer);
free(bpf_log_buffer); free(bpf_log_buffer);
} }
return ret; return ret;
} }
......
...@@ -25,7 +25,7 @@ extern "C" { ...@@ -25,7 +25,7 @@ extern "C" {
#endif #endif
int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, 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_update_elem(int fd, void *key, void *value, unsigned long long flags);
int bpf_lookup_elem(int fd, void *key, void *value); int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key); int bpf_delete_elem(int fd, void *key);
......
...@@ -32,6 +32,7 @@ struct TableDesc { ...@@ -32,6 +32,7 @@ struct TableDesc {
size_t key_size; // sizes are in bytes size_t key_size; // sizes are in bytes
size_t leaf_size; size_t leaf_size;
size_t max_entries; size_t max_entries;
int flags;
std::string key_desc; std::string key_desc;
std::string leaf_desc; std::string leaf_desc;
llvm::Function *key_sscanf; llvm::Function *key_sscanf;
......
...@@ -24,7 +24,7 @@ enum bpf_prog_type { ...@@ -24,7 +24,7 @@ enum bpf_prog_type {
BPF_PROG_TYPE_SCHED_ACT, 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_update_elem(int fd, void *key, void *value, unsigned long long flags);
int bpf_lookup_elem(int fd, void *key, void *value); int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key); int bpf_delete_elem(int fd, void *key);
...@@ -72,6 +72,8 @@ int bpf_table_type(void *program, const char *table_name); ...@@ -72,6 +72,8 @@ int bpf_table_type(void *program, const char *table_name);
int bpf_table_type_id(void *program, size_t id); 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(void *program, const char *table_name);
size_t bpf_table_max_entries_id(void *program, size_t id); 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_name(void *program, size_t id);
const char * bpf_table_key_desc(void *program, const char *table_name); const char * bpf_table_key_desc(void *program, const char *table_name);
const char * bpf_table_key_desc_id(void *program, size_t id); const char * bpf_table_key_desc_id(void *program, size_t id);
......
...@@ -47,6 +47,8 @@ lib.bpf_table_type_id.restype = ct.c_int ...@@ -47,6 +47,8 @@ lib.bpf_table_type_id.restype = ct.c_int
lib.bpf_table_type_id.argtypes = [ct.c_void_p, ct.c_ulonglong] 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.restype = ct.c_ulonglong
lib.bpf_table_max_entries_id.argtypes = [ct.c_void_p, 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.restype = ct.c_char_p
lib.bpf_table_key_desc.argtypes = [ct.c_void_p, 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 lib.bpf_table_leaf_desc.restype = ct.c_char_p
......
...@@ -118,6 +118,7 @@ class TableBase(MutableMapping): ...@@ -118,6 +118,7 @@ class TableBase(MutableMapping):
self.Key = keytype self.Key = keytype
self.Leaf = leaftype self.Leaf = leaftype
self.ttype = lib.bpf_table_type_id(self.bpf.module, self.map_id) 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 = {} self._cbs = {}
def key_sprintf(self, key): def key_sprintf(self, key):
......
#!/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()
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