| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670 |
- /*
- * Copyright (c) 2016 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #pragma once
- #include <errno.h>
- #include <sys/epoll.h>
- #include <cstring>
- #include <exception>
- #include <map>
- #include <memory>
- #include <string>
- #include <utility>
- #include <vector>
- #include "bcc_exception.h"
- #include "bcc_syms.h"
- #include "bpf_module.h"
- #include "libbpf.h"
- #include "perf_reader.h"
- #include "table_desc.h"
- #include "linux/bpf.h"
- namespace ebpf {
- template<class ValueType>
- class BPFQueueStackTableBase {
- public:
- size_t capacity() const { return desc.max_entries; }
- StatusTuple string_to_leaf(const std::string& value_str, ValueType* value) {
- return desc.leaf_sscanf(value_str.c_str(), value);
- }
- StatusTuple leaf_to_string(const ValueType* value, std::string& value_str) {
- char buf[8 * desc.leaf_size];
- StatusTuple rc = desc.leaf_snprintf(buf, sizeof(buf), value);
- if (rc.ok())
- value_str.assign(buf);
- return rc;
- }
- int get_fd() { return desc.fd; }
- protected:
- explicit BPFQueueStackTableBase(const TableDesc& desc) : desc(desc) {}
- bool pop(void *value) {
- return bpf_lookup_and_delete(desc.fd, nullptr, value) >= 0;
- }
- // Flags are extremely useful, since they completely changes extraction behaviour
- // (eg. if flag BPF_EXIST, then if the queue/stack is full remove the oldest one)
- bool push(void *value, unsigned long long int flags) {
- return bpf_update_elem(desc.fd, nullptr, value, flags) >= 0;
- }
- bool peek(void *value) {
- return bpf_lookup_elem(desc.fd, nullptr, value) >= 0;
- }
- const TableDesc& desc;
- };
- template <class KeyType, class ValueType>
- class BPFTableBase {
- public:
- size_t capacity() { return desc.max_entries; }
- StatusTuple string_to_key(const std::string& key_str, KeyType* key) {
- return desc.key_sscanf(key_str.c_str(), key);
- }
- StatusTuple string_to_leaf(const std::string& value_str, ValueType* value) {
- return desc.leaf_sscanf(value_str.c_str(), value);
- }
- StatusTuple key_to_string(const KeyType* key, std::string& key_str) {
- char buf[8 * desc.key_size];
- StatusTuple rc = desc.key_snprintf(buf, sizeof(buf), key);
- if (rc.ok())
- key_str.assign(buf);
- return rc;
- }
- StatusTuple leaf_to_string(const ValueType* value, std::string& value_str) {
- char buf[8 * desc.leaf_size];
- StatusTuple rc = desc.leaf_snprintf(buf, sizeof(buf), value);
- if (rc.ok())
- value_str.assign(buf);
- return rc;
- }
- int get_fd() {
- return desc.fd;
- }
- protected:
- explicit BPFTableBase(const TableDesc& desc) : desc(desc) {}
- bool lookup(void* key, void* value) {
- return bpf_lookup_elem(desc.fd, key, value) >= 0;
- }
- bool first(void* key) {
- return bpf_get_first_key(desc.fd, key, desc.key_size) >= 0;
- }
- bool next(void* key, void* next_key) {
- return bpf_get_next_key(desc.fd, key, next_key) >= 0;
- }
- bool update(void* key, void* value) {
- return bpf_update_elem(desc.fd, key, value, 0) >= 0;
- }
- bool remove(void* key) { return bpf_delete_elem(desc.fd, key) >= 0; }
- const TableDesc& desc;
- };
- class BPFTable : public BPFTableBase<void, void> {
- public:
- BPFTable(const TableDesc& desc);
- StatusTuple get_value(const std::string& key_str, std::string& value);
- StatusTuple get_value(const std::string& key_str,
- std::vector<std::string>& value);
- StatusTuple update_value(const std::string& key_str,
- const std::string& value_str);
- StatusTuple update_value(const std::string& key_str,
- const std::vector<std::string>& value_str);
- StatusTuple remove_value(const std::string& key_str);
- StatusTuple clear_table_non_atomic();
- StatusTuple get_table_offline(std::vector<std::pair<std::string, std::string>> &res);
- StatusTuple get_table_offline_ptr(std::vector<std::pair<std::vector<char>, std::vector<char>>> &res);
- static size_t get_possible_cpu_count();
- };
- template <class ValueType>
- void* get_value_addr(ValueType& t) {
- return &t;
- }
- template <class ValueType>
- void* get_value_addr(std::vector<ValueType>& t) {
- return t.data();
- }
- template<class ValueType>
- class BPFQueueStackTable : public BPFQueueStackTableBase<void> {
- public:
- explicit BPFQueueStackTable(const TableDesc& desc) : BPFQueueStackTableBase(desc) {
- if (desc.type != BPF_MAP_TYPE_QUEUE &&
- desc.type != BPF_MAP_TYPE_STACK)
- throw std::invalid_argument("Table '" + desc.name +
- "' is not a queue/stack table");
- }
- virtual StatusTuple pop_value(ValueType& value) {
- if (!this->pop(get_value_addr(value)))
- return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- virtual StatusTuple push_value(const ValueType& value, unsigned long long int flags = 0) {
- if (!this->push(get_value_addr(const_cast<ValueType&>(value)), flags))
- return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- virtual StatusTuple get_head(const ValueType& value) {
- if (!this->peek(get_value_addr(const_cast<ValueType&>(value))))
- return StatusTuple(-1, "Error peeking value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- };
- template <class ValueType>
- class BPFArrayTable : public BPFTableBase<int, ValueType> {
- public:
- BPFArrayTable(const TableDesc& desc) : BPFTableBase<int, ValueType>(desc) {
- if (desc.type != BPF_MAP_TYPE_ARRAY &&
- desc.type != BPF_MAP_TYPE_PERCPU_ARRAY)
- throw std::invalid_argument("Table '" + desc.name +
- "' is not an array table");
- }
- virtual StatusTuple get_value(const int& index, ValueType& value) {
- if (!this->lookup(const_cast<int*>(&index), get_value_addr(value)))
- return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- virtual StatusTuple update_value(const int& index, const ValueType& value) {
- if (!this->update(const_cast<int*>(&index),
- get_value_addr(const_cast<ValueType&>(value))))
- return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- ValueType operator[](const int& key) {
- ValueType value;
- get_value(key, value);
- return value;
- }
- std::vector<ValueType> get_table_offline() {
- std::vector<ValueType> res(this->capacity());
- for (int i = 0; i < (int)this->capacity(); i++) {
- get_value(i, res[i]);
- }
- return res;
- }
- };
- template <class ValueType>
- class BPFPercpuArrayTable : public BPFArrayTable<std::vector<ValueType>> {
- public:
- BPFPercpuArrayTable(const TableDesc& desc)
- : BPFArrayTable<std::vector<ValueType>>(desc),
- ncpus(BPFTable::get_possible_cpu_count()) {
- if (desc.type != BPF_MAP_TYPE_PERCPU_ARRAY)
- throw std::invalid_argument("Table '" + desc.name +
- "' is not a percpu array table");
- // leaf structures have to be aligned to 8 bytes as hardcoded in the linux
- // kernel.
- if (sizeof(ValueType) % 8)
- throw std::invalid_argument("leaf must be aligned to 8 bytes");
- }
- StatusTuple get_value(const int& index, std::vector<ValueType>& value) {
- value.resize(ncpus);
- return BPFArrayTable<std::vector<ValueType>>::get_value(index, value);
- }
- StatusTuple update_value(const int& index,
- const std::vector<ValueType>& value) {
- if (value.size() != ncpus)
- return StatusTuple(-1, "bad value size");
- return BPFArrayTable<std::vector<ValueType>>::update_value(index, value);
- }
- private:
- unsigned int ncpus;
- };
- template <class KeyType, class ValueType>
- class BPFHashTable : public BPFTableBase<KeyType, ValueType> {
- public:
- explicit BPFHashTable(const TableDesc& desc)
- : BPFTableBase<KeyType, ValueType>(desc) {
- if (desc.type != BPF_MAP_TYPE_HASH &&
- desc.type != BPF_MAP_TYPE_PERCPU_HASH &&
- desc.type != BPF_MAP_TYPE_LRU_HASH &&
- desc.type != BPF_MAP_TYPE_LRU_PERCPU_HASH)
- throw std::invalid_argument("Table '" + desc.name +
- "' is not a hash table");
- }
- virtual StatusTuple get_value(const KeyType& key, ValueType& value) {
- if (!this->lookup(const_cast<KeyType*>(&key), get_value_addr(value)))
- return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- virtual StatusTuple update_value(const KeyType& key, const ValueType& value) {
- if (!this->update(const_cast<KeyType*>(&key),
- get_value_addr(const_cast<ValueType&>(value))))
- return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- virtual StatusTuple remove_value(const KeyType& key) {
- if (!this->remove(const_cast<KeyType*>(&key)))
- return StatusTuple(-1, "Error removing value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- ValueType operator[](const KeyType& key) {
- ValueType value;
- get_value(key, value);
- return value;
- }
- std::vector<std::pair<KeyType, ValueType>> get_table_offline() {
- std::vector<std::pair<KeyType, ValueType>> res;
- KeyType cur;
- ValueType value;
- StatusTuple r(0);
- if (!this->first(&cur))
- return res;
- while (true) {
- r = get_value(cur, value);
- if (!r.ok())
- break;
- res.emplace_back(cur, value);
- if (!this->next(&cur, &cur))
- break;
- }
- return res;
- }
- StatusTuple clear_table_non_atomic() {
- KeyType cur;
- while (this->first(&cur))
- TRY2(remove_value(cur));
- return StatusTuple::OK();
- }
- };
- template <class KeyType, class ValueType>
- class BPFPercpuHashTable
- : public BPFHashTable<KeyType, std::vector<ValueType>> {
- public:
- explicit BPFPercpuHashTable(const TableDesc& desc)
- : BPFHashTable<KeyType, std::vector<ValueType>>(desc),
- ncpus(BPFTable::get_possible_cpu_count()) {
- if (desc.type != BPF_MAP_TYPE_PERCPU_HASH &&
- desc.type != BPF_MAP_TYPE_LRU_PERCPU_HASH)
- throw std::invalid_argument("Table '" + desc.name +
- "' is not a percpu hash table");
- // leaf structures have to be aligned to 8 bytes as hardcoded in the linux
- // kernel.
- if (sizeof(ValueType) % 8)
- throw std::invalid_argument("leaf must be aligned to 8 bytes");
- }
- StatusTuple get_value(const KeyType& key, std::vector<ValueType>& value) {
- value.resize(ncpus);
- return BPFHashTable<KeyType, std::vector<ValueType>>::get_value(key, value);
- }
- StatusTuple update_value(const KeyType& key,
- const std::vector<ValueType>& value) {
- if (value.size() != ncpus)
- return StatusTuple(-1, "bad value size");
- return BPFHashTable<KeyType, std::vector<ValueType>>::update_value(key,
- value);
- }
- private:
- unsigned int ncpus;
- };
- // From src/cc/export/helpers.h
- static const int BPF_MAX_STACK_DEPTH = 127;
- struct stacktrace_t {
- uintptr_t ip[BPF_MAX_STACK_DEPTH];
- };
- class BPFStackTable : public BPFTableBase<int, stacktrace_t> {
- public:
- BPFStackTable(const TableDesc& desc, bool use_debug_file,
- bool check_debug_file_crc);
- BPFStackTable(BPFStackTable&& that);
- ~BPFStackTable();
- void free_symcache(int pid);
- void clear_table_non_atomic();
- std::vector<uintptr_t> get_stack_addr(int stack_id);
- std::vector<std::string> get_stack_symbol(int stack_id, int pid);
- private:
- bcc_symbol_option symbol_option_;
- std::map<int, void*> pid_sym_;
- };
- // from src/cc/export/helpers.h
- struct stacktrace_buildid_t {
- struct bpf_stack_build_id trace[BPF_MAX_STACK_DEPTH];
- };
- class BPFStackBuildIdTable : public BPFTableBase<int, stacktrace_buildid_t> {
- public:
- BPFStackBuildIdTable(const TableDesc& desc, bool use_debug_file,
- bool check_debug_file_crc, void *bsymcache);
- ~BPFStackBuildIdTable() = default;
- void clear_table_non_atomic();
- std::vector<bpf_stack_build_id> get_stack_addr(int stack_id);
- std::vector<std::string> get_stack_symbol(int stack_id);
- private:
- void *bsymcache_;
- bcc_symbol_option symbol_option_;
- };
- class BPFPerfBuffer : public BPFTableBase<int, int> {
- public:
- BPFPerfBuffer(const TableDesc& desc);
- ~BPFPerfBuffer();
- StatusTuple open_all_cpu(perf_reader_raw_cb cb, perf_reader_lost_cb lost_cb,
- void* cb_cookie, int page_cnt);
- StatusTuple open_all_cpu(perf_reader_raw_cb cb, perf_reader_lost_cb lost_cb,
- void* cb_cookie, int page_cnt, int wakeup_events);
- StatusTuple close_all_cpu();
- int poll(int timeout_ms);
- int consume();
- private:
- StatusTuple open_on_cpu(perf_reader_raw_cb cb, perf_reader_lost_cb lost_cb,
- void* cb_cookie, int page_cnt, struct bcc_perf_buffer_opts& opts);
- StatusTuple close_on_cpu(int cpu);
- std::map<int, perf_reader*> cpu_readers_;
- int epfd_;
- std::unique_ptr<epoll_event[]> ep_events_;
- };
- class BPFPerfEventArray : public BPFTableBase<int, int> {
- public:
- BPFPerfEventArray(const TableDesc& desc);
- ~BPFPerfEventArray();
- StatusTuple open_all_cpu(uint32_t type, uint64_t config, int pid = -1);
- StatusTuple close_all_cpu();
- private:
- StatusTuple open_on_cpu(int cpu, uint32_t type, uint64_t config, int pid = -1);
- StatusTuple close_on_cpu(int cpu);
- std::map<int, int> cpu_fds_;
- };
- class BPFProgTable : public BPFTableBase<int, int> {
- public:
- BPFProgTable(const TableDesc& desc);
- StatusTuple update_value(const int& index, const int& prog_fd);
- StatusTuple remove_value(const int& index);
- };
- class BPFCgroupArray : public BPFTableBase<int, int> {
- public:
- BPFCgroupArray(const TableDesc& desc);
- StatusTuple update_value(const int& index, const int& cgroup2_fd);
- StatusTuple update_value(const int& index, const std::string& cgroup2_path);
- StatusTuple remove_value(const int& index);
- };
- class BPFDevmapTable : public BPFTableBase<int, int> {
- public:
- BPFDevmapTable(const TableDesc& desc);
- StatusTuple update_value(const int& index, const int& value);
- StatusTuple get_value(const int& index, int& value);
- StatusTuple remove_value(const int& index);
- };
- class BPFXskmapTable : public BPFTableBase<int, int> {
- public:
- BPFXskmapTable(const TableDesc& desc);
- StatusTuple update_value(const int& index, const int& value);
- StatusTuple get_value(const int& index, int& value);
- StatusTuple remove_value(const int& index);
- };
- template <class KeyType>
- class BPFMapInMapTable : public BPFTableBase<KeyType, int> {
- public:
- BPFMapInMapTable(const TableDesc& desc) : BPFTableBase<KeyType, int>(desc) {
- if (desc.type != BPF_MAP_TYPE_ARRAY_OF_MAPS &&
- desc.type != BPF_MAP_TYPE_HASH_OF_MAPS)
- throw std::invalid_argument("Table '" + desc.name +
- "' is not a map-in-map table");
- }
- virtual StatusTuple update_value(const KeyType& key, const int& inner_map_fd) {
- if (!this->update(const_cast<KeyType*>(&key),
- const_cast<int*>(&inner_map_fd)))
- return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- virtual StatusTuple remove_value(const KeyType& key) {
- if (!this->remove(const_cast<KeyType*>(&key)))
- return StatusTuple(-1, "Error removing value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- };
- class BPFSockmapTable : public BPFTableBase<int, int> {
- public:
- BPFSockmapTable(const TableDesc& desc);
- StatusTuple update_value(const int& index, const int& value);
- StatusTuple remove_value(const int& index);
- };
- class BPFSockhashTable : public BPFTableBase<int, int> {
- public:
- BPFSockhashTable(const TableDesc& desc);
- StatusTuple update_value(const int& key, const int& value);
- StatusTuple remove_value(const int& key);
- };
- template <class ValueType>
- class BPFSkStorageTable : public BPFTableBase<int, ValueType> {
- public:
- BPFSkStorageTable(const TableDesc& desc) : BPFTableBase<int, ValueType>(desc) {
- if (desc.type != BPF_MAP_TYPE_SK_STORAGE)
- throw std::invalid_argument("Table '" + desc.name +
- "' is not a sk_storage table");
- }
- virtual StatusTuple get_value(const int& sock_fd, ValueType& value) {
- if (!this->lookup(const_cast<int*>(&sock_fd), get_value_addr(value)))
- return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- virtual StatusTuple update_value(const int& sock_fd, const ValueType& value) {
- if (!this->update(const_cast<int*>(&sock_fd),
- get_value_addr(const_cast<ValueType&>(value))))
- return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- virtual StatusTuple remove_value(const int& sock_fd) {
- if (!this->remove(const_cast<int*>(&sock_fd)))
- return StatusTuple(-1, "Error removing value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- };
- template <class ValueType>
- class BPFInodeStorageTable : public BPFTableBase<int, ValueType> {
- public:
- BPFInodeStorageTable(const TableDesc& desc) : BPFTableBase<int, ValueType>(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<int*>(&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<int*>(&fd),
- get_value_addr(const_cast<ValueType&>(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<int*>(&fd)))
- return StatusTuple(-1, "Error removing value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- };
- template <class ValueType>
- class BPFTaskStorageTable : public BPFTableBase<int, ValueType> {
- public:
- BPFTaskStorageTable(const TableDesc& desc) : BPFTableBase<int, ValueType>(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<int*>(&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<int*>(&fd),
- get_value_addr(const_cast<ValueType&>(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<int*>(&fd)))
- return StatusTuple(-1, "Error removing value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- };
- template <class ValueType>
- class BPFCgStorageTable : public BPFTableBase<int, ValueType> {
- public:
- BPFCgStorageTable(const TableDesc& desc) : BPFTableBase<int, ValueType>(desc) {
- if (desc.type != BPF_MAP_TYPE_CGROUP_STORAGE)
- throw std::invalid_argument("Table '" + desc.name +
- "' is not a cgroup_storage table");
- }
- virtual StatusTuple get_value(struct bpf_cgroup_storage_key& key,
- ValueType& value) {
- if (!this->lookup(const_cast<struct bpf_cgroup_storage_key*>(&key),
- get_value_addr(value)))
- return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- virtual StatusTuple update_value(struct bpf_cgroup_storage_key& key, const ValueType& value) {
- if (!this->update(const_cast<struct bpf_cgroup_storage_key*>(&key),
- get_value_addr(const_cast<ValueType&>(value))))
- return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- };
- template <class ValueType>
- class BPFPercpuCgStorageTable : public BPFTableBase<int, std::vector<ValueType>> {
- public:
- BPFPercpuCgStorageTable(const TableDesc& desc)
- : BPFTableBase<int, std::vector<ValueType>>(desc) {
- if (desc.type != BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
- throw std::invalid_argument("Table '" + desc.name +
- "' is not a percpu_cgroup_storage table");
- if (sizeof(ValueType) % 8)
- throw std::invalid_argument("leaf must be aligned to 8 bytes");
- ncpus = BPFTable::get_possible_cpu_count();
- }
- virtual StatusTuple get_value(struct bpf_cgroup_storage_key& key,
- std::vector<ValueType>& value) {
- value.resize(ncpus);
- if (!this->lookup(const_cast<struct bpf_cgroup_storage_key*>(&key),
- get_value_addr(value)))
- return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- virtual StatusTuple update_value(struct bpf_cgroup_storage_key& key,
- std::vector<ValueType>& value) {
- value.resize(ncpus);
- if (!this->update(const_cast<struct bpf_cgroup_storage_key*>(&key),
- get_value_addr(const_cast<std::vector<ValueType>&>(value))))
- return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
- return StatusTuple::OK();
- }
- private:
- unsigned int ncpus;
- };
- } // namespace ebpf
|