Revision c09f8d98

View differences:

network_builder.py
1

  
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:
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

  
56
class GraphNet(PowerNet):
57
    def __init__(self,edges_file,draw=True,**params):
58
        super(GraphNet,self).__init__(**params)
59
        info("\nReading "+edges_file+"\n")
60

  
61
        g = loadGraph(edges_file, connected=True)
62

  
63
        nodeCounter = 0
64
        nodeMap = {}
65
        for name in g.nodes():
66
            nodeMap[name] = "h"+str(name)+"_"+str(nodeCounter)
67
            nodeCounter += 1
68

  
69
        self.gg = nx.relabel_nodes(g,nodeMap)
70

  
71
        self.hosts_port = {}
72

  
73
        # add nodes
74
        for n in self.gg.nodes():
75
            self.addHost(n)
76
            self.hosts_port[n] = 1 
77

  
78
        # add edges
79
        for e in self.gg.edges(data=True):
80
            # 10 Mbps, 5ms delay, 10% loss, 1000 packet queue
81
            # htp: Hierarchical Token Bucket rate limiter
82
#            quality_params = {"bw":10,"delay":'5ms', "loss":100-100.0/e[2]['weight'], "use_htb":True}
83
            quality_params = {}
84
            quality_params["bw"] = 10
85
#            quality_params["delay"] = '5ms'
86
#            quality_params["loss"] = 100-100.0/e[2]['weight']
87
            quality_params["use_htb"] = True
88
            self.insertLink(self.get(e[0]),self.get(e[1]),quality_params)
89

  
90
        if draw:
91
            showGraph(self.gg)
92

  
93
    def pickHostAddrPort(self, node):
94
        port = self.hosts_port[node.name]
95
        addr = "10.0."+node.name.split('_')[-1]+"."+str(port)+"/8"
96
        self.hosts_port[node.name] += 1
97
        return addr,port
98

  
99
    def insertLink(self, n1, n2, quality_params={}):
100
        addr1, port1 = self.pickHostAddrPort(n1)
101
        addr2, port2 = self.pickHostAddrPort(n2)
102

  
103
        self.addLink(n1, n2,  \
104
                port1 = port1, \
105
                port2 = port2, \
106
                params1=dict([('ip',addr1)] + quality_params.items()), \
107
                params2=dict([('ip',addr2)] + quality_params.items()) \
108
                )
109

  
110
    def setShortestRoutes(self):
111
        paths = nx.shortest_path(self.gg,weight='weight')
112
        for node1 in paths.keys():
113
            host1 = self.get(node1)
114
            debug("Starting node: "+node1+'\n')
115
            debug("\tpaths: "+str(paths[node1])+'\n')
116
            for node2 in paths[node1].keys():
117
                if node2 != node1 :
118
                    if len(paths[node1][node2])>2:
119
                        debug("\tDestination node: "+node2+'\n')
120
                        nextHop = self.get(paths[node1][node2][1])
121
                        debug("\tNextHop node: "+nextHop.name+'\n')
122
                        dsts = self.getNodeAddrs(self.get(node2))
123
                        intfs = host1.connectionsTo(nextHop)
124
                        nextAddrs = [ couple[1].ip for couple in intfs ]
125
                        rintf = intfs[0][0] # WARNING we just consider one link
126
                        for dst in dsts:
127
                            for addr in nextAddrs:
128
                                host1.cmd("ip route add "+dst+" via "+addr+" dev "+rintf.name)
129
                                debug("\tip route add "+dst+" via "+addr+'\n')
130
                    else :
131
                        host2 = self.get(node2)
132
                        intfs = [ couple[0] for couple in host1.connectionsTo(host2) ]
133
                        rintf = intfs[0] # WARNING we just consider one link
134
                        raddrs = self.getNodeAddrs(host2)
135
                        for addr in raddrs:
136
                            host1.setHostRoute(addr,rintf.name)
137

  
138

  
test_code/__init__.py
1
import os
2
import glob
3
modules = glob.glob(os.path.dirname(__file__)+"/*.py")
4
__all__ = [ os.path.basename(f)[:-3] for f in modules]
test_code/peerstreamer.py
1

  
2
import sys
3
sys.path.append('../')
4
from network_builder import *
5
from os import kill, path, makedirs
6
from matplotlib.pyplot import ion
7
from random import sample, randint
8

  
9
from test_generic import *
10

  
11
class PSTest(MininetTest):
12
    def __init__(self,mininet,duration=300):
