Statistics
| Branch: | Revision:

nepatest_popbabel / scripts / multiprocessTimerouter.py @ 60ba786f

History | View | Annotate | Download (8.81 KB)

1
import glob
2
import json
3
from pprint import pprint
4
import sys
5
import os
6
import numpy as np
7
import matplotlib
8
matplotlib.use('Agg')
9
from matplotlib import pyplot as plt
10
from pprint import pprint
11
import code
12
from multiprocessing import Process, Manager
13

    
14

    
15
class MyTime:
16
        string = "0:0:0.0"
17
        
18
        @classmethod
19
        def vecToString(cls, vec):
20
                mus=vec[-1]
21
                highORlow="high"
22
                if (mus<0.5):
23
                        highORlow="low"
24
                return str(vec[0])+":"+str(vec[1])+":"+str(vec[2])+"-"+highORlow
25
        
26
        def __init__(self, timestring="0:0:0.0"):
27
                self.string=timestring
28
                spl=self.string.split(':')
29
                self.mh=int(spl[-3])
30
                self.mm=int(spl[-2])
31
                self.ms=int(spl[-1].split('.')[0])
32
                self.mus=int(spl[-1].split('.')[1]) * (10**-6)
33
                self.time=self.mh *60 * 60 + self.mm * 60 + self.ms + self.mus
34

    
35
        def asHMSUVector(self):
36
                if (self.mus<0.5):
37
                        retmus=0
38
                else:
39
                        retmus=5
40
                #print "\t\tmus="+str(self.mus)+", retmus="+str(retmus)
41
                return (self.mh,self.mm,self.ms,retmus)
42

    
43
        def asHMSVector(self):
44
                return (self.mh,self.mm,self.ms)
45

    
46
        def toString(self):
47
                return self.string
48

    
49
        def toFloat(self):
50
                return self.time
51

    
52
        #se self e' piu' tardi ritorna 1, -1 altrimenti
53
        #si assume che i log siano stati fatti nella stessa ora!
54
        def vecCompare(self,v2):
55
                h1,m1,s1,hl1=self.asHMSUVector()
56
                h2,m2,s2,hl2=v2
57
                if (h2 != h1):
58
                        if (h2>h1):
59
                                return -1
60
                        else:
61
                                return 1
62
                if (m2 != m1):
63
                        if (m2>m1):
64
                                return -1
65
                        else:
66
                                return 1
67
                if (s2 != s1):
68
                        if (s2>s1):
69
                                return -1
70
                        else:
71
                                return 1
72
                if (hl2 != hl1):
73
                        if (hl2>hl1):
74
                                return -1
75
                        else:
76
                                return 1
77
                return 0
78

    
79
        def __cmp__(self,obj):
80
                return self.vecCompare(obj.asHMSUVector())
81

    
82

    
83
        #return 1 if self older than other
84

    
85
class DestNotFound(Exception):
86
        def __init__(self, value):
87
                self.value = value
88
        def __str__(self):
89
                return repr(self.value)
90

    
91
#ok, let me call this function like this...
92
#currently works only because ALL routes are \32 addresses
93
def longestPrefixMatchNextHop(rt,dest):
94
        for entry in rt.keys():
95
                if entry.startswith(dest):
96
                        return rt[entry]
97
        raise DestNotFound("DEST 404: "+str(dest))
98

    
99

    
100

    
101
#time2N2RT: <secondo, N2RT>
102
time2N2RT={}
103
#N2RT: <node_id, RT>
104
#N2RT = {}
105
#RT: <dest, next_hop>
106
#ip2node: <ip, node_id>
107

    
108
def navigateRoutingTable(node2rt,ip2node,node2ips,sec,failedNodesId):
109
        ips=ip2node.keys()
110
        
111
        #remove ips of failed_nodes, given we want to check how many routes among ips of active nodes pass trough the dead node
112
        remIps=node2ips[failedNodesId]
113
        ips = list(set(ips) - set(remIps))
114

    
115
        black_holes=0
116
        loops=0
117
        routes=[]
118
        for s in ips:
119
                for d in ips:
120
                        #print "\t\tlooking for route from "+str(s)+"..->.."+str(d)
121
                        #r=route->list of IPs crossed
122
                        r = []
123
                        nr = []
124
                        r.append(s)
125
                        source_node=ip2node[s]
126
                        nr.append(source_node)
127
                        target_node=ip2node[d]
128
                        try:
129
                                nexthop=longestPrefixMatchNextHop(node2rt[source_node],d)
130
                        except DestNotFound as dnf:
