You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AF_PACKET捕获并桥接重注入RoCEv2 Infiniband数据包时标记规则不匹配及多tap方案实现问题

AF_PACKET捕获并桥接重注入RoCEv2 Infiniband数据包时标记规则不匹配及多tap方案实现问题

我来帮你拆解下遇到的两个核心问题,一步步解决:


一、标记规则不匹配的原因与解决

你现在遇到的标记不生效问题,核心是用错了套接字标记选项:
你代码里用的是SOL_SOCKET层的SO_MARK,但这个选项是给传输层连接(比如TCP/UDP)打标记的,对AF_PACKET这类原始套接字来说,内核不会自动把socket的SO_MARK同步到数据包的skb->nfmark字段——而ebtables的--mark匹配的正是这个nfmark值,所以规则自然匹配不上。

修复方法

把代码里的setsockopt调用改成AF_PACKET专属的PACKET_MARK选项(属于SOL_PACKET层):

// 替换原来的SO_MARK设置代码
int mark = PACKET_MARK;
if (setsockopt(send_sock, SOL_PACKET, PACKET_MARK, &mark, sizeof(mark)) < 0) {
    perror("setsockopt(PACKET_MARK)");
    exit(EXIT_FAILURE);
}

另外还要注意ebtables的链选择:
你当前的规则只配置了OUTPUT链,但从rxe0→br0→gretap1的转发流量属于FORWARD链(OUTPUT链仅处理本地进程生成的数据包)。所以需要同时配置两个链的规则,确保原始流量被拦截,只有标记后的重注入流量放行:

# 处理桥转发的流量
sudo ebtables -A FORWARD -o gretap1 --mark 0x42 -j ACCEPT
sudo ebtables -A FORWARD -o gretap1 -j DROP

# 处理你程序重注入的本地生成流量
sudo ebtables -A OUTPUT -o gretap1 --mark 0x42 -j ACCEPT
sudo ebtables -A OUTPUT -o gretap1 -j DROP

二、重复数据包检测方案

因为你的程序会捕获gretap1上的所有数据包(包括自己重注入的),很容易陷入循环捕获的死循环。推荐两种简单可行的方案:

1. BPF过滤排除标记数据包

给接收套接字绑定BPF过滤器,直接跳过带有0x42标记的数据包,这样重注入的数据包不会被再次捕获。代码示例:

#include <linux/filter.h>

// 构建BPF过滤规则:只捕获没有0x42标记的数据包
struct sock_filter filter[] = {
    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct sk_buff, mark)),
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, PACKET_MARK, 0, 1),
    BPF_STMT(BPF_RET | BPF_K, 0),          // 丢弃带标记的数据包
    BPF_STMT(BPF_RET | BPF_K, 0xFFFF),     // 放行其他数据包
};
struct sock_fprog fprog = {
    .len = sizeof(filter)/sizeof(filter[0]),
    .filter = filter,
};

// 给接收套接字绑定过滤器
if (setsockopt(recv_sock, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)) < 0) {
    perror("SO_ATTACH_FILTER");
    exit(EXIT_FAILURE);
}

2. 修改数据包标识字段(复杂度较高)

比如修改IP头部的ID字段(需要重新计算IP校验和),或者给RoCEv2的UDP封装添加自定义标识,但这种方法需要处理协议正确性,不如BPF过滤直接高效。


三、多tap接口方案实现

如果想改用“捕获gretap1,重注入到gretap2”的方案,按以下步骤操作即可解决地址问题:

1. 在两端创建第二个GRE隧道

在Machine A上:

sudo ip link add gretap2 type gretap local <A的公网IP> remote <B的公网IP> ttl 64
sudo ip link set gretap2 up
sudo brctl addif br0 gretap2

在Machine B上对应创建:

sudo ip link add gretap2 type gretap local <B的公网IP> remote <A的公网IP> ttl 64
sudo ip link set gretap2 up
sudo brctl addif br0 gretap2

2. 调整ebtables规则

禁止原始流量从gretap1流出,放行gretap2方向的流量:

# 拦截gretap1的所有出站流量
sudo ebtables -A FORWARD -o gretap1 -j DROP
sudo ebtables -A OUTPUT -o gretap1 -j DROP

# 放行gretap2的所有出站流量
sudo ebtables -A FORWARD -o gretap2 -j ACCEPT
sudo ebtables -A OUTPUT -o gretap2 -j ACCEPT

3. 修改程序的接口配置

把代码里的捕获接口改为gretap1,发送接口改为gretap2即可——这样捕获的原始流量会通过第二个GRE隧道传输,完全避免重复捕获的问题。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 11:58:00