13
        super(PSTest,self).__init__(mininet)
14
        self.source = None
15
        self.hosts = []
16
        self.duration = duration
17
        self.prefix = ''
18

  
19
    def setPrefix(self,name):
20
        self.prefix = str(name)+'_'+str(self.duration)+'_'+str(len(self.hosts)+1)+'hosts/' 
21
        if not path.exists(self.prefix):
22
                makedirs(self.prefix)
23

  
24
    def launchPS(self,host,params,stdout,stderr):
25
        cmd = "./streamer"
26
        params['-c'] = '38'
27
#        params['-M'] = '5'
28
#        params['-O'] = '3'
29
        params['--chunk_log'] = ''
30
        params['>'] = stdout
31
        params['2>'] = stderr
32
        return self.bgCmd(host,True,cmd,*reduce(lambda x, y: x + y, params.items()))
33

  
34
    def launchPeer(self,host,source,source_port=7000):
35
        idps = randint(0,100)
36
        logfile = self.prefix+host.name.split('_')[0]+"-"+str(idps)+"_peerstreamer_normal_$(date +%s).log"
37
        params = {}
38
        params['-i'] = source.defaultIntf().ip
39
        params['-p'] = str(source_port)
40
        params['-P'] = str(randint(4000,8000))
41
        return self.launchPS(host,params,'/dev/null',logfile)
42

  
43
    def launchSource(self,host,chunk_mult=1,source_port=7000):
44
        idps = randint(0,100)
45
        video_file = "bunny.ts,loop=1"
46
        logfile = self.prefix+host.name.split('_')[0]+"-"+str(idps)+"_source_normal_$(date +%s).log"
47
        params = {}
48
        params['-I'] = host.defaultIntf().name
49
        params['-P'] = str(source_port)
50
        params['-f'] = video_file
51
        params['-m'] = str(chunk_mult)
52
        return self.launchPS(host,params,'/dev/null',logfile)
53

  
54
    def runTest(self):
55
        info("*** Launching PeerStreamer test\n")
56
        info("Data folder: "+self.prefix+"\n")
57
        if self.source:
58
            self.launchSource(self.source)
59

  
60
        for h in self.hosts:
61
            self.launchPeer(h,self.source)
62
        info("Waiting completion...\n")
63
        sleep(self.duration)
64

  
65
        self.killAll()
66

  
67
class PSHostsTest(PSTest):
68
    def __init__(self,mininet,source_name,peer_names,duration=300,name=None):
69
        super(PSHostsTest,self).__init__(mininet,duration=duration)
70
        self.source = mininet.get(source_name)
71
        for n in peer_names:
72
            self.hosts.append(mininet.get(n))
73
        self.setPrefix(name)
74

  
75
class PSRandomTest(PSTest):
76
    def __init__(self,mininet,duration=300,num_peers=5,name=None):
77
        super(PSRandomTest,self).__init__(mininet,duration)
78
        self.hosts = self.getHostSample(num_peers)
79
        if len(self.hosts) > 0:
80
            self.source = self.hosts.pop()
81
        self.setPrefix(name)
82

  
83

  
test_generic.py
1

  
2
import signal
3
from random import sample
4
from psutil import Process
5
from time import sleep
6

  
7
from mininet.log import info, error, debug, output
8

  
9
class MininetTest(object):
10
    def __init__(self,mininet):
11
        self.net = mininet
12
        self.pendingProc = {} 
13
    
14
    def getHostSample(self,num):
15
        hosts = sample(self.net.values(),num)
16
        return hosts[:num]
17

  
18
    def bgCmd(self,host,force_multiple_processes,*args):
19
        # here it's a little workaround for tracing the resulting pid
20
        # it launch the new process using the mininet interface
21
        # but it check the newly created process id using psutil
22
        host_proc = Process(host.pid)
23
        host_ps = set(host_proc.get_children())
24
        debug("Sending cmd: \n\t"+str(args)+"\n")
