我创建了
ns3
作为路由器命名空间。
我创建了 ns1
和 ns2
作为客户。
ns3 和 ns1 有对等点 veth3_1、veth1_3。
ns3 和 ns2 有对等点 veth3_2、veth2_3。
veth2_3中部署的XDP程序收到了从ns1到ns2的UDP数据包。
SEC("xdp_ingress")
int xdp_ingress_func(struct xdp_md* ctx) {
void* data_end = (void*)(long)ctx->data_end;
void* data = (void*)(long)ctx->data;
struct ethhdr* eth = data;
if ((void*)(eth + 1) > data_end) {
return XDP_PASS;
}
if (eth->h_proto != __builtin_bswap16(ETH_P_IP)) {
return XDP_PASS;
}
char tmp_mac[6];
__builtin_memcpy(tmp_mac, eth->h_dest, ETH_ALEN);
__builtin_memcpy(eth->h_dest, eth->h_source, ETH_ALEN);
__builtin_memcpy(eth->h_source, tmp_mac, ETH_ALEN);
return XDP_TX;
}
但是,在接口 veth3_2 上使用 tcpdump 时,我只能观察到 ns2 的数据包。 但我无法观察到数据包转发回来。 这是环境的设置外壳:
ip link add veth1_3 type veth peer name veth3_1
ip link add veth2_3 type veth peer name veth3_2
# ns3
ip link set veth3_1 netns ns5
ip link set veth3_2 netns ns5
ip netns exec ns3 sysctl -w net.ipv4.ip_forward=1
ip netns exec ns3 ip link add name br0 type bridge
ip netns exec ns3 ip link set br0 up
ip netns exec ns3 ip link set veth3_1 master br0
ip netns exec ns3 ip link set veth3_2 master br0
ip netns exec ns3 ip link set veth3_1 up
ip netns exec ns3 ip link set veth3_2 up
ip netns exec ns3 ip addr add 10.0.0.1/8 dev br0
# ns1
ip link set veth1_3 netns ns1
ip netns exec ns1 ip addr add 10.0.0.2/8 dev veth1_3
ip netns exec ns1 ip link set veth1_3 up
ip netns exec ns1 ip link set lo up
ip netns exec ns1 ip route add default via 10.0.0.1
# ns2
ip link set veth2_3 netns ns2
ip netns exec ns2 ip addr add 10.0.0.3/8 dev veth2_3
ip netns exec ns2 ip link set veth2_3 up
ip netns exec ns2 ip link set lo up
ip netns exec ns2 ip route add default via 10.0.0.1
以上是简化的问题。
实际上,在 veth1_3 的 tc 出口处,我在原始 L3 标头之前推送了另一个 IP 和 UDP 标头。 如|IP|TCP|到|IP|UDP|IP|TCP|。
我已检查 L2 地址是否正确。
我在bpf_printk中检查到数据包被XDP程序接收,并执行到
return XDP_TX;
。
我在关于XDP的veth实现中发现了这一点。 你应该部署至少一个XDP程序,除了返回XDP_PASS;之外什么都不做,然后你就可以正常使用XDP_TX了。
这是因为,XDP_TX是通过xdp_ring来传输数据的,但是xdp_ring只有在veth双方都应用了XDP程序时才起作用。
我注意到,在旧版本的 veth 驱动程序中,当对等方不使用 XDP 时,会出现回退。 它正在以正常方式传输数据包。 但它在当前版本的内核中被删除了。