Changeset 1611
- Timestamp:
- 06/21/09 19:39:37 (9 months ago)
- Files:
-
- netsukuku/trunk/pyntk/ntk/core/qspn.py (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
netsukuku/trunk/pyntk/ntk/core/qspn.py
r1581 r1611 4 4 # 5 5 # This source code is free software; you can redistribute it and/or 6 # modify it under the terms of the GNU General Public License as published 6 # modify it under the terms of the GNU General Public License as published 7 7 # by the Free Software Foundation; either version 2 of the License, 8 8 # or (at your option) any later version. … … 18 18 ## 19 19 20 from operator import add 21 22 from ntk.core.route import NullRem, DeadRem 23 from ntk.lib.event import Event 20 24 from ntk.lib.micro import microfunc 21 from ntk.lib.event import Event22 from ntk.core.route import NullRem, DeadRem23 25 24 26 def is_listlist_empty(l): 25 """ 26 Returns true if l=[[],[], ...] 27 l is a list of lists. 28 """ 29 return not any(l) 30 31 class Etp: 27 """Returns true if l=[[],[], ...] 28 :type l: a list of lists. 29 """ 30 return not any(l) 31 32 class Etp(object): 32 33 """Extended Tracer Packet""" 33 34 34 35 def __init__(self, radar, maproute): 35 36 36 self. neigh =radar.neigh37 self.ne tid =radar.netid38 self.maproute =maproute37 self.radar = radar 38 self.neigh = radar.neigh 39 self.maproute = maproute 39 40 40 41 self.neigh.events.listen('NEIGH_NEW', self.etp_new_changed) … … 52 53 ## Create R 53 54 def gw_is_neigh((dst, gw, rem)): 54 return gw == neigh.id55 R =self.maproute.bestroutes_get(gw_is_neigh)55 return gw == neigh.id 56 R = self.maproute.bestroutes_get(gw_is_neigh) 56 57 ## 57 58 … … 61 62 62 63 if is_listlist_empty(R): 63 # R is empty, that is we don't have routes passing by `gw'.64 # Therefore, nothing to update, nothing to do.65 return66 64 # R is empty, that is we don't have routes passing by `gw'. 65 # Therefore, nothing to update, nothing to do. 66 return None 67 67 68 ## Create R2 68 69 def rem_or_none(r): 69 if r is not None:70 return r.rem71 return DeadRem()72 73 R2 = [ 70 if r is not None: 71 return r.rem 72 return DeadRem() 73 74 R2 = [ 74 75 [ (dst, rem_or_none(self.maproute.node_get(lvl, dst).best_route())) 75 76 for (dst,gw,rem) in R[lvl] … … 101 102 ## Create R 102 103 def gw_isnot_neigh((dst, gw, rem)): 103 return gw != neigh.id 104 return gw != neigh.id 105 104 106 R = self.maproute.bestroutes_get(gw_isnot_neigh) 107 105 108 if is_listlist_empty(R): 106 # R is empty: no need to proceed107 return109 # R is empty: no need to proceed 110 return None 108 111 109 112 def takeoff_gw((dst, gw, rem)): 110 return (dst, rem) 113 return (dst, rem) 114 111 115 def takeoff_gw_lvl(L): 112 return map(takeoff_gw, L) 113 R=map(takeoff_gw_lvl, R) 116 return map(takeoff_gw, L) 117 118 R = map(takeoff_gw_lvl, R) 114 119 ## 115 120 … … 124 129 def etp_exec(self, sender_nip, R, TPL, flag_of_interest): 125 130 """Executes a received ETP 126 131 127 132 sender_nip: sender ntk ip (see map.py) 128 133 R : the set of routes of the ETP 129 134 TPL: the tracer packet of the path covered until now by this ETP. 130 This TP may have covered different levels. In general, TPL 135 This TP may have covered different levels. In general, TPL 131 136 is a list of blocks. Each block is a (lvl, TP) pair, where lvl is 132 137 the level of the block and TP is the tracer packet composed … … 136 141 """ 137 142 138 gwnip = sender_nip139 neigh = self.neigh.ip_to_neigh(self.maproute.nip_to_ip(gwnip))140 gw = neigh.id141 gwrem = neigh.rem143 gwnip = sender_nip 144 neigh = self.neigh.ip_to_neigh(self.maproute.nip_to_ip(gwnip)) 145 gw = neigh.id 146 gwrem = neigh.rem 142 147 143 148 ## Collision check 144 149 colliding, R = self.collision_check(gwnip, neigh, R) 145 150 if colliding: 146 # collision detected. rehook.147 self.events.send('NET_COLLISION',148 ([nr for nr in self.neigh.neigh_list()149 if nr.netid == neigh.netid],)150 )151 return# drop the packet151 # collision detected. rehook. 152 self.events.send('NET_COLLISION', 153 ([nr for nr in self.neigh.neigh_list() 154 if nr.netid == neigh.netid],) 155 ) 156 return None # drop the packet 152 157 ## 153 158 … … 155 160 level = self.maproute.nip_cmp(self.maproute.me, gwnip) 156 161 for block in TPL: 157 lvl = block[0] # the level of the block158 if lvl < level:159 block[0] = level160 blockrem = sum([rem for hop, rem in block[1]], NullRem())161 block[1] = [[gwnip[level], blockrem]]162 R[lvl] = []163 164 162 lvl = block[0] # the level of the block 163 if lvl < level: 164 block[0] = level 165 blockrem = sum([rem for hop, rem in block[1]], NullRem()) 166 block[1] = [[gwnip[level], blockrem]] 167 R[lvl] = [] 168 169 165 170 ### Collapse blocks of the same level 166 171 #Note: we're assuming the two blocks with the same level are one after 167 172 # another. 168 TPL2=[TPL[0]] 173 TPL2 = [TPL[0]] 174 169 175 for block in TPL[1:]: 170 if block[0] == TPL2[-1][0]:171 TPL2[-1][1]+=block[1]172 else:173 TPL2.append(block)174 TPL =TPL2176 if block[0] == TPL2[-1][0]: 177 TPL2[-1][1]+=block[1] 178 else: 179 TPL2.append(block) 180 TPL = TPL2 175 181 ### 176 182 177 183 ### Remove dups 178 184 def remove_contiguos_dups_in_TP(L): 179 L2=[]180 prec=[None, NullRem()]181 for x in L:182 if x[0] != prec[0]:183 prec=x184 L2.append(x)185 else:186 prec[1]+=x[1]187 return L2185 L2 = [] 186 prec = [None, NullRem()] 187 for x in L: 188 if x[0] != prec[0]: 189 prec = x 190 L2.append(x) 191 else: 192 prec[1] += x[1] 193 return L2 188 194 189 195 for block in TPL: 190 block[1]=remove_contiguos_dups_in_TP(block[1])196 block[1] = remove_contiguos_dups_in_TP(block[1]) 191 197 ### 192 198 … … 195 201 ## ATP rule 196 202 for block in TPL: 197 if self.maproute.me[block[0]] in block[1]:198 return # drop the pkt203 if self.maproute.me[block[0]] in block[1]: 204 return # drop the pkt 199 205 ## 200 206 … … 206 212 207 213 ## Update the map from the TPL 208 tprem =gwrem214 tprem = gwrem 209 215 TPL_is_interesting = False 210 216 for block in reversed(TPL): … … 229 235 if r.gw != gw 230 236 ] for lvl in xrange(self.maproute.levels) ] 231 237 232 238 #-- 233 239 # Step 5 omitted, see qspn.pdf, 4.1 Extended Tracer Packet: … … 243 249 ## 244 250 245 ## R2 251 ## R2 246 252 R2 = [ [ (dst, rem) 247 253 for dst, rem in R[lvl] … … 253 259 254 260 if not is_listlist_empty(R2) or TPL_is_interesting: 255 if TPL[-1][0] != 0:256 # The last block isn't of level 0. Let's add a new block257 TP = [[self.maproute.me[0], gwrem]]258 TPL.append([0, TP])259 else:260 # The last block is of level 0. We can append our ID261 TPL[-1][1].append([self.maproute.me[0], gwrem])262 263 264 etp = (R2, TPL, flag_of_interest)265 self.etp_forward(etp, [neigh.id])261 if TPL[-1][0] != 0: 262 # The last block isn't of level 0. Let's add a new block 263 TP = [[self.maproute.me[0], gwrem]] 264 TPL.append([0, TP]) 265 else: 266 # The last block is of level 0. We can append our ID 267 TPL[-1][1].append([self.maproute.me[0], gwrem]) 268 269 270 etp = (R2, TPL, flag_of_interest) 271 self.etp_forward(etp, [neigh.id]) 266 272 ## 267 273 … … 271 277 """Forwards the `etp' to all our neighbours, 272 278 excluding those contained in `exclude' 273 279 274 280 `Exclude' is a list of "Neighbour.id"s""" 275 281 276 282 for nr in self.neigh.neigh_list(): 277 if nr.id not in exclude:278 nr.ntkd.etp.etp_exec(self.maproute.me, *etp)279 283 if nr.id not in exclude: 284 nr.ntkd.etp.etp_exec(self.maproute.me, *etp) 285 280 286 def collision_check(self, gwnip, neigh, R): 281 287 """ Checks if we are colliding with the network of `neigh'. 282 288 283 289 It returns True if we are colliding and we are going to rehook. 284 290 !NOTE! the set R will be modified: all the colliding routes will 285 291 be removed. 286 292 """ 287 288 if neigh.netid == self.netid \ 289 or self.netid == -1: 290 self.netid = neigh.netid 291 return (False, R) # all ok 293 294 if neigh.netid == self.radar.netid or self.radar.netid == -1: 295 self.radar.netid = neigh.netid 296 return (False, R) # all ok 292 297 293 298 # uhm... we are in different networks 294 299 295 300 ## Calculate the size of the two nets 296 def add(a,b):return a+b297 301 mynetsz = reduce(add, self.maproute.node_nb) 298 302 ngnetsz = reduce(add, map(len, R)) 299 303 300 if mynetsz > ngnetsz or \301 (mynetsz == ngnetsz and self.netid > neigh.netid):304 if mynetsz > ngnetsz or \ 305 (mynetsz == ngnetsz and self.radar.netid > neigh.netid): 302 306 # we don't care if we are colliding or not. We can simply 303 307 # ignore colliding routes, the rest will be done by the other … … 305 309 306 310 ### Remove colliding routes from R 307 R = [ [ (dst, rem) 308 for dst, rem in R[lvl] 309 if self.maproute.node_get(lvl, dst).is_empty() ] 310 for lvl in xrange(self.maproute.levels) ] 311 R = [[(dst, rem) for dst, rem in R[lvl] 312 if self.maproute.node_get(lvl, dst).is_empty() 313 ] 314 for lvl in xrange(self.maproute.levels) 315 ] 311 316 ### 312 317 return (False, R) … … 319 324 level = self.maproute.nip_cmp(self.maproute.me, gwnip) + 1 320 325 if level < self.maproute.levels: 321 for dst, rem in R[level]:322 if dst == self.maproute.me[level]:323 # we are colliding! LET'S REHOOK324 return (True, R)325 ## 326 for dst, rem in R[level]: 327 if dst == self.maproute.me[level]: 328 # we are colliding! LET'S REHOOK 329 return (True, R) 330 ## 326 331 327 332 ## Remove colliding routes directly from our map 328 333 for lvl in xrange(self.maproute.levels): 329 for dst, rem in R[lvl]:330 self.maproute.node_get(lvl, dst).route_reset()334 for dst, rem in R[lvl]: 335 self.maproute.node_get(lvl, dst).route_reset() 331 336 ## 332 337 333 338 return (False, R) 334
