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