基于XDP实现双向数据包转发失败的技术求助
XDP双向转发失效问题排查与修复
1. 语法错误直接导致ARP回复转发逻辑失效
你提供的代码里,ARP分支的第二个return语句缺少分号:
} else if (ctx->ingress_ifindex == IFINDEX_3) { return bpf_redirect(IFINDEX_2, 0) // 这里没有分号,语法错误 }
这个错误会让编译器无法正确解析这段逻辑,要么程序加载失败,要么ARP回复的转发逻辑被直接跳过,数据包走到return XDP_PASS,而server2内核默认没开转发,导致ARP回复无法到达server1。
2. 接口索引与实际设备不匹配
根据你的网络拓扑,server2用于转发的接口是enp129s0f0np0和enp129s0f1np1,但代码里的宏定义写的是对应enp129s0f0和enp129s0f1的ifindex(2和3),这明显和实际接口名不符,对应的ifindex大概率不是2和3。
你可以用以下命令查看实际接口的ifindex:
ip link show
必须把宏定义的IFINDEX值替换成实际查到的数值,否则转发逻辑根本不会触发。
3. XDP重定向Flags可能存在问题
bpf_redirect的第二个参数用0(XDP_REDIRECT_FLAGS_NONE)在多队列接口场景下可能转发失败,建议换成XDP_REDIRECT_FLAGS_TX(值为1)强制走TX路径:
return bpf_redirect(目标IFINDEX, XDP_REDIRECT_FLAGS_TX);
4. 内核转发兜底配置(可选)
虽然XDP转发不需要内核IP转发,但如果XDP程序没覆盖所有数据包类型,可以临时开启内核转发作为兜底:
sysctl -w net.ipv4.ip_forward=1
修复后的完整代码
#include <linux/bpf.h> #include <bpf/bpf_helpers.h> #include <linux/if_ether.h> #include <linux/ip.h> #include <linux/icmp.h> #include <linux/udp.h> #include <linux/in.h> #include <linux/if_arp.h> // 替换成ip link show查到的实际ifindex #define IFINDEX_LEFT 实际值 // 对应enp129s0f0np0 #define IFINDEX_RIGHT 实际值 // 对应enp129s0f1np1 SEC("xdp_redirect") int xdp_redirect_prog(struct xdp_md *ctx) { void *data = (void *)(long)ctx->data; void *data_end = (void *)(long)ctx->data_end; struct ethhdr *eth = data; if ((void *)(eth + 1) > data_end) return XDP_DROP; // 处理ARP数据包 if (eth->h_proto == bpf_htons(ETH_P_ARP)) { if (ctx->ingress_ifindex == IFINDEX_LEFT) { return bpf_redirect(IFINDEX_RIGHT, XDP_REDIRECT_FLAGS_TX); } else if (ctx->ingress_ifindex == IFINDEX_RIGHT) { return bpf_redirect(IFINDEX_LEFT, XDP_REDIRECT_FLAGS_TX); } } // 处理IP类数据包(TCP/UDP/ICMP都包含在内) if (eth->h_proto == bpf_htons(ETH_P_IP)) { if (ctx->ingress_ifindex == IFINDEX_LEFT) { return bpf_redirect(IFINDEX_RIGHT, XDP_REDIRECT_FLAGS_TX); } else if (ctx->ingress_ifindex == IFINDEX_RIGHT) { return bpf_redirect(IFINDEX_LEFT, XDP_REDIRECT_FLAGS_TX); } } return XDP_PASS; } char _license[] SEC("license") = "GPL";
内容的提问来源于stack exchange,提问作者테스트입니다
相关产品推荐
相关产品推荐

