Commit 8ac3ea7e authored by Brenden Blanco's avatar Brenden Blanco

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: default avatarBrenden Blanco <bblanco@plumgrid.com>
parent 0a1dc297
......@@ -225,9 +225,10 @@ int BPFModule::annotate() {
// 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 @@ unsigned BPFModule::kern_version() const {
}
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
......
......@@ -87,8 +87,8 @@ class BPFModule {
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_;
};
......
......@@ -1218,7 +1218,7 @@ StatusTuple CodegenLLVM::visit_func_decl_stmt_node(FuncDeclStmtNode *n) {
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 @@ StatusTuple CodegenLLVM::visit(Node* root, map<string, TableDesc> &tables) {
//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);
}
......
......@@ -63,7 +63,7 @@ class CodegenLLVM : public Visitor {
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;
......
......@@ -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 @@ BLoader::~BLoader() {
}
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 @@ int BLoader::parse(llvm::Module *mod, const string &filename, const string &prot
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);
......
......@@ -38,7 +38,7 @@ class BLoader {
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_;
......
......@@ -87,65 +87,7 @@ bool BMapDeclVisitor::VisitBuiltinType(const BuiltinType *T) {
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 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) {
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 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
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 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
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 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
<< "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 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
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 @@ bool BTypeConsumer::HandleTopLevelDecl(DeclGroupRef D) {
}
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() {
......
......@@ -53,25 +53,6 @@ class BMapDeclVisitor : public clang::RecursiveASTVisitor<BMapDeclVisitor> {
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 BScanfVisitor : public clang::RecursiveASTVisitor<BScanfVisitor> {
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 @@ class BTypeVisitor : public clang::RecursiveASTVisitor<BTypeVisitor> {
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 BTypeVisitor : public clang::RecursiveASTVisitor<BTypeVisitor> {
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 @@ class BFrontendAction : public clang::ASTFrontendAction {
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
......@@ -64,8 +64,7 @@ ClangLoader::ClangLoader(llvm::LLVMContext *ctx)
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;
......
......@@ -38,8 +38,7 @@ class ClangLoader {
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_;
......
......@@ -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
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