Statistics
| Branch: | Revision:

nepatest_popbabel / test_code / babel.py @ cafb67a9

History | View | Annotate | Download (11.8 KB)

1
import sys
2
sys.path.append('../')
3
sys.path.append('scripts/pop-routing/')
4
sys.path.append('../mylib/')
5
sys.path.append('mylib/')
6
import os
7
from network_builder import *
8
from random import sample, randint
9
import time
10
from dummyrouting import dummyRoutingRandomTest
11
from compute_theoretical_values import ComputeTheoreticalValues
12
import signal
13

    
14
import code
15

    
16
from test_generic import *
17

    
18

    
19
class BABELTest(dummyRoutingRandomTest):
20
    sigtoname=dict([[v,k] for k,v in signal.__dict__.items()])
21

    
22
    def launchBabel(self, runPrefix, host, cmdargs):
23

    
24
        hostname=host.name.split('_')[0]
25
        idps = randint(0,100)
26

    
27
        directory=self.prefix+runPrefix+"/"
28
        if not os.path.exists(directory):
29
            os.makedirs(directory)
30

    
31
        logfile = directory + "log" + hostname + ".log"
32
        exportCentFolder = directory + hostname
33
        topofile = directory + "topo" + hostname + ".json"
34
        neighfile = directory + "neigh" + hostname + ".json"
35

    
36
        iflist=host.intfList()
37
        intf_list = ' '.join([i.name for i in iflist])
38

    
39
        cmd = "babeld "+ intf_list
40
        params = {}
41
        params['-d'] = "0"
42
        params['-h'] = "1"
43
        params['-H'] = "1"
44
        params['-I']= directory+hostname+str(idps)+"pidf.pid"
45
        params['-L'] = logfile
46
        #params['-e'] = exportCentFolder+"_cdump.csv"
47
        params['-n'] = topofile
48
        #params['-N'] = neighfile
49
        params['-w'] = ""
50
        params.update(cmdargs)
51
        #info("### Launching babel on "+hostname+" ###\n")
52
        return self.bgCmd(host, True, cmd,
53
            *reduce(lambda x, y: x + y, params.items()) )
54

    
55
    def runTest(self):
56

    
57
        info("*** Launching BABEL test\n")
58
        info("Data folder: "+self.prefix+"\n")
59

    
60
        self.stopNodeList = []
61
        if self.stopAllNodes:
62
            self.stopNodeList = self.getCentrality()[:self.stopAllNodes]
63
        elif self.stopList:
64
            self.stopNodeList = [self.number_to_host(i) for i in self.stopList]
65
        run_ids = range(len(self.stopNodeList))
66

    
67
        if not run_ids:
68
            # do at least one run
69
            run_ids = [0]
70
        for run_id in run_ids:
71
            info("\nStarting run " + str(run_id) + "\n")
72
            if self.stopNodeList:
73
                self.nodeCrashed = self.stopNodeList.pop(0)
74
            else:
75
                self.nodeCrashed = None
76

    
77
            if not self.startRun(run_id=run_id, nodeCrashed=self.nodeCrashed):
78
                # sometimes processes are not killed in time, UDP
79
                # ports are still busy and next run can not
80
                # start correctly. I kill everything, wait some time, try
81
                # to restart. If something still goes wrong i stop
82
                # the emulation
83

    
84
                self.killAll()
85
                time.sleep(10)
86
                info("\nWARNING: run_id " + str(run_id) +
87
                     " could not start, retrying...\n")
88
                if not self.startRun(run_id):
89
                    error("\nERROR: run_id " + str(run_id) +
90
                          " could not start!" +
91
                          "please check the logs\n")
92
                    sys.exit(1)
93
            #eventDict={}
94
            eventDict = {
95
                self.startLog: ["start logging ",
96
                                self.sendSignal, {"sig": signal.SIGUSR1}
97
                                ],
98
                self.stopLog: ["stop logging ",
99
                               self.sendSignal, {"sig": signal.SIGUSR1}
100
                               ]
101
                }
102

    
103
            if self.nodeCrashed:
104
                eventDict[self.stopTime] = ["Stopping node(s) " + str(self.nodeCrashed) +
105
                                " at time " + str(self.stopTime) + "\n", 
106
                                self.sendSignal,
107
                                {"sig": signal.SIGQUIT,
108
                                 "hostName": self.nodeCrashed}
109
                                ]
110

    
111

    
112
            eventList = []
113
            relativeTime = 0
114
            for e in sorted(eventDict.keys()):
115
                if e > 0:
116
                    data = eventDict[e]
