def bgp_announce(self, asn4, local_asn, peer_asn): ibgp = (local_asn == peer_asn) # we do not store or send MED message = '' if AttributeID.ORIGIN in self: message += self[AttributeID.ORIGIN].pack() elif self.autocomplete: message += Origin(Origin.IGP).pack() if AttributeID.AS_PATH in self: asp = self[AttributeID.AS_PATH] message += self._as_path(asn4, asp) elif self.autocomplete: if ibgp: asp = ASPath(asn4, ASPath.AS_SEQUENCE, []) else: asp = ASPath(asn4, ASPath.AS_SEQUENCE, [local_asn]) message += self._as_path(asn4, asp) else: raise RuntimeError('Generated routes must always have an AS_PATH ') if AttributeID.NEXT_HOP in self: afi = self[AttributeID.NEXT_HOP].next_hop.afi safi = self[AttributeID.NEXT_HOP].next_hop.safi if afi == AFI.ipv4 and safi in [SAFI.unicast, SAFI.multicast]: message += self[AttributeID.NEXT_HOP].pack() if ibgp: if AttributeID.LOCAL_PREF in self: message += self[AttributeID.LOCAL_PREF].pack() else: message += LocalPreference(100).pack() if AttributeID.MED in self: if local_asn != peer_asn: message += self[AttributeID.MED].pack() if AttributeID.PMSI_TUNNEL in self: message += self[AttributeID.PMSI_TUNNEL].pack() for attribute in [ AttributeID.COMMUNITY, AttributeID.EXTENDED_COMMUNITY ]: if attribute in self: message += self[attribute].pack() return message
def __new_ASPath(self, data, asn4=False): if len(data) == 0: return ASPath(asn4) if asn4: size = 4 decoder = 'L' # could it be 'I' as well ? else: size = 2 decoder = 'H' stype = ord(data[0]) slen = ord(data[1]) sdata = data[2:2 + (slen * size)] ASPS = ASPath(asn4, stype) format = '!' + (decoder * slen) for c in unpack(format, sdata): ASPS.add(c) return ASPS
def __new_ASPath (self,data,asn4=False): if len(data) == 0: return ASPath(asn4) if asn4: size = 4 decoder = 'L' # could it be 'I' as well ? else: size = 2 decoder = 'H' stype = ord(data[0]) slen = ord(data[1]) sdata = data[2:2+(slen*size)] ASPS = ASPath(asn4,stype) format = '!'+(decoder*slen) for c in unpack(format,sdata): ASPS.add(c) return ASPS
def _route_aspath (self,scope,tokens): aspath = ASPath() asn = tokens.pop(0) try: if asn == '[': while True: try: asn = tokens.pop(0) except IndexError: self._error = self._str_route_error if self.debug: raise return False if asn == ']': break aspath.add(self._newASN(asn)) else: aspath.add(self._newASN(asn)) except ValueError: self._error = self._str_route_error if self.debug: raise return False scope[-1]['routes'][-1].attributes.add(aspath) return True
def __merge_attributes(self): as2path = self.attributes[AttributeID.AS_PATH] as4path = self.attributes[AttributeID.AS4_PATH] newASPS = ASPath(True, as2path.asptype) len2 = len(as2path.aspsegment) len4 = len(as4path.aspsegment) if len2 < len4: for asn in as4path.aspsegment: newASPS.add(asn) else: for asn in as2path.aspsegment[:-len4]: newASPS.add(asn) for asn in as4path.aspsegment: newASPS.add(asn) self.attributes.remove(AttributeID.AS_PATH) self.attributes.remove(AttributeID.AS4_PATH) self.attributes.add(newASPS)
def _as_path(self, asn4, asp): message = '' # if the peer does not understand ASN4, we need to build a transitive AS4_PATH if not asn4: has_asn4 = False aspath = ASPath(False, asp.asptype) as4path = AS4Path(asp.asptype) for segment in asp.aspsegment: if segment.asn4(): has_asn4 = True aspath.add(AS_TRANS) as4path.add(segment) else: aspath.add(segment) as4path.add(segment) message += aspath.pack() if has_asn4: message += as4path.pack() else: message += ASPath(True, asp.asptype, asp.aspsegment).pack() return message
def __merge_attributes (self): as2path = self.attributes[AttributeID.AS_PATH] as4path = self.attributes[AttributeID.AS4_PATH] newASPS = ASPath(True,as2path.asptype) len2 = len(as2path.aspsegment) len4 = len(as4path.aspsegment) if len2 < len4: for asn in as4path.aspsegment: newASPS.add(asn) else: for asn in as2path.aspsegment[:-len4]: newASPS.add(asn) for asn in as4path.aspsegment: newASPS.add(asn) self.attributes.remove(AttributeID.AS_PATH) self.attributes.remove(AttributeID.AS4_PATH) self.attributes.add(newASPS)