Convert bpf_module structures to use vector instead of map for tables
It was bothering me that a whole bunch of accesses to the tables were
based on a string hash lookup, in addition to the vectors that were kept
to convert ids to names. Switch those around, as well as the api
internally.
Signed-off-by: Brenden Blanco <bblanco@plumgrid.com>
diff --git a/src/cc/bpf_module.cc b/src/cc/bpf_module.cc
index 707e979..448ee23 100644
--- a/src/cc/bpf_module.cc
+++ b/src/cc/bpf_module.cc
@@ -225,9 +225,10 @@
// separate module to hold the reader functions
auto m = make_unique<Module>("sscanf", *ctx_);
+ size_t id = 0;
for (auto table : *tables_) {
- table_names_.push_back(table.first);
- GlobalValue *gvar = mod_->getNamedValue(table.first);
+ table_names_[table.name] = id++;
+ GlobalValue *gvar = mod_->getNamedValue(table.name);
if (!gvar) continue;
if (PointerType *pt = dyn_cast<PointerType>(gvar->getType())) {
if (StructType *st = dyn_cast<StructType>(pt->getElementType())) {
@@ -366,66 +367,66 @@
}
size_t BPFModule::num_tables() const {
- return table_names_.size();
+ return tables_->size();
}
int BPFModule::table_fd(const string &name) const {
- auto table_it = tables_->find(name);
- if (table_it == tables_->end()) return -1;
- return table_it->second.fd;
+ auto it = table_names_.find(name);
+ if (it == table_names_.end()) return -1;
+ return table_fd(it->second);
}
int BPFModule::table_fd(size_t id) const {
- if (id >= table_names_.size()) return -1;
- return table_fd(table_names_[id]);
+ if (id >= tables_->size()) return -1;
+ return (*tables_)[id].fd;
}
const char * BPFModule::table_name(size_t id) const {
- if (id >= table_names_.size()) return nullptr;
- return table_names_[id].c_str();
+ if (id >= tables_->size()) return nullptr;
+ return (*tables_)[id].name.c_str();
}
const char * BPFModule::table_key_desc(size_t id) const {
- if (id >= table_names_.size()) return nullptr;
- return table_key_desc(table_names_[id]);
+ if (b_loader_) return nullptr;
+ if (id >= tables_->size()) return nullptr;
+ return (*tables_)[id].key_desc.c_str();
}
const char * BPFModule::table_key_desc(const string &name) const {
- if (b_loader_) return nullptr;
- auto table_it = tables_->find(name);
- if (table_it == tables_->end()) return nullptr;
- return table_it->second.key_desc.c_str();
+ auto it = table_names_.find(name);
+ if (it == table_names_.end()) return nullptr;
+ return table_key_desc(it->second);
}
const char * BPFModule::table_leaf_desc(size_t id) const {
- if (id >= table_names_.size()) return nullptr;
- return table_leaf_desc(table_names_[id]);
+ if (b_loader_) return nullptr;
+ if (id >= tables_->size()) return nullptr;
+ return (*tables_)[id].leaf_desc.c_str();
}
const char * BPFModule::table_leaf_desc(const string &name) const {
- if (b_loader_) return nullptr;
- auto table_it = tables_->find(name);
- if (table_it == tables_->end()) return nullptr;
- return table_it->second.leaf_desc.c_str();
+ auto it = table_names_.find(name);
+ if (it == table_names_.end()) return nullptr;
+ return table_leaf_desc(it->second);
}
size_t BPFModule::table_key_size(size_t id) const {
- if (id >= table_names_.size()) return 0;
- return table_key_size(table_names_[id]);
+ if (id >= tables_->size()) return 0;
+ return (*tables_)[id].key_size;
}
size_t BPFModule::table_key_size(const string &name) const {
- auto table_it = tables_->find(name);
- if (table_it == tables_->end()) return 0;
- return table_it->second.key_size;
+ auto it = table_names_.find(name);
+ if (it == table_names_.end()) return 0;
+ return table_key_size(it->second);
}
size_t BPFModule::table_leaf_size(size_t id) const {
- if (id >= table_names_.size()) return 0;
- return table_leaf_size(table_names_[id]);
+ if (id >= tables_->size()) return 0;
+ return (*tables_)[id].leaf_size;
}
size_t BPFModule::table_leaf_size(const string &name) const {
- auto table_it = tables_->find(name);
- if (table_it == tables_->end()) return 0;
- return table_it->second.leaf_size;
+ auto it = table_names_.find(name);
+ if (it == table_names_.end()) return 0;
+ return table_leaf_size(it->second);
}
// load a B file, which comes in two parts
diff --git a/src/cc/bpf_module.h b/src/cc/bpf_module.h
index f8d0a7a..2a4d26d 100644
--- a/src/cc/bpf_module.h
+++ b/src/cc/bpf_module.h
@@ -87,8 +87,8 @@
std::unique_ptr<BLoader> b_loader_;
std::unique_ptr<ClangLoader> clang_loader_;
std::map<std::string, std::tuple<uint8_t *, uintptr_t>> sections_;
- std::unique_ptr<std::map<std::string, TableDesc>> tables_;
- std::vector<std::string> table_names_;
+ std::unique_ptr<std::vector<TableDesc>> tables_;
+ std::map<std::string, size_t> table_names_;
std::vector<std::string> function_names_;
std::map<llvm::Type *, llvm::Function *> readers_;
};
diff --git a/src/cc/frontends/b/codegen_llvm.cc b/src/cc/frontends/b/codegen_llvm.cc
index 26cc063..f470e81 100644
--- a/src/cc/frontends/b/codegen_llvm.cc
+++ b/src/cc/frontends/b/codegen_llvm.cc
@@ -1218,7 +1218,7 @@
return mkstatus(0);
}
-StatusTuple CodegenLLVM::visit(Node* root, map<string, TableDesc> &tables) {
+StatusTuple CodegenLLVM::visit(Node* root, vector<TableDesc> &tables) {
scopes_->set_current(scopes_->top_state());
scopes_->set_current(scopes_->top_var());
@@ -1232,13 +1232,14 @@
//TRY2(print_parser());
for (auto table : tables_) {
- TableDesc desc = {
+ tables.push_back({
+ table.first->id_->name_,
table_fds_[table.first],
table.first->key_type_->bit_width_ >> 3,
table.first->leaf_type_->bit_width_ >> 3,
table.first->size_,
- };
- tables[table.first->id_->name_] = desc;
+ "", "",
+ });
}
return mkstatus(0);
}
diff --git a/src/cc/frontends/b/codegen_llvm.h b/src/cc/frontends/b/codegen_llvm.h
index d63375f..47ffef9 100644
--- a/src/cc/frontends/b/codegen_llvm.h
+++ b/src/cc/frontends/b/codegen_llvm.h
@@ -63,7 +63,7 @@
EXPAND_NODES(VISIT)
#undef VISIT
- virtual STATUS_RETURN visit(Node* n, std::map<string, TableDesc> &tables);
+ virtual STATUS_RETURN visit(Node* n, std::vector<TableDesc> &tables);
int get_table_fd(const std::string &name) const;
diff --git a/src/cc/frontends/b/loader.cc b/src/cc/frontends/b/loader.cc
index cd7ea64..92d32fc 100644
--- a/src/cc/frontends/b/loader.cc
+++ b/src/cc/frontends/b/loader.cc
@@ -21,9 +21,9 @@
#include "table_desc.h"
using std::get;
-using std::map;
using std::string;
using std::unique_ptr;
+using std::vector;
namespace ebpf {
@@ -34,7 +34,7 @@
}
int BLoader::parse(llvm::Module *mod, const string &filename, const string &proto_filename,
- unique_ptr<map<string, TableDesc>> *tables) {
+ unique_ptr<vector<TableDesc>> *tables) {
int rc;
proto_parser_ = make_unique<ebpf::cc::Parser>(proto_filename);
@@ -61,7 +61,7 @@
return -1;
}
- *tables = make_unique<map<string, TableDesc>>();
+ *tables = make_unique<vector<TableDesc>>();
codegen_ = ebpf::make_unique<ebpf::cc::CodegenLLVM>(mod, parser_->scopes_.get(), proto_parser_->scopes_.get());
ret = codegen_->visit(parser_->root_node_, **tables);
diff --git a/src/cc/frontends/b/loader.h b/src/cc/frontends/b/loader.h
index 50ef0da..d928023 100644
--- a/src/cc/frontends/b/loader.h
+++ b/src/cc/frontends/b/loader.h
@@ -38,7 +38,7 @@
BLoader();
~BLoader();
int parse(llvm::Module *mod, const std::string &filename, const std::string &proto_filename,
- std::unique_ptr<std::map<std::string, TableDesc>> *tables);
+ std::unique_ptr<std::vector<TableDesc>> *tables);
private:
std::unique_ptr<cc::Parser> parser_;
std::unique_ptr<cc::Parser> proto_parser_;
diff --git a/src/cc/frontends/clang/b_frontend_action.cc b/src/cc/frontends/clang/b_frontend_action.cc
index 8c3330a..14bad3b 100644
--- a/src/cc/frontends/clang/b_frontend_action.cc
+++ b/src/cc/frontends/clang/b_frontend_action.cc
@@ -87,65 +87,7 @@
return true;
}
-BScanfVisitor::BScanfVisitor(ASTContext &C)
- : C(C), n_args_(0) {}
-
-bool BScanfVisitor::VisitFieldDecl(FieldDecl *D) {
- args_ += "&val->" + D->getName().str();
- ++n_args_;
- return true;
-}
-
-bool BScanfVisitor::TraverseRecordDecl(RecordDecl *D) {
- // skip children, handled in Visit...
- if (!WalkUpFromRecordDecl(D))
- return false;
- return true;
-}
-
-bool BScanfVisitor::VisitRecordDecl(RecordDecl *D) {
- if (type_.empty())
- type_ = "struct " + D->getDefinition()->getName().str();
- fmt_ += "{ ";
- for (auto F : D->getDefinition()->fields()) {
- TraverseDecl(F);
- if (F->isBitField())
- fmt_ += ", " + to_string(F->getBitWidthValue(C));
- fmt_ += ", ";
- args_ += ", ";
- }
- if (!D->getDefinition()->field_empty()) {
- fmt_.erase(fmt_.end() - 2);
- args_.erase(args_.end() - 2);
- }
- fmt_ += "}";
- return true;
-}
-bool BScanfVisitor::VisitTagType(const TagType *T) {
- return TraverseDecl(T->getDecl()->getDefinition());
-}
-bool BScanfVisitor::VisitTypedefType(const TypedefType *T) {
- return TraverseDecl(T->getDecl());
-}
-bool BScanfVisitor::VisitBuiltinType(const BuiltinType *T) {
- if (type_.empty()) {
- type_ = T->getName(C.getPrintingPolicy());
- args_ += "val";
- ++n_args_;
- }
- fmt_ += "%i";
- return true;
-}
-void BScanfVisitor::finalize(string &result) {
- result = "int read_entry(const char *str, void *buf) {\n";
- result += " " + type_ + " *val = buf;\n";
- result += " int n = sscanf(str, \"" + fmt_ + "\", " + args_ + ");\n";
- result += " if (n < " + std::to_string(n_args_) + ") return -1;\n";
- result += " return 0;\n";
- result += "}\n";
-}
-
-BTypeVisitor::BTypeVisitor(ASTContext &C, Rewriter &rewriter, map<string, TableDesc> &tables)
+BTypeVisitor::BTypeVisitor(ASTContext &C, Rewriter &rewriter, vector<TableDesc> &tables)
: C(C), rewriter_(rewriter), out_(llvm::errs()), tables_(tables) {
}
@@ -200,13 +142,15 @@
string args = rewriter_.getRewrittenText(argRange);
// find the table fd, which was opened at declaration time
- auto table_it = tables_.find(Ref->getDecl()->getName());
+ auto table_it = tables_.begin();
+ for (; table_it != tables_.end(); ++table_it)
+ if (table_it->name == Ref->getDecl()->getName()) break;
if (table_it == tables_.end()) {
C.getDiagnostics().Report(Ref->getLocEnd(), diag::err_expected)
<< "initialized handle for bpf_table";
return false;
}
- string fd = to_string(table_it->second.fd);
+ string fd = to_string(table_it->fd);
string prefix, suffix;
string map_update_policy = "BPF_ANY";
string txt;
@@ -419,7 +363,10 @@
return false;
}
const RecordDecl *RD = R->getDecl()->getDefinition();
+
TableDesc table;
+ table.name = Decl->getName();
+
unsigned i = 0;
for (auto F : RD->fields()) {
size_t sz = C.getTypeSize(F->getType()) >> 3;
@@ -428,19 +375,11 @@
BMapDeclVisitor visitor(C, table.key_desc);
if (!visitor.TraverseType(F->getType()))
return false;
- BScanfVisitor scanf_visitor(C);
- if (!scanf_visitor.TraverseType(F->getType()))
- return false;
- scanf_visitor.finalize(table.key_reader);
} else if (F->getName() == "leaf") {
table.leaf_size = sz;
BMapDeclVisitor visitor(C, table.leaf_desc);
if (!visitor.TraverseType(F->getType()))
return false;
- BScanfVisitor scanf_visitor(C);
- if (!scanf_visitor.TraverseType(F->getType()))
- return false;
- scanf_visitor.finalize(table.leaf_reader);
} else if (F->getName() == "data") {
table.max_entries = sz / table.leaf_size;
}
@@ -472,7 +411,7 @@
<< "valid bpf fd";
return false;
}
- tables_[Decl->getName()] = std::move(table);
+ tables_.push_back(std::move(table));
} else if (const PointerType *P = Decl->getType()->getAs<PointerType>()) {
// if var is a pointer to a packet type, clone the annotation into the var
// decl so that the packet dext/dins rewriter can catch it
@@ -489,7 +428,7 @@
return true;
}
-BTypeConsumer::BTypeConsumer(ASTContext &C, Rewriter &rewriter, map<string, TableDesc> &tables)
+BTypeConsumer::BTypeConsumer(ASTContext &C, Rewriter &rewriter, vector<TableDesc> &tables)
: visitor_(C, rewriter, tables) {
}
@@ -500,7 +439,7 @@
}
BFrontendAction::BFrontendAction(llvm::raw_ostream &os)
- : rewriter_(new Rewriter), os_(os), tables_(new map<string, TableDesc>) {
+ : rewriter_(new Rewriter), os_(os), tables_(new vector<TableDesc>) {
}
void BFrontendAction::EndSourceFileAction() {
diff --git a/src/cc/frontends/clang/b_frontend_action.h b/src/cc/frontends/clang/b_frontend_action.h
index 6491326..b21e72a 100644
--- a/src/cc/frontends/clang/b_frontend_action.h
+++ b/src/cc/frontends/clang/b_frontend_action.h
@@ -53,25 +53,6 @@
std::string &result_;
};
-// Helper visitor for constructing a fscanf routine for key/leaf decl
-class BScanfVisitor : public clang::RecursiveASTVisitor<BScanfVisitor> {
- public:
- explicit BScanfVisitor(clang::ASTContext &C);
- bool TraverseRecordDecl(clang::RecordDecl *Decl);
- bool VisitRecordDecl(clang::RecordDecl *Decl);
- bool VisitFieldDecl(clang::FieldDecl *Decl);
- bool VisitBuiltinType(const clang::BuiltinType *T);
- bool VisitTypedefType(const clang::TypedefType *T);
- bool VisitTagType(const clang::TagType *T);
- void finalize(std::string &result);
- private:
- clang::ASTContext &C;
- size_t n_args_;
- std::string fmt_;
- std::string args_;
- std::string type_;
-};
-
// Type visitor and rewriter for B programs.
// It will look for B-specific features and rewrite them into a valid
// C program. As part of the processing, open the necessary BPF tables
@@ -79,7 +60,7 @@
class BTypeVisitor : public clang::RecursiveASTVisitor<BTypeVisitor> {
public:
explicit BTypeVisitor(clang::ASTContext &C, clang::Rewriter &rewriter,
- std::map<std::string, TableDesc> &tables);
+ std::vector<TableDesc> &tables);
bool TraverseCallExpr(clang::CallExpr *Call);
bool TraverseMemberExpr(clang::MemberExpr *E);
bool VisitFunctionDecl(clang::FunctionDecl *D);
@@ -94,7 +75,7 @@
clang::ASTContext &C;
clang::Rewriter &rewriter_; /// modifications to the source go into this class
llvm::raw_ostream &out_; /// for debugging
- std::map<std::string, TableDesc> &tables_; /// store the open FDs
+ std::vector<TableDesc> &tables_; /// store the open FDs
std::vector<clang::ParmVarDecl *> fn_args_;
};
@@ -102,7 +83,7 @@
class BTypeConsumer : public clang::ASTConsumer {
public:
explicit BTypeConsumer(clang::ASTContext &C, clang::Rewriter &rewriter,
- std::map<std::string, TableDesc> &tables);
+ std::vector<TableDesc> &tables);
bool HandleTopLevelDecl(clang::DeclGroupRef D) override;
private:
BTypeVisitor visitor_;
@@ -125,11 +106,11 @@
CreateASTConsumer(clang::CompilerInstance &Compiler, llvm::StringRef InFile) override;
// take ownership of the table-to-fd mapping data structure
- std::unique_ptr<std::map<std::string, TableDesc>> take_tables() { return move(tables_); }
+ std::unique_ptr<std::vector<TableDesc>> take_tables() { return move(tables_); }
private:
std::unique_ptr<clang::Rewriter> rewriter_;
llvm::raw_ostream &os_;
- std::unique_ptr<std::map<std::string, TableDesc>> tables_;
+ std::unique_ptr<std::vector<TableDesc>> tables_;
};
} // namespace visitor
diff --git a/src/cc/frontends/clang/loader.cc b/src/cc/frontends/clang/loader.cc
index eea2ff2..c4ee097 100644
--- a/src/cc/frontends/clang/loader.cc
+++ b/src/cc/frontends/clang/loader.cc
@@ -64,8 +64,7 @@
ClangLoader::~ClangLoader() {}
-int ClangLoader::parse(unique_ptr<llvm::Module> *mod,
- unique_ptr<map<string, TableDesc>> *tables,
+int ClangLoader::parse(unique_ptr<llvm::Module> *mod, unique_ptr<vector<TableDesc>> *tables,
const string &file, bool in_memory) {
using namespace clang;
diff --git a/src/cc/frontends/clang/loader.h b/src/cc/frontends/clang/loader.h
index d8b72fc..c657d5c 100644
--- a/src/cc/frontends/clang/loader.h
+++ b/src/cc/frontends/clang/loader.h
@@ -38,8 +38,7 @@
public:
explicit ClangLoader(llvm::LLVMContext *ctx);
~ClangLoader();
- int parse(std::unique_ptr<llvm::Module> *mod,
- std::unique_ptr<std::map<std::string, TableDesc>> *tables,
+ int parse(std::unique_ptr<llvm::Module> *mod, std::unique_ptr<std::vector<TableDesc>> *tables,
const std::string &file, bool in_memory);
private:
llvm::LLVMContext *ctx_;
diff --git a/src/cc/table_desc.h b/src/cc/table_desc.h
index ca067f6..d2e762b 100644
--- a/src/cc/table_desc.h
+++ b/src/cc/table_desc.h
@@ -20,14 +20,13 @@
namespace ebpf {
struct TableDesc {
+ std::string name;
int fd;
size_t key_size; // sizes are in bytes
size_t leaf_size;
size_t max_entries;
std::string key_desc;
std::string leaf_desc;
- std::string key_reader;
- std::string leaf_reader;
};
} // namespace ebpf