bpf_xdp_attach源码分析

bpf_xdp_attach

int bpf_xdp_attach(int ifindex, int prog_fd, __u32 flags, const struct bpf_xdp_attach_opts *opts)
{
   
   
	int old_prog_fd, err;
	
	//首先检查一下对应的flags是否合法
	if (!OPTS_VALID(opts, bpf_xdp_attach_opts))
		return libbpf_err(-EINVAL);
	
	//从opts中获取fd值,
	//如果old_prog_fd不为空,设置标志位位replace,替换掉原来的程序
	//否则将old_prog_fd设置为-1
	old_prog_fd = OPTS_GET(opts, old_prog_fd, 0);
	if (old_prog_fd)
		flags |= XDP_FLAGS_REPLACE;
	else
		old_prog_fd = -1;
	
	//将BPF程序附加到指定的网络接口上
	err = __bpf_set_link_xdp_fd_replace(ifindex, prog_fd, old_prog_fd, flags);
	return libbpf_err(err);
}

首先我们来看一下对应的:

struct bpf_xdp_attach_opts {
   
   
	size_t sz;
	int old_prog_fd;
	size_t :0;
};

我们看一下如何使用上面这个函数, 这个函数的第一个参数是ifindex, -1表示对应的

  • bpf_xdp_attach(ifindex, -1, flags, opts); 关闭对应的程序
  • 我们可以看一下对应的flags
#define XDP_FLAGS_UPDATE_IF_NOEXIST	(1U << 0)
#define XDP_FLAGS_SKB_MODE		(1U << 1)
#define XDP_FLAGS_DRV_MODE		(1U << 2)
#define XDP_FLAGS_HW_MODE		(1U << 3)
#define XDP_FLAGS_REPLACE		(1U << 4)
  1. XDP_FLAGS_UPDATE_IF_NOEXIST:如果设置此标志,并且网络接口上没有已附加的XDP程序,则更新该接口的XDP程序。
  2. XDP_FLAGS_SKB_MODE:设置此标志表示XDP程序将在skb(socket buffer)模式下运行,这是XDP的传统运行模式。
  3. XDP_FLAGS_DRV_MODE:设置此标志表示XDP程序将在驱动模式下运行,这通常用于某些特定的硬件或驱动程序。
  4. XDP_FLAGS_HW_MODE:设置此标志表示XDP程序将在硬件模式下运行,这要求硬件支持XDP。
  5. XDP_FLAGS_REPLACE设置此标志表示如果网络接口上已经有一个XDP程序,那么新的XDP程序将替换它。

然后是这个函数 __bpf_set_link_xdp_fd_replace(ifindex, prog_fd, old_prog_fd, flags) 挂载对应的程序

然后是下面这个函数,我们也来分析一下,函数参数我们在之前已经说的的比较清晰了, 下面这个函数最终会调用一个libbpf_netlink_send_recv函数, 这个函数是通过netlink这个套接字来完成对应的功能的, 那么什么东西是net link呢, net link是一个提供用户空间进程与内核之间的通信方法, 这种方式是比ioctl要好很多的,