117
                    eventList.append([e - relativeTime] + data)
118
                    relativeTime += (e - relativeTime)
119

    
120
            waitTime = self.duration - relativeTime
121

    
122
            for event in eventList:
123
                sleep(event[0])
124
                info(event[1] + str(time.time()) + "\n")
125
                event[2](**event[3])
126
            sleep(waitTime)
127
            for pid in self.pendingProc.keys():
128
                self.sendSig(pid, signal.SIGTERM)
129
            time.sleep(2)
130
            self.killAll()
131
            time.sleep(2)
132

    
133

    
134
    def getCentrality(self):
135

    
136
        node_centrality_posteriori = {}
137
        centrality = {}
138
        for n in self.graph.nodes():
139
            gg = self.graph.copy()
140
            edges = self.graph.edges([n]) 
141
            gg.remove_node(n)
142
            # compute the connected components
143
            # WARNING: connected_components should return a list 
144
            # sorted by size, largest first. It does not, so i resort them
145
            unsorted_comp = list(nx.connected_components(gg))
146
            comp = sorted(unsorted_comp, key = lambda x: -len(x))
147
            # re-add the node
148
            gg.add_node(n)
149
            # re-add the edges to nodes in the main component
150
            for (fr, to) in edges:
151
                if fr in comp[0]:
152
                    gg.add_edge(fr, n)
153
                if to in comp[0]:
154
                    gg.add_edge(n, to)
155
            # now compute the centrality. This tells how important is the node
156
            # for the main connected component. If this is 0, it is not worth
157
            # to remove this node
158
            cent = nx.betweenness_centrality(gg)[n]
159
            isolated_nodes = [x for component in comp[1:] for x in component]
160
            node_centrality_posteriori[n] = [cent, [n] + isolated_nodes]
161
            centrality[n] = cent
162
        betw = [x for x in nx.betweenness_centrality(self.graph).items()\
163
                if x[1] > 0 and node_centrality_posteriori[x[0]][0] > 0]
164

    
165
        return [node_centrality_posteriori[k[0]][1] for k in sorted(betw, key=lambda x: -x[1])]
166

    
167
    def startRun(self, run_id=0, nodeCrashed=None):
168

    
169
        rNode = ""
170
        host_list = self.getAllHosts()
171

    
172
        runPrefix="run"+str(run_id)
173
        if nodeCrashed:
174
            runPrefix=str(nodeCrashed)+"run"+str(run_id)
175

    
176
        # default values
177
        hello_timer = self.HelloInterval
178
        tc_timer = self.TcInterval
179

    
180
        if rNode:
181
            info("\nChosen node " + str(rNode) + " to fail\n")
182

    
183
        
184
        if self.popRouting:
185
            #cmdargs = {}
186
            c = ComputeTheoreticalValues(graph_file=None, graph=self.graph,
187
                    cH=hello_timer, cTC=tc_timer)
188
            cent = nx.load_centrality(self.graph)
189
            deg = nx.degree(self.graph)
190
            for (h, cc) in sorted(cent.items(), key = lambda x: -x[1]):
191
                print deg[h],",", cent[h], ",", c.Hi[h], ",", c.TCi[h]
192
            #cmdargs['-h'] = str(c.Hi[str(h)])
193

    
194
        # h_load_pop = 0
195
        # h_load_nopop = 0
196
        # tc_load_pop = 0
197
        # tc_load_nopop = 0
198
        #for h in host_list:
199
        #    h_load_pop += len(self.graph[h.name])/c.Hi[h.name]
200
        #    h_load_nopop += len(self.graph[h.name])/hello_timer
201
        #    tc_load_pop += len(self.graph.edges())/c.TCi[h.name]
202
        #    tc_load_nopop += len(self.graph.edges())/tc_timer
203
        #print "XXXXXXXXX POP, h,tc", h_load_pop, tc_load_pop
204
        #print "XXXXXXXXX NOPOP, h,tc", h_load_nopop, tc_load_nopop
205
        for idx, h in enumerate(host_list):
206

    
207
            log_folder = self.logPrefix + "Babel-log-run" + str(self.runId) + "/"
208
            try:
209
                os.makedirs(log_folder)
210
            except:
211
                pass
212
            if self.popRouting:
213
                hi=c.Hi[str(h)]
214
                sh = "%.4f" % (hi)
215
                launch_pid = self.launchBabel(runPrefix, h, {'-H': sh, '-h': sh})
216
            else:
217
                sh=str(self.HelloInterval)
218
                launch_pid = self.launchBabel(runPrefix, h, {'-H': sh, '-h': sh})
