[eBPF] sockops类型运行梳理

本文详细介绍了eBPF的sockops程序类型如何在Linux内核的socket事件中实现埋点,以及如何通过tcp_connect函数触发BPF程序执行,展示了从内核源码到实际应用的完整流程。

[eBPF] sockops类型运行梳理

BPF_PROG_TYPE_SOCK_OPS程序类型

内核中socket事件(本质是各函数)中的埋点,能够在socket的生命周期每个节点执行BPF程序。

  • 进入Linux内核的commit
  • session定义SEC_DEF("sockops", SOCK_OPS, BPF_CGROUP_SOCK_OPS, SEC_ATTACHABLE_OPT)
  • 参数,由BPF_PROG_TYPE(BPF_PROG_TYPE_SOCK_OPS, sock_ops, struct bpf_sock_ops, struct bpf_sock_ops_kern)可知:bpf程序的入参是bpf_sock_ops,对应内核中的上下文是bpf_sock_ops_kern。
  • 使用场景:参考博客

示例代码

__section("sockops") // 加载到 ELF 中的 `sockops` 区域,有 socket operations 时触发执行
int bpf_sockmap(struct bpf_sock_ops *skops)
{
   
   
    switch (skops->op) {
   
   
        case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: // 被动建连
        case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:  // 主动建连
            if (skops->family == 2) {
   
                // AF_INET
                bpf_sock_ops_ipv4(skops);         // 将 socket 信息记录到到 sockmap
            }
            break;
        default:
            break;
    }
    return 0;
}

Hook位置梳理

  1. tcp_output.c,中核心函数int tcp_connect(struct sock *sk)一开始就埋了点:
// https://elixir.bootlin.com/linux/v6.6.4/source/net/ipv4/tcp_output.c#L3946
/* Build a SYN and send it off. */
int tcp_connect(struct sock *sk)
{
   
   
	struct tcp_sock *tp = tcp_sk(sk);
	struct sk_buff *buff;
	int err;

	
### eBPF 程序类型及其用途 #### 1. Socket 过滤器 (Socket Filters) 这类程序用于过滤到达套接字的数据包。通过挂载到特定的 socket 上,能够决定哪些数据包应该传递给应用程序,哪些应当被丢弃。这使得开发者能够在应用层面上实现高效的流量控制机制。 ```c SEC("socket") int sock_filter(struct __sk_buff *skb) { // 对传入的数据包执行某些操作... } ``` 这种类型的 BPF 程序可以直接访问 `struct __sk_buff` 提供的信息[^3],从而允许对网络数据包的内容进行深入分析和处理。 #### 2. Kprobe 和 Uprobes Kprobes 允许在内核函数入口处插入探测点;Uprobes 则是在用户空间进程中设置断点。这两种探针都可以触发关联的 BPF 程序运行,以便收集性能统计数据或调试信息。 ```c // 定义一个kprobe事件处理器 SEC("kprobe/do_sys_open") int handle_do_sys_open(struct pt_regs *ctx){ // 执行日志记录或其他动作... } // 用户态uprobe示例 SEC("uprobe/bin/bash:/usr/bin/bash:do_execve") int uprobe_handler(struct pt_regs *ctx, const char *filename) { // 处理execve调用... } ``` 此类程序对于追踪系统行为非常有用,并且可以通过 bpftool 工具与 kallsyms 结合使用来解析辅助函数地址[^1]。 #### 3. TC Classifier and Action Programs TC(Traffic Control)分类器负责根据预定义规则区分不同类别的网络流;而动作程序则决定了如何处置这些已分类的数据包——比如重新路由、修改报文头部等。两者共同作用于Linux Traffic Control子系统之上。 ```bash # 使用tc命令加载ebpf程序作为qdisc的一部分 $ tc qdisc add dev eth0 clsact $ tc filter add dev eth0 ingress bpf da obj classifier.o sec prog ``` 上述配置将使指定网卡上的所有进入流量经过由 ebpf 编写的分类逻辑判断后再做相应处理。 #### 4. XDP (eXpress Data Path) XDP 是一种位于驱动层面的工作模式,它让 BPF 程序尽可能早地介入到数据接收路径当中,以此获得极低延迟下的高性能表现。适用于构建高速防火墙、DDoS防护等功能模块。 ```c SEC("xdp") int xdp_drop_all(struct xdp_md *ctx) { return XDP_DROP; } ``` 此代码片段展示了一个简单的 XDP 程序实例,该程序会无条件拒绝所有收到的数据帧。 #### 5. Tracepoints Tracepoint 类型的 BPF 程序可以附加到预先设定好的跟踪点上,当达到某个感兴趣的事件时就会激活对应的回调函数。这种方式提供了轻量级的日志记录能力而不必担心引入过多开销。 ```c SEC("tracepoint/block:block_rq_issue") int trace_block_request(struct trace_event_raw_block_rq *ctx) { // 记录磁盘I/O请求详情... } ``` 以上就是几种常见的 eBPF 应用场景概述。每种类型都有其独特的优势所在,可以根据实际需求灵活选用合适的方案来进行开发实践。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值