Statistics
| Branch: | Revision:

nepatest_popbabel / test_code / babel.py @ 60ba786f

History | View | Annotate | Download (11.3 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 code
13

    
14
import signal
15

    
16
from test_generic import *
17

    
18

    
19
class BABELTest(dummyRoutingRandomTest):
20

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

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

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

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

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

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

    
54
    def runTest(self):
55

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

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

    
66
        if not run_ids:
67
            # do at least one run
68
            run_ids = [0]
69
        for run_id in run_ids:
70
            info("\nStarting run " + str(run_id) + "\n")
71
            if self.stopNodeList:
72
                #code.interact(local=dict(globals(), **locals()))
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
                #code.interact(local=dict(globals(), **locals()))
125
                event[2](**event[3])
126
                info(event[1] + str(time.time()) + "\n")
127
            sleep(waitTime)
128
            for pid in self.pendingProc.keys():
129
                self.sendSig(pid, signal.SIGTERM)
130
            time.sleep(2)
131
            self.killAll()
132
            time.sleep(2)
133

    
134

    
135
    def getCentrality(self):
136

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

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

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

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

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

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

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

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

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

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

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

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

    
228

    
229
    def get_random_destination(self):
230

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

    
236
    def sendSignal(self, sig, hostName=""):
237
        strsig="uknown signal"
238
        if (sig == signal.SIGUSR1):
239
            strsig="SIGUSR1"
240
        if (sig == signal.SIGQUIT):
241
            strsig="SIGQUIT"
242
        elif (sig == signal.SIGTERM):
243
            strsig="SIGTERM"
244
        elif (sig == signal.SIGKILL):
245
            strsig="SIGKILL"
246
        for pid, h in self.pendingProc.items():
247
            if hostName:
248
                if h.name == hostName:
249
                    print "sending signal to host:", h.name, ", pid", pid
250
                    self.sendSig(pid, sig)
251
            # send to all
252
            else:
253
                print "sending signal to all hosts:", strsig
254
                self.sendSig(pid, sig)
255

    
256
    def __init__(self, mininet, name, args):
257

    
258
        super(BABELTest, self).__init__(mininet, name, args)
259

    
260
        self.mininet = mininet
261
        self.centList = []
262
        self.stopNodes = []
263
        self.stopNodeList = []
264

    
265
        self.conf_file = """
266
        DebugLevel  1
267
        IpVersion 4
268
        FIBMetric "flat"
269
        LinkQualityFishEye  0
270
        LockFile "%s"
271
        Hna4
272
        {
273
        }
274
        Hna6
275
        {
276
        }
277
        LoadPlugin "../olsrd/lib/dumprt/olsrd_dumprt.so.0.0"{
278
        PlParam "run_id" "%d"
279
        PlParam "log_file" "%s"
280
        PlParam "log_interval_msec" "300"
281
        }
282

283
        InterfaceDefaults {
284
        }
285

286
        Interface %s
287
        {
288
        HelloInterval       %f
289
        HelloValidityTime   %f
290
        TcInterval          %f
291
        TcValidityTime      %f
292
        }
293
        """
294
        if "logPrefix" in args.keys():
295
            self.logPrefix = args["logPrefix"]
296
        else:
297
            self.logPrefix = "/tmp/"
298

    
299
        if "runId" in args.keys():
300
            self.runId = args["runId"]
301
        else:
302
            self.runId = 0
303

    
304
        if "popRouting" in args.keys() and\
305
                args['popRouting'] == 'True':
306
            self.popRouting = True
307
        else:
308
            self.popRouting = False
309

    
310
        if "NumPing" in args.keys():
311
            self.NumPing = int(args["NumPing"])
312
        else:
313
            self.NumPing = 1
314

    
315
        if "HelloInterval" in args.keys():
316
            self.HelloInterval = float(args["HelloInterval"])
317
        else:
318
            self.HelloInterval = 2
319

    
320
        if "TcInterval" in args.keys():
321
            self.TcInterval = float(args["TcInterval"])
322
        else:
323
            self.TcInterval = 5
324

    
325
        if "stopAllNodes" in args.keys():
326
            self.stopAllNodes = int(args["stopAllNodes"])
327
        else:
328
            self.stopAllNodes = []
329

    
330
        if "stopList" in args.keys():
331
            self.stopList = map(int, args["stopList"].split(","))
332
        else:
333
            self.stopList = []
334

    
335
        # TODO import parseTime from dummyrouting
336
        if "stopTime" in args.keys():
337
            self.stopTime = float(args["stopTime"])
338
        elif self.stopAllNodes or self.stopList:
339
            print "ERROR: you set one of stopAllNodes/stopList" +\
340
                  "but did not set stopTime"
341
            exit()
342
        else:
343
            self.stopTime = 0