static int __bpf_set_link_xdp_fd_replace(
int ifindex, int fd, int old_fd, __u32 flags)
{
   
   
	struct nlattr *nla;
	int ret;
	struct libbpf_nla_req req;

	memset(&am
上面两个数据包和这些奇数长度的数据包区别是什么? <idle>-0 [012] ..s.. 30604.011456: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:110 before bpf_xdp_adjust_head ,pkt_len = 107 <idle>-0 [012] ..s.. 30604.011457: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:118 AD84 F358 52C1 E51C 0304 0161 FFFF 8005 <idle>-0 [012] ..s.. 30604.011459: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:118 0008 0045 5900 E947 0040 063E 1D5C A8C0 <idle>-0 [012] ..s.. 30604.011460: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:118 420C A8C0 060B 30E4 5114 9BD5 2F40 C1CB <idle>-0 [012] ..s.. 30604.011461: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:118 00AC ECCF F601 E498 0000 0101 0A08 9796 <idle>-0 [012] ..s.. 30604.011463: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:118 5B5B 8A91 C30A 7167 6271 7573 7566 6634 <idle>-0 [012] ..s.. 30604.011465: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:118 6633 3774 636B 6F6C 7832 7332 7873 7875 <idle>-0 [012] ..s.. 30604.011466: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:143 [XDP] remove caqm_hdr success <idle>-0 [012] ..s.. 30604.011466: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:155 after bpf_xdp_adjust_head ,pkt_len = 103 <idle>-0 [012] ..s.. 30604.011468: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:162 AD84 F358 52C1 E51C 0304 0161 0008 0045 <idle>-0 [012] ..s.. 30604.011469: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:162 5900 E947 0040 063E 1D5C A8C0 420C A8C0 <idle>-0 [012] ..s.. 30604.011470: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:162 060B 30E4 5114 9BD5 2F40 C1CB 00AC ECCF <idle>-0 [012] ..s.. 30604.011471: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:162 F601 E498 0000 0101 0A08 9796 5B5B 8A91 <idle>-0 [012] ..s.. 30604.011472: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:162 C30A 7167 6271 7573 7566 6634 6633 3774 <idle>-0 [012] ..s.. 30604.011474: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:162 636B 6F6C 7832 7332 7873 7875 6463 746F <idle>-0 [012] ..s.. 30604.011475: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/bpf_caqm.h:174 [parse_pkt_key] offset=0 <idle>-0 [012] ..s.. 30604.011476: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:286 [XDP]parse_pkt_key after remove CAQM hdr success! <idle>-0 [012] ..s.. 30604.011477: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:321 [XDP] Exiting XDP program with XDP_PASS <idle>-0 [012] ..s.. 30604.021192: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:275 [XDP] begin remove_caqm_hdr <idle>-0 [012] ..s.. 30604.021195: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:110 before bpf_xdp_adjust_head ,pkt_len = 71 <idle>-0 [012] ..s.. 30604.021196: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:118 AD84 F358 52C1 E51C 0304 0161 FFFF 8005 <idle>-0 [012] ..s.. 30604.021197: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:118 0008 0045 3500 EA47 0040 063E 405C A8C0 <idle>-0 [012] ..s.. 30604.021199: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:118 420C A8C0 060B 30E4 5114 9BD5 5440 C1CB <idle>-0 [012] ..s.. 30604.021200: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:118 00AC 458C F601 C098 0000 0101 0A08 9796 <idle>-0 [012] ..s.. 30604.021201: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:143 [XDP] remove caqm_hdr success <idle>-0 [012] ..s.. 30604.021202: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:155 after bpf_xdp_adjust_head ,pkt_len = 67 <idle>-0 [012] ..s.. 30604.021205: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:162 AD84 F358 52C1 E51C 0304 0161 0008 0045 <idle>-0 [012] ..s.. 30604.021206: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:162 3500 EA47 0040 063E 405C A8C0 420C A8C0 <idle>-0 [012] ..s.. 30604.021208: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:162 060B 30E4 5114 9BD5 5440 C1CB 00AC 458C <idle>-0 [012] ..s.. 30604.021209: bpf_trace_printk: [INFO] /root/app/src/bpf_kern/xdp_remove_caqm.c:162 F601 C098 0000 0101 0A08 9796 645B 8A91
最新发布
11-25
```markdown ### 题目重述 分析两组BPF日志中数据包的变化,重点比较在调用 `bpf_xdp_adjust_head` 前后报文长度和内容的差异,并解释“奇数长度”数据包与之前正常包的区别。 --- ### 详解 从日志可以看出,XDP程序执行了头部操作(`bpf_xdp_adjust_head`),目的是**移除一个称为 CAQM 的封装头**。我们通过前后 `pkt_len` 和打印内容来分析其行为。 #### 1. 数据流概览(以第一个完整流程为例) - **before adjust_head, pkt_len = 107** - 打印地址为 `:118` 的数据(含 `FFFF 8005`)→ 包含 CAQM 头 - **after adjust_head, pkt_len = 103** - 打印地址为 `:162` 的数据(无 `FFFF 8005`)→ 已去除 CAQM 头 - 程序输出 `[XDP] remove caqm_hdr success` 说明:`bpf_xdp_adjust_head` 被用来将数据包指针前移,跳过 CAQM 头部,从而“剥离”该层。 #### 2. 对比两个阶段的数据格式 ##### 调整前(:118 行打印): ``` AD84 F358 52C1 E51C 0304 0161 FFFF 8005 0008 0045 ... ``` 关键特征:存在 `FFFF 8005` → 很可能是 **CAQM 头部标志字段** 推测结构: ``` [Ethernet Header (14B)] [CAQM Header (4B): 0xFFFF, 0x8005] [Actual IP Packet...] ``` ##### 调整后(:162 行打印): ``` AD84 F358 52C1 E51C 0304 0161 0008 0045 5900 E947 ... ``` 此时 `FFFF 8005` 消失,紧接着就是 `0008 0045` → 即 `EtherType=0x0800`, Version=4, IHL=5 ✅ 说明:`bpf_xdp_adjust_head` 成功去除了4字节的 CAQM 头(`FFFF 8005` 及可能前导字段),使原始IP包暴露。 验证长度变化: - `107 → 103`,减少4字节 → 符合 CAQM 头为 4 字节的假设 同样,在第二个流程中: - `pkt_len = 71 → 67`,也减少了4字节 --- #### 3. “奇数长度”数据包的含义? 注意:这里的“奇数长度”并非数学意义上的奇数,而是指: > **非标准、异常或经过封装的报文长度**,例如: - `107` 字节:不是常见以太网帧最小长度(64)或典型对齐长度(如 60、1500) - 经过 `adjust_head` 后变为 `103`,仍为非对齐值 但这不重要,因为 XDP 中 `pkt_len` 是实际字节数,不受“偶数字节”限制。 真正区别在于: | 特征 | 调整前(奇数长度包) | 调整后(标准IP包) | |------|------------------|----------------| | 是否包含 CAQM 头 | ✅ 是(`FFFF 8005`) | ❌ 否 | | pkt_len 大小 | 多4字节 | 减少4字节 | | 打印位置 | 在 `remove` 前(:118) | 在 `remove` 后(:162) | | 协议解析难度 | 需先识别并剥离 CAQM | 可直接解析 IP/TCP | | 是否可被上层处理 | ❌ 不可(格式非法) | ✅ 可(还原标准格式) | 因此,“奇数长度”的本质是:**带有额外封装头(CAQM)导致长度增加且结构异常的数据包**。 --- #### 4. 关于 `bpf_xdp_adjust_head` 此函数用于调整 XDP 数据包的起始位置,语法如下: ```c bpf_xdp_adjust_head(ctx, delta); ``` - 若 `delta > 0`:向后移动指针(丢弃头部) - 若 `delta < 0`:向前预留空间(添加头部) 本例中应为: ```c bpf_xdp_adjust_head(ctx, 4); // 移除4字节 CAQM 头 ``` 之后 `data` 指针指向原 +4 字节处,即跳过 `FFFF 8005` --- ### 知识点 - **XDP元数据与真实长度分离**:`pkt_len` 是实际链路层帧长,可通过 `adjust_head` 修改可见部分,不影响物理接收。 - **封装协议剥离技术**:类似VLAN/GRE,CAQM是一种私有封装,需在转发前由XDP程序识别并移除。 - **内存对齐与高效处理**:尽管出现“奇数长度”,但现代NIC和BPF支持任意字节访问,无需严格对齐。 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值