25
        if force_multiple_processes:
26
            host.waiting = False
27
        host.sendCmd(*(args+("&",)))
28
        sleep(0.5)
29
        try :
30
            pid = (set(host_proc.get_children()).difference(host_ps)).pop().pid
31
            info("BGProcess: "+str(pid)+"; ")
32
            self.pendingProc[pid] = host
33
        except:
34
            info("*** Unable to launch command:\n\t "+str(args))
35
            return None
36
        return pid
37

  
38
    def sendSig(self,pid,sig=signal.SIGTERM):
39
        try:
40
            info("Killing BGProcess: "+str(pid)+"; ")
41
            kill( pid, sig )
42
        except OSError:
43
            error("Error while killing process "+str(pid))
44
            pass
45

  
46
    def killAll(self):
47
        for pid in self.pendingProc.keys():
48
            self.sendSig(pid,signal.SIGKILL)
49
            self.pendingProc[pid].monitor() # wait exiting
50
        self.pendingProc.clear()
51

  
52

  
wcn_simulator.py
1 1
#!/usr/bin/env python
2 2
import sys
3
sys.path.append('community_networks_analysis')
4 3

  
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
4
sys.path.append('test_code')
12 5

  
13
import networkx as nx
14
from time import sleep, time
15
from os import kill, path, makedirs
16
from psutil import Process
17
import signal
18
from matplotlib.pyplot import ion
19
from random import sample, randint
6
from network_builder import *
7
from test_code import *
20 8

  
21
from gengraphs import loadGraph
22
from misclibs import showGraph
9
from os import path
10
from time import time
23 11

  
24
from parameters_parser import parameters
25

  
26
sys.path.append("community_networks_analysis/")
27

  
28
class PowerNet(Mininet):
29
    def __init__(self,**params):
30
        if 'controller' not in params.keys():
31
            params['controller'] = OVSController
32
        if 'host' not in params.keys():
33
            params['host'] = CPULimitedHost
34
        if 'link' not in params.keys():
35
            params['link'] = TCLink
36
        super(PowerNet,self).__init__(**params)
37

  
38
    def enableForwarding(self):
39
        for node in self.values():
40
            node.cmd("echo 1 > /proc/sys/net/ipv4/ip_forward")
41

  
42
    def setNeighboursRoutes(self):
43
        for node in self.values():
44
            for intf in node.intfList():
45
                if intf.link:
46
                    rintf = self.remoteIntf(intf)
47
                    raddrs = self.getNodeAddrs(rintf.node)
48
                    for addr in raddrs:
49
                        node.setHostRoute(addr,intf.name)
50

  
51
    def getNodeAddrs(self,node):
52
        r = []
53
        for intf in node.intfList():
54
            if intf.link:
55
                r.append(intf.ip)
56
        return r
57

  
58
    def remoteIntf(self,intf):
59
        if intf.link:
60
            intfs = [ intf.link.intf1, intf.link.intf2 ]
61
            intfs.remove(intf)
62
            return intfs[0]
63
        return None
64

  
65

  
66
class GraphNet(PowerNet):
67
    def __init__(self,edges_file,draw=True,**params):
68
        super(GraphNet,self).__init__(**params)
69
        info("\nReading "+edges_file+"\n")
70

  
71
        g = loadGraph(edges_file, connected=True)
72

  
73
        nodeCounter = 0
74
        nodeMap = {}
75
        for name in g.nodes():
76
            nodeMap[name] = "h"+str(name)+"_"+str(nodeCounter)
77
            nodeCounter += 1
78

  
79
        self.gg = nx.relabel_nodes(g,nodeMap)
80

  
81
        self.hosts_port = {}
82

  
83
        # add nodes
84
        for n in self.gg.nodes():
85
            self.addHost(n)
86
            self.hosts_port[n] = 1 
87

  
88
        # add edges
89
        for e in self.gg.edges(data=True):
90
            # 10 Mbps, 5ms delay, 10% loss, 1000 packet queue
91
            # htp: Hierarchical Token Bucket rate limiter
92
#            quality_params = {"bw":10,"delay":'5ms', "loss":100-100.0/e[2]['weight'], "use_htb":True}
93
            quality_params = {}
94
            quality_params["bw"] = 10
