From: Huapeng Zhou Date: Wed, 7 Dec 2016 02:10:38 +0000 (-0800) Subject: add support for bpf map flags X-Git-Tag: v0.3.0~108^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=de11d07d0a25ac5b94745b2bea61e1b0098517dc;p=platform%2Fupstream%2Fbcc.git add support for bpf map flags --- diff --git a/src/cc/bpf_common.cc b/src/cc/bpf_common.cc index 15f5602..4a71197 100644 --- a/src/cc/bpf_common.cc +++ b/src/cc/bpf_common.cc @@ -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(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(program); + if (!mod) return -1; + return mod->table_flags(id); +} + const char * bpf_table_name(void *program, size_t id) { auto mod = static_cast(program); if (!mod) return nullptr; diff --git a/src/cc/bpf_common.h b/src/cc/bpf_common.h index 2b3ea54..0abdbd4 100644 --- a/src/cc/bpf_common.h +++ b/src/cc/bpf_common.h @@ -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); diff --git a/src/cc/bpf_module.cc b/src/cc/bpf_module.cc index d9700b3..be0a524 100644 --- a/src/cc/bpf_module.cc +++ b/src/cc/bpf_module.cc @@ -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(); diff --git a/src/cc/bpf_module.h b/src/cc/bpf_module.h index 86fbdcf..aca8633 100644 --- a/src/cc/bpf_module.h +++ b/src/cc/bpf_module.h @@ -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; diff --git a/src/cc/export/helpers.h b/src/cc/export/helpers.h index 6530dd3..c140851 100644 --- a/src/cc/export/helpers.h +++ b/src/cc/export/helpers.h @@ -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) \ diff --git a/src/cc/frontends/b/codegen_llvm.cc b/src/cc/frontends/b/codegen_llvm.cc index 3b4f36b..410bfd6 100644 --- a/src/cc/frontends/b/codegen_llvm.cc +++ b/src/cc/frontends/b/codegen_llvm.cc @@ -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 &tables) { table.first->key_type_->bit_width_ >> 3, table.first->leaf_type_->bit_width_ >> 3, table.first->size_, + 0, "", "", }); } diff --git a/src/cc/frontends/clang/b_frontend_action.cc b/src/cc/frontends/clang/b_frontend_action.cc index 57d8454..9370386 100644 --- a/src/cc/frontends/clang/b_frontend_action.cc +++ b/src/cc/frontends/clang/b_frontend_action.cc @@ -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: ..[-] - 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(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?") << diff --git a/src/cc/frontends/clang/loader.h b/src/cc/frontends/clang/loader.h index 67b9969..5e7c490 100644 --- a/src/cc/frontends/clang/loader.h +++ b/src/cc/frontends/clang/loader.h @@ -30,11 +30,6 @@ namespace ebpf { struct TableDesc; -namespace cc { -class Parser; -class CodegenLLVM; -} - class ClangLoader { public: explicit ClangLoader(llvm::LLVMContext *ctx, unsigned flags); diff --git a/src/cc/libbpf.c b/src/cc/libbpf.c index 6df35d2..24967b9 100644 --- a/src/cc/libbpf.c +++ b/src/cc/libbpf.c @@ -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; } diff --git a/src/cc/libbpf.h b/src/cc/libbpf.h index f55fa33..cc4e0f3 100644 --- a/src/cc/libbpf.h +++ b/src/cc/libbpf.h @@ -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); diff --git a/src/cc/table_desc.h b/src/cc/table_desc.h index 2161c09..a5196e2 100644 --- a/src/cc/table_desc.h +++ b/src/cc/table_desc.h @@ -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; diff --git a/src/lua/bcc/libbcc.lua b/src/lua/bcc/libbcc.lua index db356a8..2628445 100644 --- a/src/lua/bcc/libbcc.lua +++ b/src/lua/bcc/libbcc.lua @@ -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); diff --git a/src/python/bcc/libbcc.py b/src/python/bcc/libbcc.py index 04563c1..f03a1b7 100644 --- a/src/python/bcc/libbcc.py +++ b/src/python/bcc/libbcc.py @@ -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 diff --git a/src/python/bcc/table.py b/src/python/bcc/table.py index 49bf2a2..516cfa1 100644 --- a/src/python/bcc/table.py +++ b/src/python/bcc/table.py @@ -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): diff --git a/tests/python/test_flags.py b/tests/python/test_flags.py new file mode 100644 index 0000000..a5d2b42 --- /dev/null +++ b/tests/python/test_flags.py @@ -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()