Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
bcc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
bcc
Commits
3bb44859
Commit
3bb44859
authored
Apr 28, 2018
by
yonghong-song
Committed by
GitHub
Apr 28, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1716 from palmtenor/cppmisc
Misc improvements to C++ API and example
parents
bbc3fbfe
ce657b11
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
155 additions
and
108 deletions
+155
-108
examples/cpp/RecordMySQLQuery.cc
examples/cpp/RecordMySQLQuery.cc
+5
-4
examples/cpp/TCPSendStack.cc
examples/cpp/TCPSendStack.cc
+35
-20
src/cc/api/BPF.cc
src/cc/api/BPF.cc
+9
-10
src/cc/api/BPF.h
src/cc/api/BPF.h
+10
-7
src/cc/api/BPFTable.cc
src/cc/api/BPFTable.cc
+52
-27
src/cc/api/BPFTable.h
src/cc/api/BPFTable.h
+44
-40
No files found.
examples/cpp/RecordMySQLQuery.cc
View file @
3bb44859
...
...
@@ -83,10 +83,11 @@ int main(int argc, char** argv) {
auto
table_handle
=
bpf
.
get_hash_table
<
query_probe_t
,
int
>
(
"queries"
);
auto
table
=
table_handle
.
get_table_offline
();
std
::
sort
(
table
.
begin
(),
table
.
end
(),
[](
std
::
pair
<
query_probe_t
,
int
>
a
,
std
::
pair
<
query_probe_t
,
int
>
b
)
{
return
a
.
first
.
ts
<
b
.
first
.
ts
;
});
std
::
sort
(
table
.
begin
(),
table
.
end
(),
[](
std
::
pair
<
query_probe_t
,
int
>
a
,
std
::
pair
<
query_probe_t
,
int
>
b
)
{
return
a
.
first
.
ts
<
b
.
first
.
ts
;
});
std
::
cout
<<
table
.
size
()
<<
" queries recorded:"
<<
std
::
endl
;
for
(
auto
it
:
table
)
{
std
::
cout
<<
"Time: "
<<
it
.
first
.
ts
<<
" PID: "
<<
it
.
first
.
pid
...
...
examples/cpp/TCPSendStack.cc
View file @
3bb44859
...
...
@@ -27,17 +27,15 @@ struct stack_key_t {
int kernel_stack;
};
BPF_STACK_TRACE(stack_traces, 1
0240
);
BPF_STACK_TRACE(stack_traces, 1
6384
);
BPF_HASH(counts, struct stack_key_t, uint64_t);
int on_tcp_send(struct pt_regs *ctx) {
struct stack_key_t key = {};
key.pid = bpf_get_current_pid_tgid() >> 32;
bpf_get_current_comm(&key.name, sizeof(key.name));
key.kernel_stack = stack_traces.get_stackid(ctx, BPF_F_REUSE_STACKID);
key.user_stack = stack_traces.get_stackid(
ctx, BPF_F_REUSE_STACKID | BPF_F_USER_STACK
);
key.kernel_stack = stack_traces.get_stackid(ctx, 0);
key.user_stack = stack_traces.get_stackid(ctx, BPF_F_USER_STACK);
u64 zero = 0, *val;
val = counts.lookup_or_init(&key, &zero);
...
...
@@ -76,39 +74,56 @@ int main(int argc, char** argv) {
std
::
cout
<<
"Probing for "
<<
probe_time
<<
" seconds"
<<
std
::
endl
;
sleep
(
probe_time
);
auto
detach_res
=
bpf
.
detach_kprobe
(
"tcp_sendmsg"
);
if
(
detach_res
.
code
()
!=
0
)
{
std
::
cerr
<<
detach_res
.
msg
()
<<
std
::
endl
;
return
1
;
}
auto
table
=
bpf
.
get_hash_table
<
stack_key_t
,
uint64_t
>
(
"counts"
).
get_table_offline
();
std
::
sort
(
table
.
begin
(),
table
.
end
(),
[](
std
::
pair
<
stack_key_t
,
uint64_t
>
a
,
std
::
pair
<
stack_key_t
,
uint64_t
>
b
)
{
return
a
.
second
<
b
.
second
;
});
std
::
sort
(
table
.
begin
(),
table
.
end
(),
[](
std
::
pair
<
stack_key_t
,
uint64_t
>
a
,
std
::
pair
<
stack_key_t
,
uint64_t
>
b
)
{
return
a
.
second
<
b
.
second
;
});
auto
stacks
=
bpf
.
get_stack_table
(
"stack_traces"
);
int
lost_stacks
=
0
;
for
(
auto
it
:
table
)
{
std
::
cout
<<
"PID: "
<<
it
.
first
.
pid
<<
" ("
<<
it
.
first
.
name
<<
") "
<<
"made "
<<
it
.
second
<<
" TCP sends on following stack: "
<<
std
::
endl
;
std
::
cout
<<
" Kernel Stack:"
<<
std
::
endl
;
if
(
it
.
first
.
kernel_stack
>=
0
)
{
std
::
cout
<<
" Kernel Stack:"
<<
std
::
endl
;
auto
syms
=
stacks
.
get_stack_symbol
(
it
.
first
.
kernel_stack
,
-
1
);
for
(
auto
sym
:
syms
)
std
::
cout
<<
" "
<<
sym
<<
std
::
endl
;
}
else
std
::
cout
<<
" "
<<
it
.
first
.
kernel_stack
<<
std
::
endl
;
std
::
cout
<<
" User Stack:"
<<
std
::
endl
;
}
else
{
// -EFAULT normally means the stack is not availiable and not an error
if
(
it
.
first
.
kernel_stack
!=
-
EFAULT
)
{
lost_stacks
++
;
std
::
cout
<<
" [Lost Kernel Stack"
<<
it
.
first
.
kernel_stack
<<
"]"
<<
std
::
endl
;
}
}
if
(
it
.
first
.
user_stack
>=
0
)
{
std
::
cout
<<
" User Stack:"
<<
std
::
endl
;
auto
syms
=
stacks
.
get_stack_symbol
(
it
.
first
.
user_stack
,
it
.
first
.
pid
);
for
(
auto
sym
:
syms
)
std
::
cout
<<
" "
<<
sym
<<
std
::
endl
;
}
else
std
::
cout
<<
" "
<<
it
.
first
.
user_stack
<<
std
::
endl
;
}
else
{
// -EFAULT normally means the stack is not availiable and not an error
if
(
it
.
first
.
user_stack
!=
-
EFAULT
)
{
lost_stacks
++
;
std
::
cout
<<
" [Lost User Stack "
<<
it
.
first
.
user_stack
<<
"]"
<<
std
::
endl
;
}
}
}
auto
detach_res
=
bpf
.
detach_kprobe
(
"tcp_sendmsg"
);
if
(
detach_res
.
code
()
!=
0
)
{
std
::
cerr
<<
detach_res
.
msg
()
<<
std
::
endl
;
return
1
;
}
if
(
lost_stacks
>
0
)
std
::
cout
<<
"Total "
<<
lost_stacks
<<
" stack-traces lost due to "
<<
"hash collision or stack table full"
<<
std
::
endl
;
return
0
;
}
src/cc/api/BPF.cc
View file @
3bb44859
...
...
@@ -39,9 +39,9 @@
namespace
ebpf
{
static
const
char
*
syscall_prefix
[]
=
{
"sys_"
,
"__x64_sys_"
,
static
const
char
*
syscall_prefix
[]
=
{
"sys_"
,
"__x64_sys_"
,
};
std
::
string
uint_to_hex
(
uint64_t
value
)
{
...
...
@@ -63,7 +63,7 @@ StatusTuple BPF::init(const std::string& bpf_program,
const
std
::
vector
<
USDT
>&
usdt
)
{
std
::
string
all_bpf_program
;
bcc_symbol_option
symbol_option
=
{};
void
*
ksym_cache
;
void
*
ksym_cache
;
uint64_t
addr
;
int
ret
;
...
...
@@ -284,8 +284,8 @@ StatusTuple BPF::attach_tracepoint(const std::string& tracepoint,
int
probe_fd
;
TRY2
(
load_func
(
probe_func
,
BPF_PROG_TYPE_TRACEPOINT
,
probe_fd
));
int
res_fd
=
bpf_attach_tracepoint
(
probe_fd
,
tp_category
.
c_str
(),
tp_name
.
c_str
());
int
res_fd
=
bpf_attach_tracepoint
(
probe_fd
,
tp_category
.
c_str
(),
tp_name
.
c_str
());
if
(
res_fd
<
0
)
{
TRY2
(
unload_func
(
probe_func
));
...
...
@@ -341,8 +341,8 @@ StatusTuple BPF::attach_perf_event(uint32_t ev_type, uint32_t ev_config,
}
StatusTuple
BPF
::
attach_perf_event_raw
(
void
*
perf_event_attr
,
const
std
::
string
&
probe_func
,
pid_t
pid
,
int
cpu
,
int
group_fd
)
{
const
std
::
string
&
probe_func
,
pid_t
pid
,
int
cpu
,
int
group_fd
)
{
auto
attr
=
static_cast
<
struct
perf_event_attr
*>
(
perf_event_attr
);
auto
ev_pair
=
std
::
make_pair
(
attr
->
type
,
attr
->
config
);
if
(
perf_events_
.
find
(
ev_pair
)
!=
perf_events_
.
end
())
...
...
@@ -377,7 +377,6 @@ StatusTuple BPF::attach_perf_event_raw(void* perf_event_attr,
p
.
per_cpu_fd
=
fds
;
perf_events_
[
ev_pair
]
=
std
::
move
(
p
);
return
StatusTuple
(
0
);
}
StatusTuple
BPF
::
detach_kprobe
(
const
std
::
string
&
kernel_func
,
...
...
@@ -567,7 +566,7 @@ StatusTuple BPF::unload_func(const std::string& func_name) {
return
StatusTuple
(
0
);
}
std
::
string
BPF
::
get_syscall_fnname
(
const
std
::
string
&
name
)
{
std
::
string
BPF
::
get_syscall_fnname
(
const
std
::
string
&
name
)
{
std
::
string
fn_name
=
syscall_prefix
[
syscall_prefix_idx_
]
+
name
;
return
std
::
move
(
fn_name
);
}
...
...
src/cc/api/BPF.h
View file @
3bb44859
...
...
@@ -47,7 +47,8 @@ class BPF {
explicit
BPF
(
unsigned
int
flag
=
0
,
TableStorage
*
ts
=
nullptr
,
bool
rw_engine_enabled
=
true
)
:
flag_
(
flag
),
syscall_prefix_idx_
(
0
),
:
flag_
(
flag
),
syscall_prefix_idx_
(
0
),
bpf_module_
(
new
BPFModule
(
flag
,
ts
,
rw_engine_enabled
))
{}
StatusTuple
init
(
const
std
::
string
&
bpf_program
,
const
std
::
vector
<
std
::
string
>&
cflags
=
{},
...
...
@@ -91,7 +92,7 @@ class BPF {
int
group_fd
=
-
1
);
StatusTuple
detach_perf_event
(
uint32_t
ev_type
,
uint32_t
ev_config
);
StatusTuple
detach_perf_event_raw
(
void
*
perf_event_attr
);
std
::
string
get_syscall_fnname
(
const
std
::
string
&
name
);
std
::
string
get_syscall_fnname
(
const
std
::
string
&
name
);
BPFTable
get_table
(
const
std
::
string
&
name
)
{
TableStorage
::
iterator
it
;
...
...
@@ -109,7 +110,8 @@ class BPF {
}
template
<
class
ValueType
>
BPFPercpuArrayTable
<
ValueType
>
get_percpu_array_table
(
const
std
::
string
&
name
)
{
BPFPercpuArrayTable
<
ValueType
>
get_percpu_array_table
(
const
std
::
string
&
name
)
{
TableStorage
::
iterator
it
;
if
(
bpf_module_
->
table_storage
().
Find
(
Path
({
bpf_module_
->
id
(),
name
}),
it
))
return
BPFPercpuArrayTable
<
ValueType
>
(
it
->
second
);
...
...
@@ -125,7 +127,8 @@ class BPF {
}
template
<
class
KeyType
,
class
ValueType
>
BPFPercpuHashTable
<
KeyType
,
ValueType
>
get_percpu_hash_table
(
const
std
::
string
&
name
)
{
BPFPercpuHashTable
<
KeyType
,
ValueType
>
get_percpu_hash_table
(
const
std
::
string
&
name
)
{
TableStorage
::
iterator
it
;
if
(
bpf_module_
->
table_storage
().
Find
(
Path
({
bpf_module_
->
id
(),
name
}),
it
))
return
BPFPercpuHashTable
<
KeyType
,
ValueType
>
(
it
->
second
);
...
...
@@ -159,9 +162,9 @@ class BPF {
BPFPerfBuffer
*
get_perf_buffer
(
const
std
::
string
&
name
);
// Poll an opened Perf Buffer of given name with given timeout, using callback
// provided when opening. Do nothing if such open Perf Buffer doesn't exist.
// Returns:
// -1 on error or if perf buffer with such name doesn't exist;
// 0, if no data was available before timeout;
// Returns:
// -1 on error or if perf buffer with such name doesn't exist;
// 0, if no data was available before timeout;
// number of CPUs that have new data, otherwise.
int
poll_perf_buffer
(
const
std
::
string
&
name
,
int
timeout_ms
=
-
1
);
...
...
src/cc/api/BPFTable.cc
View file @
3bb44859
...
...
@@ -14,10 +14,10 @@
* limitations under the License.
*/
#include <fcntl.h>
#include <linux/elf.h>
#include <linux/perf_event.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <cinttypes>
...
...
@@ -145,28 +145,25 @@ StatusTuple BPFTable::remove_value(const std::string& key_str) {
}
StatusTuple
BPFTable
::
clear_table_non_atomic
()
{
if
(
desc
.
type
==
BPF_MAP_TYPE_HASH
||
desc
.
type
==
BPF_MAP_TYPE_PERCPU_HASH
||
if
(
desc
.
type
==
BPF_MAP_TYPE_HASH
||
desc
.
type
==
BPF_MAP_TYPE_PERCPU_HASH
||
desc
.
type
==
BPF_MAP_TYPE_LRU_HASH
||
desc
.
type
==
BPF_MAP_TYPE_PERCPU_HASH
||
desc
.
type
==
BPF_MAP_TYPE_HASH_OF_MAPS
)
{
// For hash maps, use the first() interface (which uses get_next_key) to
// iterate through the map and clear elements
auto
key
=
std
::
unique_ptr
<
void
,
decltype
(
::
free
)
*>
(
::
malloc
(
desc
.
key_size
),
::
free
);
auto
key
=
std
::
unique_ptr
<
void
,
decltype
(
::
free
)
*>
(
::
malloc
(
desc
.
key_size
),
::
free
);
while
(
this
->
first
(
key
.
get
()))
if
(
!
this
->
remove
(
key
.
get
()))
{
return
StatusTuple
(
-
1
,
"Failed to delete element when clearing table %s"
,
desc
.
name
.
c_str
());
return
StatusTuple
(
-
1
,
"Failed to delete element when clearing table %s"
,
desc
.
name
.
c_str
());
}
}
else
if
(
desc
.
type
==
BPF_MAP_TYPE_ARRAY
||
desc
.
type
==
BPF_MAP_TYPE_PERCPU_ARRAY
)
{
return
StatusTuple
(
-
1
,
"Array map %s do not support clearing elements"
,
desc
.
name
.
c_str
());
return
StatusTuple
(
-
1
,
"Array map %s do not support clearing elements"
,
desc
.
name
.
c_str
());
}
else
if
(
desc
.
type
==
BPF_MAP_TYPE_PROG_ARRAY
||
desc
.
type
==
BPF_MAP_TYPE_PERF_EVENT_ARRAY
||
desc
.
type
==
BPF_MAP_TYPE_STACK_TRACE
||
...
...
@@ -176,26 +173,25 @@ StatusTuple BPFTable::clear_table_non_atomic() {
this
->
remove
(
&
i
);
}
}
else
{
return
StatusTuple
(
-
1
,
"Clearing for map type of %s not supported yet"
,
desc
.
name
.
c_str
());
return
StatusTuple
(
-
1
,
"Clearing for map type of %s not supported yet"
,
desc
.
name
.
c_str
());
}
return
StatusTuple
(
0
);
}
size_t
BPFTable
::
get_possible_cpu_count
()
{
return
get_possible_cpus
().
size
();
}
size_t
BPFTable
::
get_possible_cpu_count
()
{
return
get_possible_cpus
().
size
();
}
BPFStackTable
::
BPFStackTable
(
const
TableDesc
&
desc
,
bool
use_debug_file
,
BPFStackTable
::
BPFStackTable
(
const
TableDesc
&
desc
,
bool
use_debug_file
,
bool
check_debug_file_crc
)
:
BPFTableBase
<
int
,
stacktrace_t
>
(
desc
)
{
symbol_option_
=
{
.
use_debug_file
=
use_debug_file
,
.
check_debug_file_crc
=
check_debug_file_crc
,
.
use_symbol_type
=
(
1
<<
STT_FUNC
)
|
(
1
<<
STT_GNU_IFUNC
)
};
if
(
desc
.
type
!=
BPF_MAP_TYPE_STACK_TRACE
)
throw
std
::
invalid_argument
(
"Table '"
+
desc
.
name
+
"' is not a stack table"
);
symbol_option_
=
{.
use_debug_file
=
use_debug_file
,
.
check_debug_file_crc
=
check_debug_file_crc
,
.
use_symbol_type
=
(
1
<<
STT_FUNC
)
|
(
1
<<
STT_GNU_IFUNC
)};
}
BPFStackTable
::
BPFStackTable
(
BPFStackTable
&&
that
)
...
...
@@ -254,6 +250,13 @@ std::vector<std::string> BPFStackTable::get_stack_symbol(int stack_id,
return
res
;
}
BPFPerfBuffer
::
BPFPerfBuffer
(
const
TableDesc
&
desc
)
:
BPFTableBase
<
int
,
int
>
(
desc
),
epfd_
(
-
1
)
{
if
(
desc
.
type
!=
BPF_MAP_TYPE_PERF_EVENT_ARRAY
)
throw
std
::
invalid_argument
(
"Table '"
+
desc
.
name
+
"' is not a perf buffer"
);
}
StatusTuple
BPFPerfBuffer
::
open_on_cpu
(
perf_reader_raw_cb
cb
,
perf_reader_lost_cb
lost_cb
,
int
cpu
,
void
*
cb_cookie
,
int
page_cnt
)
{
...
...
@@ -350,7 +353,8 @@ StatusTuple BPFPerfBuffer::close_all_cpu() {
int
BPFPerfBuffer
::
poll
(
int
timeout_ms
)
{
if
(
epfd_
<
0
)
return
-
1
;
int
cnt
=
epoll_wait
(
epfd_
,
ep_events_
.
get
(),
cpu_readers_
.
size
(),
timeout_ms
);
int
cnt
=
epoll_wait
(
epfd_
,
ep_events_
.
get
(),
cpu_readers_
.
size
(),
timeout_ms
);
for
(
int
i
=
0
;
i
<
cnt
;
i
++
)
perf_reader_event_read
(
static_cast
<
perf_reader
*>
(
ep_events_
[
i
].
data
.
ptr
));
return
cnt
;
...
...
@@ -363,6 +367,13 @@ BPFPerfBuffer::~BPFPerfBuffer() {
<<
std
::
endl
;
}
BPFPerfEventArray
::
BPFPerfEventArray
(
const
TableDesc
&
desc
)
:
BPFTableBase
<
int
,
int
>
(
desc
)
{
if
(
desc
.
type
!=
BPF_MAP_TYPE_PERF_EVENT_ARRAY
)
throw
std
::
invalid_argument
(
"Table '"
+
desc
.
name
+
"' is not a perf event array"
);
}
StatusTuple
BPFPerfEventArray
::
open_all_cpu
(
uint32_t
type
,
uint64_t
config
)
{
if
(
cpu_fds_
.
size
()
!=
0
)
return
StatusTuple
(
-
1
,
"Previously opened perf event not cleaned"
);
...
...
@@ -411,8 +422,8 @@ StatusTuple BPFPerfEventArray::open_on_cpu(int cpu, uint32_t type,
}
if
(
!
update
(
&
cpu
,
&
fd
))
{
bpf_close_perf_event_fd
(
fd
);
return
StatusTuple
(
-
1
,
"Unable to open perf event on CPU %d: %s"
,
cpu
,
std
::
strerror
(
errno
));
return
StatusTuple
(
-
1
,
"Unable to open perf event on CPU %d: %s"
,
cpu
,
std
::
strerror
(
errno
));
}
cpu_fds_
[
cpu
]
=
fd
;
return
StatusTuple
(
0
);
...
...
@@ -436,6 +447,13 @@ BPFPerfEventArray::~BPFPerfEventArray() {
}
}
BPFProgTable
::
BPFProgTable
(
const
TableDesc
&
desc
)
:
BPFTableBase
<
int
,
int
>
(
desc
)
{
if
(
desc
.
type
!=
BPF_MAP_TYPE_PROG_ARRAY
)
throw
std
::
invalid_argument
(
"Table '"
+
desc
.
name
+
"' is not a prog table"
);
}
StatusTuple
BPFProgTable
::
update_value
(
const
int
&
index
,
const
int
&
prog_fd
)
{
if
(
!
this
->
update
(
const_cast
<
int
*>
(
&
index
),
const_cast
<
int
*>
(
&
prog_fd
)))
return
StatusTuple
(
-
1
,
"Error updating value: %s"
,
std
::
strerror
(
errno
));
...
...
@@ -448,6 +466,13 @@ StatusTuple BPFProgTable::remove_value(const int& index) {
return
StatusTuple
(
0
);
}
BPFCgroupArray
::
BPFCgroupArray
(
const
TableDesc
&
desc
)
:
BPFTableBase
<
int
,
int
>
(
desc
)
{
if
(
desc
.
type
!=
BPF_MAP_TYPE_CGROUP_ARRAY
)
throw
std
::
invalid_argument
(
"Table '"
+
desc
.
name
+
"' is not a cgroup array"
);
}
StatusTuple
BPFCgroupArray
::
update_value
(
const
int
&
index
,
const
int
&
cgroup2_fd
)
{
if
(
!
this
->
update
(
const_cast
<
int
*>
(
&
index
),
const_cast
<
int
*>
(
&
cgroup2_fd
)))
...
...
src/cc/api/BPFTable.h
View file @
3bb44859
...
...
@@ -16,9 +16,9 @@
#pragma once
#include <cstring>
#include <errno.h>
#include <sys/epoll.h>
#include <cstring>
#include <exception>
#include <map>
#include <memory>
...
...
@@ -83,9 +83,7 @@ class BPFTableBase {
return
bpf_update_elem
(
desc
.
fd
,
key
,
value
,
0
)
>=
0
;
}
bool
remove
(
void
*
key
)
{
return
bpf_delete_elem
(
desc
.
fd
,
key
)
>=
0
;
}
bool
remove
(
void
*
key
)
{
return
bpf_delete_elem
(
desc
.
fd
,
key
)
>=
0
;
}
const
TableDesc
&
desc
;
};
...
...
@@ -111,19 +109,23 @@ class BPFTable : public BPFTableBase<void, void> {
};
template
<
class
ValueType
>
void
*
get_value_addr
(
ValueType
&
t
)
{
return
&
t
;
}
void
*
get_value_addr
(
ValueType
&
t
)
{
return
&
t
;
}
template
<
class
ValueType
>
void
*
get_value_addr
(
std
::
vector
<
ValueType
>&
t
)
{
return
t
.
data
();
}
void
*
get_value_addr
(
std
::
vector
<
ValueType
>&
t
)
{
return
t
.
data
();
}
template
<
class
ValueType
>
class
BPFArrayTable
:
public
BPFTableBase
<
int
,
ValueType
>
{
public:
BPFArrayTable
(
const
TableDesc
&
desc
)
:
BPFTableBase
<
int
,
ValueType
>
(
desc
)
{
public:
BPFArrayTable
(
const
TableDesc
&
desc
)
:
BPFTableBase
<
int
,
ValueType
>
(
desc
)
{
if
(
desc
.
type
!=
BPF_MAP_TYPE_ARRAY
&&
desc
.
type
!=
BPF_MAP_TYPE_PERCPU_ARRAY
)
throw
std
::
invalid_argument
(
"Table '"
+
desc
.
name
+
"' is not an array table"
);
throw
std
::
invalid_argument
(
"Table '"
+
desc
.
name
+
"' is not an array table"
);
}
virtual
StatusTuple
get_value
(
const
int
&
index
,
ValueType
&
value
)
{
...
...
@@ -133,7 +135,8 @@ public:
}
virtual
StatusTuple
update_value
(
const
int
&
index
,
const
ValueType
&
value
)
{
if
(
!
this
->
update
(
const_cast
<
int
*>
(
&
index
),
get_value_addr
(
const_cast
<
ValueType
&>
(
value
))))
if
(
!
this
->
update
(
const_cast
<
int
*>
(
&
index
),
get_value_addr
(
const_cast
<
ValueType
&>
(
value
))))
return
StatusTuple
(
-
1
,
"Error updating value: %s"
,
std
::
strerror
(
errno
));
return
StatusTuple
(
0
);
}
...
...
@@ -147,7 +150,7 @@ public:
std
::
vector
<
ValueType
>
get_table_offline
()
{
std
::
vector
<
ValueType
>
res
(
this
->
capacity
());
for
(
int
i
=
0
;
i
<
(
int
)
this
->
capacity
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
this
->
capacity
();
i
++
)
{
get_value
(
i
,
res
[
i
]);
}
...
...
@@ -162,8 +165,10 @@ class BPFPercpuArrayTable : public BPFArrayTable<std::vector<ValueType>> {
:
BPFArrayTable
<
std
::
vector
<
ValueType
>>
(
desc
),
ncpus
(
BPFTable
::
get_possible_cpu_count
())
{
if
(
desc
.
type
!=
BPF_MAP_TYPE_PERCPU_ARRAY
)
throw
std
::
invalid_argument
(
"Table '"
+
desc
.
name
+
"' is not a percpu array table"
);
// leaf structures have to be aligned to 8 bytes as hardcoded in the linux kernel.
throw
std
::
invalid_argument
(
"Table '"
+
desc
.
name
+
"' is not a percpu array table"
);
// leaf structures have to be aligned to 8 bytes as hardcoded in the linux
// kernel.
if
(
sizeof
(
ValueType
)
%
8
)
throw
std
::
invalid_argument
(
"leaf must be aligned to 8 bytes"
);
}
...
...
@@ -173,11 +178,13 @@ class BPFPercpuArrayTable : public BPFArrayTable<std::vector<ValueType>> {
return
BPFArrayTable
<
std
::
vector
<
ValueType
>>::
get_value
(
index
,
value
);
}
StatusTuple
update_value
(
const
int
&
index
,
const
std
::
vector
<
ValueType
>&
value
)
{
StatusTuple
update_value
(
const
int
&
index
,
const
std
::
vector
<
ValueType
>&
value
)
{
if
(
value
.
size
()
!=
ncpus
)
return
StatusTuple
(
-
1
,
"bad value size"
);
return
BPFArrayTable
<
std
::
vector
<
ValueType
>>::
update_value
(
index
,
value
);
}
private:
unsigned
int
ncpus
;
};
...
...
@@ -191,7 +198,8 @@ class BPFHashTable : public BPFTableBase<KeyType, ValueType> {
desc
.
type
!=
BPF_MAP_TYPE_PERCPU_HASH
&&
desc
.
type
!=
BPF_MAP_TYPE_LRU_HASH
&&
desc
.
type
!=
BPF_MAP_TYPE_LRU_PERCPU_HASH
)
throw
std
::
invalid_argument
(
"Table '"
+
desc
.
name
+
"' is not a hash table"
);
throw
std
::
invalid_argument
(
"Table '"
+
desc
.
name
+
"' is not a hash table"
);
}
virtual
StatusTuple
get_value
(
const
KeyType
&
key
,
ValueType
&
value
)
{
...
...
@@ -201,7 +209,8 @@ class BPFHashTable : public BPFTableBase<KeyType, ValueType> {
}
virtual
StatusTuple
update_value
(
const
KeyType
&
key
,
const
ValueType
&
value
)
{
if
(
!
this
->
update
(
const_cast
<
KeyType
*>
(
&
key
),
get_value_addr
(
const_cast
<
ValueType
&>
(
value
))))
if
(
!
this
->
update
(
const_cast
<
KeyType
*>
(
&
key
),
get_value_addr
(
const_cast
<
ValueType
&>
(
value
))))
return
StatusTuple
(
-
1
,
"Error updating value: %s"
,
std
::
strerror
(
errno
));
return
StatusTuple
(
0
);
}
...
...
@@ -247,15 +256,18 @@ class BPFHashTable : public BPFTableBase<KeyType, ValueType> {
};
template
<
class
KeyType
,
class
ValueType
>
class
BPFPercpuHashTable
:
public
BPFHashTable
<
KeyType
,
std
::
vector
<
ValueType
>>
{
class
BPFPercpuHashTable
:
public
BPFHashTable
<
KeyType
,
std
::
vector
<
ValueType
>>
{
public:
explicit
BPFPercpuHashTable
(
const
TableDesc
&
desc
)
:
BPFHashTable
<
KeyType
,
std
::
vector
<
ValueType
>>
(
desc
),
ncpus
(
BPFTable
::
get_possible_cpu_count
())
{
if
(
desc
.
type
!=
BPF_MAP_TYPE_PERCPU_HASH
&&
desc
.
type
!=
BPF_MAP_TYPE_LRU_PERCPU_HASH
)
throw
std
::
invalid_argument
(
"Table '"
+
desc
.
name
+
"' is not a percpu hash table"
);
// leaf structures have to be aligned to 8 bytes as hardcoded in the linux kernel.
throw
std
::
invalid_argument
(
"Table '"
+
desc
.
name
+
"' is not a percpu hash table"
);
// leaf structures have to be aligned to 8 bytes as hardcoded in the linux
// kernel.
if
(
sizeof
(
ValueType
)
%
8
)
throw
std
::
invalid_argument
(
"leaf must be aligned to 8 bytes"
);
}
...
...
@@ -265,11 +277,14 @@ class BPFPercpuHashTable : public BPFHashTable<KeyType, std::vector<ValueType>>
return
BPFHashTable
<
KeyType
,
std
::
vector
<
ValueType
>>::
get_value
(
key
,
value
);
}
StatusTuple
update_value
(
const
KeyType
&
key
,
const
std
::
vector
<
ValueType
>&
value
)
{
StatusTuple
update_value
(
const
KeyType
&
key
,
const
std
::
vector
<
ValueType
>&
value
)
{
if
(
value
.
size
()
!=
ncpus
)
return
StatusTuple
(
-
1
,
"bad value size"
);
return
BPFHashTable
<
KeyType
,
std
::
vector
<
ValueType
>>::
update_value
(
key
,
value
);
return
BPFHashTable
<
KeyType
,
std
::
vector
<
ValueType
>>::
update_value
(
key
,
value
);
}
private:
unsigned
int
ncpus
;
};
...
...
@@ -282,8 +297,7 @@ struct stacktrace_t {
class
BPFStackTable
:
public
BPFTableBase
<
int
,
stacktrace_t
>
{
public:
BPFStackTable
(
const
TableDesc
&
desc
,
bool
use_debug_file
,
BPFStackTable
(
const
TableDesc
&
desc
,
bool
use_debug_file
,
bool
check_debug_file_crc
);
BPFStackTable
(
BPFStackTable
&&
that
);
~
BPFStackTable
();
...
...
@@ -299,8 +313,7 @@ class BPFStackTable : public BPFTableBase<int, stacktrace_t> {
class
BPFPerfBuffer
:
public
BPFTableBase
<
int
,
int
>
{
public:
BPFPerfBuffer
(
const
TableDesc
&
desc
)
:
BPFTableBase
<
int
,
int
>
(
desc
),
epfd_
(
-
1
)
{}
BPFPerfBuffer
(
const
TableDesc
&
desc
);
~
BPFPerfBuffer
();
StatusTuple
open_all_cpu
(
perf_reader_raw_cb
cb
,
perf_reader_lost_cb
lost_cb
,
...
...
@@ -321,8 +334,7 @@ class BPFPerfBuffer : public BPFTableBase<int, int> {
class
BPFPerfEventArray
:
public
BPFTableBase
<
int
,
int
>
{
public:
BPFPerfEventArray
(
const
TableDesc
&
desc
)
:
BPFTableBase
<
int
,
int
>
(
desc
)
{}
BPFPerfEventArray
(
const
TableDesc
&
desc
);
~
BPFPerfEventArray
();
StatusTuple
open_all_cpu
(
uint32_t
type
,
uint64_t
config
);
...
...
@@ -336,24 +348,16 @@ class BPFPerfEventArray : public BPFTableBase<int, int> {
};
class
BPFProgTable
:
public
BPFTableBase
<
int
,
int
>
{
public:
BPFProgTable
(
const
TableDesc
&
desc
)
:
BPFTableBase
<
int
,
int
>
(
desc
)
{
if
(
desc
.
type
!=
BPF_MAP_TYPE_PROG_ARRAY
)
throw
std
::
invalid_argument
(
"Table '"
+
desc
.
name
+
"' is not a prog table"
);
}
public:
BPFProgTable
(
const
TableDesc
&
desc
);
StatusTuple
update_value
(
const
int
&
index
,
const
int
&
prog_fd
);
StatusTuple
remove_value
(
const
int
&
index
);
};
class
BPFCgroupArray
:
public
BPFTableBase
<
int
,
int
>
{
public:
BPFCgroupArray
(
const
TableDesc
&
desc
)
:
BPFTableBase
<
int
,
int
>
(
desc
)
{
if
(
desc
.
type
!=
BPF_MAP_TYPE_CGROUP_ARRAY
)
throw
std
::
invalid_argument
(
"Table '"
+
desc
.
name
+
"' is not a cgroup array"
);
}
public:
BPFCgroupArray
(
const
TableDesc
&
desc
);
StatusTuple
update_value
(
const
int
&
index
,
const
int
&
cgroup2_fd
);
StatusTuple
update_value
(
const
int
&
index
,
const
std
::
string
&
cgroup2_path
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment