耗时半个月排查问题的小结

这次是最近遇到的比较 tricky 问题的升级版本,当然他们二者没什么关系了,基本上我这半个月的时间都耗在这上面了,尝试了各种手法,包括 systemtap, dropwatch(感谢 @bitstream 的帮忙),不管如何,最终还是在我们 director 的帮助下一起解决了,虽然最后的 root cause 不是什么很高深的理论,懂点 TCP/IP 的应该都能理解,但是整个排查的过程我认为还是很值得参考的。本次 debug 仅仅涉及到 IP 层以下的内容,跟上层应用没有什么关系,对 IP、MAC 等数字不敏感的建议不要读了,即使要读也务必理清楚了再往下,下面会涉及大量的 VLAN IP 段,如果想知道最终的结果,直接跳到最后就好了。

在升级完我们所有的 10G 网络之后,出现了如下的现象。
1. 所有只配有一个内网的机器没有任何的问题,通过默认的 GW 可以访问其他 VLAN 机器,比如这个,默认都通过 10.118.10.250 出去:
[email protected]:~$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.118.10.0      0.0.0.0         255.255.255.0   U     0      0        0 eth1
0.0.0.0         10.118.10.250    0.0.0.0         UG    0      0        0 eth1

2. 所有配有公网的服务器到一部分内网的 VLAN 不通而到另外一部分内网 VLAN 则是通的:
[email protected]:~$ ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    link/ether 78:2b:cb:53:d6:55 brd ff:ff:ff:ff:ff:ff
    inet 111.111.111.230/26 brd 111.111.111.255 scope global eth0
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    link/ether 78:2b:cb:53:d6:56 brd ff:ff:ff:ff:ff:ff
    inet 10.118.10.20/24 brd 10.118.10.255 scope global eth1

[email protected]:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
111.111.111.192 0.0.0.0         255.255.255.192 U     0      0        0 eth0
10.118.20.0      0.0.0.0         255.255.255.0   U     0      0        0 eth1
10.118.10.0      0.0.0.0         255.255.255.0   U     0      0        0 eth1
10.111.0.0       0.0.0.0         255.255.255.0   U     0      0        0 eth1
0.0.0.0         111.111.111.193 0.0.0.0         UG    100    0        0 eth0

[email protected]:~# ping 10.118.20.1
PING 10.118.20.1 (10.118.20.1) 56(84) bytes of data.
64 bytes from 10.118.20.1: icmp_seq=1 ttl=63 time=43.6 ms
64 bytes from 10.118.20.1: icmp_seq=2 ttl=63 time=30.4 ms
^C
— 10.118.20.1 ping statistics —
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 30.453/37.054/43.655/6.601 ms

[email protected]:~# ping 10.111.0.1
PING 10.111.0.1 (10.111.0.1) 56(84) bytes of data.
From 10.118.10.21 icmp_seq=2 Destination Host Unreachable
From 10.118.10.21 icmp_seq=3 Destination Host Unreachable
From 10.118.10.21 icmp_seq=4 Destination Host Unreachable
^C
— 10.111.0.1 ping statistics —
5 packets transmitted, 0 received, +3 errors, 100% packet loss, time 4008ms
, pipe 3

当时我在现场发现了这个问题,看路由表,写的好像有些问题。抱着试一试的态度,反正也是不通,死马当活马医,找了一台有问题的机器把之前的:
[email protected]:~# route add -net 10.111.0.0 netmask 255.255.255.0 eth1
改成了下面的这种方式:
[email protected]:~# route add -net 10.111.0.0 netmask 255.255.255.0 gw 10.118.10.250

「神奇」的是,竟然 work 了。现场任务繁重,没有那么时间仔细考虑,恢复系统要紧,我很快把我们剩余的出现问题的机器都按照这种方式修改了 route。至此,线上的机器总算能恢复正常了,虽然当时不清楚为什么。回来之后,当然要做详细分析了。为了复现当时的问题,我又找了几台机器。

