IP标头中Ping的“往返时间”存储在哪里?


9

如果使用ICMP ping,我们知道TTL并round-trip time存储在IP标头中。在下面的IP标头图中,我们知道TTL的位置,但是往返时间在哪里?

在此处输入图片说明

它存储在Options吗?

Answers:


23

往返时间实际上并未存储在任何地方。发送主机使用ICMP的16位标识符和序列字段来记住发送每个ICMP Echo Request消息的时间。当它收到ICMP Echo Reply时,它记下当前时间,找到它发送了由该响应标识的匹配Request数据包的时间,计算差异并报告。

通常,ping使用ICMP的标识字段来区分多个同时ping,而序列字段则用于区分单个数据包。

取决于实现方式来决定将给定数据包的传出时间存储在何处:通常不是在表中将其存储在主机上,而是通常在传出请求中将其发送并在回复中使用副本来计算时间。(感谢评论者指出这一点。)它以便于实现的任何方式发送,并且当然必须信任远端以及任何介入的设备才能正确复制数据。已知某些系统以16字节(微秒)的分辨率表示时间,有些以8字节(毫秒)的分辨率表示时间。

dataIP数据包部分中的格式是ICMP回显请求/应答消息,该消息从RFC 792 “ Internet控制消息格式”(p14)复制到此处。

Type对于请求为8,对于答复为0;Code是0。

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Type      |     Code      |          Checksum             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Identifier          |        Sequence Number        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Data ...
   +-+-+-+-+-

PS。为了清楚起见,IP标头的标识字段通常设置为任意值,每个传出数据包都不同,用于重组任何碎片,并且与ICMP主体中的值不相同。

此外,尽管定义了一种机制来将时间戳记作为选项添加到IP报头中,但这不是ping的常规机制,因为很多路由器都配置为不通过某些IP选项。请参阅Internet协议时间戳选项的RFC 781规范。

最后,尽管这里的所有内容都是从IPv4角度编写的,但仍是最初的问题。但是IPv6中的ping非常相似,请参阅ICMPv6 RFC 4443


3
AIUI的“标识”字段用于标识用于片段重组的数据包。回声请求通过ICMP头中的id和seq字段与回声答复进行匹配。
彼得·格林

感谢您指出:我澄清说,这是ICMP而不是IP ID(和您所说的seq)。
jonathanjo

我很确定ping在Linux 上至少有一种实现将时间戳存储Data在ICMP有效负载部分中。当回声答复遍历Internet交换时,这会导致一些非常有趣的错误消息,该Internet交换损坏了每个数据包中该位置的位。
kasperd

您当然是对的,我更新了答案,这样说;尽管自然地,存储的是根据发送方时钟发送的绝对时间,而不是RTT本身。
jonathanjo

3

至少使用pingLinux 上的通用实用程序,发送数据包的时间存储在回显请求数据包的数据部分中,即IP和ICMP标头之后。当接收方回复回音答复时,数据部分保持不变,因此发送方可以计算往返时间。

ping实用程序手册页中对此进行了描述(在“ ICMP数据包详细信息”下):

如果数据空间至少为struct timevalping 大小,则使用该空间的开始字节来包含时间戳记,以用于往返时间的计算。如果数据空间较短,则不会给出往返时间。

在我的机器上sizeof(struct timeval)是16,因此将数据包数据大小设置为15会阻止ping显示往返时间:

$ ping -s 15 8.8.8.8 
PING 8.8.8.8 (8.8.8.8) 15(43) bytes of data.
23 bytes from 8.8.8.8: icmp_seq=1 ttl=121

当然,如@jonathanjo的答案所描述的那样,将发送时间戳存储在实用程序中也是可能的实现。甚至Linux实用程序也需要一些内部记账,因为它可以检测到重复的数据包。


1
当您将数据大小设置为小于16时,它们无法显示RTT感觉就像是一个程序错误。
canadadry

@canadadry,好吧,将时间戳放入数据包本身是显而易见的:唯一需要的情况是答复数据包到来时,因此在本地存储它没有用。当然,该程序似乎源于80年代BSD的原始版本,因此它也可能与时代有关。无论如何,我不确定为什么有人会使用这种超小的数据包。请注意,即使最小的以太网帧大小也足以容纳以太网,IP和ICMP标头以及16字节的时间戳。(尽管还有2个字节,所以没有更多的扩展空间了。)
ilkkachu

@ilkkachu感谢您提醒我时间通常存放在哪里;我更新了答案。关于小数据包:许多网络问题在数据包大小上有所不同。
jonathanjo

@ikkachu我看了一下Cisco的ping数据包:它们还有时间,以64位毫秒为单位。
jonathanjo
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.