1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
import yaml, os
import numpy as np
class YAMLPlatformFile:
def __init__(self, file_path):
self.file_path=file_path
self.default={
"breakpoints": [],
"breakpoints_every": None,
"debug": False,
"interferences": True,
"node_count": 0,
"implementations": [],
"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.parse_error("platform file has no nodes section")
##### Interfaces
if "interfaces" in self.platform:
self.parse_interfaces()
else:
self.parse_error("platform file has no interfaces section")
def parse_error(self,msg):
raise Exception("Fail to parse platform file \""+self.file_path+"\": "+msg)
def parse_link_range(self,r):
elt=r.split("-")
if len(elt) == 2:
return(range(int(elt[0]),int(elt[1])))
else:
return([int(elt[0])])
def parse_link_bw(self,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 parse_link_lat(self,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)
def parse_link(self,link):
words=link.split()
if len(words) == 4:
return((
self.parse_link_range(words[0]),
self.parse_link_bw(words[1]),
self.parse_link_lat(words[2]),
self.parse_link_range(words[3])))
elif len(words) == 2:
return((
range(0,self.default["node_count"]),
self.parse_link_bw(words[0]),
self.parse_link_lat(words[1]),
range(0,self.default["node_count"])))
return(None)
def parse_interfaces(self):
interfaces=self.platform["interfaces"]
node_count=self.default["node_count"]
for i in interfaces:
is_wired=interfaces[i]["wireless"]
links=list()
if type(interfaces[i]["links"]) == list:
for link in interfaces[i]["links"]:
links.append(self.parse_link(link))
else:
links.append(self.parse_link(interfaces[i]["links"]))
##### Create network matrix
for link in links:
BW=np.full((node_count,node_count),0)
LAT=np.full((node_count,node_count),0)
for n1 in link[0]:
for n2 in link[3]:
BW[n1][n2]=link[1]
LAT[n1][n2]=link[2]
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.parse_error("node count should be a number")
self.default["node_count"]=nodes["count"]
if "implementations" in nodes:
if type(nodes["implementations"]) != list:
self.parse_error("nodes implementations should be a list of file path")
for file in nodes["implementations"]:
if not os.path.exists(file):
self.parse_error("File "+file+ " not found")
path, extension = os.path.splitext(file)
if extension != ".py":
self.parse_error("File "+file+" must be a python file")
self.default["implementations"].append(path)
count = len(nodes["implementations"])
if count > 1 and count != self.default["node_count"]:
self.parse_error("If more than one implementation is specified, each node implementation should be provided ("+str(self.default["node_count"])+" in total)")
def parse_general(self):
general=self.platform["general"]
if "breakpoints" in general:
if type(general["breakpoints"]) != list:
self.parse_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.parse_error("breakpoints_every should be a number")
self.default["breakpoints_every"]=general["breakpoints_every"]
if "debug" in general:
if type(general["debug"]) != bool:
self.parse_error("debug should be on or off")
self.default["debug"]=general["debug"]
if "interferences" in general:
if type(general["interferences"]) != bool:
self.parse_error("interferences should be on or off")
self.default["interferences"]=general["interferences"]
|