0

I am trying to send ethernet frames over a Gigabit link with python. Therefore I used this code:

while (package_count < packets):
  package_count += 1
  s.send(eth_header+eth_payload)
  sleep(delay)

The socket is opened before. The size of a frame (eth_header + eth_payload) is 1500 bytes, to use the full Gigabit link, the delay time would be far away from the minimum delay time of a few ms. Any idea how to control the speed of sending data using the full Gigabit over sockets in python?

who93
  • 55
  • 2
  • 6
  • Are you using TCP or UDP? Blocking sockets or non-blocking? What happens if you just get rid of the sleep() command entirely? – Jeremy Friesner Jul 17 '17 at 02:34
  • I am using raw Ethernet frames with SOCK_RAW (checked with wireshark). When I delete the sleep, I get full speed - but I want to control the speed I am sending – who93 Jul 17 '17 at 06:09
  • 1
    You can control both the delay and number of eth chunks to achieve the approximate bandwidth rate. – zwer Jul 17 '17 at 14:42

1 Answers1

1

There's no explicit facility to control send-rate; you need to do it yourself by sleep()ing for the appropriate amount of time. Calculating the appropriate value to pass in to sleep() is the only tricky part; I do it by keeping a counter of the number of bytes that have been sent so far, and subtracting from that counter the number of bytes that "should have been sent" in the amount of time that has elapsed. That way I know at any given time how many bytes-ahead-of-schedule I am, which translates directly into how many seconds-ahead-of-schedule I am, which is how long I ought to sleep for in order to be back "on schedule".

Example code is below; it sends UDP packets rather than raw data but the logic is the same.

import socket
import time

# We'll limit ourself to a 40KB/sec maximum send rate
maxSendRateBytesPerSecond = (40*1024)

def ConvertSecondsToBytes(numSeconds):
   return numSeconds*maxSendRateBytesPerSecond

def ConvertBytesToSeconds(numBytes):
   return float(numBytes)/maxSendRateBytesPerSecond

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.connect(('127.0.0.1', 8888))

# We'll add to this tally as we send() bytes, and subtract from
# at the schedule specified by (maxSendRateBytesPerSecond)
bytesAheadOfSchedule = 0

# Dummy data buffer, just for testing
dataBuf = bytearray(1024)

prevTime = None

while True:
   now = time.time()
   if (prevTime != None):
      bytesAheadOfSchedule -= ConvertSecondsToBytes(now-prevTime)
   prevTime = now

   numBytesSent = sock.send(dataBuf)
   if (numBytesSent > 0):
      bytesAheadOfSchedule += numBytesSent
      if (bytesAheadOfSchedule > 0):
         time.sleep(ConvertBytesToSeconds(bytesAheadOfSchedule))
   else:
      print "Error sending data, exiting!"
      break
Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
  • thank you for your answer. I'll tried this in a simplified form, but the sleep command is only working reliable for around 10ms, for Gigabit speed I need less then 1ms. I implemented it now in C, working perfect! – who93 Jul 17 '17 at 15:52