Index: trunk/routing/twistedbgp/src/bgp.py |
— | — | @@ -86,6 +86,8 @@ |
87 | 87 | ATTR_TYPE_AGGREGATOR = 7 |
88 | 88 | ATTR_TYPE_COMMUNITY = 8 |
89 | 89 | |
| 90 | +ATTR_TYPE_INT_LAST_UPDATE = 256 + 1 |
| 91 | + |
90 | 92 | # Exception classes |
91 | 93 | |
92 | 94 | class BGPException(Exception): |
— | — | @@ -171,32 +173,42 @@ |
172 | 174 | raise ValueError |
173 | 175 | |
174 | 176 | def __repr__(self): |
175 | | - return repr(".".join([str(ord(o)) for o in self.prefix]) + '/%d' % self.prefixlen) |
| 177 | + return repr(str(self)) |
176 | 178 | # TODO: IPv6 |
177 | 179 | |
| 180 | + def __str__(self): |
| 181 | + return ".".join([str(ord(o)) for o in self.prefix]) + '/%d' % self.prefixlen |
| 182 | + |
178 | 183 | def __eq__(self, other): |
| 184 | + # FIXME: masked ips |
179 | 185 | return self.prefixlen == other.prefixlen and self.prefix == other.prefix |
180 | 186 | |
181 | 187 | def __ne__(self, other): |
182 | 188 | return not self.__eq__(other) |
183 | 189 | |
184 | 190 | def __lt__(self, other): |
185 | | - return self.prefixlen < other.prefixlen or \ |
186 | | - (self.prefixlen == other.prefixlen and self.prefix < other.prefix) |
| 191 | + return self.prefix < other.prefix or \ |
| 192 | + (self.prefix == other.prefix and self.prefixlen < other.prefixlen) |
187 | 193 | |
188 | 194 | def __le__(self, other): |
189 | 195 | return self.__lt__(other) or self.__eq__(other) |
190 | 196 | |
191 | 197 | def __gt__(self, other): |
192 | | - return self.prefixlen > other.prefixlen or \ |
193 | | - (self.prefixlen == other.prefixlen and self.prefix > other.prefix) |
| 198 | + return self.prefix > other.prefix or \ |
| 199 | + (self.prefix == other.prefix and self.prefixlen > other.prefixlen) |
194 | 200 | |
195 | 201 | def __ge__(self, other): |
196 | 202 | return self.__gt__(other) or self.__eq__(other) |
197 | 203 | |
198 | 204 | def __hash__(self): |
199 | | - return self.prefix.__hash__() ^ self.prefixlen.__hash__() |
| 205 | + return hash(self.prefix) ^ hash(self.prefixlen) |
| 206 | + |
| 207 | + def __len__(self): |
| 208 | + return self.prefixlen |
200 | 209 | |
| 210 | + def ipToInt(self): |
| 211 | + return reduce(lambda x, y: x * 256 + y, map(ord, self.prefix)) |
| 212 | + |
201 | 213 | class IPv4IP(IPPrefix): |
202 | 214 | """Class that represents a single non-prefix IPv4 IP.""" |
203 | 215 | |
— | — | @@ -206,8 +218,8 @@ |
207 | 219 | else: |
208 | 220 | super(IPv4IP, self).__init__((ip, 32)) |
209 | 221 | |
210 | | - def __repr__(self): |
211 | | - return repr(".".join([str(ord(o)) for o in self.prefix])) |
| 222 | + def __str__(self): |
| 223 | + return ".".join([str(ord(o)) for o in self.prefix]) |
212 | 224 | |
213 | 225 | class Attribute(object): |
214 | 226 | """Base class for all BGP attribute classes""" |
— | — | @@ -418,7 +430,15 @@ |
419 | 431 | |
420 | 432 | def __str__(self): |
421 | 433 | return str(["%d:%d" % (c / 2**16, c % 2**16) for c in self.value]) |
| 434 | + |
| 435 | +class LastUpdateIntAttribute(Attribute): |
| 436 | + name = 'Last Update' |
422 | 437 | |
| 438 | + def __init__(self, attrTuple): |
| 439 | + super(LastUpdateIntAttribute, self).__init__(attrTuple) |
| 440 | + |
| 441 | + self.value = attrTuple[2] |
| 442 | + |
423 | 443 | Attribute.typeToClass = { |
424 | 444 | ATTR_TYPE_ORIGIN: OriginAttribute, |
425 | 445 | ATTR_TYPE_AS_PATH: ASPathAttribute, |
— | — | @@ -427,7 +447,9 @@ |
428 | 448 | ATTR_TYPE_LOCAL_PREF: LocalPrefAttribute, |
429 | 449 | ATTR_TYPE_ATOMIC_AGGREGATE: AtomicAggregateAttribute, |
430 | 450 | ATTR_TYPE_AGGREGATOR: AggregatorAttribute, |
431 | | - ATTR_TYPE_COMMUNITY: CommunityAttribute |
| 451 | + ATTR_TYPE_COMMUNITY: CommunityAttribute, |
| 452 | + |
| 453 | + ATTR_TYPE_INT_LAST_UPDATE: LastUpdateIntAttribute |
432 | 454 | } |
433 | 455 | |
434 | 456 | class AttributeSet(set): |
Index: trunk/routing/twistedbgp/src/test.py |
— | — | @@ -0,0 +1,95 @@ |
| 2 | + |
| 3 | +from zope.interface import implements |
| 4 | + |
| 5 | +from twisted.internet import reactor, interfaces, task |
| 6 | +import bgp, radix |
| 7 | + |
| 8 | +import datetime, random |
| 9 | + |
| 10 | +class BGPDebug(object): |
| 11 | + implements(interfaces.IConsumer) |
| 12 | + |
| 13 | + def __init__(self): |
| 14 | + self.prefixes = radix.Radix() |
| 15 | + self.nlriCount = 0 |
| 16 | + self.withdrawnCount = 0 |
| 17 | + |
| 18 | + def registerProducer(self, producer, streaming): |
| 19 | + self.producer = producer |
| 20 | + |
| 21 | + task.LoopingCall(self.printStats).start(5.0) |
| 22 | + |
| 23 | + def unregisterProducer(self): |
| 24 | + pass |
| 25 | + |
| 26 | + def write(self, data): |
| 27 | + withdrawnPrefixes, attrSet, nlri = data |
| 28 | + |
| 29 | + self.withdrawnCount += len(withdrawnPrefixes) |
| 30 | + self.nlriCount += len(nlri) |
| 31 | + |
| 32 | + # DEBUG |
| 33 | +# print "UPDATE:", withdrawnPrefixes, nlri |
| 34 | +# for a in attrSet: |
| 35 | +# print a.name, a |
| 36 | + |
| 37 | + # Add internal attribute 'last update' |
| 38 | + attrSet.add(bgp.LastUpdateIntAttribute((0, bgp.ATTR_TYPE_INT_LAST_UPDATE, datetime.datetime.now()))) |
| 39 | + |
| 40 | + #for prefix in withdrawnPrefixes: |
| 41 | + # try: |
| 42 | + # del self.prefixes[prefix] |
| 43 | + # except KeyError: |
| 44 | + # print "withdrawn prefix", prefix, "not found." |
| 45 | + |
| 46 | + for prefix in nlri: |
| 47 | + #self.prefixes[prefix] = attrSet |
| 48 | + p = self.prefixes.add(str(prefix)) |
| 49 | + p.data["attributes"] = attrSet |
| 50 | + #print p.prefix |
| 51 | + |
| 52 | + def printStats(self): |
| 53 | + print "Now %d prefixes in table, %d total nlri, %d withdrawals" % (len(self.prefixes.nodes()), self.nlriCount, self.withdrawnCount) |
| 54 | + |
| 55 | + #p = bgp.IPPrefix('145.97.32/20') |
| 56 | + try: |
| 57 | + p = random.choice(self.prefixes.nodes()) |
| 58 | + attrSet = p.data["attributes"] |
| 59 | + print p.prefix |
| 60 | + for a in attrSet: |
| 61 | + print "\t", a.name, a |
| 62 | + except: pass |
| 63 | + |
| 64 | +#bgpprot = bgp.BGP(myASN=14907, bgpId=1) |
| 65 | + |
| 66 | +#print [ord(i) for i in bgpprot.constructOpen()] |
| 67 | + |
| 68 | +peers = {} |
| 69 | + |
| 70 | +peering = bgp.BGPPeering() |
| 71 | +peering.peerAddr = '145.97.39.131' |
| 72 | + |
| 73 | +peers[peering.peerAddr] = peering |
| 74 | + |
| 75 | +peering2 = bgp.BGPPeering() |
| 76 | +peering2.peerAddr = '127.0.0.1' |
| 77 | + |
| 78 | +#peers[peering2.peerAddr] = peering2 |
| 79 | + |
| 80 | +peering3 = bgp.BGPPeering() |
| 81 | +peering3.peerAddr = '192.168.37.1' |
| 82 | + |
| 83 | + |
| 84 | +#peers[peering3.peerAddr] = peering3 |
| 85 | + |
| 86 | +for peer in peers.values(): |
| 87 | + peer.myASN = 64600 |
| 88 | + peer.bgpId = 111 |
| 89 | + peer.registerConsumer(BGPDebug()) |
| 90 | + |
| 91 | +bgpServer = bgp.BGPServerFactory(peers) |
| 92 | +reactor.listenTCP(1000+bgp.PORT, bgpServer) |
| 93 | + |
| 94 | +for p in peers.itervalues(): p.manualStart() |
| 95 | + |
| 96 | +reactor.run() |
\ No newline at end of file |