Commit 8cea2e95 authored by 4ast's avatar 4ast

Merge pull request #127 from iovisor/bblanco_dev

Changes to support map entry read/write in fuse
parents f04003e1 2582ecfc
...@@ -104,6 +104,12 @@ size_t bpf_num_tables(void *program) { ...@@ -104,6 +104,12 @@ size_t bpf_num_tables(void *program) {
return mod->num_tables(); 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) { int bpf_table_fd(void *program, const char *table_name) {
auto mod = static_cast<ebpf::BPFModule *>(program); auto mod = static_cast<ebpf::BPFModule *>(program);
if (!mod) return -1; if (!mod) return -1;
...@@ -170,27 +176,26 @@ size_t bpf_table_leaf_size_id(void *program, size_t id) { ...@@ -170,27 +176,26 @@ size_t bpf_table_leaf_size_id(void *program, size_t id) {
return mod->table_leaf_size(id); return mod->table_leaf_size(id);
} }
int bpf_table_update(void *program, const char *table_name, const char *key, const char *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); auto mod = static_cast<ebpf::BPFModule *>(program);
if (!mod) return 0; if (!mod) return -1;
return mod->table_update(table_name, key, leaf); 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) {
int bpf_table_update_id(void *program, size_t id, const char *key, const char *leaf) {
auto mod = static_cast<ebpf::BPFModule *>(program); auto mod = static_cast<ebpf::BPFModule *>(program);
if (!mod) return 0; if (!mod) return -1;
return mod->table_update(id, key, leaf); return mod->table_leaf_printf(id, buf, buflen, leaf);
} }
int bpf_table_key_snprintf(void *program, size_t id, char *buf, size_t buflen, const void *key) { int bpf_table_key_sscanf(void *program, size_t id, const char *buf, void *key) {
auto mod = static_cast<ebpf::BPFModule *>(program); auto mod = static_cast<ebpf::BPFModule *>(program);
if (!mod) return 0; if (!mod) return -1;
return mod->table_key_printf(id, buf, buflen, key); return mod->table_key_scanf(id, buf, key);
} }
int bpf_table_leaf_snprintf(void *program, size_t id, char *buf, size_t buflen, const void *leaf) { int bpf_table_leaf_sscanf(void *program, size_t id, const char *buf, void *leaf) {
auto mod = static_cast<ebpf::BPFModule *>(program); auto mod = static_cast<ebpf::BPFModule *>(program);
if (!mod) return 0; if (!mod) return -1;
return mod->table_key_printf(id, buf, buflen, leaf); return mod->table_leaf_scanf(id, buf, leaf);
} }
} }
...@@ -37,6 +37,7 @@ void * bpf_function_start(void *program, const char *name); ...@@ -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_id(void *program, size_t id);
size_t bpf_function_size(void *program, const char *name); size_t bpf_function_size(void *program, const char *name);
size_t bpf_num_tables(void *program); 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(void *program, const char *table_name);
int bpf_table_fd_id(void *program, size_t id); int bpf_table_fd_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);
...@@ -50,10 +51,8 @@ size_t bpf_table_leaf_size(void *program, const char *table_name); ...@@ -50,10 +51,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); 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_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_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_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_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 #ifdef __cplusplus
} }
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <linux/bpf.h> #include <linux/bpf.h>
#include <llvm/ADT/STLExtras.h> #include <llvm/ADT/STLExtras.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/ExecutionEngine/MCJIT.h> #include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h> #include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include <llvm/IRReader/IRReader.h> #include <llvm/IRReader/IRReader.h>
...@@ -64,6 +63,9 @@ using std::unique_ptr; ...@@ -64,6 +63,9 @@ using std::unique_ptr;
using std::vector; using std::vector;
using namespace llvm; 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; const string BPFModule::FN_PREFIX = BPF_FN_PREFIX;
// Snooping class to remember the sections as the JIT creates them // 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, ...@@ -147,9 +149,9 @@ static void parse_type(IRBuilder<> &B, vector<Value *> *args, string *fmt,
else if (it->getBitWidth() <= 16) else if (it->getBitWidth() <= 16)
*fmt += "%h"; *fmt += "%h";
else if (it->getBitWidth() <= 32) else if (it->getBitWidth() <= 32)
*fmt += "%l"; *fmt += "%";
else else
*fmt += "%ll"; *fmt += "%l";
if (is_writer) if (is_writer)
*fmt += "x"; *fmt += "x";
else else
...@@ -171,15 +173,11 @@ Function * BPFModule::make_reader(Module *mod, Type *type) { ...@@ -171,15 +173,11 @@ Function * BPFModule::make_reader(Module *mod, Type *type) {
IRBuilder<> B(*ctx_); IRBuilder<> B(*ctx_);
// The JIT currently supports a limited number of function prototypes, use the vector<Type *> fn_args({B.getInt8PtrTy(), PointerType::getUnqual(type)});
// int (*) (int, char **, const char **) version
vector<Type *> fn_args({B.getInt32Ty(), B.getInt8PtrTy(), PointerType::getUnqual(type)});
FunctionType *fn_type = FunctionType::get(B.getInt32Ty(), fn_args, /*isVarArg=*/false); FunctionType *fn_type = FunctionType::get(B.getInt32Ty(), fn_args, /*isVarArg=*/false);
Function *fn = Function::Create(fn_type, GlobalValue::ExternalLinkage, Function *fn = Function::Create(fn_type, GlobalValue::ExternalLinkage,
"reader" + std::to_string(readers_.size()), mod); "reader" + std::to_string(readers_.size()), mod);
auto arg_it = fn->arg_begin(); auto arg_it = fn->arg_begin();
Argument *arg_argc = arg_it++;
arg_argc->setName("argc");
Argument *arg_in = arg_it++; Argument *arg_in = arg_it++;
arg_in->setName("in"); arg_in->setName("in");
Argument *arg_out = arg_it++; Argument *arg_out = arg_it++;
...@@ -197,6 +195,9 @@ Function * BPFModule::make_reader(Module *mod, Type *type) { ...@@ -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)})); 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()}); vector<Type *> sscanf_fn_args({B.getInt8PtrTy(), B.getInt8PtrTy()});
FunctionType *sscanf_fn_type = FunctionType::get(B.getInt32Ty(), sscanf_fn_args, /*isVarArg=*/true); FunctionType *sscanf_fn_type = FunctionType::get(B.getInt32Ty(), sscanf_fn_args, /*isVarArg=*/true);
Function *sscanf_fn = mod->getFunction("sscanf"); Function *sscanf_fn = mod->getFunction("sscanf");
...@@ -234,17 +235,15 @@ Function * BPFModule::make_writer(Module *mod, Type *type) { ...@@ -234,17 +235,15 @@ Function * BPFModule::make_writer(Module *mod, Type *type) {
IRBuilder<> B(*ctx_); IRBuilder<> B(*ctx_);
// The JIT currently supports a limited number of function prototypes, use the vector<Type *> fn_args({B.getInt8PtrTy(), B.getInt64Ty(), PointerType::getUnqual(type)});
// int (*) (int, char **, const char **) version
vector<Type *> fn_args({B.getInt32Ty(), B.getInt8PtrTy(), PointerType::getUnqual(type)});
FunctionType *fn_type = FunctionType::get(B.getInt32Ty(), fn_args, /*isVarArg=*/false); FunctionType *fn_type = FunctionType::get(B.getInt32Ty(), fn_args, /*isVarArg=*/false);
Function *fn = Function::Create(fn_type, GlobalValue::ExternalLinkage, Function *fn = Function::Create(fn_type, GlobalValue::ExternalLinkage,
"writer" + std::to_string(writers_.size()), mod); "writer" + std::to_string(writers_.size()), mod);
auto arg_it = fn->arg_begin(); auto arg_it = fn->arg_begin();
Argument *arg_len = arg_it++;
arg_len->setName("len");
Argument *arg_out = arg_it++; Argument *arg_out = arg_it++;
arg_out->setName("out"); arg_out->setName("out");
Argument *arg_len = arg_it++;
arg_len->setName("len");
Argument *arg_in = arg_it++; Argument *arg_in = arg_it++;
arg_in->setName("in"); arg_in->setName("in");
...@@ -331,18 +330,18 @@ int BPFModule::annotate() { ...@@ -331,18 +330,18 @@ int BPFModule::annotate() {
if (st->getNumElements() < 2) continue; if (st->getNumElements() < 2) continue;
Type *key_type = st->elements()[0]; Type *key_type = st->elements()[0];
Type *leaf_type = st->elements()[1]; Type *leaf_type = st->elements()[1];
table.key_reader = make_reader(&*m, key_type); table.key_sscanf = make_reader(&*m, key_type);
if (!table.key_reader) if (!table.key_sscanf)
errs() << "Failed to compile reader for " << *key_type << "\n"; errs() << "Failed to compile sscanf for " << *key_type << "\n";
table.leaf_reader = make_reader(&*m, leaf_type); table.leaf_sscanf = make_reader(&*m, leaf_type);
if (!table.leaf_reader) if (!table.leaf_sscanf)
errs() << "Failed to compile reader for " << *leaf_type << "\n"; errs() << "Failed to compile sscanf for " << *leaf_type << "\n";
table.key_writer = make_writer(&*m, key_type); table.key_snprintf = make_writer(&*m, key_type);
if (!table.key_writer) if (!table.key_snprintf)
errs() << "Failed to compile writer for " << *key_type << "\n"; errs() << "Failed to compile snprintf for " << *key_type << "\n";
table.leaf_writer = make_writer(&*m, leaf_type); table.leaf_snprintf = make_writer(&*m, leaf_type);
if (!table.leaf_writer) if (!table.leaf_snprintf)
errs() << "Failed to compile writer for " << *leaf_type << "\n"; errs() << "Failed to compile snprintf for " << *leaf_type << "\n";
} }
} }
} }
...@@ -474,10 +473,14 @@ size_t BPFModule::num_tables() const { ...@@ -474,10 +473,14 @@ size_t BPFModule::num_tables() const {
return tables_->size(); 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); auto it = table_names_.find(name);
if (it == table_names_.end()) return -1; if (it == table_names_.end()) return ~0ull;
return table_fd(it->second); 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 { int BPFModule::table_fd(size_t id) const {
...@@ -497,9 +500,7 @@ const char * BPFModule::table_key_desc(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 { const char * BPFModule::table_key_desc(const string &name) const {
auto it = table_names_.find(name); return table_key_desc(table_id(name));
if (it == table_names_.end()) return nullptr;
return table_key_desc(it->second);
} }
const char * BPFModule::table_leaf_desc(size_t id) const { const char * BPFModule::table_leaf_desc(size_t id) const {
...@@ -509,18 +510,14 @@ 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 { const char * BPFModule::table_leaf_desc(const string &name) const {
auto it = table_names_.find(name); return table_leaf_desc(table_id(name));
if (it == table_names_.end()) return nullptr;
return table_leaf_desc(it->second);
} }
size_t BPFModule::table_key_size(size_t id) const { size_t BPFModule::table_key_size(size_t id) const {
if (id >= tables_->size()) return 0; if (id >= tables_->size()) return 0;
return (*tables_)[id].key_size; return (*tables_)[id].key_size;
} }
size_t BPFModule::table_key_size(const string &name) const { size_t BPFModule::table_key_size(const string &name) const {
auto it = table_names_.find(name); return table_key_size(table_id(name));
if (it == table_names_.end()) return 0;
return table_key_size(it->second);
} }
size_t BPFModule::table_leaf_size(size_t id) const { size_t BPFModule::table_leaf_size(size_t id) const {
...@@ -528,42 +525,7 @@ 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; return (*tables_)[id].leaf_size;
} }
size_t BPFModule::table_leaf_size(const string &name) const { size_t BPFModule::table_leaf_size(const string &name) const {
auto it = table_names_.find(name); return table_leaf_size(table_id(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);
} }
struct TableIterator { struct TableIterator {
...@@ -576,52 +538,90 @@ struct TableIterator { ...@@ -576,52 +538,90 @@ struct TableIterator {
}; };
int BPFModule::table_key_printf(size_t id, char *buf, size_t buflen, const void *key) { int BPFModule::table_key_printf(size_t id, char *buf, size_t buflen, const void *key) {
if (id >= tables_->size()) { if (id >= tables_->size()) return -1;
fprintf(stderr, "table id %zu out of range\n", id); const TableDesc &desc = (*tables_)[id];
if (!desc.key_snprintf) {
fprintf(stderr, "Key snprintf not available\n");
return -1;
}
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; return -1;
} }
int rc = (*fn)(buf, buflen, key);
if (rc < 0) {
perror("snprintf");
return -1;
}
if ((size_t)rc >= buflen) {
fprintf(stderr, "snprintf ran out of buffer space\n");
return -1;
}
return 0;
}
int BPFModule::table_leaf_printf(size_t id, char *buf, size_t buflen, const void *leaf) {
if (id >= tables_->size()) return -1;
const TableDesc &desc = (*tables_)[id]; const TableDesc &desc = (*tables_)[id];
if (!desc.key_writer) { if (!desc.leaf_snprintf) {
fprintf(stderr, "table snprintf not implemented for %s key\n", desc.name.c_str()); fprintf(stderr, "Key snprintf not available\n");
return -1;
}
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; return -1;
} }
GenericValue gv_buflen; int rc = (*fn)(buf, buflen, leaf);
gv_buflen.IntVal = APInt(32, buflen, true); if (rc < 0) {
vector<GenericValue> args({gv_buflen, GenericValue((void *)buf), GenericValue((void *)key)});
GenericValue rc = rw_engine_->runFunction(desc.key_writer, args);
if (rc.IntVal.isNegative()) {
perror("snprintf"); perror("snprintf");
return -1; return -1;
} }
if (rc.IntVal.sge(buflen)) { if ((size_t)rc >= buflen) {
fprintf(stderr, "snprintf ran out of buffer space\n"); fprintf(stderr, "snprintf ran out of buffer space\n");
return -1; return -1;
} }
return 0; return 0;
} }
int BPFModule::table_leaf_printf(size_t id, char *buf, size_t buflen, const void *leaf) { int BPFModule::table_key_scanf(size_t id, const char *key_str, void *key) {
if (id >= tables_->size()) { if (id >= tables_->size()) return -1;
fprintf(stderr, "table id %zu out of range\n", id); const TableDesc &desc = (*tables_)[id];
if (!desc.key_sscanf) {
fprintf(stderr, "Key sscanf not available\n");
return -1; return -1;
} }
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]; const TableDesc &desc = (*tables_)[id];
if (!desc.leaf_writer) { if (!desc.leaf_sscanf) {
fprintf(stderr, "table snprintf not implemented for %s leaf\n", desc.name.c_str()); fprintf(stderr, "Key sscanf not available\n");
return -1; return -1;
} }
GenericValue gv_buflen;
gv_buflen.IntVal = buflen; sscanf_fn fn = (sscanf_fn)rw_engine_->getPointerToFunction(desc.leaf_sscanf);
vector<GenericValue> args({gv_buflen, GenericValue((void *)buf), GenericValue((void *)leaf)}); if (!fn) {
GenericValue rc = rw_engine_->runFunction(desc.leaf_writer, args); fprintf(stderr, "Leaf sscanf not available in JIT Engine\n");
if (rc.IntVal.isNegative()) {
perror("snprintf");
return -1; return -1;
} }
if (rc.IntVal.sge(buflen)) { int rc = (*fn)(leaf_str, leaf);
fprintf(stderr, "snprintf ran out of buffer space\n"); if (rc != 0) {
perror("sscanf");
return -1; return -1;
} }
return 0; return 0;
......
...@@ -64,6 +64,7 @@ class BPFModule { ...@@ -64,6 +64,7 @@ class BPFModule {
size_t function_size(size_t id) const; size_t function_size(size_t id) const;
size_t function_size(const std::string &name) const; size_t function_size(const std::string &name) const;
size_t num_tables() 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(size_t id) const;
int table_fd(const std::string &name) const; int table_fd(const std::string &name) const;
const char * table_name(size_t id) const; const char * table_name(size_t id) const;
...@@ -72,13 +73,13 @@ class BPFModule { ...@@ -72,13 +73,13 @@ class BPFModule {
size_t table_key_size(size_t id) const; size_t table_key_size(size_t id) const;
size_t table_key_size(const std::string &name) 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_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(size_t id) const;
const char * table_leaf_desc(const std::string &name) 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(size_t id) const;
size_t table_leaf_size(const std::string &name) 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_printf(size_t id, char *buf, size_t buflen, const void *leaf);
int table_update(size_t id, const char *key, const char *leaf); int table_leaf_scanf(size_t id, const char *buf, void *leaf);
int table_update(const std::string &name, const char *key, const char *leaf);
char * license() const; char * license() const;
unsigned kern_version() const; unsigned kern_version() const;
private: private:
......
...@@ -31,10 +31,10 @@ struct TableDesc { ...@@ -31,10 +31,10 @@ struct TableDesc {
size_t max_entries; size_t max_entries;
std::string key_desc; std::string key_desc;
std::string leaf_desc; std::string leaf_desc;
llvm::Function *key_reader; llvm::Function *key_sscanf;
llvm::Function *leaf_reader; llvm::Function *leaf_sscanf;
llvm::Function *key_writer; llvm::Function *key_snprintf;
llvm::Function *leaf_writer; llvm::Function *leaf_snprintf;
}; };
} // namespace ebpf } // namespace ebpf
...@@ -39,14 +39,26 @@ lib.bpf_function_start.restype = ct.c_void_p ...@@ -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_start.argtypes = [ct.c_void_p, ct.c_char_p]
lib.bpf_function_size.restype = ct.c_size_t lib.bpf_function_size.restype = ct.c_size_t
lib.bpf_function_size.argtypes = [ct.c_void_p, ct.c_char_p] 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.restype = ct.c_int
lib.bpf_table_fd.argtypes = [ct.c_void_p, ct.c_char_p] 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.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
lib.bpf_table_leaf_desc.argtypes = [ct.c_void_p, 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_key_snprintf.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.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 # keep in sync with libbpf.h
lib.bpf_get_next_key.restype = ct.c_int lib.bpf_get_next_key.restype = ct.c_int
...@@ -92,12 +104,49 @@ class BPF(object): ...@@ -92,12 +104,49 @@ class BPF(object):
self.fd = fd self.fd = fd
class Table(MutableMapping): 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.bpf = bpf
self.map_id = map_id
self.map_fd = map_fd self.map_fd = map_fd
self.Key = keytype self.Key = keytype
self.Leaf = leaftype 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): def __getitem__(self, key):
key_p = ct.pointer(key) key_p = ct.pointer(key)
leaf = self.Leaf() leaf = self.Leaf()
...@@ -245,6 +294,7 @@ class BPF(object): ...@@ -245,6 +294,7 @@ class BPF(object):
return cls return cls
def get_table(self, name, keytype=None, leaftype=None): 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")) map_fd = lib.bpf_table_fd(self.module, name.encode("ascii"))
if map_fd < 0: if map_fd < 0:
raise Exception("Failed to find BPF Table %s" % name) raise Exception("Failed to find BPF Table %s" % name)
...@@ -258,13 +308,7 @@ class BPF(object): ...@@ -258,13 +308,7 @@ class BPF(object):
if not leaf_desc: if not leaf_desc:
raise Exception("Failed to load BPF Table %s leaf desc" % name) raise Exception("Failed to load BPF Table %s leaf desc" % name)
leaftype = BPF._decode_table_type(json.loads(leaf_desc.decode())) leaftype = BPF._decode_table_type(json.loads(leaf_desc.decode()))
return BPF.Table(self, map_fd, keytype, leaftype) return BPF.Table(self, map_id, 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")
@staticmethod @staticmethod
def attach_raw_socket(fn, dev): def attach_raw_socket(fn, dev):
......
...@@ -55,9 +55,11 @@ int foo(void *ctx) { ...@@ -55,9 +55,11 @@ int foo(void *ctx) {
""" """
b = BPF(text=text, debug=0) b = BPF(text=text, debug=0)
fn = b.load_func("foo", BPF.KPROBE) fn = b.load_func("foo", BPF.KPROBE)
b.update_table("stats", "2", "{ 2 3 0x1000000004 { 5 6 }}")
t = b.get_table("stats") 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.a, 2)
self.assertEqual(l.b, 3) self.assertEqual(l.b, 3)
self.assertEqual(l.c, 4) self.assertEqual(l.c, 4)
......
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