This is a static archive of our old Q&A Site. Please post any new questions and answers at ask.wireshark.org.

show ICMP RTTs

1

I have a packet trace consisting solely of ICMP echo requests (probes) with a low ttl and corresponding ICMP time-exceeded messages (replies).

Is there a way for Wireshark to show the round-trip time (RTT) for each probe packet that I sent?

asked 11 Dec '13, 09:08

rick_r's gravatar image

rick_r
21115
accept rate: 0%


2 Answers:

2

Option #1:

Take a look at the following output of tshark

[email protected]:/tmp$ tshark -nr icmp.pcap -T fields -e frame.number -e frame.time_relative -e ip.src -e ip.dst -e icmp.type -e icmp.code -e icmp.ident -e icmp.seq -E separator=\; -E header=y

Output (copy to editor to remove possible wrap-around):

frame.number;frame.time_relative;ip.src;ip.dst;icmp.type;icmp.code;icmp.ident;icmp.seq
10;8.271326000;192.168.158.186;80.190.158.9;8;0;25976,30821;1
11;8.271483000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;11,8;0,0;25976,30821;1
35;13.305895000;192.168.158.186;80.190.158.9;8;0;25976,30821;2
36;13.306017000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;11,8;0,0;25976,30821;2
45;18.338883000;192.168.158.186;80.190.158.9;8;0;25976,30821;3
46;18.339073000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;11,8;0,0;25976,30821;3
52;19.553171000;192.168.158.186;80.190.158.9;8;0;25977,31077;1
53;19.553253000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;11,8;0,0;25977,31077;1
66;24.581539000;192.168.158.186;80.190.158.9;8;0;25977,31077;2
67;24.581686000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;11,8;0,0;25977,31077;2
72;27.909485000;192.168.158.186;80.190.158.9;8;0;25978,31333;1
73;27.909622000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;11,8;0,0;25978,31333;1
81;32.932901000;192.168.158.186;80.190.158.9;8;0;25978,31333;2
82;32.933046000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;11,8;0,0;25978,31333;2
101;37.959543000;192.168.158.186;80.190.158.9;8;0;25978,31333;3
102;37.959667000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;11,8;0,0;25978,31333;3

Wireshark (tshark) will also dissect the ICMP ECHO Request header within ICMP Time Exceeded. Frame #10 is the ECHO Request. Frame #11 is the TIME Exeeded for that ECHO Request. As you can see, you will find the necessary information in the output (IP Adresses, ICMP Identifier and Sequence number) to match those two frames. Then take the time stamp of both (here frame.time_relative) to calculate the RTT. Of course you will need some script (Perl, Python or whatever you speak fluently) to extract and calculate that. However, there is no way to do the same in Wireshark (without programming, e.g. a Lua Listener), especially if you have bursts of requests and replies.

Option #2:

Another option would be to use the field icmp.data_time of the ICMP Time Exceeded frames in conjunction with the time stamp of the Time Exceed frame itself. The delta should be equal to the RTT. However, on my test system that did not work, as I had a strange offset, which might be caused by VMware. However, you can still try it in your environment and see what happens.

[email protected]:/tmp$ tshark -nr icmp.pcap -Y 'icmp.type eq 11 and icmp.code eq 0' -T fields -e frame.number -e frame.time -e ip.src -e ip.dst -e icmp.data_time -E separator=\; -E header=y

Output (copy to editor to remove possible wrap-around):

frame.number;frame.time;ip.src;ip.dst;icmp.data_time
11;Dec 11, 2013 21:28:00.039026000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;Dec 11, 2013 21:28:00.000000000
36;Dec 11, 2013 21:28:05.073560000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;Dec 11, 2013 21:28:05.000000000
46;Dec 11, 2013 21:28:10.106616000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;Dec 11, 2013 21:28:10.000000000
53;Dec 11, 2013 21:28:11.320796000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;Dec 11, 2013 21:28:11.000000000
67;Dec 11, 2013 21:28:16.349229000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;Dec 11, 2013 21:28:16.000000000
73;Dec 11, 2013 21:28:19.677165000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;Dec 11, 2013 21:28:19.000000000
82;Dec 11, 2013 21:28:24.700589000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;Dec 11, 2013 21:28:24.000000000
102;Dec 11, 2013 21:28:29.727210000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;Dec 11, 2013 21:28:29.000000000

Then take the two time stamps to calculate the difference, which is again the RTT. HOWEVER: As you can see the data time stamp is allway xx:xx:xx.0000000, which is simply wrong. I'm not yet sure if that's a Wireshark bug or a problem with VMware and time stamping the frames. If you see the same problem on your system, please use method #1.

Option #3:

