12

I'm trying to write a scapy script which can make an average on the ping time, so I need to get the time elapsed between ICMP echo/reply packet sent and reply packet received. For now, I have this:

#! /usr/bin/env python
from scapy.all import *
from time import *

def QoS_ping(host, count=3):
  packet = Ether()/IP(dst=host)/ICMP()
  t=0.0
  for x in range(count):
      t1=time()
      ans=srp(packet,iface="eth0", verbose=0)
      t2=time()
      t+=t2-t1
  return (t/count)*1000

The problem is that using time() function doesn't rise a good result. For example, I find 134 ms on one domain, and with the ping system function on the same domain, I have found 30 ms (average of course).

My question is: Is there a way to get the exactly time elpased beetween sent packet and received packet by scapy? I don't want to use popen() function or other system call because I need scapy for futur packet management.

Mike Pennington
  • 41,899
  • 19
  • 136
  • 174
user1789326
  • 141
  • 1
  • 3
  • 8

3 Answers3

8

Is there a way to get the exactly time elpased beetween sent packet and received packet by scapy?

You can use pak.time and pak.sent_time

I modified your script to use them...

import statistics
import os

from scapy.all import Ether, IP, ICMP, srp

if os.geteuid() > 0:
    raise OSError("This script must run as root")

ping_rtt_list = list()
def ping_addr(host, count=3):
    packet = Ether()/IP(dst=host)/ICMP()
    t=0.0
    for x in range(count):
        x += 1  # Start with x = 1 (not zero)
        ans, unans = srp(packet, iface="eth0", filter='icmp', verbose=0)
        rx = ans[0][1]
        tx = ans[0][0]
        delta = rx.time - tx.sent_time
        print("ping #{0} rtt: {1} second".format(x, round(delta, 6)))
        ping_rtt_list.append(round(delta, 6))
    return ping_rtt_list

if __name__=="__main__":
    ping_rtt_list = ping_addr('172.16.15.1')
    rtt_avg = round(statistics.mean(ping_rtt_list), 6)
    print("Avg ping rtt (seconds):", rtt_avg)

An example run:

$ sudo /opt/virtual_env/py37_test/bin/python ./ping_w_scapy.py
ping #1 rtt: 0.002019 second
ping #2 rtt: 0.002347 second
ping #3 rtt: 0.001807 second
Avg ping rtt (seconds): 0.002058
Mike Pennington
  • 41,899
  • 19
  • 136
  • 174
  • The average of 285.5ms + 230.9ms + 219.9ms is 245ms; individual packets response times are printed in seconds, and the average is converted to milliseconds during the `return` – Mike Pennington Nov 02 '12 at 13:50
  • **A warning to future readers**: Using `rx.time-tx.sent_time` can result in negative time measurements (scapy 2.4.0-2.4.3rc1). I have created an issue ([#1952](https://github.com/secdev/scapy/issues/1952)) on this for anyone interested. – Felix ZY Mar 28 '19 at 17:18
0

BTW, using unbuffered python (python -u to start it) increases the timing accuracy as python is not waiting for the buffers to decide to dump. Using your above script, it changed my results from being off by 0.4 ms to being off by 0.1-ish.

fantadisco
  • 21
  • 4
0

Mike, just a small fix in order to get the average time, change:

print "Average %0.3f" % float(match.group(1))

to:

 print "Average %0.3f" % float(match.group(2))

since (match.group(1)) will get the min time and not the avg as mentioned.