From f8ee5bf0e4dd424d2b6b55b8b4334a26a4186472 Mon Sep 17 00:00:00 2001 From: Brenden Blanco Date: Wed, 12 Aug 2015 08:55:09 -0700 Subject: [PATCH 1/2] Add sscanf C api for parsing key/leaf ascii to binary Expose an individual API of the what is done in table_update, that lets the caller use the module to parse keys for it. Signed-off-by: Brenden Blanco --- src/cc/bpf_common.cc | 11 +++++++++++ src/cc/bpf_common.h | 4 ++-- src/cc/bpf_module.cc | 36 ++++++++++++++++++++++++++++++++++++ src/cc/bpf_module.h | 2 ++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/cc/bpf_common.cc b/src/cc/bpf_common.cc index 212e1efe7a5c..19f6eb189d94 100644 --- a/src/cc/bpf_common.cc +++ b/src/cc/bpf_common.cc @@ -193,4 +193,15 @@ int bpf_table_leaf_snprintf(void *program, size_t id, char *buf, size_t buflen, return mod->table_key_printf(id, buf, buflen, leaf); } +int bpf_table_key_sscanf(void *program, size_t id, const char *buf, void *key) { + auto mod = static_cast(program); + if (!mod) return 0; + return mod->table_key_scanf(id, buf, key); +} +int bpf_table_leaf_sscanf(void *program, size_t id, const char *buf, void *leaf) { + auto mod = static_cast(program); + if (!mod) return 0; + return mod->table_key_scanf(id, buf, leaf); +} + } diff --git a/src/cc/bpf_common.h b/src/cc/bpf_common.h index c483f38c9dd5..f79103651ea8 100644 --- a/src/cc/bpf_common.h +++ b/src/cc/bpf_common.h @@ -50,8 +50,8 @@ size_t bpf_table_leaf_size(void *program, const char *table_name); size_t bpf_table_leaf_size_id(void *program, size_t id); int bpf_table_key_snprintf(void *program, size_t id, char *buf, size_t buflen, const void *key); int bpf_table_leaf_snprintf(void *program, size_t id, char *buf, size_t buflen, const void *leaf); -//int bpf_table_key_sscanf(void *program, size_t id, const char *buf, void *key); -//int bpf_table_leaf_sscanf(void *program, size_t id, const char *buf, void *leaf); +int bpf_table_key_sscanf(void *program, size_t id, const char *buf, void *key); +int bpf_table_leaf_sscanf(void *program, size_t id, const char *buf, void *leaf); int bpf_table_update(void *program, const char *table_name, const char *key, const char *leaf); int bpf_table_update_id(void *program, size_t id, const char *key, const char *leaf); diff --git a/src/cc/bpf_module.cc b/src/cc/bpf_module.cc index 0b6e02cb371f..fa237c0e58b8 100644 --- a/src/cc/bpf_module.cc +++ b/src/cc/bpf_module.cc @@ -627,6 +627,42 @@ int BPFModule::table_leaf_printf(size_t id, char *buf, size_t buflen, const void return 0; } +int BPFModule::table_key_scanf(size_t id, const char *key_str, void *key) { + if (id >= tables_->size()) return -1; + + const TableDesc &desc = (*tables_)[id]; + if (desc.fd < 0) return -1; + + if (!rw_engine_ || !desc.key_reader) { + fprintf(stderr, "Table sscanf not available\n"); + return -1; + } + + vector args({GenericValue(), GenericValue((void *)key_str), GenericValue(key)}); + GenericValue rc = rw_engine_->runFunction(desc.key_reader, args); + if (rc.IntVal != 0) + return -1; + return 0; +} + +int BPFModule::table_leaf_scanf(size_t id, const char *leaf_str, void *leaf) { + if (id >= tables_->size()) return -1; + + const TableDesc &desc = (*tables_)[id]; + if (desc.fd < 0) return -1; + + if (!rw_engine_ || !desc.leaf_reader) { + fprintf(stderr, "Table sscanf not available\n"); + return -1; + } + + vector args({GenericValue(), GenericValue((void *)leaf_str), GenericValue(leaf)}); + GenericValue rc = rw_engine_->runFunction(desc.leaf_reader, args); + if (rc.IntVal != 0) + return -1; + return 0; +} + // load a B file, which comes in two parts int BPFModule::load_b(const string &filename, const string &proto_filename) { if (!sections_.empty()) { diff --git a/src/cc/bpf_module.h b/src/cc/bpf_module.h index 6b11ea03121d..ef5c2e458707 100644 --- a/src/cc/bpf_module.h +++ b/src/cc/bpf_module.h @@ -72,11 +72,13 @@ class BPFModule { size_t table_key_size(size_t id) const; size_t table_key_size(const std::string &name) const; int table_key_printf(size_t id, char *buf, size_t buflen, const void *key); + int table_key_scanf(size_t id, const char *buf, void *key); const char * table_leaf_desc(size_t id) const; const char * table_leaf_desc(const std::string &name) const; size_t table_leaf_size(size_t id) const; size_t table_leaf_size(const std::string &name) const; int table_leaf_printf(size_t id, char *buf, size_t buflen, const void *leaf); + int table_leaf_scanf(size_t id, const char *buf, void *leaf); int table_update(size_t id, const char *key, const char *leaf); int table_update(const std::string &name, const char *key, const char *leaf); char * license() const; From 2582ecfc190b169d4a4a70ea4f3e374c2f7492eb Mon Sep 17 00:00:00 2001 From: Brenden Blanco Date: Wed, 12 Aug 2015 12:08:00 -0700 Subject: [PATCH 2/2] Add testing for scanf/printf in python, deprecate table_update Signed-off-by: Brenden Blanco --- src/cc/bpf_common.cc | 30 +++--- src/cc/bpf_common.h | 3 +- src/cc/bpf_module.cc | 190 +++++++++++++++---------------------- src/cc/bpf_module.h | 3 +- src/cc/table_desc.h | 8 +- src/python/bpf/__init__.py | 64 +++++++++++-- tests/cc/test_clang.py | 6 +- 7 files changed, 153 insertions(+), 151 deletions(-) diff --git a/src/cc/bpf_common.cc b/src/cc/bpf_common.cc index 19f6eb189d94..6c779a189f85 100644 --- a/src/cc/bpf_common.cc +++ b/src/cc/bpf_common.cc @@ -104,6 +104,12 @@ size_t bpf_num_tables(void *program) { return mod->num_tables(); } +size_t bpf_table_id(void *program, const char *table_name) { + auto mod = static_cast(program); + if (!mod) return ~0ull; + return mod->table_id(table_name); +} + int bpf_table_fd(void *program, const char *table_name) { auto mod = static_cast(program); if (!mod) return -1; @@ -170,38 +176,26 @@ size_t bpf_table_leaf_size_id(void *program, size_t id) { return mod->table_leaf_size(id); } -int bpf_table_update(void *program, const char *table_name, const char *key, const char *leaf) { - auto mod = static_cast(program); - if (!mod) return 0; - return mod->table_update(table_name, key, leaf); -} - -int bpf_table_update_id(void *program, size_t id, const char *key, const char *leaf) { - auto mod = static_cast(program); - if (!mod) return 0; - return mod->table_update(id, key, leaf); -} - int bpf_table_key_snprintf(void *program, size_t id, char *buf, size_t buflen, const void *key) { auto mod = static_cast(program); - if (!mod) return 0; + if (!mod) return -1; return mod->table_key_printf(id, buf, buflen, key); } int bpf_table_leaf_snprintf(void *program, size_t id, char *buf, size_t buflen, const void *leaf) { auto mod = static_cast(program); - if (!mod) return 0; - return mod->table_key_printf(id, buf, buflen, leaf); + if (!mod) return -1; + return mod->table_leaf_printf(id, buf, buflen, leaf); } int bpf_table_key_sscanf(void *program, size_t id, const char *buf, void *key) { auto mod = static_cast(program); - if (!mod) return 0; + if (!mod) return -1; return mod->table_key_scanf(id, buf, key); } int bpf_table_leaf_sscanf(void *program, size_t id, const char *buf, void *leaf) { auto mod = static_cast(program); - if (!mod) return 0; - return mod->table_key_scanf(id, buf, leaf); + if (!mod) return -1; + return mod->table_leaf_scanf(id, buf, leaf); } } diff --git a/src/cc/bpf_common.h b/src/cc/bpf_common.h index f79103651ea8..48adf0b4c3f9 100644 --- a/src/cc/bpf_common.h +++ b/src/cc/bpf_common.h @@ -37,6 +37,7 @@ void * bpf_function_start(void *program, const char *name); size_t bpf_function_size_id(void *program, size_t id); size_t bpf_function_size(void *program, const char *name); size_t bpf_num_tables(void *program); +size_t bpf_table_id(void *program, const char *table_name); int bpf_table_fd(void *program, const char *table_name); int bpf_table_fd_id(void *program, size_t id); const char * bpf_table_name(void *program, size_t id); @@ -52,8 +53,6 @@ int bpf_table_key_snprintf(void *program, size_t id, char *buf, size_t buflen, c int bpf_table_leaf_snprintf(void *program, size_t id, char *buf, size_t buflen, const void *leaf); int bpf_table_key_sscanf(void *program, size_t id, const char *buf, void *key); int bpf_table_leaf_sscanf(void *program, size_t id, const char *buf, void *leaf); -int bpf_table_update(void *program, const char *table_name, const char *key, const char *leaf); -int bpf_table_update_id(void *program, size_t id, const char *key, const char *leaf); #ifdef __cplusplus } diff --git a/src/cc/bpf_module.cc b/src/cc/bpf_module.cc index fa237c0e58b8..3b2b6e326557 100644 --- a/src/cc/bpf_module.cc +++ b/src/cc/bpf_module.cc @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -64,6 +63,9 @@ using std::unique_ptr; using std::vector; using namespace llvm; +typedef int (* sscanf_fn) (const char *, void *); +typedef int (* snprintf_fn) (char *, size_t, const void *); + const string BPFModule::FN_PREFIX = BPF_FN_PREFIX; // Snooping class to remember the sections as the JIT creates them @@ -147,9 +149,9 @@ static void parse_type(IRBuilder<> &B, vector *args, string *fmt, else if (it->getBitWidth() <= 16) *fmt += "%h"; else if (it->getBitWidth() <= 32) - *fmt += "%l"; + *fmt += "%"; else - *fmt += "%ll"; + *fmt += "%l"; if (is_writer) *fmt += "x"; else @@ -171,15 +173,11 @@ Function * BPFModule::make_reader(Module *mod, Type *type) { IRBuilder<> B(*ctx_); - // The JIT currently supports a limited number of function prototypes, use the - // int (*) (int, char **, const char **) version - vector fn_args({B.getInt32Ty(), B.getInt8PtrTy(), PointerType::getUnqual(type)}); + vector fn_args({B.getInt8PtrTy(), PointerType::getUnqual(type)}); FunctionType *fn_type = FunctionType::get(B.getInt32Ty(), fn_args, /*isVarArg=*/false); Function *fn = Function::Create(fn_type, GlobalValue::ExternalLinkage, "reader" + std::to_string(readers_.size()), mod); auto arg_it = fn->arg_begin(); - Argument *arg_argc = arg_it++; - arg_argc->setName("argc"); Argument *arg_in = arg_it++; arg_in->setName("in"); Argument *arg_out = arg_it++; @@ -197,6 +195,9 @@ Function * BPFModule::make_reader(Module *mod, Type *type) { args[1] = B.CreateInBoundsGEP(fmt_gvar, vector({B.getInt64(0), B.getInt64(0)})); + if (0) + debug_printf(mod, B, "%p %p\n", vector({arg_in, arg_out})); + vector sscanf_fn_args({B.getInt8PtrTy(), B.getInt8PtrTy()}); FunctionType *sscanf_fn_type = FunctionType::get(B.getInt32Ty(), sscanf_fn_args, /*isVarArg=*/true); Function *sscanf_fn = mod->getFunction("sscanf"); @@ -234,17 +235,15 @@ Function * BPFModule::make_writer(Module *mod, Type *type) { IRBuilder<> B(*ctx_); - // The JIT currently supports a limited number of function prototypes, use the - // int (*) (int, char **, const char **) version - vector fn_args({B.getInt32Ty(), B.getInt8PtrTy(), PointerType::getUnqual(type)}); + vector fn_args({B.getInt8PtrTy(), B.getInt64Ty(), PointerType::getUnqual(type)}); FunctionType *fn_type = FunctionType::get(B.getInt32Ty(), fn_args, /*isVarArg=*/false); Function *fn = Function::Create(fn_type, GlobalValue::ExternalLinkage, "writer" + std::to_string(writers_.size()), mod); auto arg_it = fn->arg_begin(); - Argument *arg_len = arg_it++; - arg_len->setName("len"); Argument *arg_out = arg_it++; arg_out->setName("out"); + Argument *arg_len = arg_it++; + arg_len->setName("len"); Argument *arg_in = arg_it++; arg_in->setName("in"); @@ -331,18 +330,18 @@ int BPFModule::annotate() { if (st->getNumElements() < 2) continue; Type *key_type = st->elements()[0]; Type *leaf_type = st->elements()[1]; - table.key_reader = make_reader(&*m, key_type); - if (!table.key_reader) - errs() << "Failed to compile reader for " << *key_type << "\n"; - table.leaf_reader = make_reader(&*m, leaf_type); - if (!table.leaf_reader) - errs() << "Failed to compile reader for " << *leaf_type << "\n"; - table.key_writer = make_writer(&*m, key_type); - if (!table.key_writer) - errs() << "Failed to compile writer for " << *key_type << "\n"; - table.leaf_writer = make_writer(&*m, leaf_type); - if (!table.leaf_writer) - errs() << "Failed to compile writer for " << *leaf_type << "\n"; + table.key_sscanf = make_reader(&*m, key_type); + if (!table.key_sscanf) + errs() << "Failed to compile sscanf for " << *key_type << "\n"; + table.leaf_sscanf = make_reader(&*m, leaf_type); + if (!table.leaf_sscanf) + errs() << "Failed to compile sscanf for " << *leaf_type << "\n"; + table.key_snprintf = make_writer(&*m, key_type); + if (!table.key_snprintf) + errs() << "Failed to compile snprintf for " << *key_type << "\n"; + table.leaf_snprintf = make_writer(&*m, leaf_type); + if (!table.leaf_snprintf) + errs() << "Failed to compile snprintf for " << *leaf_type << "\n"; } } } @@ -474,10 +473,14 @@ size_t BPFModule::num_tables() const { return tables_->size(); } -int BPFModule::table_fd(const string &name) const { +size_t BPFModule::table_id(const string &name) const { auto it = table_names_.find(name); - if (it == table_names_.end()) return -1; - return table_fd(it->second); + if (it == table_names_.end()) return ~0ull; + return it->second; +} + +int BPFModule::table_fd(const string &name) const { + return table_fd(table_id(name)); } int BPFModule::table_fd(size_t id) const { @@ -497,9 +500,7 @@ const char * BPFModule::table_key_desc(size_t id) const { } const char * BPFModule::table_key_desc(const string &name) const { - auto it = table_names_.find(name); - if (it == table_names_.end()) return nullptr; - return table_key_desc(it->second); + return table_key_desc(table_id(name)); } const char * BPFModule::table_leaf_desc(size_t id) const { @@ -509,18 +510,14 @@ const char * BPFModule::table_leaf_desc(size_t id) const { } const char * BPFModule::table_leaf_desc(const string &name) const { - auto it = table_names_.find(name); - if (it == table_names_.end()) return nullptr; - return table_leaf_desc(it->second); + return table_leaf_desc(table_id(name)); } size_t BPFModule::table_key_size(size_t id) const { if (id >= tables_->size()) return 0; return (*tables_)[id].key_size; } size_t BPFModule::table_key_size(const string &name) const { - auto it = table_names_.find(name); - if (it == table_names_.end()) return 0; - return table_key_size(it->second); + return table_key_size(table_id(name)); } size_t BPFModule::table_leaf_size(size_t id) const { @@ -528,42 +525,7 @@ size_t BPFModule::table_leaf_size(size_t id) const { return (*tables_)[id].leaf_size; } size_t BPFModule::table_leaf_size(const string &name) const { - auto it = table_names_.find(name); - if (it == table_names_.end()) return 0; - return table_leaf_size(it->second); -} - -int BPFModule::table_update(const string &name, const char *key_str, const char *leaf_str) { - auto it = table_names_.find(name); - if (it == table_names_.end()) return 0; - return table_update(it->second, key_str, leaf_str); -} - -int BPFModule::table_update(size_t id, const char *key_str, const char *leaf_str) { - if (id >= tables_->size()) return -1; - - const TableDesc &desc = (*tables_)[id]; - if (desc.fd < 0) return -1; - - if (!rw_engine_ || !desc.key_reader || !desc.leaf_reader) { - fprintf(stderr, "Table sscanf not available\n"); - return -1; - } - - unique_ptr key(new uint8_t[desc.key_size]); - unique_ptr leaf(new uint8_t[desc.leaf_size]); - GenericValue rc; - rc = rw_engine_->runFunction(desc.key_reader, vector({GenericValue(), - GenericValue((void *)key_str), - GenericValue((void *)key.get())})); - if (rc.IntVal != 0) - return -1; - rc = rw_engine_->runFunction(desc.leaf_reader, vector({GenericValue(), - GenericValue((void *)leaf_str), - GenericValue((void *)leaf.get())})); - if (rc.IntVal != 0) - return -1; - return bpf_update_elem(desc.fd, key.get(), leaf.get(), 0); + return table_leaf_size(table_id(name)); } struct TableIterator { @@ -576,25 +538,23 @@ struct TableIterator { }; int BPFModule::table_key_printf(size_t id, char *buf, size_t buflen, const void *key) { - if (id >= tables_->size()) { - fprintf(stderr, "table id %zu out of range\n", id); + if (id >= tables_->size()) return -1; + const TableDesc &desc = (*tables_)[id]; + if (!desc.key_snprintf) { + fprintf(stderr, "Key snprintf not available\n"); return -1; } - - const TableDesc &desc = (*tables_)[id]; - if (!desc.key_writer) { - fprintf(stderr, "table snprintf not implemented for %s key\n", desc.name.c_str()); + snprintf_fn fn = (snprintf_fn)rw_engine_->getPointerToFunction(desc.key_snprintf); + if (!fn) { + fprintf(stderr, "Key snprintf not available in JIT Engine\n"); return -1; } - GenericValue gv_buflen; - gv_buflen.IntVal = APInt(32, buflen, true); - vector args({gv_buflen, GenericValue((void *)buf), GenericValue((void *)key)}); - GenericValue rc = rw_engine_->runFunction(desc.key_writer, args); - if (rc.IntVal.isNegative()) { + int rc = (*fn)(buf, buflen, key); + if (rc < 0) { perror("snprintf"); return -1; } - if (rc.IntVal.sge(buflen)) { + if ((size_t)rc >= buflen) { fprintf(stderr, "snprintf ran out of buffer space\n"); return -1; } @@ -602,25 +562,23 @@ int BPFModule::table_key_printf(size_t id, char *buf, size_t buflen, const void } int BPFModule::table_leaf_printf(size_t id, char *buf, size_t buflen, const void *leaf) { - if (id >= tables_->size()) { - fprintf(stderr, "table id %zu out of range\n", id); + if (id >= tables_->size()) return -1; + const TableDesc &desc = (*tables_)[id]; + if (!desc.leaf_snprintf) { + fprintf(stderr, "Key snprintf not available\n"); return -1; } - - const TableDesc &desc = (*tables_)[id]; - if (!desc.leaf_writer) { - fprintf(stderr, "table snprintf not implemented for %s leaf\n", desc.name.c_str()); + snprintf_fn fn = (snprintf_fn)rw_engine_->getPointerToFunction(desc.leaf_snprintf); + if (!fn) { + fprintf(stderr, "Leaf snprintf not available in JIT Engine\n"); return -1; } - GenericValue gv_buflen; - gv_buflen.IntVal = buflen; - vector args({gv_buflen, GenericValue((void *)buf), GenericValue((void *)leaf)}); - GenericValue rc = rw_engine_->runFunction(desc.leaf_writer, args); - if (rc.IntVal.isNegative()) { + int rc = (*fn)(buf, buflen, leaf); + if (rc < 0) { perror("snprintf"); return -1; } - if (rc.IntVal.sge(buflen)) { + if ((size_t)rc >= buflen) { fprintf(stderr, "snprintf ran out of buffer space\n"); return -1; } @@ -629,37 +587,43 @@ int BPFModule::table_leaf_printf(size_t id, char *buf, size_t buflen, const void int BPFModule::table_key_scanf(size_t id, const char *key_str, void *key) { if (id >= tables_->size()) return -1; - const TableDesc &desc = (*tables_)[id]; - if (desc.fd < 0) return -1; - - if (!rw_engine_ || !desc.key_reader) { - fprintf(stderr, "Table sscanf not available\n"); + if (!desc.key_sscanf) { + fprintf(stderr, "Key sscanf not available\n"); return -1; } - vector args({GenericValue(), GenericValue((void *)key_str), GenericValue(key)}); - GenericValue rc = rw_engine_->runFunction(desc.key_reader, args); - if (rc.IntVal != 0) + sscanf_fn fn = (sscanf_fn)rw_engine_->getPointerToFunction(desc.key_sscanf); + if (!fn) { + fprintf(stderr, "Key sscanf not available in JIT Engine\n"); + return -1; + } + int rc = (*fn)(key_str, key); + if (rc != 0) { + perror("sscanf"); return -1; + } return 0; } int BPFModule::table_leaf_scanf(size_t id, const char *leaf_str, void *leaf) { if (id >= tables_->size()) return -1; - const TableDesc &desc = (*tables_)[id]; - if (desc.fd < 0) return -1; - - if (!rw_engine_ || !desc.leaf_reader) { - fprintf(stderr, "Table sscanf not available\n"); + if (!desc.leaf_sscanf) { + fprintf(stderr, "Key sscanf not available\n"); return -1; } - vector args({GenericValue(), GenericValue((void *)leaf_str), GenericValue(leaf)}); - GenericValue rc = rw_engine_->runFunction(desc.leaf_reader, args); - if (rc.IntVal != 0) + sscanf_fn fn = (sscanf_fn)rw_engine_->getPointerToFunction(desc.leaf_sscanf); + if (!fn) { + fprintf(stderr, "Leaf sscanf not available in JIT Engine\n"); return -1; + } + int rc = (*fn)(leaf_str, leaf); + if (rc != 0) { + perror("sscanf"); + return -1; + } return 0; } diff --git a/src/cc/bpf_module.h b/src/cc/bpf_module.h index ef5c2e458707..320ebf3f5dc1 100644 --- a/src/cc/bpf_module.h +++ b/src/cc/bpf_module.h @@ -64,6 +64,7 @@ class BPFModule { size_t function_size(size_t id) const; size_t function_size(const std::string &name) const; size_t num_tables() const; + size_t table_id(const std::string &name) const; int table_fd(size_t id) const; int table_fd(const std::string &name) const; const char * table_name(size_t id) const; @@ -79,8 +80,6 @@ class BPFModule { size_t table_leaf_size(const std::string &name) const; int table_leaf_printf(size_t id, char *buf, size_t buflen, const void *leaf); int table_leaf_scanf(size_t id, const char *buf, void *leaf); - int table_update(size_t id, const char *key, const char *leaf); - int table_update(const std::string &name, const char *key, const char *leaf); char * license() const; unsigned kern_version() const; private: diff --git a/src/cc/table_desc.h b/src/cc/table_desc.h index afecad1f956c..13cc685a487c 100644 --- a/src/cc/table_desc.h +++ b/src/cc/table_desc.h @@ -31,10 +31,10 @@ struct TableDesc { size_t max_entries; std::string key_desc; std::string leaf_desc; - llvm::Function *key_reader; - llvm::Function *leaf_reader; - llvm::Function *key_writer; - llvm::Function *leaf_writer; + llvm::Function *key_sscanf; + llvm::Function *leaf_sscanf; + llvm::Function *key_snprintf; + llvm::Function *leaf_snprintf; }; } // namespace ebpf diff --git a/src/python/bpf/__init__.py b/src/python/bpf/__init__.py index eaadb7da7767..df1068c722d4 100644 --- a/src/python/bpf/__init__.py +++ b/src/python/bpf/__init__.py @@ -39,14 +39,26 @@ lib.bpf_function_start.argtypes = [ct.c_void_p, ct.c_char_p] lib.bpf_function_size.restype = ct.c_size_t lib.bpf_function_size.argtypes = [ct.c_void_p, ct.c_char_p] +lib.bpf_table_id.restype = ct.c_ulonglong +lib.bpf_table_id.argtypes = [ct.c_void_p, ct.c_char_p] lib.bpf_table_fd.restype = ct.c_int lib.bpf_table_fd.argtypes = [ct.c_void_p, 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_leaf_desc.restype = ct.c_char_p lib.bpf_table_leaf_desc.argtypes = [ct.c_void_p, ct.c_char_p] -lib.bpf_table_update.restype = ct.c_int -lib.bpf_table_update.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_char_p, ct.c_char_p] +lib.bpf_table_key_snprintf.restype = ct.c_int +lib.bpf_table_key_snprintf.argtypes = [ct.c_void_p, ct.c_ulonglong, + ct.c_char_p, ct.c_ulonglong, ct.c_void_p] +lib.bpf_table_leaf_snprintf.restype = ct.c_int +lib.bpf_table_leaf_snprintf.argtypes = [ct.c_void_p, ct.c_ulonglong, + ct.c_char_p, ct.c_ulonglong, ct.c_void_p] +lib.bpf_table_key_sscanf.restype = ct.c_int +lib.bpf_table_key_sscanf.argtypes = [ct.c_void_p, ct.c_ulonglong, + ct.c_char_p, ct.c_void_p] +lib.bpf_table_leaf_sscanf.restype = ct.c_int +lib.bpf_table_leaf_sscanf.argtypes = [ct.c_void_p, ct.c_ulonglong, + ct.c_char_p, ct.c_void_p] # keep in sync with libbpf.h lib.bpf_get_next_key.restype = ct.c_int @@ -92,12 +104,49 @@ def __init__(self, bpf, name, fd): self.fd = fd class Table(MutableMapping): - def __init__(self, bpf, map_fd, keytype, leaftype): + def __init__(self, bpf, map_id, map_fd, keytype, leaftype): self.bpf = bpf + self.map_id = map_id self.map_fd = map_fd self.Key = keytype self.Leaf = leaftype + def key_sprintf(self, key): + key_p = ct.pointer(key) + buf = ct.create_string_buffer(ct.sizeof(self.Key) * 8) + res = lib.bpf_table_key_snprintf(self.bpf.module, self.map_id, + buf, len(buf), key_p) + if res < 0: + raise Exception("Could not printf key") + return buf.value + + def leaf_sprintf(self, leaf): + leaf_p = ct.pointer(leaf) + buf = ct.create_string_buffer(ct.sizeof(self.Leaf) * 8) + res = lib.bpf_table_leaf_snprintf(self.bpf.module, self.map_id, + buf, len(buf), leaf_p) + if res < 0: + raise Exception("Could not printf leaf") + return buf.value + + def key_scanf(self, key_str): + key = self.Key() + key_p = ct.pointer(key) + res = lib.bpf_table_key_sscanf(self.bpf.module, self.map_id, + key_str, key_p) + if res < 0: + raise Exception("Could not scanf key") + return key + + def leaf_scanf(self, leaf_str): + leaf = self.Leaf() + leaf_p = ct.pointer(leaf) + res = lib.bpf_table_leaf_sscanf(self.bpf.module, self.map_id, + leaf_str, leaf_p) + if res < 0: + raise Exception("Could not scanf leaf") + return leaf + def __getitem__(self, key): key_p = ct.pointer(key) leaf = self.Leaf() @@ -245,6 +294,7 @@ def _decode_table_type(desc): return cls def get_table(self, name, keytype=None, leaftype=None): + map_id = lib.bpf_table_id(self.module, name.encode("ascii")) map_fd = lib.bpf_table_fd(self.module, name.encode("ascii")) if map_fd < 0: raise Exception("Failed to find BPF Table %s" % name) @@ -258,13 +308,7 @@ def get_table(self, name, keytype=None, leaftype=None): if not leaf_desc: raise Exception("Failed to load BPF Table %s leaf desc" % name) leaftype = BPF._decode_table_type(json.loads(leaf_desc.decode())) - return BPF.Table(self, map_fd, keytype, leaftype) - - def update_table(self, name, key, leaf): - res = lib.bpf_table_update(self.module, name.encode("ascii"), key.encode("ascii"), - leaf.encode("ascii")) - if res < 0: - raise Exception("update_table failed") + return BPF.Table(self, map_id, map_fd, keytype, leaftype) @staticmethod def attach_raw_socket(fn, dev): diff --git a/tests/cc/test_clang.py b/tests/cc/test_clang.py index bd67b56d209b..b41e40843d06 100755 --- a/tests/cc/test_clang.py +++ b/tests/cc/test_clang.py @@ -55,9 +55,11 @@ def test_sscanf(self): """ b = BPF(text=text, debug=0) fn = b.load_func("foo", BPF.KPROBE) - b.update_table("stats", "2", "{ 2 3 0x1000000004 { 5 6 }}") t = b.get_table("stats") - l = t[t.Key(2)] + s1 = t.key_sprintf(t.Key(2)) + self.assertEqual(s1, b"0x2") + s2 = t.leaf_sprintf(t.Leaf(2, 3, 4, 1, (5, 6))) + l = t.leaf_scanf(s2) self.assertEqual(l.a, 2) self.assertEqual(l.b, 3) self.assertEqual(l.c, 4)