def messages(self, negotiated, include_withdraw=True): # sort the nlris nlris = [] mp_nlris = {} for nlri in sorted(self.nlris): if nlri.family() in negotiated.families: if nlri.afi == AFI.ipv4 and nlri.safi in [ SAFI.unicast, SAFI.multicast ] and nlri.nexthop.afi == AFI.ipv4: nlris.append(nlri) else: mp_nlris.setdefault(nlri.family(), {}).setdefault(nlri.action, []).append(nlri) if not nlris and not mp_nlris: return # If all we have is MP_UNREACH_NLRI, we do not need the default # attributes. See RFC4760 that states the following: # # An UPDATE message that contains the MP_UNREACH_NLRI is not required # to carry any other path attributes. # include_defaults = True if mp_nlris and not nlris: for family, actions in mp_nlris.items(): afi, safi = family if safi not in (SAFI.unicast, SAFI.multicast): break if set(actions.keys()) != {OUT.WITHDRAW}: break else: include_defaults = False attr = self.attributes.pack(negotiated, include_defaults) # Withdraws/NLRIS (IPv4 unicast and multicast) msg_size = negotiated.msg_size - 19 - 2 - 2 - len( attr) # 2 bytes for each of the two prefix() header if msg_size < 0: # raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') Logger().critical( 'attributes size is so large we can not even pack one NLRI', 'parser') return if msg_size == 0 and (nlris or mp_nlris): # raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') Logger().critical( 'attributes size is so large we can not even pack one NLRI', 'parser') return withdraws = b'' announced = b'' for nlri in nlris: packed = nlri.pack(negotiated) if len(announced + withdraws + packed) <= msg_size: if nlri.action == OUT.ANNOUNCE: announced += packed elif include_withdraw: withdraws += packed continue if not withdraws and not announced: # raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') Logger().critical( 'attributes size is so large we can not even pack one NLRI', 'parser') return if announced: yield self._message( Update.prefix(withdraws) + Update.prefix(attr) + announced) else: yield self._message( Update.prefix(withdraws) + Update.prefix(b'') + announced) if nlri.action == OUT.ANNOUNCE: announced = packed withdraws = b'' elif include_withdraw: withdraws = packed announced = b'' else: withdraws = b'' announced = b'' if announced or withdraws: if announced: yield self._message( Update.prefix(withdraws) + Update.prefix(attr) + announced) else: yield self._message( Update.prefix(withdraws) + Update.prefix(b'') + announced) for family in mp_nlris.keys(): afi, safi = family mp_reach = b'' mp_unreach = b'' mp_announce = MPRNLRI(afi, safi, mp_nlris[family].get(OUT.ANNOUNCE, [])) mp_withdraw = MPURNLRI(afi, safi, mp_nlris[family].get(OUT.WITHDRAW, [])) for mprnlri in mp_announce.packed_attributes( negotiated, msg_size - len(withdraws + announced)): if mp_reach: yield self._message( Update.prefix(withdraws) + Update.prefix(attr + mp_reach) + announced) announced = b'' withdraws = b'' mp_reach = mprnlri if include_withdraw: for mpurnlri in mp_withdraw.packed_attributes( negotiated, msg_size - len(withdraws + announced + mp_reach)): if mp_unreach: yield self._message( Update.prefix(withdraws) + Update.prefix(attr + mp_unreach + mp_reach) + announced) mp_reach = b'' announced = b'' withdraws = b'' mp_unreach = mpurnlri yield self._message( Update.prefix(withdraws) + Update.prefix(attr + mp_unreach + mp_reach) + announced) # yield mpr/mpur per family withdraws = b'' announced = b''
def messages (self, negotiated, include_withdraw=True): # sort the nlris add_nlri = [] del_nlri = [] add_mp = {} del_mp = {} for nlri in self.nlris: if nlri.family() in negotiated.families: if nlri.afi == AFI.ipv4 and nlri.safi in [SAFI.unicast, SAFI.multicast]: if nlri.action == OUT.ANNOUNCE: add_nlri.append(nlri) elif include_withdraw: del_nlri.append(nlri) else: if nlri.action == OUT.ANNOUNCE: add_mp.setdefault(nlri.family(),[]).append(nlri) elif include_withdraw: del_mp.setdefault(nlri.family(),[]).append(nlri) if not add_nlri and not del_nlri and not add_mp and not del_mp: return if add_nlri or add_mp: attr = self.attributes.pack(negotiated,True) else: attr = '' # withdrawn IPv4 packed_del = '' msg_size = negotiated.msg_size - 19 - 2 - 2 # 2 bytes for each of the two prefix() header while del_nlri: nlri = del_nlri.pop() packed = nlri.pack(negotiated) seen_size = len(packed_del + packed) if seen_size > msg_size: if not packed_del: raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') yield self._message(Update.prefix(packed_del) + Update.prefix('')) packed_del = packed else: packed_del += packed # withdrawn MP packed_mp_del = '' families = del_mp.keys() while families: family = families.pop() afi,safi = family mps = del_mp[family] seen_size = len(packed_del + packed_mp_del) mp_packed_generator = MPURNLRI(afi,safi,mps).packed_attributes(negotiated) try: while True: packed = mp_packed_generator.next() seen_size = len(packed_del + packed_mp_del + packed) if seen_size > msg_size: if not packed_mp_del and not packed_del: raise Notify(6,0,'attributes size is so large we can not even pack one MPURNLRI') yield self._message(Update.prefix(packed_del) + Update.prefix(packed_mp_del)) packed_del = '' packed_mp_del = packed else: packed_mp_del += packed except StopIteration: pass # add MP # we have some MPRNLRI so we need to add the attributes, recalculate # and make sure we do not overflow packed_mp_add = '' if add_mp: msg_size = negotiated.msg_size - 19 - 2 - 2 - len(attr) # 2 bytes for each of the two prefix() header seen_size = len(packed_del + packed_mp_del) if seen_size > msg_size: yield self._message(Update.prefix(packed_del) + Update.prefix(packed_mp_del)) packed_del = '' packed_mp_del = '' families = add_mp.keys() while families: family = families.pop() afi,safi = family mps = add_mp[family] seen_size = len(packed_del + packed_mp_del + packed_mp_add) mp_packed_generator = MPRNLRI(afi,safi,mps).packed_attributes(negotiated) try: while True: packed = mp_packed_generator.next() seen_size = len(packed_del + packed_mp_del + packed_mp_add + packed) if seen_size > msg_size: if not packed_mp_add and not packed_mp_del and not packed_del: raise Notify(6,0,'attributes size is so large we can not even pack on MPURNLRI') yield self._message(Update.prefix(packed_del) + Update.prefix(attr + packed_mp_del + packed_mp_add)) packed_del = '' packed_mp_del = '' packed_mp_add = packed else: packed_mp_add += packed except StopIteration: pass # ADD Ipv4 packed_add = '' if add_nlri: msg_size = negotiated.msg_size - 19 - 2 - 2 - len(attr) # 2 bytes for each of the two prefix() header seen_size = len(packed_del + packed_mp_del + packed_mp_add) if seen_size > msg_size: yield self._message(Update.prefix(packed_del) + Update.prefix(packed_mp_del)) packed_del = '' packed_mp_del = '' addpath = negotiated.addpath.send(AFI.ipv4,SAFI.unicast) while add_nlri: nlri = add_nlri.pop() packed = nlri.pack(negotiated) seen_size = len(packed_del + packed_mp_del + packed_mp_add + packed_add + packed) if seen_size > msg_size: if not packed_add and not packed_mp_add and not packed_mp_del and not packed_del: raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') if packed_mp_add: yield self._message(Update.prefix(packed_del) + Update.prefix(attr + packed_mp_del + packed_mp_add) + packed_add) msg_size = negotiated.msg_size - 19 - 2 - 2 # 2 bytes for each of the two prefix() header else: yield self._message(Update.prefix(packed_del) + Update.prefix(attr + packed_mp_del) + packed_add) packed_del = '' packed_mp_del = '' packed_mp_add = '' packed_add = packed else: packed_add += packed yield self._message(Update.prefix(packed_del) + Update.prefix(attr + packed_mp_del + packed_mp_add) + packed_add)
def messages(self, negotiated, include_withdraw=True): # sort the nlris nlris = [] mp_nlris = {} for nlri in self.nlris: if nlri.family() in negotiated.families: if nlri.afi == AFI.ipv4 and nlri.safi in [ SAFI.unicast, SAFI.multicast ]: nlris.append(nlri) else: mp_nlris.setdefault(nlri.family(), {}).setdefault(nlri.action, []).append(nlri) if not nlris and not mp_nlris: return attr = self.attributes.pack(negotiated, True) # Withdraws/NLRIS (IPv4 unicast and multicast) msg_size = negotiated.msg_size - 19 - 2 - 2 - len( attr) # 2 bytes for each of the two prefix() header withdraws = b'' announced = b'' for nlri in nlris: packed = nlri.pack(negotiated) if len(announced + withdraws + packed) > msg_size: if not withdraws and not announced: raise Notify( 6, 0, 'attributes size is so large we can not even pack one NLRI' ) yield self._message( Update.prefix(withdraws) + Update.prefix(attr) + announced) if nlri.action == OUT.ANNOUNCE: announced = packed withdraws = b'' elif include_withdraw: withdraws = packed announced = b'' else: if nlri.action == OUT.ANNOUNCE: announced += packed elif include_withdraw: withdraws += packed if mp_nlris: for family in mp_nlris.keys(): afi, safi = family mp_reach = b'' mp_unreach = b'' mp_announce = MPRNLRI(afi, safi, mp_nlris[family].get(OUT.ANNOUNCE, [])) mp_withdraw = MPURNLRI(afi, safi, mp_nlris[family].get(OUT.WITHDRAW, [])) for mprnlri in mp_announce.packed_attributes( negotiated, msg_size - len(withdraws + announced)): if mp_reach: yield self._message( Update.prefix(withdraws) + Update.prefix(attr + mp_reach) + announced) announced = b'' withdraws = b'' mp_reach = mprnlri if include_withdraw: for mpurnlri in mp_withdraw.packed_attributes( negotiated, msg_size - len(withdraws + announced + mp_reach)): if mp_unreach: yield self._message( Update.prefix(withdraws) + Update.prefix(attr + mp_unreach + mp_reach) + announced) mp_reach = b'' announced = b'' withdraws = b'' mp_unreach = mpurnlri yield self._message( Update.prefix(withdraws) + Update.prefix(attr + mp_unreach + mp_reach) + announced) # yield mpr/mpur per family withdraws = b'' announced = b'' else: yield self._message( Update.prefix(withdraws) + Update.prefix(attr) + announced)
def messages (self, negotiated): # sort the nlris add_nlri = [] del_nlri = [] add_mp = {} del_mp = {} for nlri in self.nlris: if nlri.family() in negotiated.families: if nlri.afi == AFI.ipv4 and nlri.safi in [SAFI.unicast, SAFI.multicast]: if nlri.action == OUT.ANNOUNCE: add_nlri.append(nlri) else: del_nlri.append(nlri) else: if nlri.action == OUT.ANNOUNCE: add_mp.setdefault(nlri.family(),[]).append(nlri) else: del_mp.setdefault(nlri.family(),[]).append(nlri) if not add_nlri and not del_nlri and not add_mp and not del_mp: return if add_nlri or add_mp: attr = self.attributes.pack(negotiated,True) else: attr = '' # withdrawn IPv4 packed_del = '' msg_size = negotiated.msg_size - 19 - 2 - 2 # 2 bytes for each of the two prefix() header while del_nlri: nlri = del_nlri.pop() packed = nlri.pack(negotiated) seen_size = len(packed_del + packed) if seen_size > msg_size: if not packed_del: raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') yield self._message(Update.prefix(packed_del) + Update.prefix('')) packed_del = packed else: packed_del += packed # withdrawn MP packed_mp_del = '' families = del_mp.keys() while families: family = families.pop() afi,safi = family mps = del_mp[family] seen_size = len(packed_del + packed_mp_del) mp_packed_generator = MPURNLRI(afi,safi,mps).packed_attributes(negotiated) try: while True: packed = mp_packed_generator.next() seen_size = len(packed_del + packed_mp_del + packed) if seen_size > msg_size: if not packed_mp_del and not packed_del: raise Notify(6,0,'attributes size is so large we can not even pack one MPURNLRI') yield self._message(Update.prefix(packed_del) + Update.prefix(packed_mp_del)) packed_del = '' packed_mp_del = packed else: packed_mp_del += packed except StopIteration: pass # add MP # we have some MPRNLRI so we need to add the attributes, recalculate # and make sure we do not overflow packed_mp_add = '' if add_mp: msg_size = negotiated.msg_size - 19 - 2 - 2 - len(attr) # 2 bytes for each of the two prefix() header seen_size = len(packed_del + packed_mp_del) if seen_size > msg_size: yield self._message(Update.prefix(packed_del) + Update.prefix(packed_mp_del)) packed_del = '' packed_mp_del = '' families = add_mp.keys() while families: family = families.pop() afi,safi = family mps = add_mp[family] seen_size = len(packed_del + packed_mp_del + packed_mp_add) mp_packed_generator = MPRNLRI(afi,safi,mps).packed_attributes(negotiated) try: while True: packed = mp_packed_generator.next() seen_size = len(packed_del + packed_mp_del + packed_mp_add + packed) if seen_size > msg_size: if not packed_mp_add and not packed_mp_del and not packed_del: raise Notify(6,0,'attributes size is so large we can not even pack on MPURNLRI') yield self._message(Update.prefix(packed_del) + Update.prefix(attr + packed_mp_del + packed_mp_add)) packed_del = '' packed_mp_del = '' packed_mp_add = packed else: packed_mp_add += packed except StopIteration: pass # ADD Ipv4 packed_add = '' if add_nlri: msg_size = negotiated.msg_size - 19 - 2 - 2 - len(attr) # 2 bytes for each of the two prefix() header seen_size = len(packed_del + packed_mp_del + packed_mp_add) if seen_size > msg_size: yield self._message(Update.prefix(packed_del) + Update.prefix(packed_mp_del)) packed_del = '' packed_mp_del = '' addpath = negotiated.addpath.send(AFI.ipv4,SAFI.unicast) while add_nlri: nlri = add_nlri.pop() packed = nlri.pack(negotiated) seen_size = len(packed_del + packed_mp_del + packed_mp_add + packed_add + packed) if seen_size > msg_size: if not packed_add and not packed_mp_add and not packed_mp_del and not packed_del: raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') if packed_mp_add: yield self._message(Update.prefix(packed_del) + Update.prefix(attr + packed_mp_del + packed_mp_add) + packed_add) msg_size = negotiated.msg_size - 19 - 2 - 2 # 2 bytes for each of the two prefix() header else: yield self._message(Update.prefix(packed_del) + Update.prefix(attr + packed_mp_del) + packed_add) packed_del = '' packed_mp_del = '' packed_mp_add = '' packed_add = packed else: packed_add += packed yield self._message(Update.prefix(packed_del) + Update.prefix(attr + packed_mp_del + packed_mp_add) + packed_add)
def messages (self, negotiated, include_withdraw=True): # sort the nlris nlris = [] mp_nlris = {} for nlri in self.nlris: if nlri.family() in negotiated.families: if nlri.afi == AFI.ipv4 and nlri.safi in [SAFI.unicast, SAFI.multicast]: nlris.append(nlri) else: mp_nlris.setdefault(nlri.family(), {}).setdefault(nlri.action, []).append(nlri) if not nlris and not mp_nlris: return attr = self.attributes.pack(negotiated, True) # Withdraws/NLRIS (IPv4 unicast and multicast) msg_size = negotiated.msg_size - 19 - 2 - 2 - len(attr) # 2 bytes for each of the two prefix() header withdraws = b'' announced = b'' for nlri in nlris: packed = nlri.pack(negotiated) if len(announced + withdraws + packed) > msg_size: if not withdraws and not announced: raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') yield self._message(Update.prefix(withdraws) + Update.prefix(attr) + announced) if nlri.action == OUT.ANNOUNCE: announced = packed withdraws = b'' elif include_withdraw: withdraws = packed announced = b'' else: if nlri.action == OUT.ANNOUNCE: announced += packed elif include_withdraw: withdraws += packed if mp_nlris: for family in mp_nlris.keys(): afi, safi = family mp_reach = b'' mp_unreach = b'' mp_announce = MPRNLRI(afi, safi, mp_nlris[family].get(OUT.ANNOUNCE, [])) mp_withdraw = MPURNLRI(afi, safi, mp_nlris[family].get(OUT.WITHDRAW, [])) for mprnlri in mp_announce.packed_attributes(negotiated, msg_size - len(withdraws + announced)): if mp_reach: yield self._message(Update.prefix(withdraws) + Update.prefix(attr + mp_reach) + announced) announced = b'' withdraws = b'' mp_reach = mprnlri if include_withdraw: for mpurnlri in mp_withdraw.packed_attributes(negotiated, msg_size - len(withdraws + announced + mp_reach)): if mp_unreach: yield self._message(Update.prefix(withdraws) + Update.prefix(attr + mp_unreach + mp_reach) + announced) mp_reach = b'' announced = b'' withdraws = b'' mp_unreach = mpurnlri yield self._message(Update.prefix(withdraws) + Update.prefix(attr + mp_unreach + mp_reach) + announced) # yield mpr/mpur per family withdraws = b'' announced = b'' else: yield self._message(Update.prefix(withdraws) + Update.prefix(attr) + announced)
def messages (self, negotiated, include_withdraw=True): # sort the nlris nlris = [] mp_nlris = {} for nlri in sorted(self.nlris): if nlri.family() in negotiated.families: if nlri.afi == AFI.ipv4 and nlri.safi in [SAFI.unicast, SAFI.multicast] and nlri.nexthop.afi == AFI.ipv4 and not hasattr(negotiated.neighbor,'bgpsec'): nlris.append(nlri) else: mp_nlris.setdefault(nlri.family(), {}).setdefault(nlri.action, []).append(nlri) if not nlris and not mp_nlris: return if hasattr(negotiated.neighbor,'bgpsec') and negotiated.neighbor.bgpsec : mp_nlris_values = mp_nlris.values() for mp_nlri in list(mp_nlris_values)[0].get(OUT.ANNOUNCE, []) : attr = self.attributes.pack(negotiated, True, mp_nlri) # Withdraws/NLRIS (IPv4 unicast and multicast) msg_size = negotiated.msg_size - 19 - 2 - 2 - len(attr) # 2 bytes for each of the two prefix() header if msg_size < 0: # raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') Logger().critical('attributes size is so large we can not even pack one NLRI','parser') return if msg_size == 0 and (nlris or mp_nlris): # raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') Logger().critical('attributes size is so large we can not even pack one NLRI','parser') return withdraws = b'' announced = b'' for family in mp_nlris.keys(): afi, safi = family mp_reach = b'' mp_unreach = b'' mp_announce = MPRNLRI(afi, safi, [mp_nlri]) mp_withdraw = MPURNLRI(afi, safi, mp_nlris[family].get(OUT.WITHDRAW, [])) for mprnlri in mp_announce.packed_attributes(negotiated, msg_size - len(withdraws + announced)): if mp_reach: yield self._message(Update.prefix(withdraws) + Update.prefix(attr + mp_reach) + announced) announced = b'' withdraws = b'' mp_reach = mprnlri if include_withdraw: for mpurnlri in mp_withdraw.packed_attributes(negotiated, msg_size - len(withdraws + announced + mp_reach)): if mp_unreach: yield self._message(Update.prefix(withdraws) + Update.prefix(attr + mp_unreach + mp_reach) + announced) mp_reach = b'' announced = b'' withdraws = b'' mp_unreach = mpurnlri yield self._message(Update.prefix(withdraws) + Update.prefix(attr + mp_unreach + mp_reach) + announced) # yield mpr/mpur per family withdraws = b'' announced = b'' else : attr = self.attributes.pack(negotiated, True) # Withdraws/NLRIS (IPv4 unicast and multicast) msg_size = negotiated.msg_size - 19 - 2 - 2 - len(attr) # 2 bytes for each of the two prefix() header if msg_size < 0: # raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') Logger().critical('attributes size is so large we can not even pack one NLRI','parser') return if msg_size == 0 and (nlris or mp_nlris): # raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') Logger().critical('attributes size is so large we can not even pack one NLRI','parser') return withdraws = b'' announced = b'' for nlri in nlris: packed = nlri.pack(negotiated) if len(announced + withdraws + packed) <= msg_size: if nlri.action == OUT.ANNOUNCE: announced += packed elif include_withdraw: withdraws += packed continue if not withdraws and not announced: # raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') Logger().critical('attributes size is so large we can not even pack one NLRI','parser') return if announced: yield self._message(Update.prefix(withdraws) + Update.prefix(attr) + announced) else: yield self._message(Update.prefix(withdraws) + Update.prefix(b'') + announced) if nlri.action == OUT.ANNOUNCE: announced = packed withdraws = b'' elif include_withdraw: withdraws = packed announced = b'' else: withdraws = b'' announced = b'' if announced or withdraws: if announced: yield self._message(Update.prefix(withdraws) + Update.prefix(attr) + announced) else: yield self._message(Update.prefix(withdraws) + Update.prefix(b'') + announced) for family in mp_nlris.keys(): afi, safi = family mp_reach = b'' mp_unreach = b'' mp_announce = MPRNLRI(afi, safi, mp_nlris[family].get(OUT.ANNOUNCE, [])) mp_withdraw = MPURNLRI(afi, safi, mp_nlris[family].get(OUT.WITHDRAW, [])) for mprnlri in mp_announce.packed_attributes(negotiated, msg_size - len(withdraws + announced)): if mp_reach: yield self._message(Update.prefix(withdraws) + Update.prefix(attr + mp_reach) + announced) announced = b'' withdraws = b'' mp_reach = mprnlri if include_withdraw: for mpurnlri in mp_withdraw.packed_attributes(negotiated, msg_size - len(withdraws + announced + mp_reach)): if mp_unreach: yield self._message(Update.prefix(withdraws) + Update.prefix(attr + mp_unreach + mp_reach) + announced) mp_reach = b'' announced = b'' withdraws = b'' mp_unreach = mpurnlri yield self._message(Update.prefix(withdraws) + Update.prefix(attr + mp_unreach + mp_reach) + announced) # yield mpr/mpur per family withdraws = b'' announced = b''