95
#            quality_params["delay"] = '5ms'
96
#            quality_params["loss"] = 100-100.0/e[2]['weight']
97
            quality_params["use_htb"] = True
98
            self.insertLink(self.get(e[0]),self.get(e[1]),quality_params)
99

  
100
        if draw:
101
            showGraph(self.gg)
102

  
103
    def pickHostAddrPort(self, node):
104
        port = self.hosts_port[node.name]
105
        addr = "10.0."+node.name.split('_')[-1]+"."+str(port)+"/8"
106
        self.hosts_port[node.name] += 1
107
        return addr,port
108 12

  
109
    def insertLink(self, n1, n2, quality_params={}):
110
        addr1, port1 = self.pickHostAddrPort(n1)
111
        addr2, port2 = self.pickHostAddrPort(n2)
112

  
113
        self.addLink(n1, n2,  \
114
                port1 = port1, \
115
                port2 = port2, \
116
                params1=dict([('ip',addr1)] + quality_params.items()), \
117
                params2=dict([('ip',addr2)] + quality_params.items()) \
118
                )
119

  
120
    def setShortestRoutes(self):
121
        paths = nx.shortest_path(self.gg,weight='weight')
122
        for node1 in paths.keys():
123
            host1 = self.get(node1)
124
            debug("Starting node: "+node1+'\n')
125
            debug("\tpaths: "+str(paths[node1])+'\n')
126
            for node2 in paths[node1].keys():
127
                if node2 != node1 :
128
                    if len(paths[node1][node2])>2:
129
                        debug("\tDestination node: "+node2+'\n')
130
                        nextHop = self.get(paths[node1][node2][1])
131
                        debug("\tNextHop node: "+nextHop.name+'\n')
132
                        dsts = self.getNodeAddrs(self.get(node2))
133
                        intfs = host1.connectionsTo(nextHop)
134
                        nextAddrs = [ couple[1].ip for couple in intfs ]
135
                        rintf = intfs[0][0] # WARNING we just consider one link
136
                        for dst in dsts:
137
                            for addr in nextAddrs:
138
                                host1.cmd("ip route add "+dst+" via "+addr+" dev "+rintf.name)
139
                                debug("\tip route add "+dst+" via "+addr+'\n')
140
                    else :
141
                        host2 = self.get(node2)
142
                        intfs = [ couple[0] for couple in host1.connectionsTo(host2) ]
143
                        rintf = intfs[0] # WARNING we just consider one link
144
                        raddrs = self.getNodeAddrs(host2)
145
                        for addr in raddrs:
146
                            host1.setHostRoute(addr,rintf.name)
147

  
148

  
149
class MininetTest(object):
150
    def __init__(self,mininet):
151
        self.net = mininet
152
        self.pendingProc = {} 
153
    
154
    def getHostSample(self,num):
155
        hosts = sample(self.net.values(),num)
156
        return hosts[:num]
157

  
158
    def bgCmd(self,host,force_multiple_processes,*args):
159
        # here it's a little workaround for tracing the resulting pid
160
        # it launch the new process using the mininet interface
161
        # but it check the newly created process id using psutil
162
        host_proc = Process(host.pid)
163
        host_ps = set(host_proc.get_children())
164
        debug("Sending cmd: \n\t"+str(args)+"\n")
165
        if force_multiple_processes:
166
            host.waiting = False
167
        host.sendCmd(*(args+("&",)))
168
        sleep(0.5)
169
        try :
170
            pid = (set(host_proc.get_children()).difference(host_ps)).pop().pid
171
            info("BGProcess: "+str(pid)+"; ")
172
            self.pendingProc[pid] = host
173
        except:
174
            info("*** Unable to launch command:\n\t "+str(args))
175
            return None
176
        return pid
177

  
178
    def sendSig(self,pid,sig=signal.SIGTERM):
179
        try:
180
            info("Killing BGProcess: "+str(pid)+"; ")
181
            kill( pid, sig )
182
        except OSError:
183
            error("Error while killing process "+str(pid))
184
            pass
185

  
186
    def killAll(self):
187
        for pid in self.pendingProc.keys():
188
            self.sendSig(pid,signal.SIGKILL)
