Traceroute packet loss and average time measurement

vbimport

#1

The Windows command line tool “tracert” is quite useful for checking the timing from one hop to the next between the PC and the remote host for diagnosing an outage.

However, two limitations I occasionally run into is that it does not measure packet loss or the average response time along the route. While pinging the individual hops seems like a workaround, there are a few issues with the ping command:

[ol]
[li]Most hosts do not reply to ping requests even though most will return a TTL expiry notice when the IP packet expires.
[/li][li]It waits at least one second between each ping, which would be very tedious to test each hop.
[/li][li]Even when ping returns a TTL expiry notice, it does not report the response time like it does when its IP packet does not expire.
[/li][/ol]

So I decided to have a go at writing a command line script that can make use of ping’s ‘-i’ switch to test each individual hop.

There were a few issues I ran into, so this tool will not be as accurate a proper executable such as the commercial tool Visual Trace Route. I’m sure there are freeware tools available also, but figured I’ll do this as a bit of a challenge as I haven’t written many scripts lately. :wink:

[ol]
[li]Ping does not delay with a single ping, so I exploited this ping method even though it added some complexity to the code.
[/li][li]I have no easy way of multi-threading the ping requests, so I limited the packet loss measurement to 5% to avoid it taking longer than 30 seconds at a hop that does not respond to TTL expiry notices. If the packet loss is 5% or higher, it will show ‘5+% loss’ for the affected hop.
[/li][li]The command line does not support decimal places in math, so the packet loss is shown in whole figures, i.e. 0%, 1%, 2%, etc.
[/li][li]The command line has a jitter of about +/-10ms per command and can only measure down to 1/100s, so I cannot accurately measure the minimum and maximum response times. The average time should be reasonably accurate as it’s measured across up to 100 responses per hop.
[/li][li]Due to the command line execution jitter, I set up the script so that it silently does a dummy run with localhost to measure how long the script takes pinging localhost (which has negligible ping time) and then uses this timing to offset the timing when calculating the average response time.
[/li][/ol]

To create the script file, copy & paste the following into Notepad and save it as “tracetime.bat”:

@echo off
setlocal enabledelayedexpansion
set Host=Unknown
if "%1"=="" (
  set /p Host=Enter host to trace:
  call %0 !Host!
  goto end
)
if "%2"=="" (
  set /a AvgTimeOffset=0
  set Host=127.0.0.1
  goto SkipCheck
) else (
  set /a AvgTimeOffset=%2
)
for /f "tokens=3" %%f in ('ping -n 1 %1') do (
  set result=%%f
  if "!result:~0,1!"=="[" set Host=!result:~1,-1!
  if "!result!"=="with" set Host=%1
)
if "%Host%"=="Unknown" echo Failed to resolve host: %1 &&goto end

:SkipCheck
if %AvgTimeOffset% GTR 0 echo Tracing route time to %1 [%Host%]:
set /a Hop=1
:repeat
set /a Count=0
set /a Lost=0
set /a AvgTime=-%AvgTimeOffset%
set IPAddress=
set Expired=false
for /l %%n in (1,1,100) do (
  if "!Lost!"=="5" goto skip
  set LastCount=!Count!
  Set /a EndTime=-1
  Set /a StartTime=1!time:~7,1!!time:~-2!-1000
  for /f "tokens=1,3,5" %%f in ('ping -i %Hop% -n 1 %Host%') do (
    if "!EndTime!"=="-1" set /a EndTime=1!time:~7,1!!time:~-2!-1000
    if "%%f"=="Reply" set /a Count+=1
    set IPCheck=%%g
    if "!IPCheck:~-1!"==":" set IPAddress=!IPCheck:~0,-1!
    if "%%h"=="expired" set Expired=true
  )
  if !EndTime! LSS !StartTime! set /a EndTime+=1000
  set /a TotalTime=!EndTime!-!StartTime!
  if "!LastCount!"=="!Count!" (
    set /a Lost+=1
  ) else (
    set /a AvgTime+=!TotalTime!
  )
)
:skip
if "%Lost%"=="5" set Lost=%Lost%+
if "%AvgTimeOffset%"=="0" echo. &&%0 %1 %AvgTime% &&goto end
set /a AvgTime+=((100-%Count%) * %AvgTimeOffset%) / 100
if %AvgTime% LSS 0 set /a AvgTime=0
if not "%Count%"=="0" (
  set /a AvgTime=%AvgTime%*10
  set /a AvgTime/=%Count%
  echo  %Hop%: %IPAddress% - %Lost%%% loss - Average = !AvgTime!ms
) else (
  echo  %Hop%: Request timed out
)
set /a Hop+=1
if "%Expired%"=="true" goto repeat
if "%Hop%"=="30" goto complete
if "%Count%"=="0" goto repeat
:complete
echo. &&echo Trace complete.
:end
if "%1"=="" pause

To run the script, just double-click the Tracetime file, type in the hostname you wish to try such as “www.myce.com”, press Enter and give it a minute to complete.

The following is an example:

It can also be run at the command line by typing in “tracetime hostname”, such as “tracetime www.myce.com”.

It has no switches and very limited error-checking, so don’t try supplying it switches, spaces, etc. or it will likely go erratic or crash. :wink: