From 0a216ce3d1d2e4033fd22dc1f968d4e48d68e04c Mon Sep 17 00:00:00 2001 From: Hengqi Chen Date: Wed, 5 Jan 2022 00:00:39 +0800 Subject: [PATCH] bcc: support BPF_MAP_TYPE_{INODE, TASK}_STORAGE maps Add support for BPF_MAP_TYPE_{INODE, TASK}_STORAGE in BCC. Like sk local storage, this commit allows creating inode/task local storage using BPF_{INODE, TASK}_STORAGE macros, and manipulating maps using map.{inode, task}_storage_get() and map.{inode, task}_storage_delete() helpers. Signed-off-by: Hengqi Chen --- src/cc/api/BPF.h | 16 +++ src/cc/api/BPFTable.h | 58 ++++++++++ src/cc/export/helpers.h | 24 +++++ src/cc/frontends/clang/b_frontend_action.cc | 16 +++ src/python/bcc/table.py | 112 +++++++++++--------- 5 files changed, 174 insertions(+), 52 deletions(-) diff --git a/src/cc/api/BPF.h b/src/cc/api/BPF.h index c266828e..2d401ff7 100644 --- a/src/cc/api/BPF.h +++ b/src/cc/api/BPF.h @@ -161,6 +161,22 @@ class BPF { return BPFSkStorageTable({}); } + template + BPFInodeStorageTable get_inode_storage_table(const std::string& name) { + TableStorage::iterator it; + if (bpf_module_->table_storage().Find(Path({bpf_module_->id(), name}), it)) + return BPFInodeStorageTable(it->second); + return BPFInodeStorageTable({}); + } + + template + BPFTaskStorageTable get_task_storage_table(const std::string& name) { + TableStorage::iterator it; + if (bpf_module_->table_storage().Find(Path({bpf_module_->id(), name}), it)) + return BPFTaskStorageTable(it->second); + return BPFTaskStorageTable({}); + } + template BPFCgStorageTable get_cg_storage_table(const std::string& name) { TableStorage::iterator it; diff --git a/src/cc/api/BPFTable.h b/src/cc/api/BPFTable.h index ca04cd1f..4b902dcb 100644 --- a/src/cc/api/BPFTable.h +++ b/src/cc/api/BPFTable.h @@ -546,6 +546,64 @@ class BPFSkStorageTable : public BPFTableBase { } }; +template +class BPFInodeStorageTable : public BPFTableBase { + public: + BPFInodeStorageTable(const TableDesc& desc) : BPFTableBase(desc) { + if (desc.type != BPF_MAP_TYPE_INODE_STORAGE) + throw std::invalid_argument("Table '" + desc.name + + "' is not a inode_storage table"); + } + + virtual StatusTuple get_value(const int& fd, ValueType& value) { + if (!this->lookup(const_cast(&fd), get_value_addr(value))) + return StatusTuple(-1, "Error getting value: %s", std::strerror(errno)); + return StatusTuple::OK(); + } + + virtual StatusTuple update_value(const int& fd, const ValueType& value) { + if (!this->update(const_cast(&fd), + get_value_addr(const_cast(value)))) + return StatusTuple(-1, "Error updating value: %s", std::strerror(errno)); + return StatusTuple::OK(); + } + + virtual StatusTuple remove_value(const int& fd) { + if (!this->remove(const_cast(&fd))) + return StatusTuple(-1, "Error removing value: %s", std::strerror(errno)); + return StatusTuple::OK(); + } +}; + +template +class BPFTaskStorageTable : public BPFTableBase { + public: + BPFTaskStorageTable(const TableDesc& desc) : BPFTableBase(desc) { + if (desc.type != BPF_MAP_TYPE_TASK_STORAGE) + throw std::invalid_argument("Table '" + desc.name + + "' is not a task_storage table"); + } + + virtual StatusTuple get_value(const int& fd, ValueType& value) { + if (!this->lookup(const_cast(&fd), get_value_addr(value))) + return StatusTuple(-1, "Error getting value: %s", std::strerror(errno)); + return StatusTuple::OK(); + } + + virtual StatusTuple update_value(const int& fd, const ValueType& value) { + if (!this->update(const_cast(&fd), + get_value_addr(const_cast(value)))) + return StatusTuple(-1, "Error updating value: %s", std::strerror(errno)); + return StatusTuple::OK(); + } + + virtual StatusTuple remove_value(const int& fd) { + if (!this->remove(const_cast(&fd))) + return StatusTuple(-1, "Error removing value: %s", std::strerror(errno)); + return StatusTuple::OK(); + } +}; + template class BPFCgStorageTable : public BPFTableBase { public: diff --git a/src/cc/export/helpers.h b/src/cc/export/helpers.h index 91c2d35f..c1253e29 100644 --- a/src/cc/export/helpers.h +++ b/src/cc/export/helpers.h @@ -414,6 +414,30 @@ __attribute__((section("maps/sk_storage"))) \ struct _name##_table_t _name = { .flags = BPF_F_NO_PREALLOC }; \ BPF_ANNOTATE_KV_PAIR(_name, int, _leaf_type) +#define BPF_INODE_STORAGE(_name, _leaf_type) \ +struct _name##_table_t { \ + int key; \ + _leaf_type leaf; \ + void * (*inode_storage_get) (void *, void *, int); \ + int (*inode_storage_delete) (void *); \ + u32 flags; \ +}; \ +__attribute__((section("maps/inode_storage"))) \ +struct _name##_table_t _name = { .flags = BPF_F_NO_PREALLOC }; \ +BPF_ANNOTATE_KV_PAIR(_name, int, _leaf_type) + +#define BPF_TASK_STORAGE(_name, _leaf_type) \ +struct _name##_table_t { \ + int key; \ + _leaf_type leaf; \ + void * (*task_storage_get) (void *, void *, int); \ + int (*task_storage_delete) (void *); \ + u32 flags; \ +}; \ +__attribute__((section("maps/task_storage"))) \ +struct _name##_table_t _name = { .flags = BPF_F_NO_PREALLOC }; \ +BPF_ANNOTATE_KV_PAIR(_name, int, _leaf_type) + #define BPF_SOCKMAP_COMMON(_name, _max_entries, _kind, _helper_name) \ struct _name##_table_t { \ u32 key; \ diff --git a/src/cc/frontends/clang/b_frontend_action.cc b/src/cc/frontends/clang/b_frontend_action.cc index 9a6e510e..7bfc4ed7 100644 --- a/src/cc/frontends/clang/b_frontend_action.cc +++ b/src/cc/frontends/clang/b_frontend_action.cc @@ -1081,6 +1081,18 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) { } else if (memb_name == "sk_storage_delete") { prefix = "bpf_sk_storage_delete"; suffix = ")"; + } else if (memb_name == "inode_storage_get") { + prefix = "bpf_inode_storage_get"; + suffix = ")"; + } else if (memb_name == "inode_storage_delete") { + prefix = "bpf_inode_storage_delete"; + suffix = ")"; + } else if (memb_name == "task_storage_get") { + prefix = "bpf_task_storage_get"; + suffix = ")"; + } else if (memb_name == "task_storage_delete") { + prefix = "bpf_task_storage_delete"; + suffix = ")"; } else if (memb_name == "get_local_storage") { prefix = "bpf_get_local_storage"; suffix = ")"; @@ -1510,6 +1522,10 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) { map_type = BPF_MAP_TYPE_ARRAY_OF_MAPS; } else if (section_attr == "maps/sk_storage") { map_type = BPF_MAP_TYPE_SK_STORAGE; + } else if (section_attr == "maps/inode_storage") { + map_type = BPF_MAP_TYPE_INODE_STORAGE; + } else if (section_attr == "maps/task_storage") { + map_type = BPF_MAP_TYPE_TASK_STORAGE; } else if (section_attr == "maps/sockmap") { map_type = BPF_MAP_TYPE_SOCKMAP; } else if (section_attr == "maps/sockhash") { diff --git a/src/python/bcc/table.py b/src/python/bcc/table.py index 1ff24114..f3a0ba47 100644 --- a/src/python/bcc/table.py +++ b/src/python/bcc/table.py @@ -56,34 +56,40 @@ BPF_MAP_TYPE_SK_STORAGE = 24 BPF_MAP_TYPE_DEVMAP_HASH = 25 BPF_MAP_TYPE_STRUCT_OPS = 26 BPF_MAP_TYPE_RINGBUF = 27 - -map_type_name = {BPF_MAP_TYPE_HASH: "HASH", - BPF_MAP_TYPE_ARRAY: "ARRAY", - BPF_MAP_TYPE_PROG_ARRAY: "PROG_ARRAY", - BPF_MAP_TYPE_PERF_EVENT_ARRAY: "PERF_EVENT_ARRAY", - BPF_MAP_TYPE_PERCPU_HASH: "PERCPU_HASH", - BPF_MAP_TYPE_PERCPU_ARRAY: "PERCPU_ARRAY", - BPF_MAP_TYPE_STACK_TRACE: "STACK_TRACE", - BPF_MAP_TYPE_CGROUP_ARRAY: "CGROUP_ARRAY", - BPF_MAP_TYPE_LRU_HASH: "LRU_HASH", - BPF_MAP_TYPE_LRU_PERCPU_HASH: "LRU_PERCPU_HASH", - BPF_MAP_TYPE_LPM_TRIE: "LPM_TRIE", - BPF_MAP_TYPE_ARRAY_OF_MAPS: "ARRAY_OF_MAPS", - BPF_MAP_TYPE_HASH_OF_MAPS: "HASH_OF_MAPS", - BPF_MAP_TYPE_DEVMAP: "DEVMAP", - BPF_MAP_TYPE_SOCKMAP: "SOCKMAP", - BPF_MAP_TYPE_CPUMAP: "CPUMAP", - BPF_MAP_TYPE_XSKMAP: "XSKMAP", - BPF_MAP_TYPE_SOCKHASH: "SOCKHASH", - BPF_MAP_TYPE_CGROUP_STORAGE: "CGROUP_STORAGE", - BPF_MAP_TYPE_REUSEPORT_SOCKARRAY: "REUSEPORT_SOCKARRAY", - BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE: "PERCPU_CGROUP_STORAGE", - BPF_MAP_TYPE_QUEUE: "QUEUE", - BPF_MAP_TYPE_STACK: "STACK", - BPF_MAP_TYPE_SK_STORAGE: "SK_STORAGE", - BPF_MAP_TYPE_DEVMAP_HASH: "DEVMAP_HASH", - BPF_MAP_TYPE_STRUCT_OPS: "STRUCT_OPS", - BPF_MAP_TYPE_RINGBUF: "RINGBUF",} +BPF_MAP_TYPE_INODE_STORAGE = 28 +BPF_MAP_TYPE_TASK_STORAGE = 29 + +map_type_name = { + BPF_MAP_TYPE_HASH: "HASH", + BPF_MAP_TYPE_ARRAY: "ARRAY", + BPF_MAP_TYPE_PROG_ARRAY: "PROG_ARRAY", + BPF_MAP_TYPE_PERF_EVENT_ARRAY: "PERF_EVENT_ARRAY", + BPF_MAP_TYPE_PERCPU_HASH: "PERCPU_HASH", + BPF_MAP_TYPE_PERCPU_ARRAY: "PERCPU_ARRAY", + BPF_MAP_TYPE_STACK_TRACE: "STACK_TRACE", + BPF_MAP_TYPE_CGROUP_ARRAY: "CGROUP_ARRAY", + BPF_MAP_TYPE_LRU_HASH: "LRU_HASH", + BPF_MAP_TYPE_LRU_PERCPU_HASH: "LRU_PERCPU_HASH", + BPF_MAP_TYPE_LPM_TRIE: "LPM_TRIE", + BPF_MAP_TYPE_ARRAY_OF_MAPS: "ARRAY_OF_MAPS", + BPF_MAP_TYPE_HASH_OF_MAPS: "HASH_OF_MAPS", + BPF_MAP_TYPE_DEVMAP: "DEVMAP", + BPF_MAP_TYPE_SOCKMAP: "SOCKMAP", + BPF_MAP_TYPE_CPUMAP: "CPUMAP", + BPF_MAP_TYPE_XSKMAP: "XSKMAP", + BPF_MAP_TYPE_SOCKHASH: "SOCKHASH", + BPF_MAP_TYPE_CGROUP_STORAGE: "CGROUP_STORAGE", + BPF_MAP_TYPE_REUSEPORT_SOCKARRAY: "REUSEPORT_SOCKARRAY", + BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE: "PERCPU_CGROUP_STORAGE", + BPF_MAP_TYPE_QUEUE: "QUEUE", + BPF_MAP_TYPE_STACK: "STACK", + BPF_MAP_TYPE_SK_STORAGE: "SK_STORAGE", + BPF_MAP_TYPE_DEVMAP_HASH: "DEVMAP_HASH", + BPF_MAP_TYPE_STRUCT_OPS: "STRUCT_OPS", + BPF_MAP_TYPE_RINGBUF: "RINGBUF", + BPF_MAP_TYPE_INODE_STORAGE: "INODE_STORAGE", + BPF_MAP_TYPE_TASK_STORAGE: "TASK_STORAGE", +} stars_max = 40 log2_index_max = 65 @@ -202,30 +208,32 @@ def get_table_type_name(ttype): def _get_event_class(event_map): - ct_mapping = { 'char' : ct.c_char, - 's8' : ct.c_char, - 'unsigned char' : ct.c_ubyte, - 'u8' : ct.c_ubyte, - 'u8 *' : ct.c_char_p, - 'char *' : ct.c_char_p, - 'short' : ct.c_short, - 's16' : ct.c_short, - 'unsigned short' : ct.c_ushort, - 'u16' : ct.c_ushort, - 'int' : ct.c_int, - 's32' : ct.c_int, - 'enum' : ct.c_int, - 'unsigned int' : ct.c_uint, - 'u32' : ct.c_uint, - 'long' : ct.c_long, - 'unsigned long' : ct.c_ulong, - 'long long' : ct.c_longlong, - 's64' : ct.c_longlong, - 'unsigned long long': ct.c_ulonglong, - 'u64' : ct.c_ulonglong, - '__int128' : (ct.c_longlong * 2), - 'unsigned __int128' : (ct.c_ulonglong * 2), - 'void *' : ct.c_void_p } + ct_mapping = { + 'char' : ct.c_char, + 's8' : ct.c_char, + 'unsigned char' : ct.c_ubyte, + 'u8' : ct.c_ubyte, + 'u8 *' : ct.c_char_p, + 'char *' : ct.c_char_p, + 'short' : ct.c_short, + 's16' : ct.c_short, + 'unsigned short' : ct.c_ushort, + 'u16' : ct.c_ushort, + 'int' : ct.c_int, + 's32' : ct.c_int, + 'enum' : ct.c_int, + 'unsigned int' : ct.c_uint, + 'u32' : ct.c_uint, + 'long' : ct.c_long, + 'unsigned long' : ct.c_ulong, + 'long long' : ct.c_longlong, + 's64' : ct.c_longlong, + 'unsigned long long': ct.c_ulonglong, + 'u64' : ct.c_ulonglong, + '__int128' : (ct.c_longlong * 2), + 'unsigned __int128' : (ct.c_ulonglong * 2), + 'void *' : ct.c_void_p, + } # handle array types e.g. "int [16]" or "char[16]" array_type = re.compile(r"([^ ]+) ?\[([0-9]+)\]$") -- 2.34.1