Statistics
| Branch: | Revision:

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