xref: /aosp_15_r20/external/bcc/src/cc/api/BPFTable.h (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
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