Skip to content

Commit

Permalink
Add TableStorage class for wrapping bpf map tracking
Browse files Browse the repository at this point in the history
Adds a TableStorage class for use by language frontends to store/access
references to loaded bpf maps. Includes support for shared and
namespaced maps, in a directory-like hierarchy.

Add a FileDesc helper class to automatically wrap open file descriptors.
The object prevents implicit copying of the fd (allows only
rvalue/move()), and takes care of the close() call.

Add a reference implementation of a TableStorageImpl that performs the
current default behavior expected by BPF_TABLE_PUBLIC, which is to share
maps between BPFModules in the same-process only. A stub implementation
for bpffs is started.

Update b/clang frontends to use this new class.

Also included is a framework for extracting the type information of maps
in an extensible way. Migrate BMapDeclVisitor to use this as the first
consumer.

Signed-off-by: Brenden Blanco <[email protected]>
  • Loading branch information
drzaeus77 committed Apr 3, 2017
1 parent 271056f commit faea8c8
Show file tree
Hide file tree
Showing 23 changed files with 806 additions and 278 deletions.
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ BasedOnStyle: Google
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
IndentCaseLabels: false
AccessModifierOffset: -2
AccessModifierOffset: -1
3 changes: 2 additions & 1 deletion src/cc/BPF.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@
#include "bcc_exception.h"
#include "bcc_syms.h"
#include "bpf_module.h"
#include "common.h"
#include "libbpf.h"
#include "perf_reader.h"
#include "common.h"
#include "table_storage.h"
#include "usdt.h"

#include "BPF.h"
Expand Down
11 changes: 10 additions & 1 deletion src/cc/BPF.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "bpf_module.h"
#include "compat/linux/bpf.h"
#include "libbpf.h"
#include "table_storage.h"

static const int DEFAULT_PERF_BUFFER_PAGE_CNT = 8;

Expand All @@ -38,12 +39,14 @@ struct open_probe_t {
};

class USDT;
class TableStorage;