219

    
220
            if self.dump:
221
                self.launch_sniffer(h)
222

    
223
        if not self.nodeCrashed and rNode:
224
            self.nodeCrashed = [rNode]
225
        return launch_pid
226

    
227

    
228
    def get_random_destination(self):
229

    
230
        host_list = self.getAllHosts()
231
        d = random.sample(host_list, 1)[0]
232
        dest_ip = d.intfList()[0].ip
233
        return dest_ip
234

    
235
    def number_to_host(self, host_number):
236
        host_list = self.getAllHosts()
237
        for host in host_list:
238
            number = int(host.name.split("_")[0][1:])
239
            if host_number == number:
240
                return host
241
        print "ERROR: no host number:", number, "in host_list:"
242
        print "  ", self.getAllHosts() 
243
        return None
244

    
245
    def sendSignal(self, sig, hostName=""):
246
        strsig="uknown signal"
247
        '''if (sig == signal.SIGUSR1):
248
            strsig="SIGUSR1"
249
        if (sig == signal.SIGQUIT):
250
            strsig="SIGQUIT"
251
        elif (sig == signal.SIGTERM):
252
            strsig="SIGTERM"
253
        elif (sig == signal.SIGKILL):
254
            strsig="SIGKILL"'''
255
        strsig = BABELTest.sigtoname[sig]
256
        if hostName:
257
            #code.interact(local=dict(globals(), **locals()))
258
            for pid, h in self.pendingProc.items():
259
                if h == hostName:
260
                    print "sending " + strsig + " to host:", h.name, ", pid", pid
261
                    self.sendSig(pid, sig)
262
        # send to all
263
        else:
264
            print "sending " + strsig + " to all hosts"
265
            for pid, h in self.pendingProc.items():
266
                self.sendSig(pid, sig)
267

    
268
    def __init__(self, mininet, name, args):
269

    
270
        super(BABELTest, self).__init__(mininet, name, args)
271

    
272
        self.mininet = mininet
273
        self.centList = []
274
        self.stopNodes = []
275
        self.stopNodeList = []
276

    
277
        self.conf_file = """
278
        DebugLevel  1
279
        IpVersion 4
280
        FIBMetric "flat"
281
        LinkQualityFishEye  0
282
        LockFile "%s"
283
        Hna4
284
        {
285
        }
286
        Hna6
287
        {
288
        }
289
        LoadPlugin "../olsrd/lib/dumprt/olsrd_dumprt.so.0.0"{
290
        PlParam "run_id" "%d"
291
        PlParam "log_file" "%s"
292
        PlParam "log_interval_msec" "300"
293
        }
294

295
        InterfaceDefaults {
296
        }
297

298
        Interface %s
299
        {
300
        HelloInterval       %f
301
        HelloValidityTime   %f
302
        TcInterval          %f
303
        TcValidityTime      %f
304
        }
305
        """
306
        if "logPrefix" in args.keys():
307
            self.logPrefix = args["logPrefix"]
308
        else:
309
            self.logPrefix = "/tmp/"
310

    
311
        if "runId" in args.keys():
312
            self.runId = args["runId"]
313
        else:
314
            self.runId = 0
315

    
316
        if "popRouting" in args.keys() and\
317
                args['popRouting'] == 'True':
318
            self.popRouting = True
319
        else:
320
            self.popRouting = False
321

    
322
        if "NumPing" in args.keys():
323
            self.NumPing = int(args["NumPing"])
324
        else:
325
            self.NumPing = 1
326

    
327
        if "HelloInterval" in args.keys():
328
            self.HelloInterval = float(args["HelloInterval"])
329
        else:
330
            self.HelloInterval = 2
331

    
332
        if "TcInterval" in args.keys():
333
            self.TcInterval = float(args["TcInterval"])
334
        else:
335
            self.TcInterval = 5
336

    
337
        if "stopAllNodes" in args.keys():
338
            self.stopAllNodes = int(args["stopAllNodes"])
339
        else:
340
            self.stopAllNodes = []
341

    
342
        if "stopList" in args.keys():
343
            self.stopList = map(int, args["stopList"].split(","))
344
        else:
345
            self.stopList = []
346

    
347
        # TODO import parseTime from dummyrouting
348
        if "stopTime" in args.keys():
349
            self.stopTime = float(args["stopTime"])
350
        elif self.stopAllNodes or self.stopList:
351
            print "ERROR: you set one of stopAllNodes/stopList" +\
352
                  "but did not set stopTime"
353
            exit()
354
        else:
355
            self.stopTime = 0