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 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 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''