Files
my-os-project2/kernel/picotcp/test/python/topology.py
2025-10-29 14:29:06 +01:00

224 lines
6.3 KiB
Python
Executable File

#!/usr/bin/python
# Python classes definition for the picoTCP
# topology test environment
#
# Copyright (c) 2013-2017 Altran Intelligent Systems. See LICENSE for usage.
import sys, os, subprocess, time, re
def test_tuntap():
if not os.geteuid()==0:
sys.exit("\nOnly root can use real devices contained in this script\n")
class Topology:
def __init__(self):
self.nets = []
self.nodes = []
self.nextn = 1
self.hosts = []
class Network:
def __init__(self, topology, real=''):
self.n = topology.nextn
topology.nextn += 1
self.nodes = []
self.topology = topology
self.topology.nets.append(self)
self.sock = "/tmp/topology/net"+`self.n`
self.nextn = 1
vdecmd = ["vde_switch", "-x" , "-s", self.sock, "-m", self.sock+".mgmt"]
if real != '':
test_tuntap()
vdecmd.append('-t')
vdecmd.append(real)
vdecmd.append('-x')
self.pop = subprocess.Popen(vdecmd, stdin=subprocess.PIPE)
self.hosts = []
print ""
print vdecmd
print "Created network "+self.sock
if real != '':
subprocess.call(["ifconfig",real,"172.16."+`self.n`+".1", "netmask", "255.255.255.0", "up"])
self.nextn = 2
class Node:
def __init__(self,topology, network = None):
if (network is None):
network = Network(topology)
self.net = network
self.n = network.nextn
network.nextn += 1
self.net.nodes.append(self)
self.topology = topology
self.topology.nodes.append(self)
class Host:
def add_routes(self, topology):
for eth in [self.eth1, self.eth2]:
if eth and not self.args.startswith("dhcpclient"):
net = eth.net
for h in topology.hosts:
if h.eth1 and h.eth2:
dst=""
gw=""
routing=False
if (h.eth2.net.n == net.n) and (self not in h.eth1.net.hosts):
if h.eth1.net.n > net.n or h.nat == False:
print "FOUND route to net "+`h.eth1.net.n`
dst_net = h.eth1.net.n
gw_net = h.eth2.net.n
gw_n = h.eth2.n
routing=True
elif (h.eth1.net.n == net.n) and (self not in h.eth2.net.hosts):
if h.eth2.net.n > net.n or h.nat == False:
print "FOUND route to net "+`h.eth2.net.n`
dst_net = h.eth2.net.n
gw_net = h.eth1.net.n
gw_n = h.eth1.n
routing=True
if (routing):
dst = "172.16."+`dst_net`+".0"
gw = "172.16."+`gw_net`+"."+`gw_n`
self.routes.append("-r")
self.routes.append(dst+":255.255.255.0:"+gw+":")
if (routing and gw_net > dst_net and h.nat == False):
dst_net -= 1
while(dst_net > 0):
dst = "172.16."+`dst_net`+".0"
self.routes.append("-r")
self.routes.append(dst+":255.255.255.0:"+gw+":")
dst_net -= 1
elif (routing and gw_net != None and gw_net < dst_net):
dst_net += 1
while(dst_net < net.topology.nextn):
dst = "172.16."+`dst_net`+".0"
self.routes.append("-r")
self.routes.append(dst+":255.255.255.0:"+gw+":")
dst_net += 1
def parse_options(self, eth, delay, bw, loss):
if (delay != "" or bw != ""):
mysock = eth.net.sock + "__" + `eth.n`
wirecmd = ['wirefilter', '-v']
wirecmd.append(mysock +":" + eth.net.sock)
if (delay != ''):
wirecmd.append("-d")
wirecmd.append(delay)
if (bw != ''):
wirecmd.append("-b")
wirecmd.append(bw)
if (loss != ''):
wirecmd.append("-l")
wirecmd.append(loss)
print wirecmd
subprocess.Popen(['vde_switch', '-s', mysock], stdin=subprocess.PIPE)
subprocess.Popen(wirecmd, stdin=subprocess.PIPE)
else:
mysock = eth.net.sock
return mysock
def __init__(self, topology, net1=None, net2=None, gw=None, args="tcpecho:5555", delay1="", bw1="", delay2="", bw2="", loss1="", loss2=""):
if net1:
self.eth1 = Node(topology, net1)
net1.hosts.append(self)
else:
self.eth1 = None
if net2:
self.eth2 = Node(topology, net2)
net2.hosts.append(self)
else:
self.eth2 = None
self.cmd = ["./build/test/picoapp.elf"]
self.gw = gw
if args.startswith("nat"):
self.nat = True
else:
self.nat = False
if (net1):
mysock = self.parse_options(self.eth1, delay1, bw1, loss1)
if (args.startswith("dhcpclient")):
self.cmd.append("--barevde")
vdeline = "eth1:"+mysock+':'
else:
self.cmd.append("--vde")
vdeline = "eth1:"+mysock+':'+"172.16."+`self.eth1.net.n`+"."+`self.eth1.n`+":255.255.255.0:"
if (self.gw and re.search("172\.16\."+`self.eth1.net`, self.gw)):
vdeline +=self.gw+":"
self.cmd.append(vdeline)
if (net2):
mysock = self.parse_options(self.eth2, delay2, bw2, loss2)
if (args.startswith("dhcpclient")):
self.cmd.append("--barevde")
vdeline = "eth2:"+mysock+':'
else:
self.cmd.append("--vde")
vdeline = "eth2:"+mysock+':'+"172.16."+`self.eth2.net.n`+"."+`self.eth2.n`+":255.255.255.0:"
if (self.gw and re.search("172\.16\."+`self.eth2.net`+".", self.gw)):
vdeline +=self.gw+":"
self.cmd.append(vdeline)
self.args = args
self.pop = None
topology.hosts.append(self)
self.routes = []
def start(self):
if self.pop:
return
for r in self.routes:
self.cmd.append(r)
self.cmd.append("-a")
self.cmd.append(self.args)
print self.cmd
self.pop = subprocess.Popen(self.cmd)
def cleanup():
try:
subprocess.call(["killall","vde_switch"])
subprocess.call(["killall","picoapp.elf"])
subprocess.call(["killall","wirefilter"])
os.unlink("/tmp/topology")
except:
pass
def loop():
while(True):
time.sleep(1)
sys.exit(0)
def sleep(n):
time.sleep(n)
def wait(x):
if (x is None):
print("start failed: "+x.cmd)
sys.exit(1)
while (x.pop.poll() == None):
time.sleep(1)
print "Goodbye"
sys.exit(0)
def start(T):
print "Calculating routes.."
for n in T.nets:
for h in n.hosts:
h.add_routes(T)
print "Done!"
print "Starting up..."
for n in T.nets:
for h in n.hosts:
h.start()
try:
os.mkdir("/tmp/topology/")
except:
pass
cleanup()