对于 veth 对,ping 无法识别接口名称,并且 tc qdisc netem 不起作用

对于 veth 对,ping 无法识别接口名称,并且 tc qdisc netem 不起作用

我有 Ubuntu 16.04 LTS 和 hwe 内核 4.13.0-39-generic。我在默认网络命名空间中配置 veth 对,如下所示:

$ sudo ip link add h1-eth0 type veth peer name h2-eth0

$ sudo ip link set dev h1-eth0 up
$ sudo ip link set dev h2-eth0 up

$ sudo ip addr add 10.0.0.1/24 dev h1-eth0
$ sudo ip addr add 10.0.0.2/24 dev h2-eth0

这是我在上述配置后得到的设置:

$ ifconfig
...
h1-eth0   Link encap:Ethernet  HWaddr ea:ee:1e:bb:66:55  
          inet addr:10.0.0.1  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          ...

h2-eth0   Link encap:Ethernet  HWaddr ba:aa:99:77:ff:78  
          inet addr:10.0.0.2  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          ...
$ ip route show
10.0.0.0/24 dev h1-eth0  proto kernel  scope link  src 10.0.0.1 
10.0.0.0/24 dev h2-eth0  proto kernel  scope link  src 10.0.0.2 
...

现在我可以从一个接口 ping 另一个接口,如下所示:

$ ping -I 10.0.0.1 -c1 10.0.0.2
PING 10.0.0.2 (10.0.0.2) from 10.0.0.1 : 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.046 ms

--- 10.0.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.046/0.046/0.046/0.000 ms

但第一个问题是,当我尝试使用接口名称而不是 IP 地址进行 ping 操作时,ping 失败:

$ ping -I h1-eth0 -c1 10.0.0.2
PING 10.0.0.2 (10.0.0.2) from 10.0.0.1 h1-eth0: 56(84) bytes of data.
From 10.0.0.1 icmp_seq=1 Destination Host Unreachable

--- 10.0.0.2 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

如果 h1-eth0 的 IP 地址为 10.0.0.1,这怎么会成为问题呢?

我认为第二个问题是相关的。我将接口配置如下:

$ sudo tc qdisc add dev h1-eth0 root netem delay 60ms
$ sudo tc qdisc add dev h2-eth0 root netem delay 60ms
$ tc qdisc show 
qdisc netem 8006: dev h2-eth0 root refcnt 2 limit 1000 delay 60.0ms
qdisc netem 8005: dev h1-eth0 root refcnt 2 limit 1000 delay 60.0ms

现在我再次 ping 延迟:

$ ping -I 10.0.0.1 -c4 10.0.0.2
PING 10.0.0.2 (10.0.0.2) from 10.0.0.1 : 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.033 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.034 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.059 ms
64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.027 ms

--- 10.0.0.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3063ms
rtt min/avg/max/mdev = 0.027/0.038/0.059/0.013 ms

并且可以看出rtt并不是预期的60ms*2=120ms。所以看起来 tc qdisc netem 不适用于我的接口。

总的来说,我发现我的配置在某种程度上被破坏了。

答案1

我在下面回答我自己的问题。

最简单的规避(我的方法):将 veth 对之一放入另一个网络命名空间。我们就这样称呼它吧test

$ sudo ip netns add test
$ sudo ip link add h1-eth0 type veth peer name h2-eth0 netns test

$ sudo ip link set dev h1-eth0 up
$ sudo ip netns exec test ip link set dev h2-eth0 up

$ sudo ip addr add 10.0.0.1/24 dev h1-eth0
$ sudo ip netns exec test ip addr add 10.0.0.2/24 dev h2-eth0

$ sudo tc qdisc add dev h1-eth0 root netem delay 60ms
$ sudo ip netns exec test tc qdisc add dev h2-eth0 root netem delay 60ms

现在我们检查:

$ ping -I h1-eth0 -c1 10.0.0.2
PING 10.0.0.2 (10.0.0.2) from 10.0.0.1 h1-eth0: 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=120 ms

--- 10.0.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 120.056/120.056/120.056/0.000 ms
$ sudo ip netns exec test ping -I h2-eth0 -c1 10.0.0.1
PING 10.0.0.1 (10.0.0.1) from 10.0.0.2 h2-eth0: 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=120 ms

--- 10.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 120.146/120.146/120.146/0.000 ms

其他方法

我发现我的问题已经被提出但还没有得到回答:https://serverfault.com/questions/585246/network-level-of-veth-doesnt-respond-to-arp。从那里我们可以看出问题出在 ARP 上。

这里提出了与 ARP 问题相关的问题如果请求的 IP 地址与另一个(禁用的)接口关联,Linux 不会回复 ARP 请求消息话题发起者得到了一些解释,但问题仍然没有解决。

问题在于,地址 10.0.0.1 和 10.0.0.2 不仅出现在主路由表中,而且出现在本地路由表中,并且本地路由表的优先级高于主路由表。下面是我的问题中的初始设置的表格,即不将 veth 对的一端放入另一个网络命名空间test

$ ip route show table local
broadcast 10.0.0.0 dev h1-eth0  proto kernel  scope link  src 10.0.0.1 
broadcast 10.0.0.0 dev h2-eth0  proto kernel  scope link  src 10.0.0.2 
local 10.0.0.1 dev h1-eth0  proto kernel  scope host  src 10.0.0.1 
local 10.0.0.2 dev h2-eth0  proto kernel  scope host  src 10.0.0.2 
broadcast 10.0.0.255 dev h1-eth0  proto kernel  scope link  src 10.0.0.1 
broadcast 10.0.0.255 dev h2-eth0  proto kernel  scope link  src 10.0.0.2 
...
$ ip route show table main
10.0.0.0/24 dev h1-eth0  proto kernel  scope link  src 10.0.0.1 
10.0.0.0/24 dev h2-eth0  proto kernel  scope link  src 10.0.0.2 
...

当 veth 对的一端位于另一个网络命名空间中时,我们不会出现两个地址同时放入本地路由表中的情况。所以,这可能就是为什么我们没有这样的问题。我尝试从本地路由表中删除地址(仅删除其中一个或两者 - 以不同的组合),但它没有帮助。总的来说,我不完全了解情况,所以我将坚持将 veth 对的末端设置到不同的网络命名空间中。更重要的是,据我所知,这就是 veth 对的主要使用方式。

相关内容