class BPF {
public:
static const int BPF_MAX_STACK_DEPTH = 127;

explicit BPF(unsigned int flag = 0) : bpf_module_(new BPFModule(flag)) {}
explicit BPF(unsigned int flag = 0, TableStorage* ts = nullptr)
: bpf_module_(new BPFModule(flag, ts)), ts_(ts) {}
StatusTuple init(const std::string& bpf_program,
std::vector<std::string> cflags = {},
std::vector<USDT> usdt = {});
Expand Down Expand Up @@ -90,6 +93,11 @@ class BPF {

template <class KeyType, class ValueType>
BPFHashTable<KeyType, ValueType> get_hash_table(const std::string& name) {
if (ts_) {
TableStorage::iterator it;
if (ts_->Find(Path({name}), it))
return BPFHashTable<KeyType, ValueType>(it->second);
}
return BPFHashTable<KeyType, ValueType>(bpf_module_.get(), name);
}

Expand Down Expand Up @@ -152,6 +160,7 @@ class BPF {
uint64_t symbol_addr, bcc_symbol* output);

std::unique_ptr<BPFModule> bpf_module_;
TableStorage* ts_;

std::map<std::string, int> funcs_;

Expand Down
8 changes: 7 additions & 1 deletion src/cc/BPFTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "bpf_module.h"
#include "libbpf.h"
#include "perf_reader.h"
#include "table_desc.h"

namespace ebpf {

Expand All @@ -44,6 +45,10 @@ class BPFTableBase {
fd_ = bpf_module->table_fd(id_);
capacity_ = bpf_module->table_max_entries(id_);
};
explicit BPFTableBase(const TableDesc& desc) {
fd_ = desc.fd;
capacity_ = desc.max_entries;
}

bool lookup(KeyType* key, ValueType* value) {
return bpf_lookup_elem(fd_, static_cast<void*>(key),
Expand All @@ -70,7 +75,8 @@ class BPFTableBase {

template <class KeyType, class ValueType>
class BPFHashTable : protected BPFTableBase<KeyType, ValueType> {
public:
public:
explicit BPFHashTable(const TableDesc& desc) : BPFTableBase<KeyType, ValueType>(desc) {}
BPFHashTable(BPFModule* bpf_module, const std::string& name)
: BPFTableBase<KeyType, ValueType>(bpf_module, name) {}

Expand Down
6 changes: 3 additions & 3 deletions src/cc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ if (CMAKE_COMPILER_IS_GNUCC AND LIBCLANG_ISSTATIC)
endif()
endif()

add_library(bcc-shared SHARED bpf_common.cc bpf_module.cc libbpf.c perf_reader.c shared_table.cc exported_files.cc bcc_elf.c bcc_perf_map.c bcc_proc.c bcc_syms.cc usdt_args.cc usdt.cc common.cc BPF.cc BPFTable.cc)
add_library(bcc-shared SHARED bpf_common.cc bpf_module.cc libbpf.c perf_reader.c table_storage.cc shared_table.cc bpffs_table.cc json_map_decl_visitor.cc exported_files.cc bcc_elf.c bcc_perf_map.c bcc_proc.c bcc_syms.cc usdt_args.cc usdt.cc common.cc BPF.cc BPFTable.cc)
set_target_properties(bcc-shared PROPERTIES VERSION ${REVISION_LAST} SOVERSION 0)
set_target_properties(bcc-shared PROPERTIES OUTPUT_NAME bcc)

add_library(bcc-loader-static STATIC libbpf.c perf_reader.c bcc_elf.c bcc_perf_map.c bcc_proc.c)
add_library(bcc-static STATIC bpf_common.cc bpf_module.cc shared_table.cc exported_files.cc bcc_syms.cc usdt_args.cc usdt.cc common.cc BPF.cc BPFTable.cc)
add_library(bcc-static STATIC bpf_common.cc bpf_module.cc shared_table.cc bpffs_table.cc json_map_decl_visitor.cc table_storage.cc exported_files.cc bcc_syms.cc usdt_args.cc usdt.cc common.cc BPF.cc BPFTable.cc)
set_target_properties(bcc-static PROPERTIES OUTPUT_NAME bcc)

set(llvm_raw_libs bitwriter bpfcodegen irreader linker
Expand All @@ -67,7 +67,7 @@ target_link_libraries(bcc-static b_frontend clang_frontend bcc-loader-static ${c

install(TARGETS bcc-shared LIBRARY COMPONENT libbcc
DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES bpf_common.h bpf_module.h bcc_syms.h bcc_exception.h libbpf.h perf_reader.h BPF.h BPFTable.h shared_table.h COMPONENT libbcc
install(FILES bpf_common.h bpf_module.h bcc_syms.h bcc_exception.h libbpf.h perf_reader.h BPF.h BPFTable.h shared_table.h table_desc.h COMPONENT libbcc
DESTINATION include/bcc)
install(DIRECTORY compat/linux/ COMPONENT libbcc
DESTINATION include/bcc/compat/linux
Expand Down
100 changes: 56 additions & 44 deletions src/cc/bpf_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -101,30 +101,26 @@ class MyMemoryManager : public SectionMemoryManager {
map<string, tuple<uint8_t *, uintptr_t>> *sections_;
};

BPFModule::BPFModule(unsigned flags)
: flags_(flags), ctx_(new LLVMContext) {
BPFModule::BPFModule(unsigned flags, TableStorage *ts)
: flags_(flags), ctx_(new LLVMContext), ts_(ts) {
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
LLVMInitializeBPFTarget();
LLVMInitializeBPFTargetMC();
LLVMInitializeBPFTargetInfo();
LLVMInitializeBPFAsmPrinter();
LLVMLinkInMCJIT(); /* call empty function to force linking of MCJIT */
if (!ts_) {
local_ts_ = createSharedTableStorage();
ts_ = &*local_ts_;
}
}

BPFModule::~BPFModule() {
engine_.reset();
rw_engine_.reset();
ctx_.reset();
if (tables_) {
for (auto table : *tables_) {
if (table.is_shared) {
SharedTables::instance()->remove_fd(table.name);
} else if (!table.is_extern) {
close(table.fd);
}
}
}
ts_->DeletePrefix(Path({std::to_string((uintptr_t)this)}));
}

static void debug_printf(Module *mod, IRBuilder<> &B, const string &fmt, vector<Value *> args) {
Expand Down Expand Up @@ -326,7 +322,8 @@ unique_ptr<ExecutionEngine> BPFModule::finalize_rw(unique_ptr<Module> m) {
// load an entire c file as a module
int BPFModule::load_cfile(const string &file, bool in_memory, const char *cflags[], int ncflags) {
clang_loader_ = make_unique<ClangLoader>(&*ctx_, flags_);
if (clang_loader_->parse(&mod_, &tables_, file, in_memory, cflags, ncflags))
if (clang_loader_->parse(&mod_, *ts_, file, in_memory, cflags, ncflags,
std::to_string((uintptr_t)this)))
return -1;
return 0;
}
Expand All @@ -338,7 +335,7 @@ int BPFModule::load_cfile(const string &file, bool in_memory, const char *cflags
// build an ExecutionEngine.
int BPFModule::load_includes(const string &text) {
clang_loader_ = make_unique<ClangLoader>(&*ctx_, flags_);
if (clang_loader_->parse(&mod_, &tables_, text, true, nullptr, 0))
if (clang_loader_->parse(&mod_, *ts_, text, true, nullptr, 0, ""))
return -1;
return 0;
}
Expand All @@ -352,7 +349,10 @@ int BPFModule::annotate() {
auto m = make_unique<Module>("sscanf", *ctx_);

size_t id = 0;
for (auto &table : *tables_) {
Path path({std::to_string((uintptr_t)this)});
for (auto it = ts_->lower_bound(path), up = ts_->upper_bound(path); it != up; ++it) {
TableDesc &table = it->second;
tables_.push_back(&it->second);
table_names_[table.name] = id++;
GlobalValue *gvar = mod_->getNamedValue(table.name);
if (!gvar) continue;
Expand Down Expand Up @@ -507,9 +507,7 @@ unsigned BPFModule::kern_version() const {
return *(unsigned *)get<0>(section->second);
}

size_t BPFModule::num_tables() const {
return tables_->size();
}
size_t BPFModule::num_tables() const { return tables_.size(); }

size_t BPFModule::table_id(const string &name) const {
auto it = table_names_.find(name);
Expand All @@ -522,46 +520,52 @@ int BPFModule::table_fd(const string &name) const {
}

int BPFModule::table_fd(size_t id) const {
if (id >= tables_->size()) return -1;
return (*tables_)[id].fd;
if (id >= tables_.size())
return -1;
return tables_[id]->fd;
}

int BPFModule::table_type(const string &name) const {
return table_type(table_id(name));
}

int BPFModule::table_type(size_t id) const {
if (id >= tables_->size()) return -1;
return (*tables_)[id].type;
if (id >= tables_.size())
return -1;
return tables_[id]->type;
}

size_t BPFModule::table_max_entries(const string &name) const {
return table_max_entries(table_id(name));
}

size_t BPFModule::table_max_entries(size_t id) const {
if (id >= tables_->size()) return 0;
return (*tables_)[id].max_entries;
if (id >= tables_.size())
return 0;
return tables_[id]->max_entries;
}

int BPFModule::table_flags(const string &name) const {
return table_flags(table_id(name));
}

int BPFModule::table_flags(size_t id) const {
if (id >= tables_->size()) return -1;
return (*tables_)[id].flags;
if (id >= tables_.size())
return -1;
return tables_[id]->flags;
}

const char * BPFModule::table_name(size_t id) const {
if (id >= tables_->size()) return nullptr;
return (*tables_)[id].name.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 (b_loader_) return nullptr;
if (id >= tables_->size()) return nullptr;
return (*tables_)[id].key_desc.c_str();
if (id >= tables_.size())
return nullptr;
return tables_[id]->key_desc.c_str();
}

const char * BPFModule::table_key_desc(const string &name) const {
Expand All @@ -570,24 +574,27 @@ const char * BPFModule::table_key_desc(const string &name) const {

const char * BPFModule::table_leaf_desc(size_t id) const {
if (b_loader_) return nullptr;
if (id >= tables_->size()) return nullptr;
return (*tables_)[id].leaf_desc.c_str();
if (id >= tables_.size())
return nullptr;
return tables_[id]->leaf_desc.c_str();
}

const char * BPFModule::table_leaf_desc(const string &name) const {
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;
if (id >= tables_.size())
return 0;
return tables_[id]->key_size;
}
size_t BPFModule::table_key_size(const string &name) const {
return table_key_size(table_id(name));
}

size_t BPFModule::table_leaf_size(size_t id) const {
if (id >= tables_->size()) return 0;
return (*tables_)[id].leaf_size;
if (id >= tables_.size())
return 0;
return tables_[id]->leaf_size;
}
size_t BPFModule::table_leaf_size(const string &name) const {
return table_leaf_size(table_id(name));
Expand All @@ -603,8 +610,9 @@ struct TableIterator {
};

int BPFModule::table_key_printf(size_t id, char *buf, size_t buflen, const void *key) {
if (id >= tables_->size()) return -1;
const TableDesc &desc = (*tables_)[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;
Expand All @@ -627,8 +635,9 @@ 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()) return -1;
const TableDesc &desc = (*tables_)[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;
Expand All @@ -651,8 +660,9 @@ 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 (id >= tables_.size())
return -1;
const TableDesc &desc = *tables_[id];
if (!desc.key_sscanf) {
fprintf(stderr, "Key sscanf not available\n");
return -1;
Expand All @@ -672,8 +682,9 @@ int BPFModule::table_key_scanf(size_t id, const char *key_str, void *key) {
}

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 (id >= tables_.size())
return -1;
const TableDesc &desc = *tables_[id];
if (!desc.leaf_sscanf) {
fprintf(stderr, "Key sscanf not available\n");
return -1;
Expand Down Expand Up @@ -714,7 +725,8 @@ int BPFModule::load_b(const string &filename, const string &proto_filename) {
return rc;

b_loader_.reset(new BLoader(flags_));
if (int rc = b_loader_->parse(&*mod_, filename, proto_filename, &tables_))
if (int rc =
b_loader_->parse(&*mod_, filename, proto_filename, *ts_, std::to_string((uintptr_t)this)))
return rc;
if (int rc = annotate())
return rc;
Expand Down
9 changes: 6 additions & 3 deletions src/cc/bpf_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class Type;
}

namespace ebpf {
struct TableDesc;
class TableDesc;
class TableStorage;
class BLoader;
class ClangLoader;

Expand All @@ -52,7 +53,7 @@ class BPFModule {
int kbuild_flags(const char *uname_release, std::vector<std::string> *cflags);
int run_pass_manager(llvm::Module &mod);
public:
BPFModule(unsigned flags);
BPFModule(unsigned flags, TableStorage *ts = nullptr);
~BPFModule();
int load_b(const std::string &filename, const std::string &proto_filename);
int load_c(const std::string &filename, const char *cflags[], int ncflags);
Expand Down Expand Up @@ -99,11 +100,13 @@ 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::vector<TableDesc>> tables_;
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_;
std::map<llvm::Type *, llvm::Function *> writers_;
TableStorage *ts_;
std::unique_ptr<TableStorage> local_ts_;
};

} // namespace ebpf
Loading

0 comments on commit faea8c8

Please sign in to comment.