在Linux下,我们一般用ping来判断网络的丢包和延迟,用traceroute来跟踪路由路径。mtr将ping和traceroute结合起来,既能判断网络路由路径,又能得到丢包和延迟等信息。

mtr的用法网上随便一搜就一大堆:https://www.mankier.com/8/mtr

mtr的数据一般长这样:

mtr数据图

其中host为“???”的地方表示该节点不让ping。

Loss%:表示该节点的丢包率;

Snt:表示每秒发送数据包的数量,默认值是10 可以通过参数 -c 来指定数量;

Last:表示最近一次的返回延时;

Avg:表示延时平均值这个应该是发送ping包的平均延时;

Best:表示最好或者说延时最短的值;

Wrst:表示最差或者说时延最常的值;

StDev:表示标准偏差。

然后我对各节点丢包率无法理解:1.前n-1行的丢包率相加和最后一行的丢包率不想等;2.某些点的丢包率超过了最后一行的丢包率;3.ping其中丢包率高的节点,ping的丢包率和mtr结果在该点的丢包率差别极大。

针对这些问题,百度,Google提供了很多很有参考价值的信息,比如:
https://www.linode.com/docs/networking/diagnostics/diagnosing-network-issues-with-mtr/

http://serverfault.com/questions/585862/why-mtr-is-much-faster-than-traceroute

http://serverfault.com/questions/260414/how-to-interpret-traceroute-output-of-mtr

http://superuser.com/questions/591804/where-is-packet-loss-occuring-interpreting-mtr

对于中间节点丢包总结起来大约是这样说的:该节点本身网络不好;ICMP速率限制引起了数据包的丢失。判断方法是:

1.如果某节点有丢包,但是下一节点没有丢包,则证明该节点是ICMP速率限制。解决方法可以增加参数 -i(设置ICMP发送一次包的时间,默认为1秒)。

2.如果连续几个节点都存在丢包,则这些节点存在因网络不好而产生的丢包,但无法判断是否存在因速率限制而产生的丢包。

3.如果最后一个节点存在丢包,则这个节点的丢包率看做整条目录的丢包率。

但是以上判断方法是如何得到的,网上就没有很多的说明了。只好从mtr的原理开始研究。

从网络抓包开始。分别对同一个目标地址进行ping和mtr,抓取这两种操作时的网络发icmp包情况如下:

mtr的路径和抓包:

ping的抓包:

由ping和mtr的抓包情况图可以看出:
mtr对目标地址发送一个icmp包,然后在一个节点返回一个icmp包;然后再对目标节点发送一个icmp包,再第二个节点返回一个icmp包;一直到最后一个节点返回icmp包,这样一次发包完成。参数 -i 便是控制这一过程时间的,默认是1秒钟。当节点比较多的时候,会出现发送了很多icmp包,之前所说的增加 -i 的参数值,能够降低这个发包频率,以达到避免被icmp限速的目的。如果其中某个节点返回的包丢掉了,则在该节点上产生了丢包率。
ping的icmp发包过程是本地发送给目标地址一个icmp包,然后目标地址返回一个icmp包。中通节点没有返回任何icmp包。如果目标地址返回的包丢失,则产生丢包率。

由抓包可以看出,mtr的发包原理和traceroute类似,如下图:

mtr图

其中TTL(Time To Live)指定IP包被路由器丢弃之前允许通过的最大网段数量,当TTL减少为0时,路由器将会丢弃收到的TTL=0的icmp包并向icmp包的发送者发送 ICMP time exceeded 消息。假设本地mtr目标主机中途经过了3个节点,本地向目标主机发送一个icmp包,TTL=1,遇到第一个路由的时候,TTL变为0,向本地返回 ICMP time exceeded in-transit 消息;然后本地再向目标主机发送一个icmp包,TTL=2,再遇到第二个路由的时候TTL变为0,返回 ICMP time exceeded in-transit;以此类推;当icmp包经过n跳到达最终的目标地址,则返回 ICMP echo reply 消息。如果某个阶段返回的icmp包丢失,则在此节点产生了丢包。

按照这个原理,理论上当某个节点的ip地址产生较大丢包的时候,我们调整发包间隔,使发包速率不大于ping的发包速率,那么这个节点mtr得到的丢包率应该和直接ping这个节点得到的丢包率相等。然而事实上mtr的丢包率远大于ping这个节点的丢包率。问题出在ping和mtr返回的icmp包上。

对于ping,本地给目标地址发送一个icmp包,如果目标主机收到了这个包,则返回一个类型为00的icmp (“ICMP echo reply”)。

对于mtr,是hop by hop 的ping,在每个节点因为TTL=0而返回一个icmp包,此时返回的icmp包类型是110(“ICMP time exceeded”),到最后一个节点返回一个跟ping类似的icmp包(“ICMP echo reply”),如果某个路由的规则对类型为110的icmp进行了限制,则可能导致该节点产生丢包,而ping该节点返回的类型为00的icmp包则没有影响,因此ping不会产生丢包。或者某一个路由为了防止icmp包攻击,只开放了ping发出的字段的icmp包。如果某一个节点因为icmp限制而产生丢包,而下一节点不对110类型的icmp包做限制,所以下一节点不产生丢包。这就是网上所说的如果本节点丢包,接下来的节点没有丢包,则该节点可能是路由限速导致的丢包,和网络好坏没有关系。另外,除了对110包的限制,还有可能返回路径和发包路径不一致,即返回路过了别的节点,那个节点对icmp限制了,但是mtr不会打印出来。这就是网上建议的两个方向进行监控。当mtr发包到达最后一个节点(即目标主机),主机正常返回一个 ICMP echo reply,相当于一个正常的ping过程,因此最后一跳存在丢包率,可以看做整个链路的丢包率

对网络路由路径和中间节点丢包率的计算,常用工具都用了TTL机制,不知道是否有其他工具能够更加准确的测试,这个有待调查。
看到一个网站上对mtr丢包率问题的回答,其中有这样一段话:

As for assigning fault based on traceroutes: I’ve professionally done senior-level network operations for over a decade, with full access to switches and routers (error counts, traffic levels, cache flows – all manners of stats and metrics – giving me visibility well beyond what a simple traceroute could provide, yet determining where packet loss was occurring to a host on a remote network was still an inexact art, mostly because the return path from the other host was obscured: Unless I had a traceroute back to me from the remote host, I could only guess at how return traffic was getting back to my workstation. I shall suggest that beyond the first or second hop in your traceroutes, there’s not much you can do (or make meaningful deductions) with ping and traceroute.