ud21 这台机器在我们已经升级完的一个 IDC 里面,其网络架构跟目前的这个一样:
[[email protected] ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
111.111.112.0   0.0.0.0         255.255.255.0   U     0      0        0 em2
10.111.50.0      0.0.0.0         255.255.255.0   U     0      0        0 em1
10.111.0.0       10.11.50.254    255.255.255.0   UG    0      0        0 em1
0.0.0.0         111.111.112.1   0.0.0.0         UG    0      0        0 em2

[[email protected] ~]# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
111.111.112.1            ether   00:00:5e:00:01:08   C                     em2
10.111.50.254             ether   00:00:0c:07:ac:32   C                     em1
10.111.50.14              ether   78:2b:cb:39:7e:36   C                     em1
10.111.50.7               ether   bc:30:5b:f3:ba:80   C                     em1

从本机(10.111.50.1) ping 同一 VLAN 的10.111.50.8,这个肯定是通的:
[[email protected] ~]# ping 10.111.50.8
PING 10.111.50.8 (10.111.50.8) 56(84) bytes of data.
64 bytes from 10.111.50.8: icmp_seq=1 ttl=64 time=0.602 ms

看 arp 信息以及抓包来看,都是跟预想一样:
[[email protected] ~]# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
10.111.50.8               ether   bc:30:5b:f3:bd:8c   C                     em1
111.111.112.1            ether   00:00:5e:00:01:08   C                     em2
10.111.50.254             ether   00:00:0c:07:ac:32   C                     em1
10.111.50.14              ether   78:2b:cb:39:7e:36   C                     em1
10.111.50.7               ether   bc:30:5b:f3:ba:80   C                     em1

[[email protected] ~]# tcpdump  -i em1  host 10.111.50.1 and -p arp -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on em1, link-type EN10MB (Ethernet), capture size 65535 bytes
16:58:38.778821 ARP, Request who-has 10.111.50.1 tell 10.111.50.8, length 46
16:58:38.778838 ARP, Reply 10.111.50.1 is-at bc:30:5b:f3:3a:40, length 28
16:58:40.870171 ARP, Reply 10.111.50.8 is-at bc:30:5b:f3:bd:8c, length 46
16:58:40.870183 ARP, Reply 10.111.50.8 is-at bc:30:5b:f3:bd:8c, length 46

接下来,我们 ping 另一 VLAN(10.111.0.0/24) 的 gateway,同样也是通的:
[[email protected] ~]# ping 10.111.0.254
PING 10.111.0.254 (10.111.0.254) 56(84) bytes of data.
64 bytes from 10.111.0.254: icmp_seq=1 ttl=255 time=1.49 ms

但是没有看到 10.111.0.254 的 ARP 信息:
[[email protected] ~]# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
10.111.50.8               ether   bc:30:5b:f3:bd:8c   C                     em1
111.111.112.1            ether   00:00:5e:00:01:08   C                     em2
10.111.50.254             ether   00:00:0c:07:ac:32   C                     em1
10.111.50.14              ether   78:2b:cb:39:7e:36   C                     em1
10.111.50.7               ether   bc:30:5b:f3:ba:80   C                     em1

抓包同样没有看到 ARP 的信息,当然还是又 ICMP 的信息的:
[[email protected] ~]# tcpdump  -i em1  host 10.111.50.1 and -p icmp -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on em1, link-type EN10MB (Ethernet), capture size 65535 bytes
17:02:29.625585 IP 10.111.50.1 > 10.111.0.1: ICMP echo request, id 55264, seq 8, length 64
17:02:29.625723 IP 10.111.0.1 > 10.111.50.1: ICMP echo reply, id 55264, seq 8, length 64
17:02:30.625568 IP 10.111.50.1 > 10.111.0.1: ICMP echo request, id 55264, seq 9, length 64
17:02:30.625733 IP 10.111.0.1 > 10.111.50.1: ICMP echo reply, id 55264, seq 9, length 64

尝试删除到 10.111.0.0/24 的路由:
[[email protected] ~]# route  del -net 10.111.0.0 netmask 255.255.255.0 em1
[[email protected] ~]# route  -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
111.111.112.0   0.0.0.0         255.255.255.0   U     0      0        0 em2
10.111.50.0      0.0.0.0         255.255.255.0   U     0      0        0 em1
0.0.0.0         111.111.112.1   0.0.0.0         UG    0      0        0 em2

然后直接以接口的方式加上:
[[email protected] ~]# route  add -net 10.111.0.0 netmask 255.255.255.0 em1
[[email protected] ~]# route  -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
111.111.112.0   0.0.0.0         255.255.255.0   U     0      0        0 em2
10.111.50.0      0.0.0.0         255.255.255.0   U     0      0        0 em1
10.111.0.0       0.0.0.0         255.255.255.0   U     0      0        0 em1
0.0.0.0         111.111.112.1   0.0.0.0         UG    0      0        0 em2

再次测试,ping 另一 VLAN(10.111.0.254) 的 GW,这次跟我们升级完 10G 的部分现象相同,不通:
[[email protected] ~]# ping 10.111.0.254
PING 10.111.0.254 (10.111.0.254) 56(84) bytes of data.
From 10.111.50.1 icmp_seq=2 Destination Host Unreachable
From 10.111.50.1 icmp_seq=3 Destination Host Unreachable
From 10.111.50.1 icmp_seq=4 Destination Host Unreachable
^C
— 10.111.0.254 ping statistics —
5 packets transmitted, 0 received, +3 errors, 100% packet loss, time 4827ms pipe 3

从抓包的情况来看,只有 arp request,而没有 reply:
17:05:07.942720 ARP, Request who-has 10.111.0.254 tell 10.111.50.1, length 28
17:05:08.942747 ARP, Request who-has 10.111.0.254 tell 10.111.50.1, length 28
17:05:09.942747 ARP, Request who-has 10.111.0.254 tell 10.111.50.1, length 28
17:05:11.943774 ARP, Request who-has 10.111.0.254 tell 10.111.50.1, length 28

很显然,10.111.0.254 不通,ping 10.111.0.1 也不会通了:
[[email protected] ~]# ping 10.111.0.1
PING 10.111.0.1 (10.111.0.1) 56(84) bytes of data.
From 10.111.50.1 icmp_seq=2 Destination Host Unreachable
From 10.111.50.1 icmp_seq=3 Destination Host Unreachable
From 10.111.50.1 icmp_seq=4 Destination Host Unreachable
^C
— 10.111.0.1 ping statistics —
5 packets transmitted, 0 received, +3 errors, 100% packet loss, time 4866ms

看一下 arp 的信息,跟上面一样:
17:05:40.309722 ARP, Request who-has 10.111.0.1 tell 10.111.50.1, length 28
17:05:41.309742 ARP, Request who-has 10.111.0.1 tell 10.111.50.1, length 28
17:05:42.309756 ARP, Request who-has 10.111.0.1 tell 10.111.50.1, length 28
17:05:44.310748 ARP, Request who-has 10.111.0.1 tell 10.111.50.1, length 28

从 arp 表也可以看到,没有 arp 信息:
[[email protected] ~]# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
10.111.0.254                      (incomplete)                              em1
10.111.50.8               ether   bc:30:5b:f3:bd:8c   C                     em1
111.111.112.1            ether   00:00:5e:00:01:08   C                     em2
10.111.50.254             ether   00:00:0c:07:ac:32   C                     em1
10.111.50.14              ether   78:2b:cb:39:7e:36   C                     em1
10.111.50.7               ether   bc:30:5b:f3:ba:80   C                     em1
10.111.0.1                        (incomplete)                              em1

跟踪一下路由,没有任何的信息:
[[email protected] ~]# mtr 10.111.0.1 -r -n
HOST: ud21.umops.us               Loss%   Snt   Last   Avg  Best  Wrst StDev


再来看下跟 un10 在完全相同网络环境下的 un11,这台机器跟 un10 在网络方面的配置除了 IP 信息不一样之外,其他的都一样,iptables 之类的也都事先排除了。
从开机启动那天起,就使用了如下的路由表:
[email protected]:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
111.111.111.192 0.0.0.0         255.255.255.192 U     0      0        0 eth0
10.118.20.0      0.0.0.0         255.255.255.0   U     0      0        0 eth1
10.118.10.0      0.0.0.0         255.255.255.0   U     0      0        0 eth1
10.111.0.0       0.0.0.0         255.255.255.0   U     0      0        0 eth1
0.0.0.0         111.111.111.193 0.0.0.0         UG    100    0        0 eth0

先看下当前的 arp 信息:
[email protected]:~# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
111.111.111.193          ether   00:00:0c:07:ac:06   C                     eth0
111.111.111.196          ether   00:16:3e:03:01:01   C                     eth0
10.118.10.250             ether   00:00:0c:07:ac:02   C                     eth1

ping 另外一个 VLAN(10.118.20.0) 的 GW,跟 ud21 的现象不同,但是跟 uode10 的现象相同,通了:
[email protected]:~# ping 10.118.20.254
PING 10.118.20.254 (10.118.20.254) 56(84) bytes of data.
64 bytes from 10.118.20.254: icmp_seq=1 ttl=255 time=27.1 ms

[email protected]:~# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
10.118.20.254             ether   e4:d3:f1:5b:ab:41   C                     eth1
111.111.111.193          ether   00:00:0c:07:ac:06   C                     eth0
111.111.111.196          ether   00:16:3e:03:01:01   C                     eth0
10.118.10.250             ether   00:00:0c:07:ac:02   C                     eth1

tcpdump 的 arp 信息有 request 有 reply:
17:27:54.333771 ARP, Request who-has 10.118.20.254 tell 10.118.10.21, length 28
17:27:54.342546 ARP, Reply 10.118.20.254 is-at e4:d3:f1:5b:ab:41, length 46

ping 该 VLAN 的其他 IP 应该也是通的:
[email protected]:~# ping 10.118.20.1
PING 10.118.20.1 (10.118.20.1) 56(84) bytes of data.
64 bytes from 10.118.20.1: icmp_seq=1 ttl=63 time=9.14 ms

[email protected]:~# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
10.118.20.254             ether   e4:d3:f1:5b:ab:41   C                     eth1
111.111.111.193          ether   00:00:0c:07:ac:06   C                     eth0
10.118.20.1               ether   e4:d3:f1:5b:ab:41   C                     eth1
111.111.111.196          ether   00:16:3e:03:01:01   C                     eth0
10.118.10.250             ether   00:00:0c:07:ac:02   C                     eth1

跟 10.118.20.254 的一样,有去有回:
[email protected]:~# tcpdump  -i eth1  host 10.118.20.1 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 96 bytes
23:05:51.018560 IP 10.118.10.21 > 10.118.20.1: ICMP echo request, id 64932, seq 9857, length 44
23:05:51.018744 IP 10.118.20.1 > 10.118.10.21: ICMP echo reply, id 64932, seq 9857, length 44
23:05:51.519475 IP 10.118.10.21 > 10.118.20.1: ICMP echo request, id 64932, seq 10113, length 44
23:05:52.020139 IP 10.118.10.21 > 10.118.20.1: ICMP echo request, id 64932, seq 10369, length 44
23:05:52.020316 IP 10.118.20.1 > 10.118.10.21: ICMP echo reply, id 64932, seq 10369, length 44
23:05:52.513547 ARP, Request who-has 10.118.20.1 tell 10.118.10.21, length 28
23:05:52.521002 IP 10.118.10.21 > 10.118.20.1: ICMP echo request, id 64932, seq 10625, length 44
23:05:52.524854 ARP, Reply 10.118.20.1 is-at e4:d3:f1:5b:ab:41, length 46
23:05:53.021734 IP 10.118.10.21 > 10.118.20.1: ICMP echo request, id 64932, seq 10881, length 44
23:05:53.021928 IP 10.118.20.1 > 10.118.10.21: ICMP echo reply, id 64932, seq 10881, length 44
23:05:53.522646 IP 10.118.10.21 > 10.118.20.1: ICMP echo request, id 64932, seq 11137, length 44
23:05:54.023330 IP 10.118.10.21 > 10.118.20.1: ICMP echo request, id 64932, seq 11393, length 44
23:05:54.023504 IP 10.118.20.1 > 10.118.10.21: ICMP echo reply, id 64932, seq 11393, length 44

跟踪路由确认一下:
[email protected]:~# mtr 10.118.20.1 -r -n
HOST: un11            Loss%   Snt   Last   Avg  Best  Wrst StDev
  1. 10.118.10.231                  0.0%    10   12.5   4.5   2.3  12.5   3.4
  2. 10.118.20.1                    0.0%    10    0.3   0.3   0.2   0.3   0.0

有没有发现一个问题,尽管我在 un10, un11 到其他的 VLAN 的路由上没有指定 GW(这个一个错误的写法),但是到 10.118.20.0/24 仍然能 ping 通,并且机器好像能自动的找到下一 hop 的地址 10.118.10.231,然后由他将包转发过去。并且,所有 10.118.20.0/24 显示的 arp 表信息都是结尾为 ab:41 的这个 arp 地址。登录到老的交换机上,果不其然,10.118.10.231 就是 SVI 的地址,ab41 也是其自动生成的那个 mac 地址:
25_23_2685_B28#show interfaces vlan 2
Vlan2 is up, line protocol is up
  Hardware is EtherSVI, address is e4d3.f15b.ab41 (bia e4d3.f15b.ab41)
  Internet address is 10.118.10.231/24
  …

现在我们再将原来的那条路由给删除,以正确的方式指定 GW:
[email protected]:~# route del -net 10.118.20.0 netmask 255.255.255.0 eth1
[email protected]:~# route add -net 10.118.20.0 netmask 255.255.255.0 gw 10.118.10.250
[email protected]:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
111.111.111.192 0.0.0.0         255.255.255.192 U     0      0        0 eth0
10.118.20.0      10.118.10.250    255.255.255.0   UG    0      0        0 eth1
10.118.10.0      0.0.0.0         255.255.255.0   U     0      0        0 eth1
0.0.0.0         111.111.111.193 0.0.0.0         UG    100    0        0 eth0

这种以增加默认 GW 的语法书写的 route 不管从什么角度分析,肯定都是通的:
[email protected]:~# ping 10.118.20.254
PING 10.118.20.254 (10.118.20.254) 56(84) bytes of data.
64 bytes from 10.118.20.254: icmp_seq=1 ttl=255 time=11.5 ms

但是,此时 un11 这台机器又拿不到 10.118.20.254 的 arp 信息了:
[email protected]:~# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
10.118.10.97              ether   d4:ae:52:b2:d0:94   C                     eth1
10.118.20.2                       (incomplete)                              eth1
10.118.10.254             ether   00:16:3e:03:02:01   C                     eth1
10.118.20.3                       (incomplete)                              eth1
10.118.10.93              ether   90:b1:1c:12:6e:f5   C                     eth1
10.118.10.96              ether   d4:ae:52:b2:d3:c1   C                     eth1
111.111.111.193          ether   00:00:0c:07:ac:06   C                     eth0
10.118.10.18              ether   78:2b:cb:53:e6:00   C                     eth1
111.111.111.196          ether   00:16:3e:03:01:01   C                     eth0
10.118.10.20              ether   78:2b:cb:53:d6:56   C                     eth1
10.118.10.250             ether   00:00:0c:07:ac:02   C                     eth1
10.118.10.92              ether   90:b1:1c:09:b8:1a   C                     eth1

抓包只能拿到 10.118.10.250 也就是本机 GW 的 arp 信息:
17:45:22.543770 ARP, Request who-has 10.118.10.250 tell 10.118.10.21, length 28
17:45:22.546526 ARP, Reply 10.118.10.250 is-at 00:00:0c:07:ac:02, length 46

ping 该 VLAN 下面其他服务器的 IP:
[email protected]:~# ping 10.118.20.1
PING 10.118.20.1 (10.118.20.1) 56(84) bytes of data.
64 bytes from 10.118.20.1: icmp_seq=1 ttl=63 time=0.257 ms

同样没有 10.118.20.1 的 arp 信息:
[email protected]:~# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
10.118.10.97              ether   d4:ae:52:b2:d0:94   C                     eth1
10.118.10.254             ether   00:16:3e:03:02:01   C                     eth1
10.118.20.3                       (incomplete)                              eth1
10.118.10.93              ether   90:b1:1c:12:6e:f5   C                     eth1
10.118.10.96              ether   d4:ae:52:b2:d3:c1   C                     eth1
111.111.111.193          ether   00:00:0c:07:ac:06   C                     eth0
10.118.10.18              ether   78:2b:cb:53:e6:00   C                     eth1
111.111.111.196          ether   00:16:3e:03:01:01   C                     eth0
10.118.10.20              ether   78:2b:cb:53:d6:56   C                     eth1
10.118.10.250             ether   00:00:0c:07:ac:02   C                     eth1
10.118.10.92              ether   90:b1:1c:09:b8:1a   C                     eth1


通过 ud21,un10, un11 这三台机器对比发现,我们发现了下面的一些结论:
1. 如果是以一个规范的路由写法来操作的话,不管什么机器,不管什么网络环境,都不会出现问题,也就是指定默认 GW 的情况:
# route add -net 10.118.20.0 netmask 255.255.255.0 gw 10.118.10.250

可以写到 /etc/sysconfig/network-scripts/route-em1 里面或者最简单粗暴的写到 /etc/rc.local(service network restart 的不会生效)里面:
[[email protected] ~]$ cat /etc/sysconfig/network-scripts/route-em1
10.111.0.0/24 via 10.11.50.254 dev em1
10.111.1.0/24 via 10.11.50.254 dev em1

2. 出现问题的机器,从服务器的角度来说,是 route 的添加方式写的不规范,在有多个 VLAN 的情况下,直接指定接口的方式是一种错误的写法:
# route add -net 10.118.20.0 netmask 255.255.255.0 eth1

3. 对于 ud21 这台机器所处的网络环境,全新的 752 架构,跟老的 3750X 可以理解为物理隔离,所以如果仅仅指定接口,交换机不会接受或者丢弃到服务器发送的 arp broadcast,这也就导致无法 ping 通任何的其他 VLAN。

4. 对于 un10, un11 这两台机器所处的网络环境,二者表现出来的现象是一致的,由于老的 3750X 跟新的 752 还是直连的,导致尽管以指定接口这种错误的路由方式运行,仍然能将 arp boradcast 出去,然后被 3750 这台老的 SW 接收到并转发出去,这也是 mtr 看到 10.118.10.231 的原因。「好像」新的 N7K 是不会主动返回 arp 请求的,但是 3750X 则会主动的接受并返回。


问题到这里已经有了不少的进展,至少已经不像当初在现场那样没头绪,但是离 root cause(3750X 为什么能跨网段收到 arp 请求) 还是有不少的距离。现在还是回到 un10 这台机器上,我们再来重现一次。
先来看一下基本的 routing、arp 信息:
[email protected]:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
111.111.111.192 0.0.0.0         255.255.255.192 U     0      0        0 eth0
10.118.20.0      0.0.0.0         255.255.255.0   U     0      0        0 eth1
10.118.10.0      0.0.0.0         255.255.255.0   U     0      0        0 eth1
0.0.0.0         111.111.111.193 0.0.0.0         UG    100    0        0 eth0

[email protected]:~# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
10.118.10.222             ether   84:78:ac:1a:b3:41   C                     eth1
10.118.10.223             ether   84:78:ac:1f:45:c1   C                     eth1
10.118.10.254             ether   00:16:3e:03:02:01   C                     eth1
111.111.111.193          ether   00:00:0c:07:ac:06   C                     eth0
10.118.10.92              ether   90:b1:1c:09:b8:1a   C                     eth1
10.118.10.21              ether   78:2b:cb:53:e6:39   C                     eth1
10.118.10.96              ether   d4:ae:52:b2:d3:c1   C                     eth1

根据前面观察到的现象,ping 10.118.20.254 应该是没有问题的:
[email protected]:~# ping 10.118.20.254
PING 10.118.20.254 (10.118.20.254) 56(84) bytes of data.
64 bytes from 10.118.20.254: icmp_seq=1 ttl=255 time=13.9 ms

看一下 arp 表,多了一个 10.118.20.254 的 arp 信息:
[email protected]:~# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
10.118.10.98              ether   d4:ae:52:b2:d0:a0   C                     eth1
10.118.10.254             ether   00:16:3e:03:02:01   C                     eth1
111.111.111.193          ether   00:00:0c:07:ac:06   C                     eth0
10.118.10.92              ether   90:b1:1c:09:b8:1a   C                     eth1
10.118.10.99              ether   d4:ae:52:b2:cf:f2   C                     eth1
10.118.10.21              ether   78:2b:cb:53:e6:39   C                     eth1
10.118.10.97              ether   d4:ae:52:b2:d0:94   C                     eth1
10.118.10.96              ether   d4:ae:52:b2:d3:c1   C                     eth1
10.118.20.254             ether   e4:d3:f1:5b:ab:41   C                     eth1

抓包得到的数据跟上面的一致:
18:09:59.275605 ARP, Request who-has 10.118.20.254 tell 10.118.10.20, length 28
18:09:59.281471 ARP, Reply 10.118.20.254 is-at e4:d3:f1:5b:ab:41, length 46

再 ping 一下 10.118.20.0/24 VLAN 里的任意一台服务器:
[email protected]n10:~# ping 10.118.20.1
PING 10.118.20.1 (10.118.20.1) 56(84) bytes of data.
64 bytes from 10.118.20.1: icmp_seq=1 ttl=63 time=50.0 ms

10.118.20.1 的 arp 也被 un10 获取到了,但是 mac 地址是跟 10.118.20.254 一样的:
[email protected]:~# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
10.118.10.18              ether   78:2b:cb:53:e6:00   C                     eth1
10.118.10.98              ether   d4:ae:52:b2:d0:a0   C                     eth1
10.118.10.254             ether   00:16:3e:03:02:01   C                     eth1
111.111.111.193          ether   00:00:0c:07:ac:06   C                     eth0
10.118.10.92              ether   90:b1:1c:09:b8:1a   C                     eth1
10.118.10.99              ether   d4:ae:52:b2:cf:f2   C                     eth1
10.118.10.21              ether   78:2b:cb:53:e6:39   C                     eth1
10.118.10.97              ether   d4:ae:52:b2:d0:94   C                     eth1
10.118.10.96              ether   d4:ae:52:b2:d3:c1   C                     eth1
10.118.20.1               ether   e4:d3:f1:5b:ab:41   C                     eth1
10.118.20.254             ether   e4:d3:f1:5b:ab:41   C                     eth1

arp 抓包有 request 以及 reply:
18:10:50.474814 ARP, Request who-has 10.118.20.1 tell 10.118.10.20, length 28
18:10:50.475962 ARP, Reply 10.118.20.1 is-at e4:d3:f1:5b:ab:41, length 46

看一下路由信息,可以看到第一 hop 是到 10.118.20.231 也就是老的 3750X 的地址:
[email protected]:~# mtr 10.118.20.1 -r -n
HOST: un10            Loss%   Snt   Last   Avg  Best  Wrst StDev
  1. 10.118.10.231                  0.0%    10   12.5  19.9   0.6 168.0  52.2
  2. 10.118.20.1                    0.0%    10   28.9  24.9  14.5  32.1   6.3

现在我们以正确的路由方式来测试:
[email protected]:~# route del -net 10.118.20.0 netmask 255.255.255.0 eth1
[email protected]:~# route add -net 10.118.20.0 netmask 255.255.255.0 gw 10.118.10.250
[email protected]:~# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
10.118.10.18              ether   78:2b:cb:53:e6:00   C                     eth1
10.118.10.98              ether   d4:ae:52:b2:d0:a0   C                     eth1
10.118.10.254             ether   00:16:3e:03:02:01   C                     eth1
111.111.111.193          ether   00:00:0c:07:ac:06   C                     eth0
10.118.10.92              ether   90:b1:1c:09:b8:1a   C                     eth1
10.118.10.99              ether   d4:ae:52:b2:cf:f2   C                     eth1
10.118.10.21              ether   78:2b:cb:53:e6:39   C                     eth1
10.118.10.97              ether   d4:ae:52:b2:d0:94   C                     eth1
10.118.10.96              ether   d4:ae:52:b2:d3:c1   C                     eth1

还是以 10.118.20.254 来测试:
[email protected]:~# ping 10.118.20.254
PING 10.118.20.254 (10.118.20.254) 56(84) bytes of data.
64 bytes from 10.118.20.254: icmp_seq=1 ttl=255 time=11.0 ms
64 bytes from 10.118.20.254: icmp_seq=2 ttl=255 time=0.542 ms
^C
— 10.118.20.254 ping statistics —
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.542/5.790/11.039/5.249 ms

根据上面的 ud21 得到的结论,看不到任何其他 VLAN 的 arp 信息:
[email protected]:~# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
10.118.10.18              ether   78:2b:cb:53:e6:00   C                     eth1
10.118.10.98              ether   d4:ae:52:b2:d0:a0   C                     eth1
10.118.10.250             ether   00:00:0c:07:ac:02   C                     eth1
10.118.10.254             ether   00:16:3e:03:02:01   C                     eth1
111.111.111.193          ether   00:00:0c:07:ac:06   C                     eth0
10.118.10.92              ether   90:b1:1c:09:b8:1a   C                     eth1
10.118.10.99              ether   d4:ae:52:b2:cf:f2   C                     eth1
10.118.10.21              ether   78:2b:cb:53:e6:39   C                     eth1
10.118.10.97              ether   d4:ae:52:b2:d0:94   C                     eth1
10.118.10.96              ether   d4:ae:52:b2:d3:c1   C                     eth1

确认下 10.118.20.1 的机器:
[email protected]:~# ping 10.118.20.1
PING 10.118.20.1 (10.118.20.1) 56(84) bytes of data.
64 bytes from 10.118.20.1: icmp_seq=1 ttl=63 time=0.262 ms
64 bytes from 10.118.20.1: icmp_seq=2 ttl=63 time=0.247 ms
64 bytes from 10.118.20.1: icmp_seq=3 ttl=63 time=0.246 ms
64 bytes from 10.118.20.1: icmp_seq=4 ttl=63 time=0.260 ms
64 bytes from 10.118.20.1: icmp_seq=5 ttl=63 time=0.261 ms
64 bytes from 10.118.20.1: icmp_seq=6 ttl=63 time=0.260 ms
^C
— 10.118.20.1 ping statistics —
6 packets transmitted, 6 received, 0% packet loss, time 4997ms
rtt min/avg/max/mdev = 0.246/0.256/0.262/0.006 ms

HSRP 的 RIP 是第一跳地址:
[email protected]:~# mtr 10.118.20.1 -r -n
HOST: un10            Loss%   Snt   Last   Avg  Best  Wrst StDev
  1. 10.118.10.223                  0.0%    10    0.6   0.6   0.6   0.6   0.0
  2. 10.118.20.1                    0.0%    10    0.3   0.3   0.3   0.3   0.0

把 10.118.10.250 这个 HSRP 的 GW 换成我们老 3750X 上的 SVI 地址继续测试:
# route del -net 10.118.20.0 netmask 255.255.255.0 gw 10.118.10.250
# route add -net 10.118.20.0 netmask 255.255.255.0 gw 10.118.10.231

[email protected]:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
111.111.111.192 0.0.0.0         255.255.255.192 U     0      0        0 eth0
10.118.20.0      10.118.10.231    255.255.255.0   UG    0      0        0 eth1
10.118.10.0      0.0.0.0         255.255.255.0   U     0      0        0 eth1
0.0.0.0         111.111.111.193 0.0.0.0         UG    100    0        0 eth0

[email protected]:~# ping 10.118.20.1
PING 10.118.20.1 (10.118.20.1) 56(84) bytes of data.
64 bytes from 10.118.20.1: icmp_seq=1 ttl=63 time=0.302 ms

可以发现这个指定 3750X GW IP 的效果跟直接以接口的方式一样:
[email protected]:~# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
10.118.10.18              ether   78:2b:cb:53:e6:00   C                     eth1
10.118.10.98              ether   d4:ae:52:b2:d0:a0   C                     eth1
10.118.10.254             ether   00:16:3e:03:02:01   C                     eth1
111.111.111.193          ether   00:00:0c:07:ac:06   C                     eth0
10.118.10.231             ether   e4:d3:f1:5b:ab:41   C                     eth1
10.118.10.92              ether   90:b1:1c:09:b8:1a   C                     eth1
10.118.10.99              ether   d4:ae:52:b2:cf:f2   C                     eth1
10.118.10.21              ether   78:2b:cb:53:e6:39   C                     eth1
10.118.10.97              ether   d4:ae:52:b2:d0:94   C                     eth1
10.118.10.96              ether   d4:ae:52:b2:d3:c1   C                     eth1

也就是,对于 3750X 的环境来说,下面两个语句是等同的:
# route add -net 10.118.20.0 netmask 255.255.255.0 eth1
# route add -net 10.118.20.0 netmask 255.255.255.0 gw 10.118.10.231

到这里会发现,所有从 3750X 出去的本地的包都是以 10.118.10.231 这个 ARP 为结尾的,这个跟上面 un11 现象是一样的,在下面这个 arp 表中,你会发现不少是以 ab:41 结尾的 arp 信息,而 ab:41 则是 10.118.10.231 这个 SVI 的 mac 地址:
[email protected]:~$ arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
10.118.10.97              ether   d4:ae:52:b2:d0:94   C                     eth1
10.118.20.254             ether   e4:d3:f1:5b:ab:41   C                     eth1
10.118.10.254             ether   00:16:3e:03:02:01   C                     eth1
10.118.10.223             ether   84:78:ac:1f:45:c1   C                     eth1
10.118.10.93              ether   90:b1:1c:12:6e:f5   C                     eth1
10.118.10.96              ether   d4:ae:52:b2:d3:c1   C                     eth1
111.111.111.193          ether   00:00:0c:07:ac:06   C                     eth0
10.118.10.18              ether   78:2b:cb:53:e6:00   C                     eth1
10.118.20.1               ether   e4:d3:f1:5b:ab:41   C                     eth1
10.118.10.20              ether   78:2b:cb:53:d6:56   C                     eth1
10.118.10.231             ether   e4:d3:f1:5b:ab:41   C                     eth1
10.118.10.92              ether   90:b1:1c:09:b8:1a   C                     eth1

继续深入抓包,不过这次是在交换机上抓的,最初是用 ethanalyzer 在 7k 以及 5k 的抓的,很不辛的是,除了跟上面在服务器上抓的类似的信息之外,没有拿到什么有效的信息了,后来看文档的时候发现,ethanalyzer 主要是用来 debug SW 本机的一些问题的,索性 mirroring,这个在 Cisco 上叫 SPAN,让我们的 NE 帮忙把三台机器都做了一下 mirror,从 tcpdump 的结果来看,同样比较失望,没拿到更多的信息了。下面两个段落是从 un10 做 mirror 到我们另外一台 un04 机器得到的 arp 请求。
第一条片段是是在指定接口的方式下抓到的包,当然全部是 arp broadcast:
[email protected]:~# cat txt_bad
16:32:16.670622 78:2b:cb:53:d6:56 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: Request who-has 10.118.20.1 tell 10.118.10.20, length 46
16:32:16.671637 e4:d3:f1:5b:ab:41 > 78:2b:cb:53:d6:56, ethertype ARP (0x0806), length 60: Reply 10.118.20.1 is-at e4:d3:f1:5b:ab:41, length 46

第二条片段是以正确的方式也就是指定 GW IP 的方式访问,除了会「自动」的找到 10.118.10.101 这个 GW 的 arp 之外,没做其他有用的信息了:
[email protected]:~# cat txt_good
16:31:11.831252 78:2b:cb:53:d6:56 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: Request who-has 10.118.10.101 tell 10.118.10.20, length 46
16:31:11.831917 e4:d3:f1:5b:ab:41 > 78:2b:cb:53:d6:56, ethertype ARP (0x0806), length 60: Reply 10.118.10.101 is-at e4:d3:f1:5b:ab:41, length 46
16:31:11.924555 84:78:ac:1a:b3:41 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: Request who-has 10.118.10.20 (ff:ff:ff:ff:ff:ff) tell 10.118.10.222, length 46
16:31:11.924665 78:2b:cb:53:d6:56 > 84:78:ac:1a:b3:41, ethertype ARP (0x0806), length 60: Reply 10.118.10.20 is-at 78:2b:cb:53:d6:56, length 46

综合上面的所有的分析以及之前得到的初步结论,我们基本可以确认,似乎是老的 3750X 能够自动的回应 broadcast 的包而新的 N752 架构过滤屏蔽了所有的 arp broadcast 包,也就是说,这是两种完全不同的机型,他们内部应该是存在着某种机制,从而得到了完全不通的结论。至于是什么机制,我们确实不是很清楚,想进一步的在 7k 上开启 debug 的模式,考虑到生产环境,还是作罢。到此为止,山穷水尽。虽然没找到 root cause,但是我们还是通过一步一步的 debug 将问题的原因缩小到了一个非常小的范围了。

最后一招,我们尝试联系我们的代理商让其帮忙在 Cisco 那边开 case,整体的流程跟 RedHat 很类似,很不幸的是,Cisco 那边限制的非常严格,3750X 的需要单独开对应到 3750X 的 case,Nexus 7000 的则需要单独开对应 Nexus 7000 的 case,像我们这种同时涉及两个产品型号的是没法同时进行的。更不辛的是,代理商最初态度强硬的帮我们开中文的 case,结果我们开的几个 case 都被北京办公室那边的负责接收了,最终的结果就是 37 的说 37 没有任何问题,7k 的说 7k 的没有任何问题,我白白的跟他们耗了两天多的时间。为了避免在这上面耗费更多的时间,我干脆直接找官方投诉了,要求换美国那边的 technical support 来支持我们,最后美国那边的工程师在凌晨打了一个手机显示 010 的电话过来了,在我把上面的现象以及遇到的问题简单的描述了一下之后,人家几乎是以肯定语气跟我们指出了原因,虽然当时内心很激动,但是依然不大放心,继续跟踪,麻烦其帮忙开了 webex,让他上线帮我们确认了下,至此,问题已经得到全部的解决,He really saved my day。
什么原因了?其实我在第二次总结的时候已经几乎要碰到那个最核心的点了,arp proxy 的问题,这个跟 DHCP relay 倒是有点像。在 3750X 的 IOS 上默认开启了 ip arp-proxy,而 Nexus 系统的 NX-OS 上则是默认关闭了改选项
泪奔了。
P.S: 如果有机会跟 RedHat、Cisco 等官方的 technical support 交流,可以优先选择英语系国家的工程师,国外的工程师不管是服务态度以及最重要的技术硬实力,都比国内的高出一大截。这个问题如果最初直接找美国那边的工程师,最少能节约 2d 的宝贵时间。

  • wych

    我看前面猜到是这个问题 之前碰到过类似的现象,默认配置是个深坑哈哈,而且我还接触不到交换机,每次出问题还得找专门的人去看 TT

    • http://jaseywang.me/ Jasey Wang

      也是 arp proxy 的?

      • wych

        arp proxy 的问题是搞别的东西的时候顺带发现的,没造成故障。给我弄出问题来的是一个防arp flood 的配置,最后变成了内网所有arp 都学不到。

  • roadli

    就和当初我在45交换机上没关闭vlan接口ip redirect导致交换机CPU高一样,不遇到不知道啊