回答:
往復時間は実際にはどこにも保存されません。送信ホストは、ICMPの16ビットの識別子とシーケンスフィールドを使用して、各ICMPエコー要求メッセージを送信した時刻を記憶しています。ICMPエコー応答を取得すると、現在の時刻を記録し、応答で識別された一致する要求パケットを送信した時刻を見つけ、差を計算して報告します。
通常、pingはICMPの識別フィールドを使用して複数の同時pingを区別し、シーケンスフィールドを使用して個々のパケットを区別します。
特定のパケットの発信時間をどこに保存するかを決定するのは実装次第です。ホストのテーブルに保存する代わりに、通常、それを発信要求で送信し、応答でコピーを使用して時間を計算します。(これを指摘してくれたコメント投稿者に感謝します。)データは、実装に都合の良い方法で送信されます。もちろん、データを適切にコピーするには、遠端および介在する機器を信頼する必要があります。一部のシステムは、マイクロ秒の分解能で16バイトで時間を表すことが知られており、ミリ秒の分解能で8バイトとして表すものもあります。
data
IPパケットの部分内の形式はICMPエコー要求/応答メッセージで、RFC 792「インターネット制御メッセージ形式」(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ヘッダーに入れるためのメカニズムが定義されていますが、非常に多くのルーターが特定のIPオプションを渡さないように構成されているため、これはpingの通常のメカニズムではありません。RFC 781インターネットプロトコルタイムスタンプオプションの仕様を参照してください。
最後に、ここではすべてがIPv4の観点から書かれていますが、元の質問によると、ただし、IPv6のpingは非常によく似ています。ICMPv6RFC 4443を参照してください。
ping
タイムスタンプを格納するLinuxの実装が少なくとも1つあると確信しData
ています。これにより、エコー応答がインターネット交換を通過したときに、非常に興味深いエラーメッセージが表示され、すべてのパケットでその場所のビットが破損していました。
少なくともping
Linux の一般的なユーティリティでは、パケットが送信された時刻は、エコー要求パケットのデータ部分に、つまりIPおよびICMPヘッダーの後に格納されます。受信側がエコー応答で応答する場合、データ部分はそのまま保持されるため、送信側は往復時間を計算できます。
これは、ping
ユーティリティのマニュアルページ(「ICMPパケットの詳細」の下)で説明されています。
データスペースが少なくとも
struct timeval
ping のサイズの場合、このスペースの最初のバイトを使用して、往復時間の計算に使用するタイムスタンプを含めます。データ領域が短い場合、往復時間は与えられません。
私のマシンで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ユーティリティでも重複パケットを検出するため、内部での記録が必要です。