标签: ebpf

如何获取 Linux 内核的 bpf_helpers.h 头文件?

我正在 Ubuntu 机器上开发 eBPF 程序:

$ uname -a
Linux ubuntu-bionic 4.18.0-16-generic #17~18.04.1-Ubuntu SMP Tue Feb 12 13:35:51 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
Run Code Online (Sandbox Code Playgroud)

为此,我需要bpf.h许多定义以及bpf_helpers.h辅助函数定义。我安装了一个带有标题的新内核:

apt-get update -y
apt-get install -y linux-image-4.18.0-16-generic linux-headers-4.18.0-16-generic
Run Code Online (Sandbox Code Playgroud)

标头包括bpf.h:

$ find /usr/src/linux-headers-4.18.0-16 -name bpf.h
/usr/src/linux-headers-4.18.0-16/include/uapi/linux/bpf.h
/usr/src/linux-headers-4.18.0-16/include/linux/bpf.h
Run Code Online (Sandbox Code Playgroud)

但不是bpf_helpers.h:

$ find /usr/src/linux-headers-4.18.0-16 -name bpf_helpers.h
Run Code Online (Sandbox Code Playgroud)

如何为我的内核获取此文件?为什么它不包含在分发标头中?

我可以签出特定版本的 Linux 内核或从master获取文件,但发行版可能会对上游进行更改,这让我这样做感到不舒服。

linux header-files linux-kernel bpf ebpf

11
推荐指数
1
解决办法
1万
查看次数

测试 XDP 与 DPDK

我确实有一些 DPDK 经验,但目前我正在阅读许多有关 XDP 的博客。我正在尝试比较这两种技术并了解 DPDK 和 XDP 之间的差异。这引发了一些问题。我希望有人能帮助我解决以下问题:

  1. 通过 DPDK,我可以将工作线程映射到 CPU 内核,并隔离 DPDK 将使用的 CPU 内核。如果是 eBPF / XDP,则使用哪些 CPU 内核?是否使用了所有可用的 CPU 内核?是否可以隔离用于 eBPF / XDP 程序的 CPU 内核?
  2. 当我测试 DPDK 应用程序的吞吐量时,我可以检查环形缓冲区(内存池)是否已满,从而导致数据包丢失。但如何检查 eBPF/XDP 程序是否因吞吐量过高而导致丢包?我假设当 eBPF / XDP 程序花费太多时间来处理数据包时,最终您会看到数据包丢失?(特别是在高速率发送64B数据包时查找可以发送的最大数据包数量)

预先感谢您的帮助!

cpu dpdk ebpf xdp-bpf

10
推荐指数
1
解决办法
7043
查看次数

是否可以拦截本地程序未加密的HTTPS请求体?

是否可以编写一个通用的 EBPF 程序来读取所有用户空间程序的未加密 HTTPS 请求和响应主体?

据我了解,EBPF 处理网络第 2、3 和 4 层的数据包。HTTPS 有效负载在这些数据包中加密,因此 EBPF 可以读取数据包元数据,但不能读取构成 HTTPS 请求/响应的有效负载?

这样做是将日志记录添加到用户空间程序的唯一方法吗?

linux https network-programming bpf ebpf

6
推荐指数
3
解决办法
1280
查看次数

动态更改 eBPF 映射大小

在内核中,eBPF 映射可以定义为:

struct bpf_map_def SEC("maps") my_map = {
    .type = BPF_MAP_TYPE_HASH,
    .key_size = sizeof(uint32_t),
    .value_size = sizeof(struct task_prov_struct),
    .max_entries = 4096,
};
Run Code Online (Sandbox Code Playgroud)

如果我提前不知道最大可能大小my_map(我也不想浪费内存),有没有办法预先分配一个小大小并根据需要动态增加大小?我知道bpf_map__resize函数,但它似乎是一个用户空间函数,只能在加载地图之前调用。我将不胜感激任何示例代码片段或参考。

linux-kernel ebpf

6
推荐指数
1
解决办法
1722
查看次数

如何计算 eBPF 探针的性能影响?

