1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker * Copyright (c) 2016 Facebook, Inc.
3*387f9dfdSAndroid Build Coastguard Worker *
4*387f9dfdSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*387f9dfdSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*387f9dfdSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*387f9dfdSAndroid Build Coastguard Worker *
8*387f9dfdSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*387f9dfdSAndroid Build Coastguard Worker *
10*387f9dfdSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*387f9dfdSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*387f9dfdSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*387f9dfdSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*387f9dfdSAndroid Build Coastguard Worker * limitations under the License.
15*387f9dfdSAndroid Build Coastguard Worker */
16*387f9dfdSAndroid Build Coastguard Worker
17*387f9dfdSAndroid Build Coastguard Worker #pragma once
18*387f9dfdSAndroid Build Coastguard Worker
19*387f9dfdSAndroid Build Coastguard Worker #include <errno.h>
20*387f9dfdSAndroid Build Coastguard Worker #include <sys/epoll.h>
21*387f9dfdSAndroid Build Coastguard Worker #include <cstring>
22*387f9dfdSAndroid Build Coastguard Worker #include <exception>
23*387f9dfdSAndroid Build Coastguard Worker #include <map>
24*387f9dfdSAndroid Build Coastguard Worker #include <memory>
25*387f9dfdSAndroid Build Coastguard Worker #include <string>
26*387f9dfdSAndroid Build Coastguard Worker #include <utility>
27*387f9dfdSAndroid Build Coastguard Worker #include <vector>
28*387f9dfdSAndroid Build Coastguard Worker
29*387f9dfdSAndroid Build Coastguard Worker #include "bcc_exception.h"
30*387f9dfdSAndroid Build Coastguard Worker #include "bcc_syms.h"
31*387f9dfdSAndroid Build Coastguard Worker #include "bpf_module.h"
32*387f9dfdSAndroid Build Coastguard Worker #include "libbpf.h"
33*387f9dfdSAndroid Build Coastguard Worker #include "perf_reader.h"
34*387f9dfdSAndroid Build Coastguard Worker #include "table_desc.h"
35*387f9dfdSAndroid Build Coastguard Worker #include "linux/bpf.h"
36*387f9dfdSAndroid Build Coastguard Worker
37*387f9dfdSAndroid Build Coastguard Worker namespace ebpf {
38*387f9dfdSAndroid Build Coastguard Worker
39*387f9dfdSAndroid Build Coastguard Worker template<class ValueType>
40*387f9dfdSAndroid Build Coastguard Worker class BPFQueueStackTableBase {
41*387f9dfdSAndroid Build Coastguard Worker public:
capacity()42*387f9dfdSAndroid Build Coastguard Worker size_t capacity() const { return desc.max_entries; }
43*387f9dfdSAndroid Build Coastguard Worker
string_to_leaf(const std::string & value_str,ValueType * value)44*387f9dfdSAndroid Build Coastguard Worker StatusTuple string_to_leaf(const std::string& value_str, ValueType* value) {
45*387f9dfdSAndroid Build Coastguard Worker return desc.leaf_sscanf(value_str.c_str(), value);
46*387f9dfdSAndroid Build Coastguard Worker }
47*387f9dfdSAndroid Build Coastguard Worker
leaf_to_string(const ValueType * value,std::string & value_str)48*387f9dfdSAndroid Build Coastguard Worker StatusTuple leaf_to_string(const ValueType* value, std::string& value_str) {
49*387f9dfdSAndroid Build Coastguard Worker char buf[8 * desc.leaf_size];
50*387f9dfdSAndroid Build Coastguard Worker StatusTuple rc = desc.leaf_snprintf(buf, sizeof(buf), value);
51*387f9dfdSAndroid Build Coastguard Worker if (rc.ok())
52*387f9dfdSAndroid Build Coastguard Worker value_str.assign(buf);
53*387f9dfdSAndroid Build Coastguard Worker return rc;
54*387f9dfdSAndroid Build Coastguard Worker }
55*387f9dfdSAndroid Build Coastguard Worker
get_fd()56*387f9dfdSAndroid Build Coastguard Worker int get_fd() { return desc.fd; }
57*387f9dfdSAndroid Build Coastguard Worker
58*387f9dfdSAndroid Build Coastguard Worker protected:
BPFQueueStackTableBase(const TableDesc & desc)59*387f9dfdSAndroid Build Coastguard Worker explicit BPFQueueStackTableBase(const TableDesc& desc) : desc(desc) {}
60*387f9dfdSAndroid Build Coastguard Worker
pop(void * value)61*387f9dfdSAndroid Build Coastguard Worker bool pop(void *value) {
62*387f9dfdSAndroid Build Coastguard Worker return bpf_lookup_and_delete(desc.fd, nullptr, value) >= 0;
63*387f9dfdSAndroid Build Coastguard Worker }
64*387f9dfdSAndroid Build Coastguard Worker // Flags are extremely useful, since they completely changes extraction behaviour
65*387f9dfdSAndroid Build Coastguard Worker // (eg. if flag BPF_EXIST, then if the queue/stack is full remove the oldest one)
push(void * value,unsigned long long int flags)66*387f9dfdSAndroid Build Coastguard Worker bool push(void *value, unsigned long long int flags) {
67*387f9dfdSAndroid Build Coastguard Worker return bpf_update_elem(desc.fd, nullptr, value, flags) >= 0;
68*387f9dfdSAndroid Build Coastguard Worker }
69*387f9dfdSAndroid Build Coastguard Worker
peek(void * value)70*387f9dfdSAndroid Build Coastguard Worker bool peek(void *value) {
71*387f9dfdSAndroid Build Coastguard Worker return bpf_lookup_elem(desc.fd, nullptr, value) >= 0;
72*387f9dfdSAndroid Build Coastguard Worker }
73*387f9dfdSAndroid Build Coastguard Worker
74*387f9dfdSAndroid Build Coastguard Worker const TableDesc& desc;
75*387f9dfdSAndroid Build Coastguard Worker };
76*387f9dfdSAndroid Build Coastguard Worker
77*387f9dfdSAndroid Build Coastguard Worker template <class KeyType, class ValueType>
78*387f9dfdSAndroid Build Coastguard Worker class BPFTableBase {
79*387f9dfdSAndroid Build Coastguard Worker public:
capacity()80*387f9dfdSAndroid Build Coastguard Worker size_t capacity() { return desc.max_entries; }
81*387f9dfdSAndroid Build Coastguard Worker
string_to_key(const std::string & key_str,KeyType * key)82*387f9dfdSAndroid Build Coastguard Worker StatusTuple string_to_key(const std::string& key_str, KeyType* key) {
83*387f9dfdSAndroid Build Coastguard Worker return desc.key_sscanf(key_str.c_str(), key);
84*387f9dfdSAndroid Build Coastguard Worker }
85*387f9dfdSAndroid Build Coastguard Worker
string_to_leaf(const std::string & value_str,ValueType * value)86*387f9dfdSAndroid Build Coastguard Worker StatusTuple string_to_leaf(const std::string& value_str, ValueType* value) {
87*387f9dfdSAndroid Build Coastguard Worker return desc.leaf_sscanf(value_str.c_str(), value);
88*387f9dfdSAndroid Build Coastguard Worker }
89*387f9dfdSAndroid Build Coastguard Worker
key_to_string(const KeyType * key,std::string & key_str)90*387f9dfdSAndroid Build Coastguard Worker StatusTuple key_to_string(const KeyType* key, std::string& key_str) {
91*387f9dfdSAndroid Build Coastguard Worker char buf[8 * desc.key_size];
92*387f9dfdSAndroid Build Coastguard Worker StatusTuple rc = desc.key_snprintf(buf, sizeof(buf), key);
93*387f9dfdSAndroid Build Coastguard Worker if (rc.ok())
94*387f9dfdSAndroid Build Coastguard Worker key_str.assign(buf);
95*387f9dfdSAndroid Build Coastguard Worker return rc;
96*387f9dfdSAndroid Build Coastguard Worker }
97*387f9dfdSAndroid Build Coastguard Worker
leaf_to_string(const ValueType * value,std::string & value_str)98*387f9dfdSAndroid Build Coastguard Worker StatusTuple leaf_to_string(const ValueType* value, std::string& value_str) {
99*387f9dfdSAndroid Build Coastguard Worker char buf[8 * desc.leaf_size];
100*387f9dfdSAndroid Build Coastguard Worker StatusTuple rc = desc.leaf_snprintf(buf, sizeof(buf), value);
101*387f9dfdSAndroid Build Coastguard Worker if (rc.ok())
102*387f9dfdSAndroid Build Coastguard Worker value_str.assign(buf);
103*387f9dfdSAndroid Build Coastguard Worker return rc;
104*387f9dfdSAndroid Build Coastguard Worker }
105*387f9dfdSAndroid Build Coastguard Worker
get_fd()106*387f9dfdSAndroid Build Coastguard Worker int get_fd() {
107*387f9dfdSAndroid Build Coastguard Worker return desc.fd;
108*387f9dfdSAndroid Build Coastguard Worker }
109*387f9dfdSAndroid Build Coastguard Worker
110*387f9dfdSAndroid Build Coastguard Worker protected:
BPFTableBase(const TableDesc & desc)111*387f9dfdSAndroid Build Coastguard Worker explicit BPFTableBase(const TableDesc& desc) : desc(desc) {}
112*387f9dfdSAndroid Build Coastguard Worker
lookup(void * key,void * value)113*387f9dfdSAndroid Build Coastguard Worker bool lookup(void* key, void* value) {
114*387f9dfdSAndroid Build Coastguard Worker return bpf_lookup_elem(desc.fd, key, value) >= 0;
115*387f9dfdSAndroid Build Coastguard Worker }
116*387f9dfdSAndroid Build Coastguard Worker
first(void * key)117*387f9dfdSAndroid Build Coastguard Worker bool first(void* key) {
118*387f9dfdSAndroid Build Coastguard Worker return bpf_get_first_key(desc.fd, key, desc.key_size) >= 0;
119*387f9dfdSAndroid Build Coastguard Worker }
120*387f9dfdSAndroid Build Coastguard Worker
next(void * key,void * next_key)121*387f9dfdSAndroid Build Coastguard Worker bool next(void* key, void* next_key) {
122*387f9dfdSAndroid Build Coastguard Worker return bpf_get_next_key(desc.fd, key, next_key) >= 0;
123*387f9dfdSAndroid Build Coastguard Worker }
124*387f9dfdSAndroid Build Coastguard Worker
update(void * key,void * value)125*387f9dfdSAndroid Build Coastguard Worker bool update(void* key, void* value) {
126*387f9dfdSAndroid Build Coastguard Worker return bpf_update_elem(desc.fd, key, value, 0) >= 0;
127*387f9dfdSAndroid Build Coastguard Worker }
128*387f9dfdSAndroid Build Coastguard Worker
remove(void * key)129*387f9dfdSAndroid Build Coastguard Worker bool remove(void* key) { return bpf_delete_elem(desc.fd, key) >= 0; }
130*387f9dfdSAndroid Build Coastguard Worker
131*387f9dfdSAndroid Build Coastguard Worker const TableDesc& desc;
132*387f9dfdSAndroid Build Coastguard Worker };
133*387f9dfdSAndroid Build Coastguard Worker
134*387f9dfdSAndroid Build Coastguard Worker class BPFTable : public BPFTableBase<void, void> {
135*387f9dfdSAndroid Build Coastguard Worker public:
136*387f9dfdSAndroid Build Coastguard Worker BPFTable(const TableDesc& desc);
137*387f9dfdSAndroid Build Coastguard Worker
138*387f9dfdSAndroid Build Coastguard Worker StatusTuple get_value(const std::string& key_str, std::string& value);
139*387f9dfdSAndroid Build Coastguard Worker StatusTuple get_value(const std::string& key_str,
140*387f9dfdSAndroid Build Coastguard Worker std::vector<std::string>& value);
141*387f9dfdSAndroid Build Coastguard Worker
142*387f9dfdSAndroid Build Coastguard Worker StatusTuple update_value(const std::string& key_str,
143*387f9dfdSAndroid Build Coastguard Worker const std::string& value_str);
144*387f9dfdSAndroid Build Coastguard Worker StatusTuple update_value(const std::string& key_str,
145*387f9dfdSAndroid Build Coastguard Worker const std::vector<std::string>& value_str);
146*387f9dfdSAndroid Build Coastguard Worker
147*387f9dfdSAndroid Build Coastguard Worker StatusTuple remove_value(const std::string& key_str);
148*387f9dfdSAndroid Build Coastguard Worker
149*387f9dfdSAndroid Build Coastguard Worker StatusTuple clear_table_non_atomic();
150*387f9dfdSAndroid Build Coastguard Worker StatusTuple get_table_offline(std::vector<std::pair<std::string, std::string>> &res);
151*387f9dfdSAndroid Build Coastguard Worker
152*387f9dfdSAndroid Build Coastguard Worker static size_t get_possible_cpu_count();
153*387f9dfdSAndroid Build Coastguard Worker };
154*387f9dfdSAndroid Build Coastguard Worker
155*387f9dfdSAndroid Build Coastguard Worker template <class ValueType>
get_value_addr(ValueType & t)156*387f9dfdSAndroid Build Coastguard Worker void* get_value_addr(ValueType& t) {
157*387f9dfdSAndroid Build Coastguard Worker return &t;
158*387f9dfdSAndroid Build Coastguard Worker }
159*387f9dfdSAndroid Build Coastguard Worker
160*387f9dfdSAndroid Build Coastguard Worker template <class ValueType>
get_value_addr(std::vector<ValueType> & t)161*387f9dfdSAndroid Build Coastguard Worker void* get_value_addr(std::vector<ValueType>& t) {
162*387f9dfdSAndroid Build Coastguard Worker return t.data();
163*387f9dfdSAndroid Build Coastguard Worker }
164*387f9dfdSAndroid Build Coastguard Worker
165*387f9dfdSAndroid Build Coastguard Worker template<class ValueType>
166*387f9dfdSAndroid Build Coastguard Worker class BPFQueueStackTable : public BPFQueueStackTableBase<void> {
167*387f9dfdSAndroid Build Coastguard Worker public:
BPFQueueStackTable(const TableDesc & desc)168*387f9dfdSAndroid Build Coastguard Worker explicit BPFQueueStackTable(const TableDesc& desc) : BPFQueueStackTableBase(desc) {
169*387f9dfdSAndroid Build Coastguard Worker if (desc.type != BPF_MAP_TYPE_QUEUE &&
170*387f9dfdSAndroid Build Coastguard Worker desc.type != BPF_MAP_TYPE_STACK)
171*387f9dfdSAndroid Build Coastguard Worker throw std::invalid_argument("Table '" + desc.name +
172*387f9dfdSAndroid Build Coastguard Worker "' is not a queue/stack table");
173*387f9dfdSAndroid Build Coastguard Worker }
174*387f9dfdSAndroid Build Coastguard Worker
pop_value(ValueType & value)175*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple pop_value(ValueType& value) {
176*387f9dfdSAndroid Build Coastguard Worker if (!this->pop(get_value_addr(value)))
177*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
178*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
179*387f9dfdSAndroid Build Coastguard Worker }
180*387f9dfdSAndroid Build Coastguard Worker
181*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple push_value(const ValueType& value, unsigned long long int flags = 0) {
182*387f9dfdSAndroid Build Coastguard Worker if (!this->push(get_value_addr(const_cast<ValueType&>(value)), flags))
183*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
184*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
185*387f9dfdSAndroid Build Coastguard Worker }
186*387f9dfdSAndroid Build Coastguard Worker
get_head(const ValueType & value)187*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple get_head(const ValueType& value) {
188*387f9dfdSAndroid Build Coastguard Worker if (!this->peek(get_value_addr(const_cast<ValueType&>(value))))
189*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error peeking value: %s", std::strerror(errno));
190*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
191*387f9dfdSAndroid Build Coastguard Worker }
192*387f9dfdSAndroid Build Coastguard Worker };
193*387f9dfdSAndroid Build Coastguard Worker
194*387f9dfdSAndroid Build Coastguard Worker template <class ValueType>
195*387f9dfdSAndroid Build Coastguard Worker class BPFArrayTable : public BPFTableBase<int, ValueType> {
196*387f9dfdSAndroid Build Coastguard Worker public:
BPFArrayTable(const TableDesc & desc)197*387f9dfdSAndroid Build Coastguard Worker BPFArrayTable(const TableDesc& desc) : BPFTableBase<int, ValueType>(desc) {
198*387f9dfdSAndroid Build Coastguard Worker if (desc.type != BPF_MAP_TYPE_ARRAY &&
199*387f9dfdSAndroid Build Coastguard Worker desc.type != BPF_MAP_TYPE_PERCPU_ARRAY)
200*387f9dfdSAndroid Build Coastguard Worker throw std::invalid_argument("Table '" + desc.name +
201*387f9dfdSAndroid Build Coastguard Worker "' is not an array table");
202*387f9dfdSAndroid Build Coastguard Worker }
203*387f9dfdSAndroid Build Coastguard Worker
get_value(const int & index,ValueType & value)204*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple get_value(const int& index, ValueType& value) {
205*387f9dfdSAndroid Build Coastguard Worker if (!this->lookup(const_cast<int*>(&index), get_value_addr(value)))
206*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
207*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
208*387f9dfdSAndroid Build Coastguard Worker }
209*387f9dfdSAndroid Build Coastguard Worker
update_value(const int & index,const ValueType & value)210*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple update_value(const int& index, const ValueType& value) {
211*387f9dfdSAndroid Build Coastguard Worker if (!this->update(const_cast<int*>(&index),
212*387f9dfdSAndroid Build Coastguard Worker get_value_addr(const_cast<ValueType&>(value))))
213*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
214*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
215*387f9dfdSAndroid Build Coastguard Worker }
216*387f9dfdSAndroid Build Coastguard Worker
217*387f9dfdSAndroid Build Coastguard Worker ValueType operator[](const int& key) {
218*387f9dfdSAndroid Build Coastguard Worker ValueType value;
219*387f9dfdSAndroid Build Coastguard Worker get_value(key, value);
220*387f9dfdSAndroid Build Coastguard Worker return value;
221*387f9dfdSAndroid Build Coastguard Worker }
222*387f9dfdSAndroid Build Coastguard Worker
get_table_offline()223*387f9dfdSAndroid Build Coastguard Worker std::vector<ValueType> get_table_offline() {
224*387f9dfdSAndroid Build Coastguard Worker std::vector<ValueType> res(this->capacity());
225*387f9dfdSAndroid Build Coastguard Worker
226*387f9dfdSAndroid Build Coastguard Worker for (int i = 0; i < (int)this->capacity(); i++) {
227*387f9dfdSAndroid Build Coastguard Worker get_value(i, res[i]);
228*387f9dfdSAndroid Build Coastguard Worker }
229*387f9dfdSAndroid Build Coastguard Worker
230*387f9dfdSAndroid Build Coastguard Worker return res;
231*387f9dfdSAndroid Build Coastguard Worker }
232*387f9dfdSAndroid Build Coastguard Worker };
233*387f9dfdSAndroid Build Coastguard Worker
234*387f9dfdSAndroid Build Coastguard Worker template <class ValueType>
235*387f9dfdSAndroid Build Coastguard Worker class BPFPercpuArrayTable : public BPFArrayTable<std::vector<ValueType>> {
236*387f9dfdSAndroid Build Coastguard Worker public:
BPFPercpuArrayTable(const TableDesc & desc)237*387f9dfdSAndroid Build Coastguard Worker BPFPercpuArrayTable(const TableDesc& desc)
238*387f9dfdSAndroid Build Coastguard Worker : BPFArrayTable<std::vector<ValueType>>(desc),
239*387f9dfdSAndroid Build Coastguard Worker ncpus(BPFTable::get_possible_cpu_count()) {
240*387f9dfdSAndroid Build Coastguard Worker if (desc.type != BPF_MAP_TYPE_PERCPU_ARRAY)
241*387f9dfdSAndroid Build Coastguard Worker throw std::invalid_argument("Table '" + desc.name +
242*387f9dfdSAndroid Build Coastguard Worker "' is not a percpu array table");
243*387f9dfdSAndroid Build Coastguard Worker // leaf structures have to be aligned to 8 bytes as hardcoded in the linux
244*387f9dfdSAndroid Build Coastguard Worker // kernel.
245*387f9dfdSAndroid Build Coastguard Worker if (sizeof(ValueType) % 8)
246*387f9dfdSAndroid Build Coastguard Worker throw std::invalid_argument("leaf must be aligned to 8 bytes");
247*387f9dfdSAndroid Build Coastguard Worker }
248*387f9dfdSAndroid Build Coastguard Worker
get_value(const int & index,std::vector<ValueType> & value)249*387f9dfdSAndroid Build Coastguard Worker StatusTuple get_value(const int& index, std::vector<ValueType>& value) {
250*387f9dfdSAndroid Build Coastguard Worker value.resize(ncpus);
251*387f9dfdSAndroid Build Coastguard Worker return BPFArrayTable<std::vector<ValueType>>::get_value(index, value);
252*387f9dfdSAndroid Build Coastguard Worker }
253*387f9dfdSAndroid Build Coastguard Worker
update_value(const int & index,const std::vector<ValueType> & value)254*387f9dfdSAndroid Build Coastguard Worker StatusTuple update_value(const int& index,
255*387f9dfdSAndroid Build Coastguard Worker const std::vector<ValueType>& value) {
256*387f9dfdSAndroid Build Coastguard Worker if (value.size() != ncpus)
257*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "bad value size");
258*387f9dfdSAndroid Build Coastguard Worker return BPFArrayTable<std::vector<ValueType>>::update_value(index, value);
259*387f9dfdSAndroid Build Coastguard Worker }
260*387f9dfdSAndroid Build Coastguard Worker
261*387f9dfdSAndroid Build Coastguard Worker private:
262*387f9dfdSAndroid Build Coastguard Worker unsigned int ncpus;
263*387f9dfdSAndroid Build Coastguard Worker };
264*387f9dfdSAndroid Build Coastguard Worker
265*387f9dfdSAndroid Build Coastguard Worker template <class KeyType, class ValueType>
266*387f9dfdSAndroid Build Coastguard Worker class BPFHashTable : public BPFTableBase<KeyType, ValueType> {
267*387f9dfdSAndroid Build Coastguard Worker public:
BPFHashTable(const TableDesc & desc)268*387f9dfdSAndroid Build Coastguard Worker explicit BPFHashTable(const TableDesc& desc)
269*387f9dfdSAndroid Build Coastguard Worker : BPFTableBase<KeyType, ValueType>(desc) {
270*387f9dfdSAndroid Build Coastguard Worker if (desc.type != BPF_MAP_TYPE_HASH &&
271*387f9dfdSAndroid Build Coastguard Worker desc.type != BPF_MAP_TYPE_PERCPU_HASH &&
272*387f9dfdSAndroid Build Coastguard Worker desc.type != BPF_MAP_TYPE_LRU_HASH &&
273*387f9dfdSAndroid Build Coastguard Worker desc.type != BPF_MAP_TYPE_LRU_PERCPU_HASH)
274*387f9dfdSAndroid Build Coastguard Worker throw std::invalid_argument("Table '" + desc.name +
275*387f9dfdSAndroid Build Coastguard Worker "' is not a hash table");
276*387f9dfdSAndroid Build Coastguard Worker }
277*387f9dfdSAndroid Build Coastguard Worker
get_value(const KeyType & key,ValueType & value)278*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple get_value(const KeyType& key, ValueType& value) {
279*387f9dfdSAndroid Build Coastguard Worker if (!this->lookup(const_cast<KeyType*>(&key), get_value_addr(value)))
280*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
281*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
282*387f9dfdSAndroid Build Coastguard Worker }
283*387f9dfdSAndroid Build Coastguard Worker
update_value(const KeyType & key,const ValueType & value)284*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple update_value(const KeyType& key, const ValueType& value) {
285*387f9dfdSAndroid Build Coastguard Worker if (!this->update(const_cast<KeyType*>(&key),
286*387f9dfdSAndroid Build Coastguard Worker get_value_addr(const_cast<ValueType&>(value))))
287*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
288*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
289*387f9dfdSAndroid Build Coastguard Worker }
290*387f9dfdSAndroid Build Coastguard Worker
remove_value(const KeyType & key)291*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple remove_value(const KeyType& key) {
292*387f9dfdSAndroid Build Coastguard Worker if (!this->remove(const_cast<KeyType*>(&key)))
293*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error removing value: %s", std::strerror(errno));
294*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
295*387f9dfdSAndroid Build Coastguard Worker }
296*387f9dfdSAndroid Build Coastguard Worker
297*387f9dfdSAndroid Build Coastguard Worker ValueType operator[](const KeyType& key) {
298*387f9dfdSAndroid Build Coastguard Worker ValueType value;
299*387f9dfdSAndroid Build Coastguard Worker get_value(key, value);
300*387f9dfdSAndroid Build Coastguard Worker return value;
301*387f9dfdSAndroid Build Coastguard Worker }
302*387f9dfdSAndroid Build Coastguard Worker
get_table_offline()303*387f9dfdSAndroid Build Coastguard Worker std::vector<std::pair<KeyType, ValueType>> get_table_offline() {
304*387f9dfdSAndroid Build Coastguard Worker std::vector<std::pair<KeyType, ValueType>> res;
305*387f9dfdSAndroid Build Coastguard Worker KeyType cur;
306*387f9dfdSAndroid Build Coastguard Worker ValueType value;
307*387f9dfdSAndroid Build Coastguard Worker
308*387f9dfdSAndroid Build Coastguard Worker StatusTuple r(0);
309*387f9dfdSAndroid Build Coastguard Worker
310*387f9dfdSAndroid Build Coastguard Worker if (!this->first(&cur))
311*387f9dfdSAndroid Build Coastguard Worker return res;
312*387f9dfdSAndroid Build Coastguard Worker
313*387f9dfdSAndroid Build Coastguard Worker while (true) {
314*387f9dfdSAndroid Build Coastguard Worker r = get_value(cur, value);
315*387f9dfdSAndroid Build Coastguard Worker if (!r.ok())
316*387f9dfdSAndroid Build Coastguard Worker break;
317*387f9dfdSAndroid Build Coastguard Worker res.emplace_back(cur, value);
318*387f9dfdSAndroid Build Coastguard Worker if (!this->next(&cur, &cur))
319*387f9dfdSAndroid Build Coastguard Worker break;
320*387f9dfdSAndroid Build Coastguard Worker }
321*387f9dfdSAndroid Build Coastguard Worker
322*387f9dfdSAndroid Build Coastguard Worker return res;
323*387f9dfdSAndroid Build Coastguard Worker }
324*387f9dfdSAndroid Build Coastguard Worker
clear_table_non_atomic()325*387f9dfdSAndroid Build Coastguard Worker StatusTuple clear_table_non_atomic() {
326*387f9dfdSAndroid Build Coastguard Worker KeyType cur;
327*387f9dfdSAndroid Build Coastguard Worker while (this->first(&cur))
328*387f9dfdSAndroid Build Coastguard Worker TRY2(remove_value(cur));
329*387f9dfdSAndroid Build Coastguard Worker
330*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
331*387f9dfdSAndroid Build Coastguard Worker }
332*387f9dfdSAndroid Build Coastguard Worker };
333*387f9dfdSAndroid Build Coastguard Worker
334*387f9dfdSAndroid Build Coastguard Worker template <class KeyType, class ValueType>
335*387f9dfdSAndroid Build Coastguard Worker class BPFPercpuHashTable
336*387f9dfdSAndroid Build Coastguard Worker : public BPFHashTable<KeyType, std::vector<ValueType>> {
337*387f9dfdSAndroid Build Coastguard Worker public:
BPFPercpuHashTable(const TableDesc & desc)338*387f9dfdSAndroid Build Coastguard Worker explicit BPFPercpuHashTable(const TableDesc& desc)
339*387f9dfdSAndroid Build Coastguard Worker : BPFHashTable<KeyType, std::vector<ValueType>>(desc),
340*387f9dfdSAndroid Build Coastguard Worker ncpus(BPFTable::get_possible_cpu_count()) {
341*387f9dfdSAndroid Build Coastguard Worker if (desc.type != BPF_MAP_TYPE_PERCPU_HASH &&
342*387f9dfdSAndroid Build Coastguard Worker desc.type != BPF_MAP_TYPE_LRU_PERCPU_HASH)
343*387f9dfdSAndroid Build Coastguard Worker throw std::invalid_argument("Table '" + desc.name +
344*387f9dfdSAndroid Build Coastguard Worker "' is not a percpu hash table");
345*387f9dfdSAndroid Build Coastguard Worker // leaf structures have to be aligned to 8 bytes as hardcoded in the linux
346*387f9dfdSAndroid Build Coastguard Worker // kernel.
347*387f9dfdSAndroid Build Coastguard Worker if (sizeof(ValueType) % 8)
348*387f9dfdSAndroid Build Coastguard Worker throw std::invalid_argument("leaf must be aligned to 8 bytes");
349*387f9dfdSAndroid Build Coastguard Worker }
350*387f9dfdSAndroid Build Coastguard Worker
get_value(const KeyType & key,std::vector<ValueType> & value)351*387f9dfdSAndroid Build Coastguard Worker StatusTuple get_value(const KeyType& key, std::vector<ValueType>& value) {
352*387f9dfdSAndroid Build Coastguard Worker value.resize(ncpus);
353*387f9dfdSAndroid Build Coastguard Worker return BPFHashTable<KeyType, std::vector<ValueType>>::get_value(key, value);
354*387f9dfdSAndroid Build Coastguard Worker }
355*387f9dfdSAndroid Build Coastguard Worker
update_value(const KeyType & key,const std::vector<ValueType> & value)356*387f9dfdSAndroid Build Coastguard Worker StatusTuple update_value(const KeyType& key,
357*387f9dfdSAndroid Build Coastguard Worker const std::vector<ValueType>& value) {
358*387f9dfdSAndroid Build Coastguard Worker if (value.size() != ncpus)
359*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "bad value size");
360*387f9dfdSAndroid Build Coastguard Worker return BPFHashTable<KeyType, std::vector<ValueType>>::update_value(key,
361*387f9dfdSAndroid Build Coastguard Worker value);
362*387f9dfdSAndroid Build Coastguard Worker }
363*387f9dfdSAndroid Build Coastguard Worker
364*387f9dfdSAndroid Build Coastguard Worker private:
365*387f9dfdSAndroid Build Coastguard Worker unsigned int ncpus;
366*387f9dfdSAndroid Build Coastguard Worker };
367*387f9dfdSAndroid Build Coastguard Worker
368*387f9dfdSAndroid Build Coastguard Worker // From src/cc/export/helpers.h
369*387f9dfdSAndroid Build Coastguard Worker static const int BPF_MAX_STACK_DEPTH = 127;
370*387f9dfdSAndroid Build Coastguard Worker struct stacktrace_t {
371*387f9dfdSAndroid Build Coastguard Worker uintptr_t ip[BPF_MAX_STACK_DEPTH];
372*387f9dfdSAndroid Build Coastguard Worker };
373*387f9dfdSAndroid Build Coastguard Worker
374*387f9dfdSAndroid Build Coastguard Worker class BPFStackTable : public BPFTableBase<int, stacktrace_t> {
375*387f9dfdSAndroid Build Coastguard Worker public:
376*387f9dfdSAndroid Build Coastguard Worker BPFStackTable(const TableDesc& desc, bool use_debug_file,
377*387f9dfdSAndroid Build Coastguard Worker bool check_debug_file_crc);
378*387f9dfdSAndroid Build Coastguard Worker BPFStackTable(BPFStackTable&& that);
379*387f9dfdSAndroid Build Coastguard Worker ~BPFStackTable();
380*387f9dfdSAndroid Build Coastguard Worker
381*387f9dfdSAndroid Build Coastguard Worker void free_symcache(int pid);
382*387f9dfdSAndroid Build Coastguard Worker void clear_table_non_atomic();
383*387f9dfdSAndroid Build Coastguard Worker std::vector<uintptr_t> get_stack_addr(int stack_id);
384*387f9dfdSAndroid Build Coastguard Worker std::vector<std::string> get_stack_symbol(int stack_id, int pid);
385*387f9dfdSAndroid Build Coastguard Worker
386*387f9dfdSAndroid Build Coastguard Worker private:
387*387f9dfdSAndroid Build Coastguard Worker bcc_symbol_option symbol_option_;
388*387f9dfdSAndroid Build Coastguard Worker std::map<int, void*> pid_sym_;
389*387f9dfdSAndroid Build Coastguard Worker };
390*387f9dfdSAndroid Build Coastguard Worker
391*387f9dfdSAndroid Build Coastguard Worker // from src/cc/export/helpers.h
392*387f9dfdSAndroid Build Coastguard Worker struct stacktrace_buildid_t {
393*387f9dfdSAndroid Build Coastguard Worker struct bpf_stack_build_id trace[BPF_MAX_STACK_DEPTH];
394*387f9dfdSAndroid Build Coastguard Worker };
395*387f9dfdSAndroid Build Coastguard Worker
396*387f9dfdSAndroid Build Coastguard Worker class BPFStackBuildIdTable : public BPFTableBase<int, stacktrace_buildid_t> {
397*387f9dfdSAndroid Build Coastguard Worker public:
398*387f9dfdSAndroid Build Coastguard Worker BPFStackBuildIdTable(const TableDesc& desc, bool use_debug_file,
399*387f9dfdSAndroid Build Coastguard Worker bool check_debug_file_crc, void *bsymcache);
400*387f9dfdSAndroid Build Coastguard Worker ~BPFStackBuildIdTable() = default;
401*387f9dfdSAndroid Build Coastguard Worker
402*387f9dfdSAndroid Build Coastguard Worker void clear_table_non_atomic();
403*387f9dfdSAndroid Build Coastguard Worker std::vector<bpf_stack_build_id> get_stack_addr(int stack_id);
404*387f9dfdSAndroid Build Coastguard Worker std::vector<std::string> get_stack_symbol(int stack_id);
405*387f9dfdSAndroid Build Coastguard Worker
406*387f9dfdSAndroid Build Coastguard Worker private:
407*387f9dfdSAndroid Build Coastguard Worker void *bsymcache_;
408*387f9dfdSAndroid Build Coastguard Worker bcc_symbol_option symbol_option_;
409*387f9dfdSAndroid Build Coastguard Worker };
410*387f9dfdSAndroid Build Coastguard Worker
411*387f9dfdSAndroid Build Coastguard Worker class BPFPerfBuffer : public BPFTableBase<int, int> {
412*387f9dfdSAndroid Build Coastguard Worker public:
413*387f9dfdSAndroid Build Coastguard Worker BPFPerfBuffer(const TableDesc& desc);
414*387f9dfdSAndroid Build Coastguard Worker ~BPFPerfBuffer();
415*387f9dfdSAndroid Build Coastguard Worker
416*387f9dfdSAndroid Build Coastguard Worker StatusTuple open_all_cpu(perf_reader_raw_cb cb, perf_reader_lost_cb lost_cb,
417*387f9dfdSAndroid Build Coastguard Worker void* cb_cookie, int page_cnt);
418*387f9dfdSAndroid Build Coastguard Worker StatusTuple open_all_cpu(perf_reader_raw_cb cb, perf_reader_lost_cb lost_cb,
419*387f9dfdSAndroid Build Coastguard Worker void* cb_cookie, int page_cnt, int wakeup_events);
420*387f9dfdSAndroid Build Coastguard Worker StatusTuple close_all_cpu();
421*387f9dfdSAndroid Build Coastguard Worker int poll(int timeout_ms);
422*387f9dfdSAndroid Build Coastguard Worker int consume();
423*387f9dfdSAndroid Build Coastguard Worker
424*387f9dfdSAndroid Build Coastguard Worker private:
425*387f9dfdSAndroid Build Coastguard Worker StatusTuple open_on_cpu(perf_reader_raw_cb cb, perf_reader_lost_cb lost_cb,
426*387f9dfdSAndroid Build Coastguard Worker void* cb_cookie, int page_cnt, struct bcc_perf_buffer_opts& opts);
427*387f9dfdSAndroid Build Coastguard Worker StatusTuple close_on_cpu(int cpu);
428*387f9dfdSAndroid Build Coastguard Worker
429*387f9dfdSAndroid Build Coastguard Worker std::map<int, perf_reader*> cpu_readers_;
430*387f9dfdSAndroid Build Coastguard Worker
431*387f9dfdSAndroid Build Coastguard Worker int epfd_;
432*387f9dfdSAndroid Build Coastguard Worker std::unique_ptr<epoll_event[]> ep_events_;
433*387f9dfdSAndroid Build Coastguard Worker };
434*387f9dfdSAndroid Build Coastguard Worker
435*387f9dfdSAndroid Build Coastguard Worker class BPFPerfEventArray : public BPFTableBase<int, int> {
436*387f9dfdSAndroid Build Coastguard Worker public:
437*387f9dfdSAndroid Build Coastguard Worker BPFPerfEventArray(const TableDesc& desc);
438*387f9dfdSAndroid Build Coastguard Worker ~BPFPerfEventArray();
439*387f9dfdSAndroid Build Coastguard Worker
440*387f9dfdSAndroid Build Coastguard Worker StatusTuple open_all_cpu(uint32_t type, uint64_t config, int pid = -1);
441*387f9dfdSAndroid Build Coastguard Worker StatusTuple close_all_cpu();
442*387f9dfdSAndroid Build Coastguard Worker
443*387f9dfdSAndroid Build Coastguard Worker private:
444*387f9dfdSAndroid Build Coastguard Worker StatusTuple open_on_cpu(int cpu, uint32_t type, uint64_t config, int pid = -1);
445*387f9dfdSAndroid Build Coastguard Worker StatusTuple close_on_cpu(int cpu);
446*387f9dfdSAndroid Build Coastguard Worker
447*387f9dfdSAndroid Build Coastguard Worker std::map<int, int> cpu_fds_;
448*387f9dfdSAndroid Build Coastguard Worker };
449*387f9dfdSAndroid Build Coastguard Worker
450*387f9dfdSAndroid Build Coastguard Worker class BPFProgTable : public BPFTableBase<int, int> {
451*387f9dfdSAndroid Build Coastguard Worker public:
452*387f9dfdSAndroid Build Coastguard Worker BPFProgTable(const TableDesc& desc);
453*387f9dfdSAndroid Build Coastguard Worker
454*387f9dfdSAndroid Build Coastguard Worker StatusTuple update_value(const int& index, const int& prog_fd);
455*387f9dfdSAndroid Build Coastguard Worker StatusTuple remove_value(const int& index);
456*387f9dfdSAndroid Build Coastguard Worker };
457*387f9dfdSAndroid Build Coastguard Worker
458*387f9dfdSAndroid Build Coastguard Worker class BPFCgroupArray : public BPFTableBase<int, int> {
459*387f9dfdSAndroid Build Coastguard Worker public:
460*387f9dfdSAndroid Build Coastguard Worker BPFCgroupArray(const TableDesc& desc);
461*387f9dfdSAndroid Build Coastguard Worker
462*387f9dfdSAndroid Build Coastguard Worker StatusTuple update_value(const int& index, const int& cgroup2_fd);
463*387f9dfdSAndroid Build Coastguard Worker StatusTuple update_value(const int& index, const std::string& cgroup2_path);
464*387f9dfdSAndroid Build Coastguard Worker StatusTuple remove_value(const int& index);
465*387f9dfdSAndroid Build Coastguard Worker };
466*387f9dfdSAndroid Build Coastguard Worker
467*387f9dfdSAndroid Build Coastguard Worker class BPFDevmapTable : public BPFTableBase<int, int> {
468*387f9dfdSAndroid Build Coastguard Worker public:
469*387f9dfdSAndroid Build Coastguard Worker BPFDevmapTable(const TableDesc& desc);
470*387f9dfdSAndroid Build Coastguard Worker
471*387f9dfdSAndroid Build Coastguard Worker StatusTuple update_value(const int& index, const int& value);
472*387f9dfdSAndroid Build Coastguard Worker StatusTuple get_value(const int& index, int& value);
473*387f9dfdSAndroid Build Coastguard Worker StatusTuple remove_value(const int& index);
474*387f9dfdSAndroid Build Coastguard Worker };
475*387f9dfdSAndroid Build Coastguard Worker
476*387f9dfdSAndroid Build Coastguard Worker class BPFXskmapTable : public BPFTableBase<int, int> {
477*387f9dfdSAndroid Build Coastguard Worker public:
478*387f9dfdSAndroid Build Coastguard Worker BPFXskmapTable(const TableDesc& desc);
479*387f9dfdSAndroid Build Coastguard Worker
480*387f9dfdSAndroid Build Coastguard Worker StatusTuple update_value(const int& index, const int& value);
481*387f9dfdSAndroid Build Coastguard Worker StatusTuple get_value(const int& index, int& value);
482*387f9dfdSAndroid Build Coastguard Worker StatusTuple remove_value(const int& index);
483*387f9dfdSAndroid Build Coastguard Worker };
484*387f9dfdSAndroid Build Coastguard Worker
485*387f9dfdSAndroid Build Coastguard Worker template <class KeyType>
486*387f9dfdSAndroid Build Coastguard Worker class BPFMapInMapTable : public BPFTableBase<KeyType, int> {
487*387f9dfdSAndroid Build Coastguard Worker public:
BPFMapInMapTable(const TableDesc & desc)488*387f9dfdSAndroid Build Coastguard Worker BPFMapInMapTable(const TableDesc& desc) : BPFTableBase<KeyType, int>(desc) {
489*387f9dfdSAndroid Build Coastguard Worker if (desc.type != BPF_MAP_TYPE_ARRAY_OF_MAPS &&
490*387f9dfdSAndroid Build Coastguard Worker desc.type != BPF_MAP_TYPE_HASH_OF_MAPS)
491*387f9dfdSAndroid Build Coastguard Worker throw std::invalid_argument("Table '" + desc.name +
492*387f9dfdSAndroid Build Coastguard Worker "' is not a map-in-map table");
493*387f9dfdSAndroid Build Coastguard Worker }
update_value(const KeyType & key,const int & inner_map_fd)494*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple update_value(const KeyType& key, const int& inner_map_fd) {
495*387f9dfdSAndroid Build Coastguard Worker if (!this->update(const_cast<KeyType*>(&key),
496*387f9dfdSAndroid Build Coastguard Worker const_cast<int*>(&inner_map_fd)))
497*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
498*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
499*387f9dfdSAndroid Build Coastguard Worker }
remove_value(const KeyType & key)500*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple remove_value(const KeyType& key) {
501*387f9dfdSAndroid Build Coastguard Worker if (!this->remove(const_cast<KeyType*>(&key)))
502*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error removing value: %s", std::strerror(errno));
503*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
504*387f9dfdSAndroid Build Coastguard Worker }
505*387f9dfdSAndroid Build Coastguard Worker };
506*387f9dfdSAndroid Build Coastguard Worker
507*387f9dfdSAndroid Build Coastguard Worker class BPFSockmapTable : public BPFTableBase<int, int> {
508*387f9dfdSAndroid Build Coastguard Worker public:
509*387f9dfdSAndroid Build Coastguard Worker BPFSockmapTable(const TableDesc& desc);
510*387f9dfdSAndroid Build Coastguard Worker
511*387f9dfdSAndroid Build Coastguard Worker StatusTuple update_value(const int& index, const int& value);
512*387f9dfdSAndroid Build Coastguard Worker StatusTuple remove_value(const int& index);
513*387f9dfdSAndroid Build Coastguard Worker };
514*387f9dfdSAndroid Build Coastguard Worker
515*387f9dfdSAndroid Build Coastguard Worker class BPFSockhashTable : public BPFTableBase<int, int> {
516*387f9dfdSAndroid Build Coastguard Worker public:
517*387f9dfdSAndroid Build Coastguard Worker BPFSockhashTable(const TableDesc& desc);
518*387f9dfdSAndroid Build Coastguard Worker
519*387f9dfdSAndroid Build Coastguard Worker StatusTuple update_value(const int& key, const int& value);
520*387f9dfdSAndroid Build Coastguard Worker StatusTuple remove_value(const int& key);
521*387f9dfdSAndroid Build Coastguard Worker };
522*387f9dfdSAndroid Build Coastguard Worker
523*387f9dfdSAndroid Build Coastguard Worker template <class ValueType>
524*387f9dfdSAndroid Build Coastguard Worker class BPFSkStorageTable : public BPFTableBase<int, ValueType> {
525*387f9dfdSAndroid Build Coastguard Worker public:
BPFSkStorageTable(const TableDesc & desc)526*387f9dfdSAndroid Build Coastguard Worker BPFSkStorageTable(const TableDesc& desc) : BPFTableBase<int, ValueType>(desc) {
527*387f9dfdSAndroid Build Coastguard Worker if (desc.type != BPF_MAP_TYPE_SK_STORAGE)
528*387f9dfdSAndroid Build Coastguard Worker throw std::invalid_argument("Table '" + desc.name +
529*387f9dfdSAndroid Build Coastguard Worker "' is not a sk_storage table");
530*387f9dfdSAndroid Build Coastguard Worker }
531*387f9dfdSAndroid Build Coastguard Worker
get_value(const int & sock_fd,ValueType & value)532*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple get_value(const int& sock_fd, ValueType& value) {
533*387f9dfdSAndroid Build Coastguard Worker if (!this->lookup(const_cast<int*>(&sock_fd), get_value_addr(value)))
534*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
535*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
536*387f9dfdSAndroid Build Coastguard Worker }
537*387f9dfdSAndroid Build Coastguard Worker
update_value(const int & sock_fd,const ValueType & value)538*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple update_value(const int& sock_fd, const ValueType& value) {
539*387f9dfdSAndroid Build Coastguard Worker if (!this->update(const_cast<int*>(&sock_fd),
540*387f9dfdSAndroid Build Coastguard Worker get_value_addr(const_cast<ValueType&>(value))))
541*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
542*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
543*387f9dfdSAndroid Build Coastguard Worker }
544*387f9dfdSAndroid Build Coastguard Worker
remove_value(const int & sock_fd)545*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple remove_value(const int& sock_fd) {
546*387f9dfdSAndroid Build Coastguard Worker if (!this->remove(const_cast<int*>(&sock_fd)))
547*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error removing value: %s", std::strerror(errno));
548*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
549*387f9dfdSAndroid Build Coastguard Worker }
550*387f9dfdSAndroid Build Coastguard Worker };
551*387f9dfdSAndroid Build Coastguard Worker
552*387f9dfdSAndroid Build Coastguard Worker template <class ValueType>
553*387f9dfdSAndroid Build Coastguard Worker class BPFInodeStorageTable : public BPFTableBase<int, ValueType> {
554*387f9dfdSAndroid Build Coastguard Worker public:
BPFInodeStorageTable(const TableDesc & desc)555*387f9dfdSAndroid Build Coastguard Worker BPFInodeStorageTable(const TableDesc& desc) : BPFTableBase<int, ValueType>(desc) {
556*387f9dfdSAndroid Build Coastguard Worker if (desc.type != BPF_MAP_TYPE_INODE_STORAGE)
557*387f9dfdSAndroid Build Coastguard Worker throw std::invalid_argument("Table '" + desc.name +
558*387f9dfdSAndroid Build Coastguard Worker "' is not a inode_storage table");
559*387f9dfdSAndroid Build Coastguard Worker }
560*387f9dfdSAndroid Build Coastguard Worker
get_value(const int & fd,ValueType & value)561*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple get_value(const int& fd, ValueType& value) {
562*387f9dfdSAndroid Build Coastguard Worker if (!this->lookup(const_cast<int*>(&fd), get_value_addr(value)))
563*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
564*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
565*387f9dfdSAndroid Build Coastguard Worker }
566*387f9dfdSAndroid Build Coastguard Worker
update_value(const int & fd,const ValueType & value)567*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple update_value(const int& fd, const ValueType& value) {
568*387f9dfdSAndroid Build Coastguard Worker if (!this->update(const_cast<int*>(&fd),
569*387f9dfdSAndroid Build Coastguard Worker get_value_addr(const_cast<ValueType&>(value))))
570*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
571*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
572*387f9dfdSAndroid Build Coastguard Worker }
573*387f9dfdSAndroid Build Coastguard Worker
remove_value(const int & fd)574*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple remove_value(const int& fd) {
575*387f9dfdSAndroid Build Coastguard Worker if (!this->remove(const_cast<int*>(&fd)))
576*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error removing value: %s", std::strerror(errno));
577*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
578*387f9dfdSAndroid Build Coastguard Worker }
579*387f9dfdSAndroid Build Coastguard Worker };
580*387f9dfdSAndroid Build Coastguard Worker
581*387f9dfdSAndroid Build Coastguard Worker template <class ValueType>
582*387f9dfdSAndroid Build Coastguard Worker class BPFTaskStorageTable : public BPFTableBase<int, ValueType> {
583*387f9dfdSAndroid Build Coastguard Worker public:
BPFTaskStorageTable(const TableDesc & desc)584*387f9dfdSAndroid Build Coastguard Worker BPFTaskStorageTable(const TableDesc& desc) : BPFTableBase<int, ValueType>(desc) {
585*387f9dfdSAndroid Build Coastguard Worker if (desc.type != BPF_MAP_TYPE_TASK_STORAGE)
586*387f9dfdSAndroid Build Coastguard Worker throw std::invalid_argument("Table '" + desc.name +
587*387f9dfdSAndroid Build Coastguard Worker "' is not a task_storage table");
588*387f9dfdSAndroid Build Coastguard Worker }
589*387f9dfdSAndroid Build Coastguard Worker
get_value(const int & fd,ValueType & value)590*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple get_value(const int& fd, ValueType& value) {
591*387f9dfdSAndroid Build Coastguard Worker if (!this->lookup(const_cast<int*>(&fd), get_value_addr(value)))
592*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
593*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
594*387f9dfdSAndroid Build Coastguard Worker }
595*387f9dfdSAndroid Build Coastguard Worker
update_value(const int & fd,const ValueType & value)596*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple update_value(const int& fd, const ValueType& value) {
597*387f9dfdSAndroid Build Coastguard Worker if (!this->update(const_cast<int*>(&fd),
598*387f9dfdSAndroid Build Coastguard Worker get_value_addr(const_cast<ValueType&>(value))))
599*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
600*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
601*387f9dfdSAndroid Build Coastguard Worker }
602*387f9dfdSAndroid Build Coastguard Worker
remove_value(const int & fd)603*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple remove_value(const int& fd) {
604*387f9dfdSAndroid Build Coastguard Worker if (!this->remove(const_cast<int*>(&fd)))
605*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error removing value: %s", std::strerror(errno));
606*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
607*387f9dfdSAndroid Build Coastguard Worker }
608*387f9dfdSAndroid Build Coastguard Worker };
609*387f9dfdSAndroid Build Coastguard Worker
610*387f9dfdSAndroid Build Coastguard Worker template <class ValueType>
611*387f9dfdSAndroid Build Coastguard Worker class BPFCgStorageTable : public BPFTableBase<int, ValueType> {
612*387f9dfdSAndroid Build Coastguard Worker public:
BPFCgStorageTable(const TableDesc & desc)613*387f9dfdSAndroid Build Coastguard Worker BPFCgStorageTable(const TableDesc& desc) : BPFTableBase<int, ValueType>(desc) {
614*387f9dfdSAndroid Build Coastguard Worker if (desc.type != BPF_MAP_TYPE_CGROUP_STORAGE)
615*387f9dfdSAndroid Build Coastguard Worker throw std::invalid_argument("Table '" + desc.name +
616*387f9dfdSAndroid Build Coastguard Worker "' is not a cgroup_storage table");
617*387f9dfdSAndroid Build Coastguard Worker }
618*387f9dfdSAndroid Build Coastguard Worker
get_value(struct bpf_cgroup_storage_key & key,ValueType & value)619*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple get_value(struct bpf_cgroup_storage_key& key,
620*387f9dfdSAndroid Build Coastguard Worker ValueType& value) {
621*387f9dfdSAndroid Build Coastguard Worker if (!this->lookup(const_cast<struct bpf_cgroup_storage_key*>(&key),
622*387f9dfdSAndroid Build Coastguard Worker get_value_addr(value)))
623*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
624*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
625*387f9dfdSAndroid Build Coastguard Worker }
626*387f9dfdSAndroid Build Coastguard Worker
update_value(struct bpf_cgroup_storage_key & key,const ValueType & value)627*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple update_value(struct bpf_cgroup_storage_key& key, const ValueType& value) {
628*387f9dfdSAndroid Build Coastguard Worker if (!this->update(const_cast<struct bpf_cgroup_storage_key*>(&key),
629*387f9dfdSAndroid Build Coastguard Worker get_value_addr(const_cast<ValueType&>(value))))
630*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
631*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
632*387f9dfdSAndroid Build Coastguard Worker }
633*387f9dfdSAndroid Build Coastguard Worker };
634*387f9dfdSAndroid Build Coastguard Worker
635*387f9dfdSAndroid Build Coastguard Worker template <class ValueType>
636*387f9dfdSAndroid Build Coastguard Worker class BPFPercpuCgStorageTable : public BPFTableBase<int, std::vector<ValueType>> {
637*387f9dfdSAndroid Build Coastguard Worker public:
BPFPercpuCgStorageTable(const TableDesc & desc)638*387f9dfdSAndroid Build Coastguard Worker BPFPercpuCgStorageTable(const TableDesc& desc)
639*387f9dfdSAndroid Build Coastguard Worker : BPFTableBase<int, std::vector<ValueType>>(desc) {
640*387f9dfdSAndroid Build Coastguard Worker if (desc.type != BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
641*387f9dfdSAndroid Build Coastguard Worker throw std::invalid_argument("Table '" + desc.name +
642*387f9dfdSAndroid Build Coastguard Worker "' is not a percpu_cgroup_storage table");
643*387f9dfdSAndroid Build Coastguard Worker if (sizeof(ValueType) % 8)
644*387f9dfdSAndroid Build Coastguard Worker throw std::invalid_argument("leaf must be aligned to 8 bytes");
645*387f9dfdSAndroid Build Coastguard Worker ncpus = BPFTable::get_possible_cpu_count();
646*387f9dfdSAndroid Build Coastguard Worker }
647*387f9dfdSAndroid Build Coastguard Worker
get_value(struct bpf_cgroup_storage_key & key,std::vector<ValueType> & value)648*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple get_value(struct bpf_cgroup_storage_key& key,
649*387f9dfdSAndroid Build Coastguard Worker std::vector<ValueType>& value) {
650*387f9dfdSAndroid Build Coastguard Worker value.resize(ncpus);
651*387f9dfdSAndroid Build Coastguard Worker if (!this->lookup(const_cast<struct bpf_cgroup_storage_key*>(&key),
652*387f9dfdSAndroid Build Coastguard Worker get_value_addr(value)))
653*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
654*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
655*387f9dfdSAndroid Build Coastguard Worker }
656*387f9dfdSAndroid Build Coastguard Worker
update_value(struct bpf_cgroup_storage_key & key,std::vector<ValueType> & value)657*387f9dfdSAndroid Build Coastguard Worker virtual StatusTuple update_value(struct bpf_cgroup_storage_key& key,
658*387f9dfdSAndroid Build Coastguard Worker std::vector<ValueType>& value) {
659*387f9dfdSAndroid Build Coastguard Worker value.resize(ncpus);
660*387f9dfdSAndroid Build Coastguard Worker if (!this->update(const_cast<struct bpf_cgroup_storage_key*>(&key),
661*387f9dfdSAndroid Build Coastguard Worker get_value_addr(const_cast<std::vector<ValueType>&>(value))))
662*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
663*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
664*387f9dfdSAndroid Build Coastguard Worker }
665*387f9dfdSAndroid Build Coastguard Worker private:
666*387f9dfdSAndroid Build Coastguard Worker unsigned int ncpus;
667*387f9dfdSAndroid Build Coastguard Worker };
668*387f9dfdSAndroid Build Coastguard Worker
669*387f9dfdSAndroid Build Coastguard Worker } // namespace ebpf
670