BobC
BobC

Reputation: 2058

Network interface simulation in Python?

I'm making a simulator for a digital radio using Python. The radio relays over RF one each of an RS-232 port and an Ethernet port, with a pair of radios making seamless pipes. Thus, the simulator will be used in pairs, with pipes between them simulating the RF link, permitting users to connect to each end using physical interfaces, virtual interfaces, or tunnels.

For the RF serial port, I'm using PySerial and virtual serial ports to make the simulator as versatile as possible: I can connect the simulator to either a physical serial port, to a network socket, or to another local program. Aside from the tools used to create the virtual serial ports on each different OS, this approach is completely cross-platform.

I'd like the simulator to be able to network with a local program via a virtual interface, with a remote program via a shared network interface, and with a remote program via a local physical interface that would be dedicated to the simulator. But so far, I haven't found a straightforward way to do this. I've been looking at SLIP/PPP, TAP/DUN, pcap/SOCK_RAW, and other possibilities, and I see no obvious or general solution.

The key difficulty seems to be that this involves an entire Ethernet interface, below the IP level, at the level of the Ethernet protocol itself: If it were only a few ports, the solution would be relatively simple. Or am I missing something blindingly obvious?

How do I use Python to create and use an RF Ethernet interface in a way that is as versatile as the RF Serial interface solution?

Upvotes: 6

Views: 3763

Answers (2)

Alexis Paques
Alexis Paques

Reputation: 1975

You can use this Python library: rawsocketpy it allows using raw sockets on Layer 2 (Using Ethernet II protocol) => No IP/TCP/UDP headers.

#!/usr/bin/env python
from rawsocketpy import RawSocket

sock = RawSocket("wlp2s0", 0xEEFA)
sock.send("some data")
sock.send("personal data", dest="\xAA\xBB\xCC\xDD\xEE\xFF")

or the server form:

#!/usr/bin/env python
from rawsocketpy import RawRequestHandler, RawAsyncServerCallback
import time

def callback(handler, server):
    print("Testing")
    handler.setup()
    handler.handle()
    handler.finish()

class LongTaskTest(RawRequestHandler):
    def handle(self):
        time.sleep(1)
        print(self.packet)

    def finish(self):
        print("End")

    def setup(self):
        print("Begin") 

def main():
    rs = RawAsyncServerCallback("wlp2s0", 0xEEFA, LongTaskTest, callback)
    rs.spin()

if __name__ == '__main__':
    main()

Upvotes: 0

BobC
BobC

Reputation: 2058

The massive number of answers people posted encouraged me to think outside of the box.

My approach will be to use Dummynet, a truly amazing and versatile tool. Unfortunately the Dummynet Windows and Linux ports are not well-maintained, which means I'll be running *BSD.

But this simplifies things, since a *BSD image can also be run as a VM, which greatly simplifies dealing with virtual interfaces.

And if I'm concerned about size, I can use picoBSD or nanoBSD to craft a tiny tailored system for my simulator.

Upvotes: 3

Related Questions