Add testing for scanf/printf in python, deprecate table_update
authorBrenden Blanco <bblanco@plumgrid.com>
Wed, 12 Aug 2015 19:08:00 +0000 (12:08 -0700)
committerBrenden Blanco <bblanco@plumgrid.com>
Wed, 12 Aug 2015 19:08:35 +0000 (12:08 -0700)
Signed-off-by: Brenden Blanco <bblanco@plumgrid.com>
src/cc/bpf_common.cc
src/cc/bpf_common.h
src/cc/bpf_module.cc
src/cc/bpf_module.h
src/cc/table_desc.h
src/python/bpf/__init__.py
tests/cc/test_clang.py

index 19f6eb1..6c779a1 100644 (file)
@@ -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<ebpf::BPFModule *>(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<ebpf::BPFModule *>(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<ebpf::BPFModule *>(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<ebpf::BPFModule *>(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<ebpf::BPFModule *>(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<ebpf::BPFModule *>(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<ebpf::BPFModule *>(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<ebpf::BPFModule *>(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);
 }
 
 }
index f791036..48adf0b 100644 (file)
@@ -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
 }
index fa237c0..3b2b6e3 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/bpf.h>
 
 #include <llvm/ADT/STLExtras.h>
-#include <llvm/ExecutionEngine/GenericValue.h>
 #include <llvm/ExecutionEngine/MCJIT.h>
 #include <llvm/ExecutionEngine/SectionMemoryManager.h>
 #include <llvm/IRReader/IRReader.h>
@@ -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<Value *> *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<Type *> fn_args({B.getInt32Ty(), B.getInt8PtrTy(), PointerType::getUnqual(type)});
+  vector<Type *> 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<Value *>({B.getInt64(0), B.getInt64(0)}));
 
+  if (0)
+    debug_printf(mod, B, "%p %p\n", vector<Value *>({arg_in, arg_out}));
+
   vector<Type *> 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<Type *> fn_args({B.getInt32Ty(), B.getInt8PtrTy(), PointerType::getUnqual(type)});
+  vector<Type *> 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<uint8_t[]> key(new uint8_t[desc.key_size]);
-  unique_ptr<uint8_t[]> leaf(new uint8_t[desc.leaf_size]);
-  GenericValue rc;
-  rc = rw_engine_->runFunction(desc.key_reader, vector<GenericValue>({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(),
-                                                                       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<GenericValue> 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<GenericValue> 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<GenericValue> 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<GenericValue> 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;
 }
 
index ef5c2e4..320ebf3 100644 (file)
@@ -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:
index afecad1..13cc685 100644 (file)
@@ -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
index eaadb7d..df1068c 100644 (file)
@@ -39,14 +39,26 @@ lib.bpf_function_start.restype = ct.c_void_p
 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 @@ class BPF(object):
             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 @@ class BPF(object):
         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 @@ class BPF(object):
             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):
index bd67b56..b41e408 100755 (executable)
@@ -55,9 +55,11 @@ int foo(void *ctx) {
 """
         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)