lorenzoghiroms / network_builder.py @ master
History | View | Annotate | Download (8.44 KB)
1 |
import re |
---|---|
2 |
import sys |
3 |
import networkx as nx |
4 |
|
5 |
from mininet.net import Mininet |
6 |
from mininet.log import setLogLevel |
7 |
from mininet.node import OVSController |
8 |
from mininet.cli import CLI |
9 |
from mininet.log import info, error, debug, output |
10 |
from mininet.node import CPULimitedHost |
11 |
from mininet.link import TCLink |
12 |
|
13 |
sys.path.append('community_networks_analysis')
|
14 |
|
15 |
from gengraphs import loadGraph |
16 |
from misclibs import showGraph |
17 |
|
18 |
class PowerNet(Mininet): |
19 |
def __init__(self,**params): |
20 |
if 'controller' not in params.keys(): |
21 |
params['controller'] = OVSController
|
22 |
if 'host' not in params.keys(): |
23 |
params['host'] = CPULimitedHost
|
24 |
if 'link' not in params.keys(): |
25 |
params['link'] = TCLink
|
26 |
super(PowerNet,self).__init__(**params) |
27 |
|
28 |
def enableForwarding(self): |
29 |
for node in self.values(): |
30 |
node.cmd("echo 1 > /proc/sys/net/ipv4/ip_forward")
|
31 |
|
32 |
def setNeighboursRoutes(self): |
33 |
for node in self.values(): |
34 |
for intf in node.intfList(): |
35 |
if intf.link:
|
36 |
rintf = self.remoteIntf(intf)
|
37 |
raddrs = self.getNodeAddrs(rintf.node)
|
38 |
for addr in raddrs: |
39 |
node.setHostRoute(addr,intf.name) |
40 |
|
41 |
def getNodeAddrs(self,node): |
42 |
r = [] |
43 |
for intf in node.intfList(): |
44 |
if intf.link and intf.ip: |
45 |
r.append(intf.ip) |
46 |
return r
|
47 |
|
48 |
def remoteIntf(self,intf): |
49 |
if intf.link:
|
50 |
intfs = [ intf.link.intf1, intf.link.intf2 ] |
51 |
intfs.remove(intf) |
52 |
return intfs[0] |
53 |
return None |
54 |
|
55 |
def getLinks(self): |
56 |
# returns the hosts couples representing the links
|
57 |
links = [] |
58 |
hosts = self.values()
|
59 |
for h in hosts: |
60 |
intfs = h.intfList() |
61 |
for intf in intfs: |
62 |
if intf.link != None and intf.link not in links: |
63 |
links.append(intf.link) |
64 |
return links
|
65 |
|
66 |
def linkSentPackets(self,link): |
67 |
pstr1 = link.intf1.node.cmd("ifconfig ",link.intf1.name ,"| grep -Eo 'TX packets:[0-9]+' | cut -d':' -f 2") |
68 |
pstr2 = link.intf2.node.cmd("ifconfig ",link.intf2.name ,"| grep -Eo 'TX packets:[0-9]+' | cut -d':' -f 2") |
69 |
packets1 = int(pstr1.split("\n")[0]) |
70 |
packets2 = int(pstr2.split("\n")[0]) |
71 |
return packets1+packets2
|
72 |
|
73 |
def linkSentBytes(self,link): |
74 |
pstr1 = link.intf1.node.cmd("ifconfig ",link.intf1.name ,"| grep -Eo 'TX bytes:[0-9]+' | cut -d':' -f 2") |
75 |
pstr2 = link.intf2.node.cmd("ifconfig ",link.intf2.name ,"| grep -Eo 'TX bytes:[0-9]+' | cut -d':' -f 2") |
76 |
bytes1 = int(pstr1.split("\n")[0].split(" ")[0]) |
77 |
bytes2 = int(pstr2.split("\n")[0].split(" ")[0]) |
78 |
return bytes2+bytes1
|
79 |
|
80 |
def hostSentPackets(self,host): |
81 |
sent_packets = 0
|
82 |
sent_bytes = 0
|
83 |
intfs = host.intfNames() |
84 |
for intf in intfs: |
85 |
host.cmd("ifconfig",intf ,"| grep -Eo 'TX bytes:[0-9]+' | cut -d':' -f 2") |
86 |
sent_bytes += int(re.findall(r'\d+',host.cmd("ifconfig",intf ,"| grep -Eo 'TX bytes:[0-9]+' | cut -d':' -f 2"))[0]) |
87 |
sent_packets += int(re.findall(r'\d+',host.cmd("ifconfig ",intf ,"| grep -Eo 'TX packets:[0-9]+' | cut -d':' -f 2"))[0]) |
88 |
return (sent_packets,sent_bytes)
|
89 |
|
90 |
def hostReceivedPackets(self,host): |
91 |
received_packets = 0
|
92 |
received_bytes = 0
|
93 |
intfs = host.intfNames() |
94 |
for intf in intfs: |
95 |
received_bytes += int(re.findall(r'\d+',host.cmd("ifconfig "+intf +" | grep -Eo 'RX bytes:[0-9]+' | cut -d':' -f 2"))[0]) |
96 |
received_packets += int(re.findall(r'\d+',host.cmd("ifconfig "+intf +" | grep -Eo 'RX packets:[0-9]+' | cut -d':' -f 2"))[0]) |
97 |
return (received_packets,received_bytes)
|
98 |
|
99 |
def sentPackets(self): |
100 |
# if you experience assertion errors, you should
|
101 |
# try to make sleep the mininet thread for a second
|
102 |
sent_packets = 0
|
103 |
sent_bytes = 0
|
104 |
hosts = self.values()
|
105 |
for h in hosts: |
106 |
p,b = self.hostSentPackets(h)
|
107 |
sent_packets += p |
108 |
sent_bytes += b |
109 |
return (sent_packets,sent_bytes)
|
110 |
|
111 |
class GraphNet(PowerNet): |
112 |
def __init__(self, edges_file, draw=True, **params): |
113 |
if "link_opts" in params.keys(): |
114 |
self.link_opts = params["link_opts"] |
115 |
del params["link_opts"] |
116 |
|
117 |
super(GraphNet, self).__init__(**params) |
118 |
info("\nReading "+edges_file+"\n") |
119 |
|
120 |
g = loadGraph(edges_file, connected=True)
|
121 |
|
122 |
nodeCounter = 0
|
123 |
nodeMap = {} |
124 |
# mininet bails if host names are longer than 10 chars
|
125 |
max_name_len = 10 - len(str(len(g))) - 2 |
126 |
for name in g.nodes(): |
127 |
# remove unprintable chars from name
|
128 |
nodeMap[name] = "h" + filter(str.isalnum, str(name))[-max_name_len:]\ |
129 |
+ "_" + str(nodeCounter) |
130 |
nodeCounter += 1
|
131 |
|
132 |
self.gg = nx.relabel_nodes(g, nodeMap)
|
133 |
|
134 |
self.hosts_port = {}
|
135 |
|
136 |
# add nodes
|
137 |
for n in self.gg.nodes(): |
138 |
self.addHost(n)
|
139 |
self.hosts_port[n] = 1 |
140 |
|
141 |
# add edges
|
142 |
for e in self.gg.edges(data=True): |
143 |
# 10 Mbps, 5ms delay, 10% loss, 1000 packet queue
|
144 |
# htp: Hierarchical Token Bucket rate limiter
|
145 |
# quality_params = {"bw":10,"delay":'5ms', "loss":100-100.0/e[2]['weight'], "use_htb":True}
|
146 |
quality_params = {} |
147 |
quality_params.update(self.link_opts)
|
148 |
#quality_params["bw"] = 10
|
149 |
#quality_params["delay"] = '0.515ms'
|
150 |
#quality_params["jitter"] = '0.284ms'
|
151 |
#quality_params["delay_distribution"] = 'wifi_m0.515_s0.284'
|
152 |
if "loss" in quality_params.keys(): |
153 |
if quality_params["loss"] == "wifi_loss": |
154 |
quality_params["loss"] = \
|
155 |
100*((1-(1.0/(e[2]['weight'])))**7) |
156 |
else:
|
157 |
quality_params["loss"] = float(quality_params["loss"]) |
158 |
# the number of retransmisison (4) derives from a parameter of the
|
159 |
# 802.11 standard: dot11LongRetryLink (for Long Packets, are longer
|
160 |
# than dot11RTSthreshold)
|
161 |
quality_params["use_htb"] = True |
162 |
self.insertLink(self.get(e[0]), self.get(e[1]), quality_params) |
163 |
|
164 |
if draw:
|
165 |
showGraph(self.gg)
|
166 |
|
167 |
def pickHostAddrPort(self, node): |
168 |
port = self.hosts_port[node.name]
|
169 |
addr = "10.0."+node.name.split('_')[-1]+"."+str(port)+"/8" |
170 |
self.hosts_port[node.name] += 1 |
171 |
return addr, port
|
172 |
|
173 |
def insertLink(self, n1, n2, quality_params={}): |
174 |
addr1, port1 = self.pickHostAddrPort(n1)
|
175 |
addr2, port2 = self.pickHostAddrPort(n2)
|
176 |
self.addLink(n1, n2,
|
177 |
port1=port1, |
178 |
port2=port2, |
179 |
params1=dict([('ip', addr1)] + quality_params.items()), |
180 |
params2=dict([('ip', addr2)] + quality_params.items())) |
181 |
|
182 |
def setShortestRoutes(self): |
183 |
paths = nx.all_pairs_dijkstra_path(self.gg, weight='weight') |
184 |
for node1 in paths.keys(): |
185 |
host1 = self.get(node1)
|
186 |
debug("Starting node: "+node1+'\n') |
187 |
debug("\tpaths: "+str(paths[node1])+'\n') |
188 |
for node2 in paths[node1].keys(): |
189 |
if node2 != node1:
|
190 |
if len(paths[node1][node2]) > 2: |
191 |
debug("\tDestination node: "+node2+'\n') |
192 |
nextHop = self.get(paths[node1][node2][1]) |
193 |
debug("\tNextHop node: "+nextHop.name+'\n') |
194 |
dsts = self.getNodeAddrs(self.get(node2)) |
195 |
intfs = host1.connectionsTo(nextHop) |
196 |
nextAddrs = [ couple[1].ip for couple in intfs if couple[1].ip ] |
197 |
rintf = intfs[0][0] # WARNING we just consider one link |
198 |
for dst in dsts: |
199 |
for addr in nextAddrs: |
200 |
debug("\tip route add "+str(dst)+" via "+str(addr)+'\n') |
201 |
host1.cmd("ip route add "+dst+" via "+addr+" dev "+rintf.name) |
202 |
debug("\tip route add "+dst+" via "+addr+'\n') |
203 |
else :
|
204 |
host2 = self.get(node2)
|
205 |
intfs = [ couple[0] for couple in host1.connectionsTo(host2) ] |
206 |
rintf = intfs[0] # WARNING we just consider one link |
207 |
raddrs = self.getNodeAddrs(host2)
|
208 |
for addr in raddrs: |
209 |
host1.setHostRoute(addr,rintf.name) |
210 |
|
211 |
|