131
                                print dnf, "probably alredy flushed"
132
                                break;
133
                        except KeyError as e:
134
                                print e
135
                                #print "Unexpected error:", sys.exc_info()[0], "\n\t Actually this concludes log analysis," \
136
                                # "when stop logging\n\tsome nodes terminates before others and some RT misses"
137
                                #pass
138
                                return ()
139
                                #break;
140
                        target=ip2node[nexthop]
141
                        while(target!=target_node):
142
                                r.append(nexthop)
143
                                source_node=ip2node[nexthop]
144
                                if (source_node not in nr):
145
                                        nr.append(source_node)
146
                                else:
147
                                        #print "\t\t\t\tLoooooooop!!!!!"
148
                                        loops+=1
149
                                        break;
150
                                try:
151
                                        nexthop=longestPrefixMatchNextHop(node2rt[source_node],d)
152
                                except KeyError:
153
                                        black_holes+=1
154
                                        '''print "\t\tNode "+str(ip2node[nexthop])+" owning "+str(nexthop)+" is dead"
155
                                        sys.stdout.write("\t\t\t\t")
156
                                        for i in range(len(r)):
157
                                                if (i!=0):
158
                                                        sys.stdout.write("->")
159
                                                sys.stdout.write("c"+str(r[i]))
160
                                        print ""'''
161
                                        break;
162
                                except:
163
                                        print "IIIUnexpected error:", sys.exc_info()[0]
164
                                        break;
165
                                target=ip2node[nexthop]
166
                        r.append(d)
167
                        routes.append(r)
168
        print "\t#loops: "+str(loops)+", blackholes: "+str(black_holes)
169
        return (black_holes,loops,)
170

    
171

    
172
#the folder where to look for dumps and logs
173
folder=sys.argv[1]
174
print folder
175

    
176
'''t1=MyTime("12:00:01.200000")
177
t2=MyTime("12:00:01.700000")
178

179
print t1.vecCompare(t2.asHMSUVector())
180

181
print t2.vecCompare(t1.asHMSUVector())
182

183
print t1.vecCompare(t1.asHMSUVector())
184

185
code.interact(local=locals())'''
186

    
187

    
188
ip2node={}
189
node2ips={}
190

    
191
print "###########\n\n\n\n"
192
#Ricostruzione RT indicizzate per tempo
193
#bisogna anche salvarsi il tempo di rottura del nodo che e' morto
194
minDumpsLength=sys.maxint
195
failedNodesId=""
196
fail_time=MyTime()
197
stopTimes=[]
198
stopTimes2n={}
199

    
200

    
201
for fname in glob.glob(folder+'topo*'):
202
        print "Loading json from " + fname
203
        f=open(fname, "r")
204
        jtimedroutes=json.load(f)
205
        del(jtimedroutes[0]) #the first dummy entry always put in Babel dumps
206
        
207
        #identifyinf failed node as the one with minimun number of dumps
208
        '''if (len(jtimedroutes)<minDumpsLength):
209
                minDumpsLength=len(jtimedroutes)
210
                lastDump=jtimedroutes[-1]
211
                failedNodesId=lastDump['router_id']
212
                fail_time=MyTime(lastDump['topology_id'])
213
                print "\tFAILURE NEWS: "+failedNodesId+" stopped working at "+fail_time.toString()'''
214

    
215
        #put stopTime in a vector to see which is the first correct node that stopped logging
216
        lastDump=jtimedroutes[-1]
217
        router_id=lastDump['router_id']
218
        stopTime=MyTime(lastDump['topology_id'])
219
        stopTimes.append(stopTime)
220
        stopTimes2n[stopTime.asHMSUVector()]=router_id
221

    
222
        #pprint(time2N2RT)
223
        #Retrieving RTs dumped by this node
224
        slasttime=MyTime().toString
225
        for jtimedRT in jtimedroutes:
226
                router_id=jtimedRT['router_id']
227
                stime=jtimedRT['topology_id']
228
                routes=jtimedRT['routes']
229
                #print "\tAt time: "+stime+" we have an RT for node: "+router_id
230
                time=MyTime(stime)
231
                tk=time.asHMSUVector()
232
                #tk=tk[0]*60*60+tk[1]*60+tk[2]
233
                
234
                if (not time2N2RT or tk not in time2N2RT):
235
                        time2N2RT[tk]={}
236
                        #print "New second",router_id,tk
237
                if (not time2N2RT[tk] or router_id not in time2N2RT[tk]):
238
                        time2N2RT[tk][router_id]={}
239
                        #print "\tNew router for ",router_id,tk