eBPF 已成为轻松快速地监控流程的重要工具。然而,我无法找到如何计算探针本身对性能的影响。我确信如果我挂钩每个系统调用并在地图中推送一些信息,一定会产生一些影响,没有什么是免费的,但是我将如何正确计算这种增加的延迟?

我想到的唯一解决方案是在探测器处于活动状态和不活动状态的情况下多次运行相同的程序,并检查系统执行时间差异,但在我看来,这会受到各种因素的影响,这些因素可能会增加很多差异因此不会给出非常可靠的结果。

performance monitoring bpf ebpf

6
推荐指数
1
解决办法
1016
查看次数

在 BPF_PROG_TYPE_SK_LOOKUP 中获取连接所有者的 PID

我找到了一个 eBPF 示例,它代理请求,根据目标端口过滤哪些请求。

我试图按客户端的 process_id 而不是目标端口进行过滤,并尝试添加bpf_get_current_pid_tgid() here。然而,该方法似乎在该上下文中未找到/可用。

在这种情况下,如何找到正确的方法来获取连接所有者 process_id ?

ebpf xdp-bpf

6
推荐指数
1
解决办法
356
查看次数

5
推荐指数
1
解决办法
775
查看次数

变量属性SEC是什么意思?

目前,我正在跟踪 bpf 程序并发现一些我无法理解的内容。

有几个声明,例如:

struct bpf_map_def SEC("maps") map_parsing_context = {
...
};
struct {
...
} map_keys SEC(".maps");
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. 这个语法叫什么?
  2. 这与 相同吗__attribute__((section("name")))?
  3. map和之间有什么不同.map?它们只是用户定义的部分吗?

c bpf ebpf

5
推荐指数
1
解决办法
3339
查看次数

eBPF:raw_tracepoint 参数

我正在进入 eBPF 编程并想要使用原始跟踪点,但我不太明白如何使用它们以及如何正确访问参数。我将不胜感激任何对文档的帮助和提示。

我的问题:

  1. 如何使用 raw_tracepoint 而不是跟踪点从系统调用获取参数?
  2. uint16_t common_type;顺便说一句:原始跟踪点是什么?

系统:Ubuntu 2004,内核 5.4 通用,x86_64

解释/示例:

我从“正常跟踪点”开始sys_enter_kill,我可以在其中使用以下参数创建结构sudo cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_kill/format:


// sudo cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_kill/format
// name: sys_enter_kill
// ID: 184
// format:
//  field:unsigned short common_type;   offset:0;   size:2; signed:0;
//  field:unsigned char common_flags;   offset:2;   size:1; signed:0;
//  field:unsigned char common_preempt_count;   offset:3;   size:1;signed:0;
//  field:int common_pid;   offset:4;   size:4; signed:1;

//  field:int __syscall_nr; offset:8;   size:4; signed:1;
//  field:pid_t pid;    offset:16;  size:8; signed:0;
//  field:int sig;  offset:24;  size:8; signed:0;

struct syscalls_enter_kill_args …
Run Code Online (Sandbox Code Playgroud)

c c++ linux bpf ebpf

5
推荐指数
1
解决办法
2068
查看次数

在没有分支操作码的情况下测试一个整数与 eBPF 中的其他两个整数不同

我正在编写一个检查任务 UID 的 eBPF kprobe,即在 execve 调用之间唯一允许的 UID 更改是 setuid()、seteuid() 和 setreuid() 调用所允许的 UID 更改。

由于探测器检查所有任务,因此它使用从 init_task 开始迭代的展开循环,并且最多必须使用 1024 或 8192 个分支,具体取决于内核版本。

我的问题是,如果存在非法更改,如何实现返回非零的检查,定义为:

(new_ruid != old_euid && new_ruid != old_ruid) ||
(new_euid != old_euid && new_euid != old_ruid && new_euid != old_suid)
Run Code Online (Sandbox Code Playgroud)

但不使用分支(clang 使用跳转来短路检查之间的任何表达式是否&&计算为 true)。

assembly clang linux-kernel bpf ebpf

5
推荐指数
1
解决办法
211
查看次数