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) {
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;
......
......@@ -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);
......
......@@ -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();
......
......@@ -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;
......
......@@ -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; \
......@@ -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) \
......
......@@ -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 {
......@@ -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,
"", "",
});
}
......
......@@ -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();
......@@ -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") {
......@@ -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?") <<
......
......@@ -30,11 +30,6 @@ namespace ebpf {
struct TableDesc;
namespace cc {
class Parser;
class CodegenLLVM;
}
class ClangLoader {
public:
explicit ClangLoader(llvm::LLVMContext *ctx, unsigned flags);
......
......@@ -68,7 +68,7 @@ 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));
......@@ -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.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) {
......@@ -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()
......@@ -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;
}
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......@@ -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);
......
......@@ -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_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
......
......@@ -118,6 +118,7 @@ class TableBase(MutableMapping):
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):
......
#!/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