XDP程序挂载veth主机端后跨命名空间Ping不通问题排查
问题描述
我有两个命名空间ns1和ns2,用两对veth设备连接到主机,拓扑如下:
ns1 | host | ns2 v1 ---veth---h1 h2---veth---v2 10.244.1.1/16 10.244.1.2/16
我想用一个简单的XDP程序实现两个命名空间间的Ping互通,编写的XDP程序如下:
volatile __u32 container_1_if_id = -1; volatile __u32 container_2_if_id = -1; SEC("xdp") int xdp_redirect_tmp_test(struct xdp_md *ctx) { // bpf_printk("container_1_if_id: %d, container_2_if_id: %d, ingress_ifindex: %d", container_1_if_id, container_2_if_id, ctx->ingress_ifindex); if (ctx->ingress_ifindex == container_1_if_id) { return bpf_redirect(container_2_if_id, 0); } else if (ctx->ingress_ifindex == container_2_if_id) { return bpf_redirect(container_1_if_id, 0); } return XDP_PASS; }
container_x_if_id由用户态程序设置,已通过bpf_printk()确认值与主机侧veth设备的索引完全匹配。将XDP程序挂载到两个veth设备的主机端后,执行ip netns exec ns1 ping 10.244.1.2无法成功,抓包发现ARP请求无法到达ns2内的v2接口,需要排查问题原因及解决方法。
问题原因及排查方法
核心原因分析
- XDP重定向的二层转发逻辑限制:
bpf_redirect默认是二层转发,ARP请求是二层广播帧。当XDP直接把h1收到的ARP广播帧重定向到h2时,veth设备的内核逻辑可能不会将该帧转发到对等端v2——因为XDP绕过了内核网络栈的常规二层转发流程,veth对的转发规则未被触发。 - veth的XDP挂载模式不兼容:veth是虚拟设备,多数内核版本仅支持
XDP_MODE_SKB模式,如果挂载时用了XDP_MODE_DRV,会导致XDP程序未真正生效。 - 帧校验和问题:XDP重定向时未重新计算校验和,ARP帧的校验和可能失效,被ns2的v2接口丢弃。
具体排查步骤
- 验证XDP程序是否处理了ARP帧:打开代码中注释的
bpf_printk,执行cat /sys/kernel/debug/tracing/trace_pipe查看日志,确认ARP帧到达h1时,ingress_ifindex是否匹配container_1_if_id,程序是否执行了bpf_redirect逻辑。 - 检查veth的XDP挂载模式:执行
ip link show h1,查看输出中xdp字段的模式是skb还是drv。如果是drv,重新挂载为skb模式:ip link set dev h1 xdp obj xdp_prog.o sec xdp mode skb,h2同理。 - 逐段抓包确认帧流向:
- 在主机上执行
tcpdump -i h2 arp,查看是否有从h1重定向过来的ARP请求帧; - 如果h2能抓到帧,再在ns2内执行
ip netns exec ns2 tcpdump -i v2 arp,确认帧是否转发到v2接口。
- 在主机上执行
- 修改重定向参数:将
bpf_redirect的第二个参数改为BPF_F_INGRESS,即return bpf_redirect(container_2_if_id, BPF_F_INGRESS);,让帧以入站方向进入目标接口的网络栈,触发veth的对等端转发逻辑。 - 查看内核丢弃日志:执行
dmesg -w,同时在ns1发送ARP请求,查看是否有帧被内核丢弃的报错信息。
内容的提问来源于stack exchange,提问作者light_rain
相关产品推荐
相关产品推荐