240

    
241
                thisnodeIPs=[]
242
                for r in routes:
243
                        #RT=time2N2RT[tk][router_id]
244
                        dest=r['destination']
245
                        nexthop=r['next']
246
                        if(float(r['cost'])==0):
247
                                nexthop=dest.split('/')[0]
248
                                thisnodeIPs.append(nexthop)
249
                                ip2node[nexthop]=router_id
250
        
251
                        time2N2RT[tk][router_id][dest]=nexthop
252

    
253
                node2ips[router_id]=thisnodeIPs
254
                #N2RT[router_id]=RT
255
        f.close()
256

    
257

    
258
#code.interact(local=locals())
259
stopTimes=sorted(stopTimes)
260
fail_time=stopTimes[0]
261
failedNodesId=stopTimes2n[fail_time.asHMSUVector()]
262
stopLogTime=stopTimes[1] #[0] -> fail node stop
263

    
264
print "According to data read from json it seems that"
265
print "Failure at: "+fail_time.toString()
266
print "Stop log at: "+stopLogTime.toString()
267

    
268
'''print "ip2node"
269
pprint(ip2node)
270

271
print "node2ips"
272
pprint(node2ips)
273
print "#################\n\n\n\n"
274
pprint(time2N2RT)'''
275
print "#################\n\n\n\n"
276
srtsec=sorted(time2N2RT.keys())
277
#print "Times"
278
#pprint(srtsec)
279
#print "\n\n"
280
'''for sec in srtsec:
281
        print "Al secondo: "+ MyTime.vecToString(sec)
282
        for node in time2N2RT[sec]:
283
                print "\t\tRT("+str(node)+")={"
284
                for dest in time2N2RT[sec][node]:
285
                        print "\t\t\t\t"+str(dest)+" via "+str(time2N2RT[sec][node][dest])
286
                print "\t\t}"
287
        print "\n"'''
288

    
289
def broken_paths_discoverer(N2RT, ip2node, node2ips,sec, failedNodesId, res):
290
        print "\nProblems at time: "+MyTime.vecToString(sec)+"?"
291
        #da tenere conto di nodo_fallito e fail_time
292
        #non analizziamo i log precedenti a fail_time
293

    
294
        if (fail_time.vecCompare(sec)>0):
295
                print "\t"+MyTime.vecToString(sec) + " prior than fail_time: "+fail_time.toString()
296
                res[sec]=(-1,-1)
297

    
298
        elif (stopLogTime.vecCompare(sec)<0):
299
                print "\t"+MyTime.vecToString(sec) + " after than stopLogTime: "+stopLogTime.toString()
300
                res[sec]=(-1,-1)
301

    
302
        #"else" failTime < sec < StopLogTime ==> it is worth to navigate RTs
303
        else:
304
                res[sec]=navigateRoutingTable(time2N2RT[sec],ip2node,node2ips,sec,failedNodesId)
305
                
306

    
307

    
308
print "#################\n\n\n\n"
309
#Navigazione e conteggio disagi:
310
manager = Manager()
311
results = manager.dict()
312
#results={} #<time,vettore risultati>: disagi per secondo
313

    
314
print "Looking for problems in network for each period"
315
jobs=[]
316
for sec in srtsec:
317
        procs = len(srtsec)
318
        for i in range(0, procs):
319
                process = Process(target=broken_paths_discoverer, 
320
                                                                                  args=(time2N2RT[sec],ip2node,node2ips,sec,failedNodesId,results))
321
                jobs.append(process)
322

    
323
for j in jobs:
324
        j.start()
325
for j in jobs:
326
        j.join()
327

    
328
print "#######\n\n\n"
329
#code.interact(local=dict(globals(), **locals()))
330

    
331
#Visualiza data in pretty table
332
from prettytable import PrettyTable
333
t = PrettyTable(['Time', '#loops','#blackholes'])
334

    
335
#sava data in csv file
336
fldname=folder.strip("/")
337
f = open(folder+fldname+"-results.csv", "w")
338
f.write("Time,loops,blackholes\n")
339
for sec in srtsec:
340
        if (sec in results):
341
                if (bool(results[sec])):
342
                        #print "At sec: "+MyTime.vecToString(sec)+" #loops: "+str(results[sec][1]) + " #blackholes: "+str(results[sec][0])
343
                        t.add_row([ MyTime.vecToString(sec), str(results[sec][1]), str(results[sec][0])])
344
                        f.write(MyTime.vecToString(sec) +","+ str(results[sec][1])+","+ str(results[sec][0])+"\n")
345
f.close()
346
print t