Beispiel #1
0
    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
        addpath = negotiated.addpath.send(AFI.ipv4, SAFI.unicast)

        while del_nlri:
            nlri = del_nlri.pop()
            packed = nlri.pack(addpath)
            if len(packed_del + packed) >= 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(prefix(packed_del) + prefix(''))
                packed_del = packed
            else:
                packed_del += packed

        # withdrawn MP

        packed_mp_del = ''

        families = del_mp.keys()
        while families:
            family = families.pop()
            mps = del_mp[family]
            addpath = negotiated.addpath.send(*family)
            mp_packed_generator = MPURNLRI(mps).packed_attributes(addpath)
            try:
                while True:
                    packed = mp_packed_generator.next()
                    if len(packed_del + packed_mp_del + packed) >= 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(
                            prefix(packed_del) + 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
        if len(packed_del + packed_mp_del) >= msg_size:
            yield self._message(prefix(packed_del) + prefix(packed_mp_del))
            packed_del = ''
            packed_mp_del = ''

        families = add_mp.keys()
        while families:
            family = families.pop()
            mps = add_mp[family]
            addpath = negotiated.addpath.send(*family)
            mp_packed_generator = MPRNLRI(mps).packed_attributes(addpath)
            try:
                while True:
                    packed = mp_packed_generator.next()
                    if len(packed_del + packed_mp_del + packed_mp_add +
                           packed) >= 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(
                            prefix(packed_del) +
                            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
        if len(packed_del + packed_mp_del + packed_mp_add) >= msg_size:
            yield self._message(prefix(packed_del) + 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(addpath)
            if len(packed_del + packed_mp_del + packed_mp_add + packed_add +
                   packed) >= 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(
                        prefix(packed_del) +
                        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(
                        prefix(packed_del) + 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(
            prefix(packed_del) + prefix(attr + packed_mp_del + packed_mp_add) +
            packed_add)
Beispiel #2
0
    def messages(self, negotiated):
        attributes = ''

        asn4 = negotiated.asn4
        local_as = negotiated.local_as
        peer_as = negotiated.peer_as

        msg_size = negotiated.msg_size - 2 - 2  # 2 bytes for each of the two prefix() header

        # 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:
            attr = self.attributes.pack(asn4, local_as, peer_as, True)
        elif add_mp:
            add_default = False
            for afi, safi in add_mp:
                if safi not in (SAFI.flow_ip, SAFI.flow_vpn):
                    add_default = True
            attr = self.attributes.pack(asn4, local_as, peer_as, add_default)
        else:
            attr = ''

        # generate the message

        packed_del = ''
        packed_mp_del = ''
        packed_mp_add = ''
        packed_add = ''

        # withdrawn IPv4

        addpath = negotiated.addpath.send(AFI.ipv4, SAFI.unicast)

        while del_nlri:
            nlri = del_nlri.pop()
            packed = nlri.pack(addpath)
            if len(packed_del + packed) > 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(prefix(packed_del))
                packed_del = packed
            else:
                packed_del += packed

        # withdrawn MP

        families = del_mp.keys()
        while families:
            family = families.pop()
            mps = del_mp[family]
            addpath = negotiated.addpath.send(*family)
            mp_packed_generator = MPURNLRI(mps).packed_attributes(addpath)
            try:
                while True:
                    packed = mp_packed_generator.next()
                    if len(packed_del + packed_mp_del + packed) > 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(
                            prefix(packed_del) + prefix(packed_mp_del))
                        packed_del = ''
                        packed_mp_del = packed
                    else:
                        packed_mp_del += packed
            except StopIteration:
                pass

        # we have some MPRNLRI so we need to add the attributes, recalculate
        # and make sure we do not overflow

        if add_mp:
            msg_size = negotiated.msg_size - 2 - 2 - len(
                attr)  # 2 bytes for each of the two prefix() header
        if len(packed_del + packed_mp_del) > msg_size:
            yield self._message(prefix(packed_del) + prefix(packed_mp_del))
            packed_del = ''
            packed_mp_del = ''

        # add MP

        families = add_mp.keys()
        while families:
            family = families.pop()
            mps = add_mp[family]
            addpath = negotiated.addpath.send(*family)
            mp_packed_generator = MPRNLRI(mps).packed_attributes(addpath)
            try:
                while True:
                    packed = mp_packed_generator.next()
                    if len(packed_del + packed_mp_del + packed_mp_add +
                           packed) > 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(
                            prefix(packed_del) +
                            prefix(attributes + packed_mp_del + packed_mp_add))
                        packed_del = ''
                        packed_mp_del = ''
                        packed_mp_add = packed
                        if family not in ((AFI.ipv4, SAFI.flow_ip),
                                          (AFI.ipv4, SAFI.flow_vpn)):
                            attributes = attr
                        else:
                            attributes = ''
                    else:
                        packed_mp_add += packed
                        attributes = attr
            except StopIteration:
                pass

        # recalculate size if we do not have any more attributes to send

        if not packed_mp_add:
            msg_size = negotiated.msg_size - 2 - 2  # 2 bytes for each of the two prefix() header

        # ADD Ipv4

        addpath = negotiated.addpath.send(AFI.ipv4, SAFI.unicast)
        while add_nlri:
            nlri = add_nlri.pop()
            packed = nlri.pack(addpath)
            if len(packed_del + packed_mp_del + packed_mp_add + packed_add +
                   packed) > 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(
                        prefix(packed_del) +
                        prefix(attributes + packed_mp_del + packed_mp_add) +
                        packed_add)
                    msg_size = negotiated.msg_size - 2 - 2  # 2 bytes for each of the two prefix() header
                else:
                    yield self._message(
                        prefix(packed_del) + prefix(packed_mp_del) +
                        packed_add)
                packed_del = ''
                packed_mp_del = ''
                packed_mp_add = ''
                packed_add = packed
                attributes = attr
            else:
                packed_add += packed
                attributes = attr

        yield self._message(
            prefix(packed_del) +
            prefix(attributes + packed_mp_del + packed_mp_add) + packed_add)
Beispiel #3
0
	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
		addpath = negotiated.addpath.send(AFI.ipv4,SAFI.unicast)

		while del_nlri:
			nlri = del_nlri.pop()
			packed = nlri.pack(addpath)
			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]
			addpath = negotiated.addpath.send(*family)
			seen_size = len(packed_del + packed_mp_del)
			mp_packed_generator = MPURNLRI(afi,safi,mps).packed_attributes(addpath,msg_size-seen_size)
			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]
			addpath = negotiated.addpath.send(*family)
			seen_size = len(packed_del + packed_mp_del + packed_mp_add)
			mp_packed_generator = MPRNLRI(afi,safi,mps).packed_attributes(addpath,msg_size-seen_size)
			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(addpath)
			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)
Beispiel #4
0
	def messages (self,negotiated):
		attributes = ''

		asn4 = negotiated.asn4
		local_as = negotiated.local_as
		peer_as = negotiated.peer_as

		msg_size = negotiated.msg_size - 2 - 2  # 2 bytes for each of the two prefix() header

		# 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:
			attr = self.attributes.pack(asn4,local_as,peer_as,True)
		elif add_mp:
			add_default = False
			for afi,safi in add_mp:
				if safi not in (SAFI.flow_ip,SAFI.flow_vpn):
					add_default = True
			attr = self.attributes.pack(asn4,local_as,peer_as,add_default)
		else:
			attr = ''

		# generate the message

		packed_del = ''
		packed_mp_del = ''
		packed_mp_add = ''
		packed_add = ''


		# withdrawn IPv4

		addpath = negotiated.addpath.send(AFI.ipv4,SAFI.unicast)

		while del_nlri:
			nlri = del_nlri.pop()
			packed = nlri.pack(addpath)
			if len(packed_del + packed) > 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(prefix(packed_del))
				packed_del = packed
			else:
				packed_del += packed


		# withdrawn MP

		families = del_mp.keys()
		while families:
			family = families.pop()
			mps = del_mp[family]
			addpath = negotiated.addpath.send(*family)
			mp_packed_generator = MPURNLRI(mps).packed_attributes(addpath)
			try:
				while True:
					packed = mp_packed_generator.next()
					if len(packed_del + packed_mp_del + packed) > 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(prefix(packed_del) + prefix(packed_mp_del))
						packed_del = ''
						packed_mp_del = packed
					else:
						packed_mp_del += packed
			except StopIteration:
				pass

		# we have some MPRNLRI so we need to add the attributes, recalculate
		# and make sure we do not overflow

		if add_mp:
			msg_size = negotiated.msg_size - 2 - 2 - len(attr)  # 2 bytes for each of the two prefix() header
		if len(packed_del + packed_mp_del) > msg_size:
			yield self._message(prefix(packed_del) + prefix(packed_mp_del))
			packed_del = ''
			packed_mp_del = ''

		# add MP

		families = add_mp.keys()
		while families:
			family = families.pop()
			mps = add_mp[family]
			addpath = negotiated.addpath.send(*family)
			mp_packed_generator = MPRNLRI(mps).packed_attributes(addpath)
			try:
				while True:
					packed = mp_packed_generator.next()
					if len(packed_del + packed_mp_del + packed_mp_add + packed) > 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(prefix(packed_del) + prefix(attributes + packed_mp_del + packed_mp_add))
						packed_del = ''
						packed_mp_del = ''
						packed_mp_add = packed
						if family not in ((AFI.ipv4,SAFI.flow_ip),(AFI.ipv4,SAFI.flow_vpn)):
							attributes = attr
						else:
							attributes = ''
					else:
						packed_mp_add += packed
						attributes = attr
			except StopIteration:
				pass

		# recalculate size if we do not have any more attributes to send

		if not packed_mp_add:
			msg_size = negotiated.msg_size - 2 - 2  # 2 bytes for each of the two prefix() header

		# ADD Ipv4

		addpath = negotiated.addpath.send(AFI.ipv4,SAFI.unicast)
		while add_nlri:
			nlri = add_nlri.pop()
			packed = nlri.pack(addpath)
			if len(packed_del + packed_mp_del + packed_mp_add + packed_add + packed) > 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(prefix(packed_del) + prefix(attributes + packed_mp_del + packed_mp_add) + packed_add)
					msg_size = negotiated.msg_size - 2 - 2  # 2 bytes for each of the two prefix() header
				else:
					yield self._message(prefix(packed_del) + prefix(packed_mp_del) + packed_add)
				packed_del = ''
				packed_mp_del = ''
				packed_mp_add = ''
				packed_add = packed
				attributes = attr
			else:
				packed_add += packed
				attributes = attr

		yield self._message(prefix(packed_del) + prefix(attributes + packed_mp_del + packed_mp_add) + packed_add)