189
            self.pendingProc[pid].monitor() # wait exiting
190
        self.pendingProc.clear()
191

  
192
class PSTest(MininetTest):
193
    def __init__(self,mininet,duration=300):
194
        super(PSTest,self).__init__(mininet)
195
        self.source = None
196
        self.hosts = []
197
        self.duration = duration
198
        self.prefix = ''
199

  
200
    def setPrefix(self,name):
201
        self.prefix = str(name)+'_'+str(self.duration)+'_'+str(len(self.hosts)+1)+'hosts/' 
202
        if not path.exists(self.prefix):
203
                makedirs(self.prefix)
204

  
205
    def launchPS(self,host,params,stdout,stderr):
206
        cmd = "./streamer"
207
        params['-c'] = '38'
208
#        params['-M'] = '5'
209
#        params['-O'] = '3'
210
        params['--chunk_log'] = ''
211
        params['>'] = stdout
212
        params['2>'] = stderr
213
        return self.bgCmd(host,True,cmd,*reduce(lambda x, y: x + y, params.items()))
214

  
215
    def launchPeer(self,host,source,source_port=7000):
216
        idps = randint(0,100)
217
        logfile = self.prefix+host.name.split('_')[0]+"-"+str(idps)+"_peerstreamer_normal_$(date +%s).log"
218
        params = {}
219
        params['-i'] = source.defaultIntf().ip
220
        params['-p'] = str(source_port)
221
        params['-P'] = str(randint(4000,8000))
222
        return self.launchPS(host,params,'/dev/null',logfile)
223

  
224
    def launchSource(self,host,chunk_mult=1,source_port=7000):
225
        idps = randint(0,100)
226
        video_file = "bunny.ts,loop=1"
227
        logfile = self.prefix+host.name.split('_')[0]+"-"+str(idps)+"_source_normal_$(date +%s).log"
228
        params = {}
229
        params['-I'] = host.defaultIntf().name
230
        params['-P'] = str(source_port)
231
        params['-f'] = video_file
232
        params['-m'] = str(chunk_mult)
233
        return self.launchPS(host,params,'/dev/null',logfile)
234

  
235
    def runTest(self):
236
        info("*** Launching PeerStreamer test\n")
237
        info("Data folder: "+self.prefix+"\n")
238
        if self.source:
239
            self.launchSource(self.source)
240

  
241
        for h in self.hosts:
242
            self.launchPeer(h,self.source)
243
        info("Waiting completion...\n")
244
        sleep(self.duration)
245

  
246
        self.killAll()
247

  
248
class PSHostsTest(PSTest):
249
    def __init__(self,mininet,source_name,peer_names,duration=300,name=None):
250
        super(PSHostsTest,self).__init__(mininet,duration=duration)
251
        self.source = mininet.get(source_name)
252
        for n in peer_names:
253
            self.hosts.append(mininet.get(n))
254
        self.setPrefix(name)
13
from parameters_parser import parameters
255 14

  
256
class PSRandomTest(PSTest):
257
    def __init__(self,mininet,duration=300,num_peers=5,name=None):
258
        super(PSRandomTest,self).__init__(mininet,duration)
259
        self.hosts = self.getHostSample(num_peers)
260
        if len(self.hosts) > 0:
261
            self.source = self.hosts.pop()
262
        self.setPrefix(name)
263 15

  
264 16
class conf(parameters):
265 17
    def checkCorrectness(self):
......
288 40
    net.enableForwarding()
289 41
    net.setShortestRoutes()
290 42
#    CLI(net)
291
    test_name = P.getParam("testName")+str(int(time()))
43
    test_name = P.getParam("testName")+"_"+str(int(time()))
292 44
    for i in range(1):
293 45
        info("+++++++ Round: "+str(i+1) + '\n')
294 46
        #test = PSRandomTest(net,duration=6,name=test_name,num_peers=2)
295
        test = PSHostsTest(net, 'h0_0', ['h1_1','h1_1','h2_2'],
47
        test = peerstreamer.PSHostsTest(net, 'h0_0', ['h1_1','h1_1','h2_2'],
296 48
                duration = 600, name = test_name)
297 49
        test.runTest()
298 50
      #  sleep(60)

Also available in: Unified diff