Finally, there is icmp.data_time_relative, which is, according to the definition of that field: The timestamp of the packet, relative to the timestamp in the first 8 bytes of the icmp data. So, that's actually the RTT of the ECHO request (data part of time exceeded) and the ICMP time exceeded frame. However: That did also not work on my system. Same problem as mentioned above. Anyway, you can try this as well. Maybe it works in your environment. You can even apply that field as a column in Wireshark. Find the field in the ICMP time exceeded frame, then right click it and choose "Apply as column".

-- UPDATE --

I think I need to be more specific on Option #2 and #3, as that's only going to work if you use ping (ECHO request) on a Linux system.

man page of ping:

ICMP PACKET DETAILS
 .....

 If the data space is at least eight bytes large, ping uses the first
 eight bytes of this space to include a timestamp which it uses in the
 computation of round trip times. If less than eight bytes of pad are
 specified, no round trip times are given.

As you can see, the Linux ping command (at least on Ubuntu) will add a timestamp to the ICMP ECHO request, if there is ‘enough space’. That timestamp will be ‘detected’ by Wireshark (dissected as fields icmp.data_time and icmp.data_time_relative). So, you can use those fields to ‘calcuate’ the RTT.

You say: There is no timestamp inside an ICMP time-exceeded packet.

You are right. But, there is a timestamp in the ECHO request, if you are using ping on Linux (as I did). As every ICMP 'error frame' (I don't know a better name for that), includes the first few bytes of the packet that caused the ICMP 'error frame' (mainly the IP + TCP/UDP header), the ICMP time exceeded contains the header of the ICMP ECHO request, including the timestamp in it. See the following capture file:

ICMP on Linux:

http://cloudshark.org/captures/8676c0c2afad

See frame #1 (ECHO request): Open 'Internet Control Message Protocol' and you'll see the timestamp.

See frame #2 (TIME exceeded): Open 'Internet Control Message Protocol' and then 'Internet Control Message Protocol' again and you'll see the timestamp of the ECHO request (original packet that caused the time exceeded).

However that method (Options #2 and #3) has two problems:

  • the timestamp on Linux seems to be slightly false. There is an offset between the timestamp in the ICMP ECHO data payload and the timestamp of the ECHO frame itself. That could be due to VMware or a general problem with the ping command on Linux/Ubuntu. I have no interest to analyze that ;-)
  • If you are using Windows to send ECHO requests, the method does not work at all, as the Windows ping command does not add a timestamp to the ECHO request.

ICMP on Windows:

http://cloudshark.org/captures/e5a55c87d6fd

So, if you are using Linux to send the ICMP ECHO requests, you can use Option #2 and #3 to calculate the RTT, which is simply this:

  • timestamp of ICMP time exceeded - timestamp of ECHO request within the same frame

If you are using Windows there is no timestamp within the ECHO request, so you can only use method #1. That's gonna work in both cases.

-- UPDATE 2 --

The following (simple) Perl script will calculate the RTT, according to the method described in Option #1.

CLI:

tshark -nr icmp.pcap -Y icmp -T fields -e frame.number -e frame.time_relative -e ip.src -e ip.dst -e icmp.type -e icmp.code -e icmp.ident -e icmp.seq -E separator=';' | perl calculate_rtt.pl

Output:

RTT:8.1e-05:192.168.158.186:80.190.158.9:2:0.000081000:26494,32359:1
RTT:0.000121000000000038:192.168.158.186:80.190.158.9:4:5.011520000:26494,32359:2
RTT:0.000293999999998462:192.168.158.186:80.190.158.9:6:8.353810000:26497,33127:1
RTT:0.000146000000000868:192.168.158.186:80.190.158.9:8:13.397372000:26497,33127:2
RTT:6.70000000013715e-05:192.168.158.186:80.190.158.9:10:14.153415000:26501,34151:1
RTT:6.40000000018404e-05:192.168.158.186:80.190.158.9:12:16.978635000:26502,34407:1

The format of the output is:

RTT:{RTT time}:{src}:{dst}:{frame number}:{timestamp of time exceeded}:{ICMP Ident}:{ICMP Sequence}

Hint: The RTT values are pretty small in my example, as I used a TTL of 1 for the ECHO request and the first router on my network responded with a TIME EXCEEDED, which was within a few microseconds on a Gigabit network!

Code:

#!/usr/bin/perl

use strict; use warnings;

my %icmp_data;

while (<STDIN>) {

my $line = $_;
chomp($line);

# ECHO request 
if ($line =~ /;8;0/) {
    my ($frame_num, $time, $src, $dst, undef, undef, $ident, $seq) = (split(&#39;;&#39;, $line));

    my $key = &quot;$src + $dst + $ident + $seq&quot;;

# If the same ECHO request is found, print a WARNING
    if (exists $icmp_data{$key}-&gt;{echo_request}) {
       print &quot;WARNING: Duplicate ICMP ECHO REQUEST found\n&quot;;
       print &quot;Old Entry: \n&quot;; 
       print &quot;    Frame: &quot; + $icmp_data{$key}-&gt;{echo_request}-&gt;{frame_num} + &quot;\n&quot;;
       print &quot;    Time : &quot; + $icmp_data{$key}-&gt;{echo_request}-&gt;{time} + &quot;\n&quot;;
       print &quot;    Src  : &quot; + $icmp_data{$key}-&gt;{echo_request}-&gt;{src} + &quot;\n&quot;;
       print &quot;    Dst  : &quot; + $icmp_data{$key}-&gt;{echo_request}-&gt;{dst} + &quot;\n&quot;;
       print &quot;    Ident: &quot; + $icmp_data{$key}-&gt;{echo_request}-&gt;{ident} + &quot;\n&quot;;
       print &quot;    Seq  : &quot; + $icmp_data{$key}-&gt;{echo_request}-&gt;{seq} + &quot;\n&quot;;

       print &quot;New Entry: \n&quot;; 
       print &quot;    Frame: &quot; + $frame_num + &quot;\n&quot;;
       print &quot;    Time : &quot; + $time + &quot;\n&quot;;
       print &quot;    Src  : &quot; + $src + &quot;\n&quot;;
       print &quot;    Dst  : &quot; + $dst + &quot;\n&quot;;
       print &quot;    Ident: &quot; + $ident + &quot;\n&quot;;
       print &quot;    Seq  : &quot; + $seq + &quot;\n&quot;;
   print &quot;\n&quot;;

    } else {

       $icmp_data{$key}-&gt;{echo_request}-&gt;{frame_num} = $frame_num;
       $icmp_data{$key}-&gt;{echo_request}-&gt;{time} = $time;
       $icmp_data{$key}-&gt;{echo_request}-&gt;{src} = $src;
       $icmp_data{$key}-&gt;{echo_request}-&gt;{dst} = $dst;
       $icmp_data{$key}-&gt;{echo_request}-&gt;{ident} = $ident;
       $icmp_data{$key}-&gt;{echo_request}-&gt;{seq} = $seq;
}
}

# TIME EXCEEDED 
if ($line =~ /;11,8;0,0/) {
    my ($frame_num, $time, undef, $src_dst, undef, undef, $ident, $seq) = (split(&#39;;&#39;, $line));
    my ($src, $dst) = (split(&#39;,&#39;, $src_dst));

    my $key = &quot;$src + $dst + $ident + $seq&quot;;

    $icmp_data{$key}-&gt;{time_exceeded}-&gt;{frame_num} = $frame_num;
    $icmp_data{$key}-&gt;{time_exceeded}-&gt;{time} = $time;
    $icmp_data{$key}-&gt;{time_exceeded}-&gt;{src} = $src;
    $icmp_data{$key}-&gt;{time_exceeded}-&gt;{dst} = $dst;
    $icmp_data{$key}-&gt;{time_exceeded}-&gt;{ident} = $ident;
    $icmp_data{$key}-&gt;{time_exceeded}-&gt;{seq} = $seq;

    if (exists $icmp_data{$key}-&gt;{echo_request}) {
        my $rtt = $icmp_data{$key}-&gt;{time_exceeded}-&gt;{time} - $icmp_data{$key}-&gt;{echo_request}-&gt;{time};

    print &quot;RTT:$rtt:$src:$dst:$frame_num:$time:$ident:$seq\n&quot;;
    }
}

}

END

Sample Data, generated by:

tshark -nr icmp.pcap -Y icmp -T fields -e frame.number -e frame.time_relative -e ip.src -e ip.dst -e icmp.type -e icmp.code -e icmp.ident -e icmp.seq -E separator=';'

10;8.271326000;192.168.158.186;80.190.158.9;8;0;25976,30821;1 11;8.271483000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;11,8;0,0;25976,30821;1 35;13.305895000;192.168.158.186;80.190.158.9;8;0;25976,30821;2 36;13.306017000;192.168.158.2,192.168.158.186;192.168.158.186,80.190.158.9;11,8;0,0;25976,30821;2

Sample Output:

RTT:{RTT time}:{src}:{dst}:{frame number}:{timestamp of time exceeded}:{ICMP Ident}:{ICMP Sequence}

RTT:8.1e-05:192.168.158.186:80.190.158.9:2:0.000081000:26494,32359:1 RTT:0.000121000000000038:192.168.158.186:80.190.158.9:4:5.011520000:26494,32359:2 RTT:0.000293999999998462:192.168.158.186:80.190.158.9:6:8.353810000:26497,33127:1 RTT:0.000146000000000868:192.168.158.186:80.190.158.9:8:13.397372000:26497,33127:2 RTT:6.70000000013715e-05:192.168.158.186:80.190.158.9:10:14.153415000:26501,34151:1 RTT:6.40000000018404e-05:192.168.158.186:80.190.158.9:12:16.978635000:26502,34407:1

Regards
Kurt

answered 11 Dec ‘13, 13:00

Kurt%20Knochner's gravatar image

Kurt Knochner ♦
24.8k1039237
accept rate: 15%

edited 12 Dec ‘13, 01:42

Thank you for the detailed answer. I already have my own Python script that computes such RTTs, I just needed to doublecheck with wireshark some weird patterns that I observed. Since I am sending trains of probes, my packet trace doesn’t look like: [probe_1, reply_1, …, probe_n, reply_n], but more like: [probe_1, probe_2, …, probe_k, reply_1, reply_2,… reply_k, probe_k+1, …, reply_k+1,…]. Will this still work on wireshark? I don’t understand what icmp.data_time means. There is no timestamp inside an ICMP time-exceeded packet. It is just the pcap timestamp, so wireshark should have to match a reply with a probe and only then compute the RTT. Is it capable of doing it? Or does it just compute the difference of timestamps between two consecutive packets in the trace?

(11 Dec ‘13, 14:37) rick_r

If you are trying to measure the RTT between ICMP echo request and ICMP echo reply packets, then you could use icmp.resptime. That field won’t be present in “Time to live exceeded” packets though.

(11 Dec ‘13, 14:44) cmaynard ♦♦

see the UPDATE in my answer.

(11 Dec ‘13, 23:43) Kurt Knochner ♦

Thank you again, Kurt. In my trace I didn’t use ping. I sent my own ICMP echo request packets from a Linux box. Is there anything I can do for this trace of mine?

(12 Dec ‘13, 01:05) rick_r

see UPDATE 2 in my answer

(12 Dec ‘13, 01:17) Kurt Knochner ♦

I sent my own ICMP echo request packets from a Linux box.

can you post a small capture file somewhere (google drive, dropbox, cloudshark.org or mega.co.nz)?

(12 Dec ‘13, 01:43) Kurt Knochner ♦

You did a lot more than I could ever expect! I tried to run your script, but tshark says there is not such option as -Y icmp. There is -y, but it is [ -y <capture link type> ]. Which parameter did you think of here?

(12 Dec ‘13, 01:53) rick_r
(12 Dec ‘13, 01:57) rick_r
1

O.K. here is the sample output for your capture file. The RTT values seem to be correct (approved by manual comparison).

RTT:0.009429:193.1.13.12:138.96.116.134:12:0.009429000:0,0:0 RTT:0.008586:193.1.13.12:138.96.116.134:13:0.009479000:0,0:1 RTT:0.007735:193.1.13.12:138.96.116.134:14:0.009517000:0,0:2 RTT:0.006914:193.1.13.12:138.96.116.134:15:0.009559000:0,0:3 RTT:0.006067:193.1.13.12:138.96.116.134:16:0.009603000:0,0:4

not such option as -Y icmp.

Your tshark version is older than mine (1.10.2). You can try to use -R instead of -Y

(12 Dec ‘13, 02:10) Kurt Knochner ♦

I’m not really sure what you’re trying to accomplish. If you want to know the RTT between 193.1.13.12 and the host replying with the TTL exceeded packet, why not just send an ICMP echo request packet from 193.1.13.12 to 193.1.244.121 and then use the icmp.resptime field?

(12 Dec ‘13, 07:58) cmaynard ♦♦
showing 5 of 10 show 5 more comments

1

If you see time_exceeded messages then you did not reach your target. Or are you tracing traceroute traffic?
If you want to see the RTT to each router sending the ICMP TTL exceeded simply look at the delta time of each inbound packet from the previous outbound packet.

Just did this and here is my results with filtering on inbound ICMP packets for a given ip_address and icmp.ident: ip.dst == 173.194.34.69 and icmp.ident == 1 and ip.ttl gt 30 The frame.time__delta added as a column shows the RTT of each router on the path. alt text

The Satistics - FlowGraph on a filtered trace should also help to see the 'RTT's of each hop' alt text

answered 11 Dec '13, 09:43

mrEEde's gravatar image

mrEEde
3.9k152270
accept rate: 20%

edited 11 Dec '13, 11:30

I want to see the RTT between my host and the targeted router. As far as I could tell, delta time is the time between two consecutive packets in the packet trace, right? If so, it's of no interest to me, as I have bursts of probes and bursts of replies.

(11 Dec '13, 09:46) rick_r