summaryrefslogtreecommitdiff
path: root/esds/helpers/platform.py
diff options
context:
space:
mode:
Diffstat (limited to 'esds/helpers/platform.py')
-rw-r--r--esds/helpers/platform.py226
1 files changed, 0 insertions, 226 deletions
diff --git a/esds/helpers/platform.py b/esds/helpers/platform.py
deleted file mode 100644
index c236e60..0000000
--- a/esds/helpers/platform.py
+++ /dev/null
@@ -1,226 +0,0 @@
-
-import yaml, os, importlib
-import numpy as np
-from esds import Simulator
-
-class UnitsParser:
- def node_range(r,limit):
- if r == "all":
- return(range(0,limit))
- r=r.replace("@",str(limit-1))
- elt=r.split("-")
- if len(elt) == 2:
- min = int(elt[0])
- max = int(elt[1])
- if min < 0 or max >= limit:
- raise Exception("Outside of range limit [0-"+str(limit)+"]")
- return(range(min,max+1))
- else:
- return(list(map(int, r.split(","))))
-
- def bandwidth(bw):
- for i,c in enumerate(bw):
- if not c.isdigit() and c != ".":
- break
- number=float(bw[:i])
- unit=bw[i:]
- number=number*1000 if unit == "Mbps" else number
- number=number*1000*8 if unit == "MBps" else number
- number=number*100 if unit == "kbps" else number
- number=number*100*8 if unit == "kBps" else number
- number=number*8 if unit == "Bps" else number
- return(number)
-
- def latency(lat):
- for i,c in enumerate(lat):
- if not c.isdigit() and c != ".":
- break
- number=float(lat[:i])
- unit=lat[i:]
- number=number*60 if unit in ["m","M"] else number
- number=number*3600 if unit in ["h","H"] else number
- number=number/1000 if unit in ["ms","MS"] else number
- return(number)
-
-class YAMLPlatformFile:
-
- def __init__(self, file_path):
- self.file_path=file_path
- self.default={
- "breakpoints": [],
- "breakpoints_every": None,
- "breakpoints_file": None,
- "breakpoints_callback": lambda s:None,
- "debug": False,
- "debug_file": "./esds.debug",
- "interferences": True,
- "node_count": 0,
- "implementations": [],
- "arguments": [],
- "interfaces": dict()
- }
-
- with open(file_path) as f:
- self.platform = yaml.load(f, Loader=yaml.FullLoader)
-
- ##### General
- if "general" in self.platform:
- self.parse_general()
- ##### Nodes
- if "nodes" in self.platform:
- self.parse_nodes()
- else:
- self.parsing_error("platform file has no nodes section")
- ##### Interfaces
- if "interfaces" in self.platform:
- self.parse_interfaces()
- else:
- self.parsing_error("platform file has no interfaces section")
-
- ##### Sanity checks
- if None in self.default["implementations"]:
- self.parsing_error("Some nodes do not have assigned implementation")
-
- def parsing_error(self,msg):
- raise Exception("Fail to parse platform file \""+self.file_path+"\": "+msg)
-
- def parse_link(self,link):
- words=link.split()
- if len(words) == 4:
- return((
- UnitsParser.node_range(words[0],self.default["node_count"]),
- UnitsParser.bandwidth(words[1]),
- UnitsParser.latency(words[2]),
- UnitsParser.node_range(words[3],self.default["node_count"])))
- self.parsing_error("Invalide link \""+link+"\"")
-
- def parse_txperf(self,txperf):
- elts=txperf.split()
- return((UnitsParser.node_range(elts[0],self.default["node_count"]),UnitsParser.bandwidth(elts[1]),UnitsParser.latency(elts[2])))
-
- def parse_interfaces(self):
- interfaces=self.platform["interfaces"]
- node_count=self.default["node_count"]
- for i in interfaces:
- if interfaces[i]["type"] not in ["wireless","wired"]:
- self.parsing_error("Invalid interface type \""+interfaces[i]["type"]+"\"")
- is_wired=interfaces[i]["type"] == "wired"
- links=list()
- if type(interfaces[i]["links"]) != list:
- self.parsing_error("Invalide type of links in interface "+i)
- for link in interfaces[i]["links"]:
- links.append(self.parse_link(link))
- ##### Create network matrix
- BW=np.full((node_count,node_count),0)
- LAT=np.full((node_count,node_count),0)
- for link in links:
- for n1 in link[0]:
- for n2 in link[3]:
- BW[n1][n2]=link[1]
- LAT[n1][n2]=link[2]
-
- ##### Set txperfs for wireless interfaces
- if not is_wired:
- txperfs=interfaces[i]["txperfs"]
- for txperf in txperfs:
- p=self.parse_txperf(txperf)
- for node in p[0]:
- BW[node][node]=p[1]
- LAT[node][node]=p[2]
- if (BW.diagonal()==0).any():
- self.parsing_error("Not all node have a txpref on the wireless interface "+i)
-
- self.default["interfaces"][i]={
- "is_wired": is_wired,
- "bandwidth": BW,
- "latency": LAT
- }
-
- def parse_nodes(self):
- nodes=self.platform["nodes"]
- if "count" in nodes:
- if not str(nodes["count"]).isnumeric():
- self.parsing_error("node count should be a number")
- self.default["node_count"]=nodes["count"]
- else:
- self.parsing_error("node count not provided")
- if "implementations" in nodes:
- if type(nodes["implementations"]) != list:
- self.parsing_error("nodes implementations should be a list of file path")
- self.default["implementations"]=[None]*self.default["node_count"]
- for impl in nodes["implementations"]:
- words=impl.split()
- r=UnitsParser.node_range(words[0],self.default["node_count"])
- file="".join(words[1:])
- if not os.path.exists(file):
- self.parsing_error("File "+file+ " not found")
- path, extension = os.path.splitext(file)
- if extension != ".py":
- self.parsing_error("File "+file+" must be a python file")
- for node in r:
- self.default["implementations"][node]=path
- count = len(nodes["implementations"])
- if count > 1 and count != self.default["node_count"]:
- self.parsing_error("If more than one implementation is specified, each node implementation should be provided ("+str(self.default["node_count"])+" in total)")
- else:
- self.parsing_error("node implementation not provided")
- ##### Nodes arguments
- self.default["arguments"]=[None]*self.default["node_count"]
- if "arguments" in nodes:
- args=nodes["arguments"]
- for r in args:
- for node_id in UnitsParser.node_range(r,self.default["node_count"]):
- self.default["arguments"][node_id]=args[r]
-
- def parse_general(self):
- general=self.platform["general"]
- if "breakpoints" in general:
- if type(general["breakpoints"]) != list:
- self.parsing_error("breakpoints should be a list of number")
- self.default["breakpoints"]=general["breakpoints"]
- if "breakpoints_every" in general:
- if not str(general["breakpoints_every"]).isnumeric():
- self.parsing_error("breakpoints_every should be a number")
- self.default["breakpoints_every"]=general["breakpoints_every"]
- if "breakpoints_callback" in general:
- cb=general["breakpoints_callback"]
- file=cb["file"]
- path, ext=os.path.splitext(file)
- if not os.path.exists(file):
- self.parsing_error("File "+file+ " not found")
- path, extension = os.path.splitext(file)
- if extension != ".py":
- self.parsing_error("File "+file+" must be a python file")
- self.default["breakpoints_file"]=cb["file"]
- self.default["breakpoints_callback"]=cb["callback"]
- if "debug" in general:
- if type(general["debug"]) != bool:
- self.parsing_error("debug should be on or off")
- self.default["debug"]=general["debug"]
- if "debug_file" in general:
- self.default["debug_file"]=general["debug_file"]
- if "interferences" in general:
- if type(general["interferences"]) != bool:
- self.parsing_error("interferences should be on or off")
- self.default["interferences"]=general["interferences"]
-
- def run(self):
- ##### First load callback from file if any
- if self.default["breakpoints_file"] != None:
- module, ext=os.path.splitext(self.default["breakpoints_file"])
- imported=importlib.import_module(module)
- callback=getattr(imported, self.default["breakpoints_callback"])
- self.default["breakpoints_callback"]=callback
- ##### Create simulator
- simulator=Simulator(self.default["interfaces"])
- for node_id in range(0,self.default["node_count"]):
- simulator.create_node(self.default["implementations"][node_id], args=self.default["arguments"][node_id])
- ##### Run simulation
- simulator.run(
- breakpoints=self.default["breakpoints"],
- breakpoints_every=self.default["breakpoints_every"],
- breakpoint_callback=self.default["breakpoints_callback"],
- debug=self.default["debug"],
- debug_file_path=self.default["debug_file"],
- interferences=self.default["interferences"])
- \ No newline at end of file