0

I'm using Serial to transfer scapy packets between two NanoPi (almost identical as Raspberry Pi).

For that, I'm using the following Python code:

import time
import serial
import threading
from scapy.all import IP, ICMP

# Craft ICMP packet
icmp_packet = IP(dst="192.168.0.1") / ICMP()

ser = serial.Serial(port='/dev/ttyS1', baudrate=115200, 
parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, 
bytesize=serial.EIGHTBITS, timeout=0.5)

def write_thread(): 
    print('W - Convert to bytes', flush=True)
    start = time.time()
    arr = bytes(icmp_packet)
    t = (time.time() - start) * 1000
    print('W - Took {} ms'.format(t))
    
    print('W - Send through serial')
    start = time.time()
    c = ser.write(arr)
    t = (time.time() - start) * 1000
    print('W - {} bytes sent in {} ms'.format(c, t))

    print('W - Wait for response')
    start = time.time()
    response = ser.readline()
    t = (time.time() - start) * 1000
    print('W - Response took {} ms'.format(t))
    

def read_thread():
    while True:
        if ser.inWaiting() == 0: continue
        line = ser.readline()
        if len(line) == 0: return None
        print('R - Got a SERIAL packet')
        start = time.time()
        c =  ser.write(b'1')
        t = (time.time() - start) * 1000
        print('R - {} bytes sent in {} ms'.format(c, t))
        break

read_thread = threading.Thread(target=read_thread)
read_thread.start()

write_thread = threading.Thread(target=write_thread)
write_thread.start()

If I run it directly, I got the following output:

W - Convert to bytes
W - Took 0.19407272338867188 ms
W - Send through serial
W - 28 bytes sent in 0.015020370483398438 ms
W - Wait for response
R - Got a SERIAL packet
W - Response took 505.48624992370605 ms
R - 1 bytes sent in 0.1010894775390625 ms

So it took 500 ms just to get the response.

If I change that line c = ser.write(arr)to c = ser.write(arr + b"\n"), I got something really quicker :

W - Convert to bytes
W - Took 0.2009868621826172 ms
W - Send through serial
W - 29 bytes sent in 0.02002716064453125 ms
W - Wait for response
W - Response took 0.20265579223632812 ms
R - Got a SERIAL packet
R - 1 bytes sent in 0.08416175842285156 ms

How do you explain that ?

EDIT: I've got the same results if I remove the timeout in the Serial connection.

Manitoba
  • 8,522
  • 11
  • 60
  • 122
  • 1
    how large are your payloads? Depending on your baudrate you can calculate what should be theoretically possible.. – Marco F. Jun 30 '23 at 13:55
  • Note, `baudrate=115200` is about 14k/second in an ideal world. How much data are you sending? – JonSG Jun 30 '23 at 14:00
  • I've updated my code with some logs. It took 470ms to send 60 bytes. That is really slow. – Manitoba Jun 30 '23 at 14:11
  • That's not what your program is telling you. Firstly you start the time before you call `pkt.get_payload()`. What is that? How long does that take? Secondly timing the `ser.write()` will be completely unrepresentative of the transfer rate. The data sent at that point should be going into a buffer. – quamrana Jun 30 '23 at 14:16
  • How am I supposed to monitor the transfer rate ? – Manitoba Jun 30 '23 at 14:23
  • I don't think that `pyserial` gives you an API into the underlying serial transfers. The only thing I can think of is for the receiver to send 'acknowledgement' packets back. Monitoring those at the sender will give you an indication of transfer rate. – quamrana Jun 30 '23 at 14:27
  • pkt.get_payload() took about 4ms to execute. This is a `scapy` function to get the payload of an IP packet. If I do a basic loop: Write packet -> Read packet on one PI and Read packet -> Write packet on the second PI, it takes about 1100ms to compute (about 275ms per operation). No matter the content I write to serial (including a basic string). – Manitoba Jun 30 '23 at 14:36
  • Surprisingly, if I do c = ser.write(bytes(packet) + b"\n") it is much much faster. See my edit. – Manitoba Jun 30 '23 at 18:58

0 Answers0