Exemplo n.º 1
0
def ip_label (tokeniser,afi,safi):
	ipmask = prefix(tokeniser)

	nlri = Label(afi,safi,OUT.ANNOUNCE)
	nlri.cidr = CIDR(ipmask.pack(),ipmask.mask)

	change = Change(
		nlri,
		Attributes()
	)

	while True:
		command = tokeniser()

		if not command:
			break

		action = ParseLabel.action.get(command,'')

		if action == 'attribute-add':
			change.attributes.add(ParseLabel.known[command](tokeniser))
		elif action == 'nlri-set':
			change.nlri.assign(ParseLabel.assign[command],ParseLabel.known[command](tokeniser))
		elif action == 'nexthop-and-attribute':
			nexthop,attribute = ParseLabel.known[command](tokeniser)
			change.nlri.nexthop = nexthop
			change.attributes.add(attribute)
		else:
			raise ValueError('route: unknown command "%s"' % command)

	return [change]
Exemplo n.º 2
0
def ip_multicast(tokeniser, afi, safi):
    action = OUT.ANNOUNCE if tokeniser.announce else OUT.WITHDRAW
    ipmask = prefix(tokeniser)

    nlri = INET(afi, safi, action)
    nlri.cidr = CIDR(ipmask.pack(), ipmask.mask)

    change = Change(nlri, Attributes())

    while True:
        command = tokeniser()

        if not command:
            break

        action = AnnounceIP.action.get(command, '')

        if action == 'attribute-add':
            change.attributes.add(AnnounceIP.known[command](tokeniser))
        elif action == 'nlri-set':
            change.nlri.assign(AnnounceIP.assign[command],
                               AnnounceIP.known[command](tokeniser))
        elif action == 'nexthop-and-attribute':
            nexthop, attribute = AnnounceIP.known[command](tokeniser)
            change.nlri.nexthop = nexthop
            change.attributes.add(attribute)
        else:
            raise ValueError('unknown command "%s"' % command)

    return [change]
Exemplo n.º 3
0
def vpls(tokeniser):
    change = Change(VPLS(None, None, None, None, None), Attributes())

    while True:
        command = tokeniser()

        if not command:
            break

        action = ParseVPLS.action[command]

        if 'nlri-set' in action:
            change.nlri.assign(ParseVPLS.assign[command],
                               ParseL2VPN.known[command](tokeniser))
        elif 'attribute-add' in action:
            change.attributes.add(ParseL2VPN.known[command](tokeniser))
        elif action == 'nexthop-and-attribute':
            nexthop, attribute = ParseVPLS.known[command](tokeniser)
            change.nlri.nexthop = nexthop
            change.attributes.add(attribute)
        else:
            raise ValueError('vpls: unknown command "%s"' % command)

    return [
        change,
    ]
Exemplo n.º 4
0
def route(tokeniser):
    change = Change(Flow(), Attributes())

    while True:
        command = tokeniser()

        if not command:
            break

        action = ParseFlow.action[command]

        if action == 'nlri-add':
            for adding in ParseFlow.known[command](tokeniser):
                change.nlri.add(adding)
        elif action == 'attribute-add':
            change.attributes.add(ParseFlow.known[command](tokeniser))
        elif action == 'nexthop-and-attribute':
            nexthop, attribute = ParseFlow.known[command](tokeniser)
            change.nlri.nexthop = nexthop
            change.attributes.add(attribute)
        elif action == 'nop':
            pass  # yes nothing to do !
        else:
            raise ValueError('flow: unknown command "%s"' % command)

    if change.nlri.rd is not RouteDistinguisher.NORD:
        change.nlri.safi = SAFI.flow_vpn

    return [change]
Exemplo n.º 5
0
def ip_vpn(tokeniser, afi, safi):
    action = OUT.ANNOUNCE if tokeniser.announce else OUT.WITHDRAW
    ipmask = prefix(tokeniser)

    nlri = IPVPN(afi, safi, action)
    nlri.cidr = CIDR(ipmask.pack(), ipmask.mask)

    change = Change(nlri, Attributes())

    while True:
        command = tokeniser()

        if not command:
            break

        action = AnnounceVPN.action.get(command, '')

        if action == 'attribute-add':
            change.attributes.add(AnnounceVPN.known[command](tokeniser))
        elif action == 'nlri-set':
            change.nlri.assign(AnnounceVPN.assign[command],
                               AnnounceVPN.known[command](tokeniser))
        elif action == 'nexthop-and-attribute':
            nexthop, attribute = AnnounceVPN.known[command](tokeniser)
            change.nlri.nexthop = nexthop
            change.attributes.add(attribute)
        else:
            raise ValueError('unknown command "%s"' % command)

    if not AnnounceVPN.check(change, afi):
        raise ValueError(
            'invalid announcement (missing next-hop, label or rd ?)')

    return [change]
Exemplo n.º 6
0
def flow(tokeniser, afi, safi):
    change = Change(Flow(afi, safi, OUT.ANNOUNCE), Attributes())

    while True:
        command = tokeniser()

        if not command:
            break

        action = AnnounceFlow.action[command]

        if action == 'nlri-add':
            for adding in AnnounceFlow.known[command](tokeniser):
                change.nlri.add(adding)
        elif action == 'attribute-add':
            change.attributes.add(AnnounceFlow.known[command](tokeniser))
        elif action == 'nexthop-and-attribute':
            nexthop, attribute = AnnounceFlow.known[command](tokeniser)
            change.nlri.nexthop = nexthop
            change.attributes.add(attribute)
        elif action == 'nop':
            pass  # yes nothing to do !
        else:
            raise ValueError('flow: unknown command "%s"' % command)

    return [change]
Exemplo n.º 7
0
def ls_unicast(tokeniser):
    change = Change(LS_UNICAST(None, None, None, None, None, None, None),
                    Attributes())

    while True:
        command = tokeniser()

        if not command:
            break

        action = ParseLSUNICAST.action[command]

        if 'nlri-set' in action:
            change.nlri.assign(
                ParseLSUNICAST.assign[command],
                ParseTrafficEngineering.known[command](tokeniser))
        elif 'attribute-add' in action:
            change.attributes.add(
                ParseTrafficEngineering.known[command](tokeniser))
        elif action == 'nexthop-and-attribute':
            nexthop, attribute = ParseLSUNICAST.known[command](tokeniser)
            change.nlri.nexthop = nexthop
            change.attributes.add(attribute)
        else:
            raise ValueError('ls_unicast: unknown command "%s"' % command)

    return change
Exemplo n.º 8
0
def inet(tokeniser):
    ipmask = prefix(tokeniser)
    inet = INET(afi=IP.toafi(ipmask.top()),
                safi=IP.tosafi(ipmask.top()),
                action=OUT.UNSET)
    inet.cidr = CIDR(ipmask.ton(), ipmask.mask)

    return Change(inet, Attributes())
Exemplo n.º 9
0
def mpls(tokeniser):
    ipmask = prefix(tokeniser)
    mpls = IPVPN(afi=IP.toafi(ipmask.top()),
                 safi=IP.tosafi(ipmask.top()),
                 action=OUT.ANNOUNCE)
    mpls.cidr = CIDR(ipmask.ton(), ipmask.mask)

    return Change(mpls, Attributes())
Exemplo n.º 10
0
def attributes(tokeniser):
    ipmask = prefix(lambda: tokeniser.tokens[-1])

    if 'rd' in tokeniser.tokens or 'route-distinguisher' in tokeniser.tokens:
        nlri = IPVPN(IP.toafi(ipmask.top()), SAFI.mpls_vpn, OUT.ANNOUNCE)
    elif 'label' in tokeniser.tokens:
        nlri = Labelled(IP.toafi(ipmask.top()), SAFI.nlri_mpls, OUT.ANNOUNCE)
    else:
        nlri = INET(IP.toafi(ipmask.top()), IP.tosafi(ipmask.top()),
                    OUT.ANNOUNCE)

    nlri.cidr = CIDR(ipmask.pack(), ipmask.mask)

    change = Change(nlri, Attributes())

    while True:
        command = tokeniser()

        if not command:
            return []

        if command == 'nlri':
            break

        action = ParseStatic.action[command]

        if action == 'attribute-add':
            change.attributes.add(ParseStatic.known[command](tokeniser))
        elif action == 'nlri-set':
            change.nlri.assign(ParseStatic.assign[command],
                               ParseStatic.known[command](tokeniser))
        elif action == 'nexthop-and-attribute':
            nexthop, attribute = ParseStatic.known[command](tokeniser)
            change.nlri.nexthop = nexthop
            change.attributes.add(attribute)
        else:
            raise ValueError('route: unknown command "%s"' % command)

    attributes = change.attributes
    nexthop = change.nlri.nexthop

    changes = []
    while True:
        nlri = tokeniser.peek()
        if not nlri:
            break

        ipmask = prefix(tokeniser)
        new = Change(
            change.nlri.__class__(change.nlri.afi, change.nlri.safi,
                                  OUT.UNSET), attributes)
        new.nlri.cidr = CIDR(ipmask.pack(), ipmask.mask)
        new.nlri.nexthop = nexthop
        changes.append(new)

    return changes
Exemplo n.º 11
0
def route (tokeniser):
	action = OUT.ANNOUNCE if tokeniser.announce else OUT.WITHDRAW
	ipmask = prefix(tokeniser)
	check = lambda change,afi: True

	if 'rd' in tokeniser.tokens or 'route-distinguisher' in tokeniser.tokens:
		nlri = IPVPN(IP.toafi(ipmask.top()),SAFI.mpls_vpn,action)
		check = AnnounceVPN.check
	elif 'label' in tokeniser.tokens:
		nlri = Label(IP.toafi(ipmask.top()),SAFI.nlri_mpls,action)
		check = AnnounceLabel.check
	else:
		nlri = INET(IP.toafi(ipmask.top()), IP.tosafi(ipmask.top()), action)
		check = AnnouncePath.check

	nlri.cidr = CIDR(ipmask.pack(),ipmask.mask)

	change = Change(
		nlri,
		Attributes()
	)

	while True:
		command = tokeniser()

		if not command:
			break

		if command == 'label':
			nlri.labels = label(tokeniser)
			continue

		if command == 'rd' or command == 'route-distinguisher':
			nlri.rd = route_distinguisher(tokeniser)
			continue

		action = ParseStatic.action.get(command,'')

		if action == 'attribute-add':
			change.attributes.add(ParseStatic.known[command](tokeniser))
		elif action == 'nlri-set':
			change.nlri.assign(ParseStatic.assign[command],ParseStatic.known[command](tokeniser))
		elif action == 'nexthop-and-attribute':
			nexthop,attribute = ParseStatic.known[command](tokeniser)
			change.nlri.nexthop = nexthop
			change.attributes.add(attribute)
		else:
			raise ValueError('unknown command "%s"' % command)

	if not check(change,nlri.afi):
		raise ValueError('invalid route (missing next-hop, label or rd ?)')

	return list(ParseStatic.split(change))
Exemplo n.º 12
0
	def insert_vpls (self, scope, name, command, tokens=None):
		try:
			attributes = Attributes()
			change = Change(VPLS(None,None,None,None,None),attributes)
		except ValueError:
			return self.error.set(self.syntax)

		if 'announce' not in scope[-1]:
			scope[-1]['announce'] = []

		scope[-1]['announce'].append(change)
		return True
Exemplo n.º 13
0
def route(tokeniser):
    ipmask = prefix(tokeniser)

    if 'rd' in tokeniser.tokens or 'route-distinguisher' in tokeniser.tokens:
        nlri = IPVPN(IP.toafi(ipmask.top()), SAFI.mpls_vpn, OUT.ANNOUNCE)
    elif 'label' in tokeniser.tokens:
        nlri = Label(IP.toafi(ipmask.top()), SAFI.nlri_mpls, OUT.ANNOUNCE)
    else:
        nlri = INET(IP.toafi(ipmask.top()), IP.tosafi(ipmask.top()),
                    OUT.ANNOUNCE)

    nlri.cidr = CIDR(ipmask.pack(), ipmask.mask)

    change = Change(nlri, Attributes())

    while True:
        command = tokeniser()

        if not command:
            break

        if command == 'label':
            nlri.labels = label(tokeniser)
            continue

        if command == 'rd' or command == 'route-distinguisher':
            nlri.rd = route_distinguisher(tokeniser)
            continue

        action = ParseStatic.action.get(command, '')

        if action == 'attribute-add':
            change.attributes.add(ParseStatic.known[command](tokeniser))
        elif action == 'nlri-set':
            change.nlri.assign(ParseStatic.assign[command],
                               ParseStatic.known[command](tokeniser))
        elif action == 'nexthop-and-attribute':
            nexthop, attribute = ParseStatic.known[command](tokeniser)
            change.nlri.nexthop = nexthop
            change.attributes.add(attribute)
        else:
            raise ValueError('route: unknown command "%s"' % command)

    return list(ParseStatic.split(change))
Exemplo n.º 14
0
    def insert_static_route(self, scope, name, command, tokens):
        try:
            ip = tokens.pop(0)
        except IndexError:
            return self.error.set(self.syntax)
        try:
            ip, mask = ip.split('/')
            mask = int(mask)
        except ValueError:
            mask = 32
        try:
            if 'rd' in tokens:
                klass = MPLS
            elif 'route-distinguisher' in tokens:
                klass = MPLS
            elif 'label' in tokens:
                klass = MPLS
            else:
                klass = INET

            # nexthop must be false and its str return nothing .. an empty string does that
            update = Change(
                klass(afi=IP.toafi(ip),
                      safi=IP.tosafi(ip),
                      packed=IP.pton(ip),
                      mask=mask,
                      nexthop=None,
                      action=OUT.ANNOUNCE), Attributes())
        except ValueError:
            return self.error.set(self.syntax)

        if 'announce' not in scope[-1]:
            scope[-1]['announce'] = []

        scope[-1]['announce'].append(update)
        return True
Exemplo n.º 15
0
	def updates (self, grouped):
		if self._changes:
			dict_nlri = self._modify_nlri

			for family in self._seen:
				for change in six.itervalues(self._seen[family]):
					if change.index() not in self._modify_nlri:
						change.nlri.action = OUT.WITHDRAW
						self.insert_announced(change,True)

			for new in self._changes:
				self.insert_announced(new,True)
			self._changes = None
		# end of changes

		rr_announced = []

		for afi,safi in self._enhanced_refresh_start:
			rr_announced.append((afi,safi))
			yield Update(RouteRefresh(afi,safi,RouteRefresh.start),Attributes())

		dict_sorted = self._modify_sorted
		dict_nlri = self._modify_nlri
		dict_attr = self._cache_attribute

		for attr_index,dict_change in dict_sorted.items():
			if not dict_change:
				continue

			updates = {}
			changed = dict_change.values()
			attributes = dict_attr[attr_index].attributes

			for change in dict_change.values():
				updates.setdefault(change.nlri.family(),[]).append(change.nlri)
				nlri_index = change.index()

			# only yield once we have a consistent state, otherwise it will go wrong
			# as we will try to modify things we are iterating over and using

			if grouped:
				for nlris in six.itervalues(updates):
					yield Update(nlris, attributes)
			else:
				for nlris in six.itervalues(updates):
					for nlri in nlris:
						yield Update([nlri,], attributes)

			if self.cache:
				announced = self._seen
				for change in changed:
					if change.nlri.action == OUT.ANNOUNCE:
						announced.setdefault(change.nlri.family(),{})[change.index()] = change
					else:
						family = change.nlri.family()
						if family in announced:
							announced[family].pop(change.index(),None)

		self._modify_sorted = {}
		self._modify_nlri = {}

		if rr_announced:
			for afi,safi in rr_announced:
				self._enhanced_refresh_start.remove((afi,safi))
				yield Update(RouteRefresh(afi,safi,RouteRefresh.end),Attributes())

			for change in self._enhanced_refresh_delay:
				self.insert_announced(change,True)
			self.enhanced_refresh_delay = []

			for update in self.updates(grouped):
				yield update
Exemplo n.º 16
0
    def unpack_message(cls, data, negotiated):
        logger = Logger()

        length = len(data)

        # This could be speed up massively by changing the order of the IF
        if length == 23:
            return EOR(AFI.ipv4, SAFI.unicast, IN.announced)
        if length == 30 and data.startswith(EOR.NLRI.PREFIX):
            return EOR.unpack_message(data)

        withdrawn, _attributes, announced = cls.split(data)
        attributes = Attributes.unpack(_attributes, negotiated)

        if not withdrawn:
            logger.parser("no withdrawn NLRI")
        if not announced:
            logger.parser("no announced NLRI")

        # Is the peer going to send us some Path Information with the route (AddPath)
        addpath = negotiated.addpath.receive(AFI(AFI.ipv4), SAFI(SAFI.unicast))

        # empty string for NoIP, the packed IP otherwise (without the 3/4 bytes of attributes headers)
        nexthop = attributes.get(Attribute.ID.NEXT_HOP, NoIP).packed

        nlris = []
        while withdrawn:
            length, nlri = NLRI.unpack(AFI.ipv4, SAFI.unicast, withdrawn,
                                       addpath, nexthop, IN.withdrawn)
            logger.parser(
                LazyFormat("parsed withdraw nlri %s payload " % nlri, od,
                           withdrawn[:len(nlri)]))
            withdrawn = withdrawn[length:]
            nlris.append(nlri)

        while announced:
            length, nlri = NLRI.unpack(AFI.ipv4, SAFI.unicast, announced,
                                       addpath, nexthop, IN.announced)
            logger.parser(
                LazyFormat("parsed announce nlri %s payload " % nlri, od,
                           announced[:len(nlri)]))
            announced = announced[length:]
            nlris.append(nlri)

        # required for 'is' comparaison
        UNREACH = [
            EMPTY_MPURNLRI,
        ]
        REACH = [
            EMPTY_MPRNLRI,
        ]

        unreach = attributes.pop(MPURNLRI.ID, UNREACH)
        reach = attributes.pop(MPRNLRI.ID, REACH)

        for mpr in unreach:
            nlris.extend(mpr.nlris)

        for mpr in reach:
            nlris.extend(mpr.nlris)

        if not attributes and not nlris:
            # Careful do not use == or != as the comparaison does not work
            if unreach is UNREACH and reach is REACH:
                return EOR(AFI(AFI.ipv4), SAFI(SAFI.unicast))
            if unreach is not UNREACH:
                return EOR(unreach[0].afi, unreach[0].safi)
            if reach is not REACH:
                return EOR(reach[0].afi, reach[0].safi)
            raise RuntimeError('This was not expected')

        return Update(nlris, attributes)
Exemplo n.º 17
0
def attributes (tokeniser):
	action = OUT.ANNOUNCE if tokeniser.announce else OUT.WITHDRAW
	ipmask = prefix(lambda: tokeniser.tokens[-1])
	tokeniser.afi = ipmask.afi

	if 'rd' in tokeniser.tokens or 'route-distinguisher' in tokeniser.tokens:
		nlri = IPVPN(IP.toafi(ipmask.top()), SAFI.mpls_vpn, action)
	elif 'label' in tokeniser.tokens:
		nlri = Label(IP.toafi(ipmask.top()), SAFI.nlri_mpls, action)
	else:
		nlri = INET(IP.toafi(ipmask.top()), IP.tosafi(ipmask.top()), action)

	nlri.cidr = CIDR(ipmask.pack(),ipmask.mask)
	attr = Attributes()

	labels = None
	rd = None

	while True:
		command = tokeniser()

		if not command:
			return []

		if command == 'nlri':
			break

		if command == 'label':
			labels = label(tokeniser)
			continue

		if command == 'rd' or command == 'route-distinguisher':
			rd = route_distinguisher(tokeniser)
			continue

		action = ParseStatic.action[command]

		if action == 'attribute-add':
			attr.add(ParseStatic.known[command](tokeniser))
		elif action == 'nlri-set':
			nlri.assign(ParseStatic.assign[command],ParseStatic.known[command](tokeniser))
		elif action == 'nexthop-and-attribute':
			nexthop,attribute = ParseStatic.known[command](tokeniser)
			nlri.nexthop = nexthop
			attr.add(attribute)
		else:
			raise ValueError('unknown command "%s"' % command)

	changes = []
	while True:
		peeked_nlri = tokeniser.peek()
		if not peeked_nlri:
			break

		ipmask = prefix(tokeniser)
		new = Change(
			nlri.__class__(
				nlri.afi,
				nlri.safi,
				OUT.UNSET
			),
			attr
		)
		new.nlri.cidr = CIDR(ipmask.pack(),ipmask.mask)
		if labels:
			new.nlri.labels = labels
		if rd:
			new.nlri.rd = rd
		new.nlri.nexthop = nlri.nexthop
		changes.append(new)

	return changes
Exemplo n.º 18
0
def flow(tokeniser):
    return Change(Flow(), Attributes())
Exemplo n.º 19
0
def ls_unicast(tokeniser):
    return Change(LS_UNICAST(None, None, None, None, None, None, None),
                  Attributes())
Exemplo n.º 20
0
    def updates(self, grouped):
        if self._changes:
            dict_nlri = self._modify_nlri

            for family in self._seen:
                for change in self._seen[family].itervalues():
                    if change.index() not in self._modify_nlri:
                        change.nlri.action = OUT.WITHDRAW
                        self.insert_announced(change, True)

            for new in self._changes:
                self.insert_announced(new, True)
            self._changes = None
        # end of changes

        rr_announced = []

        for afi, safi in self._enhanced_refresh_start:
            rr_announced.append((afi, safi))
            yield Update(RouteRefresh(afi, safi, RouteRefresh.start),
                         Attributes())

        dict_sorted = self._modify_sorted
        dict_nlri = self._modify_nlri
        dict_attr = self._cache_attribute

        for attr_index, full_dict_change in dict_sorted.items():
            if self.cache:
                dict_change = {}
                for nlri_index, change in full_dict_change.iteritems():
                    family = change.nlri.family()
                    announced = self._seen.get(family, {})
                    if change.nlri.action == OUT.ANNOUNCE:
                        if nlri_index in announced:
                            old_change = announced[nlri_index]
                            # it is a duplicate route
                            if old_change.attributes.index(
                            ) == change.attributes.index(
                            ) and old_change.nlri.nexthop.index(
                            ) == change.nlri.nexthop.index():
                                continue
                    elif change.nlri.action == OUT.WITHDRAW:
                        if nlri_index not in announced:
                            if dict_nlri[
                                    nlri_index].nlri.action == OUT.ANNOUNCE:
                                continue
                    dict_change[nlri_index] = change
            else:
                dict_change = full_dict_change

            if not dict_change:
                continue

            attributes = dict_attr[attr_index].attributes

            # we NEED the copy provided by list() here as insert_announced can be called while we iterate
            changed = list(dict_change.itervalues())

            if grouped:
                updates = []
                nlris = []
                for change in dict_change.values():
                    if change.nlri.afi == AFI.ipv4:
                        nlris.append(change.nlri)
                        continue
                    updates.append(Update([change.nlri], attributes))
                if nlris:
                    updates.append(Update(nlris, attributes))
                    nlris = []

                for change in changed:
                    nlri_index = change.index()
                    del dict_sorted[attr_index][nlri_index]
                    del dict_nlri[nlri_index]
                # only yield once we have a consistent state, otherwise it will go wrong
                # as we will try to modify things we are using
                for update in updates:
                    yield update
            else:
                updates = []
                for change in changed:
                    updates.append(Update([
                        change.nlri,
                    ], attributes))
                    nlri_index = change.index()
                    del dict_sorted[attr_index][nlri_index]
                    del dict_nlri[nlri_index]
                # only yield once we have a consistent state, otherwise it will go wrong
                # as we will try to modify things we are using
                for update in updates:
                    yield update

            if self.cache:
                announced = self._seen
                for change in changed:
                    if change.nlri.action == OUT.ANNOUNCE:
                        announced.setdefault(change.nlri.family(),
                                             {})[change.index()] = change
                    else:
                        family = change.nlri.family()
                        if family in announced:
                            announced[family].pop(change.index(), None)

        if rr_announced:
            for afi, safi in rr_announced:
                self._enhanced_refresh_start.remove((afi, safi))
                yield Update(RouteRefresh(afi, safi, RouteRefresh.end),
                             Attributes())

            for change in self._enhanced_refresh_delay:
                self.insert_announced(change, True)
            self.enhanced_refresh_delay = []

            for update in self.updates(grouped):
                yield update
Exemplo n.º 21
0
    def unpack_message(cls, data, negotiated):
        logger = Logger()

        logger.debug(LazyFormat('parsing UPDATE', data), 'parser')

        length = len(data)

        # This could be speed up massively by changing the order of the IF
        if length == 4 and data == b'\x00\x00\x00\x00':
            return EOR(AFI.ipv4, SAFI.unicast)  # pylint: disable=E1101
        if length == 11 and data.startswith(EOR.NLRI.PREFIX):
            return EOR.unpack_message(data, negotiated)

        withdrawn, _attributes, announced = cls.split(data)

        if not withdrawn:
            logger.debug('withdrawn NLRI none', 'routes')

        attributes = Attributes.unpack(_attributes, negotiated)

        if not announced:
            logger.debug('announced NLRI none', 'routes')

        # Is the peer going to send us some Path Information with the route (AddPath)
        addpath = negotiated.addpath.receive(AFI.ipv4, SAFI.unicast)

        # empty string for NoNextHop, the packed IP otherwise (without the 3/4 bytes of attributes headers)
        nexthop = attributes.get(Attribute.CODE.NEXT_HOP, NoNextHop)
        # nexthop = NextHop.unpack(_nexthop.ton())

        # XXX: NEXTHOP MUST NOT be the IP address of the receiving speaker.

        nlris = []
        while withdrawn:
            nlri, left = NLRI.unpack_nlri(AFI.ipv4, SAFI.unicast, withdrawn,
                                          IN.WITHDRAWN, addpath)
            logger.debug('withdrawn NLRI %s' % nlri, 'routes')
            withdrawn = left
            nlris.append(nlri)

        while announced:
            nlri, left = NLRI.unpack_nlri(AFI.ipv4, SAFI.unicast, announced,
                                          IN.ANNOUNCED, addpath)
            nlri.nexthop = nexthop
            logger.debug('announced NLRI %s' % nlri, 'routes')
            announced = left
            nlris.append(nlri)

        unreach = attributes.pop(MPURNLRI.ID, None)
        reach = attributes.pop(MPRNLRI.ID, None)

        if unreach is not None:
            nlris.extend(unreach.nlris)

        if reach is not None:
            nlris.extend(reach.nlris)

        if not attributes and not nlris:
            # Careful do not use == or != as the comparaison does not work
            if unreach is None and reach is None:
                return EOR(AFI.ipv4, SAFI.unicast)
            if unreach is not None:
                return EOR(unreach.afi, unreach.safi)
            if reach is not None:
                return EOR(reach.afi, reach.safi)
            raise RuntimeError('This was not expected')

        update = Update(nlris, attributes)

        def parsed(_):
            # we need the import in the function as otherwise we have an cyclic loop
            # as this function currently uses Update..
            from exabgp.reactor.api.response import Response
            from exabgp.version import json as json_version
            return 'json %s' % Response.JSON(json_version).update(
                negotiated.neighbor, 'in', update, None, '', '')

        logger.debug(LazyFormat('decoded UPDATE', '', parsed), 'parser')

        return update
Exemplo n.º 22
0
    def unpack_message(cls, data, negotiated):
        logger = Logger()

        logger.parser(LazyFormat("parsing UPDATE", data))

        length = len(data)

        # This could be speed up massively by changing the order of the IF
        if length == 4 and data == b'\x00\x00\x00\x00':
            return EOR(AFI(AFI.ipv4), SAFI(SAFI.unicast))  # pylint: disable=E1101
        if length == 11 and data.startswith(EOR.NLRI.PREFIX):
            return EOR.unpack_message(data, negotiated)

        withdrawn, _attributes, announced = cls.split(data)

        if not withdrawn:
            logger.parser("withdrawn NLRI none")

        attributes = Attributes.unpack(_attributes, negotiated)

        if not announced:
            logger.parser("announced NLRI none")

        # Is the peer going to send us some Path Information with the route (AddPath)
        addpath = negotiated.addpath.receive(AFI(AFI.ipv4), SAFI(SAFI.unicast))

        # empty string for NoNextHop, the packed IP otherwise (without the 3/4 bytes of attributes headers)
        nexthop = attributes.get(Attribute.CODE.NEXT_HOP, NoNextHop)
        # nexthop = NextHop.unpack(_nexthop.ton())

        # XXX: NEXTHOP MUST NOT be the IP address of the receiving speaker.

        nlris = []
        while withdrawn:
            nlri, left = NLRI.unpack_nlri(AFI.ipv4, SAFI.unicast, withdrawn,
                                          IN.WITHDRAWN, addpath)
            logger.parser("withdrawn NLRI %s" % nlri)
            withdrawn = left
            nlris.append(nlri)

        while announced:
            nlri, left = NLRI.unpack_nlri(AFI.ipv4, SAFI.unicast, announced,
                                          IN.ANNOUNCED, addpath)
            nlri.nexthop = nexthop
            logger.parser("announced NLRI %s" % nlri)
            announced = left
            nlris.append(nlri)

        unreach = attributes.pop(MPURNLRI.ID, None)
        reach = attributes.pop(MPRNLRI.ID, None)

        if unreach is not None:
            nlris.extend(unreach.nlris)

        if reach is not None:
            nlris.extend(reach.nlris)

        if not attributes and not nlris:
            # Careful do not use == or != as the comparaison does not work
            if unreach is None and reach is None:
                return EOR(AFI(AFI.ipv4), SAFI(SAFI.unicast))
            if unreach is not None:
                return EOR(unreach.afi, unreach.safi)
            if reach is not None:
                return EOR(reach.afi, reach.safi)
            raise RuntimeError('This was not expected')

        return Update(nlris, attributes)
Exemplo n.º 23
0
def vpls(tokeniser):
    return Change(VPLS(None, None, None, None, None), Attributes())
Exemplo n.º 24
0
	def unpack_message (cls, data, negotiated):
		logger = Logger()

		logger.debug(LazyFormat('parsing UPDATE',data),'parser')

		length = len(data)

		# This could be speed up massively by changing the order of the IF
		if length == 4 and data == b'\x00\x00\x00\x00':
			return EOR(AFI.ipv4,SAFI.unicast)  # pylint: disable=E1101
		if length == 11 and data.startswith(EOR.NLRI.PREFIX):
			return EOR.unpack_message(data,negotiated)

		withdrawn, _attributes, announced = cls.split(data)

		if not withdrawn:
			logger.debug('withdrawn NLRI none','parser')

		attributes = Attributes.unpack(_attributes,negotiated)

		if not announced:
			logger.debug('announced NLRI none','parser')

		# Is the peer going to send us some Path Information with the route (AddPath)
		addpath = negotiated.addpath.receive(AFI.ipv4,SAFI.unicast)

		# empty string for NoNextHop, the packed IP otherwise (without the 3/4 bytes of attributes headers)
		nexthop = attributes.get(Attribute.CODE.NEXT_HOP,NoNextHop)
		# nexthop = NextHop.unpack(_nexthop.ton())

		# XXX: NEXTHOP MUST NOT be the IP address of the receiving speaker.

		nlris = []
		while withdrawn:
			nlri,left = NLRI.unpack_nlri(AFI.ipv4,SAFI.unicast,withdrawn,IN.WITHDRAWN,addpath)
			logger.debug('withdrawn NLRI %s' % nlri,'parser')
			withdrawn = left
			nlris.append(nlri)

		while announced:
			nlri,left = NLRI.unpack_nlri(AFI.ipv4,SAFI.unicast,announced,IN.ANNOUNCED,addpath)
			nlri.nexthop = nexthop
			logger.debug('announced NLRI %s' % nlri,'parser')
			announced = left
			nlris.append(nlri)

		unreach = attributes.pop(MPURNLRI.ID,None)
		reach = attributes.pop(MPRNLRI.ID,None)

		if unreach is not None:
			nlris.extend(unreach.nlris)

		if reach is not None:
			nlris.extend(reach.nlris)

		if not attributes and not nlris:
			# Careful do not use == or != as the comparaison does not work
			if unreach is None and reach is None:
				return EOR(AFI.ipv4,SAFI.unicast)
			if unreach is not None:
				return EOR(unreach.afi,unreach.safi)
			if reach is not None:
				return EOR(reach.afi,reach.safi)
			raise RuntimeError('This was not expected')

		return Update(nlris,attributes)
Exemplo n.º 25
0
	def unpack_message (cls, data, negotiated):
		logger = Logger()

		length = len(data)

		# This could be speed up massively by changing the order of the IF
		if length == 4 and data == '\x00\x00\x00\x00':
			return EOR(AFI.ipv4,SAFI.unicast,IN.ANNOUNCED)  # pylint: disable=E1101
		if length == 11 and data.startswith(EOR.NLRI.PREFIX):
			return EOR.unpack_message(data,negotiated)

		withdrawn, _attributes, announced = cls.split(data)
		attributes = Attributes.unpack(_attributes,negotiated)

		if not withdrawn:
			logger.parser("no withdrawn NLRI")
		if not announced:
			logger.parser("no announced NLRI")

		# Is the peer going to send us some Path Information with the route (AddPath)
		addpath = negotiated.addpath.receive(AFI(AFI.ipv4),SAFI(SAFI.unicast))

		# empty string for NoNextHop, the packed IP otherwise (without the 3/4 bytes of attributes headers)
		nexthop = attributes.get(Attribute.CODE.NEXT_HOP,NoNextHop)
		# nexthop = NextHop.unpack(_nexthop.ton())

		# XXX: NEXTHOP MUST NOT be the IP address of the receiving speaker.

		nlris = []
		while withdrawn:
			nlri,left = NLRI.unpack_nlri(AFI.ipv4,SAFI.unicast,withdrawn,IN.WITHDRAWN,addpath)
			logger.parser(LazyFormat("parsed withdraw nlri %s payload " % nlri,withdrawn[:len(nlri)]))
			withdrawn = left
			nlris.append(nlri)

		while announced:
			nlri,left = NLRI.unpack_nlri(AFI.ipv4,SAFI.unicast,announced,IN.ANNOUNCED,addpath)
			nlri.nexthop = nexthop
			logger.parser(LazyFormat("parsed announce nlri %s payload " % nlri,announced[:len(nlri)]))
			announced = left
			nlris.append(nlri)

		# required for 'is' comparaison
		UNREACH = [EMPTY_MPURNLRI,]
		REACH = [EMPTY_MPRNLRI,]

		unreach = attributes.pop(MPURNLRI.ID,UNREACH)
		reach = attributes.pop(MPRNLRI.ID,REACH)

		for mpr in unreach:
			nlris.extend(mpr.nlris)

		for mpr in reach:
			nlris.extend(mpr.nlris)

		if not attributes and not nlris:
			# Careful do not use == or != as the comparaison does not work
			if unreach is UNREACH and reach is REACH:
				return EOR(AFI(AFI.ipv4),SAFI(SAFI.unicast))
			if unreach is not UNREACH:
				return EOR(unreach[0].afi,unreach[0].safi)
			if reach is not REACH:
				return EOR(reach[0].afi,reach[0].safi)
			raise RuntimeError('This was not expected')

		return Update(nlris,attributes)
Exemplo n.º 26
0
def attributes (tokeniser):
	ipmask = prefix(lambda: tokeniser.tokens[-1])

	if 'rd' in tokeniser.tokens or 'route-distinguisher' in tokeniser.tokens:
		nlri = IPVPN(IP.toafi(ipmask.top()),SAFI.mpls_vpn,OUT.ANNOUNCE)
	elif 'label' in tokeniser.tokens:
		nlri = Label(IP.toafi(ipmask.top()),SAFI.nlri_mpls,OUT.ANNOUNCE)
	else:
		nlri = INET(IP.toafi(ipmask.top()),IP.tosafi(ipmask.top()),OUT.ANNOUNCE)

	nlri.cidr = CIDR(ipmask.pack(),ipmask.mask)
	attr = Attributes()

	labels = None
	rd = None

	while True:
		command = tokeniser()

		if not command:
			return []

		if command == 'nlri':
			break

		if command == 'label':
			labels = label(tokeniser)
			continue

		if command == 'rd' or command == 'route-distinguisher':
			rd = route_distinguisher(tokeniser)
			continue

		action = ParseStatic.action[command]

		if action == 'attribute-add':
			attr.add(ParseStatic.known[command](tokeniser))
		elif action == 'nlri-set':
			nlri.assign(ParseStatic.assign[command],ParseStatic.known[command](tokeniser))
		elif action == 'nexthop-and-attribute':
			nexthop,attribute = ParseStatic.known[command](tokeniser)
			nlri.nexthop = nexthop
			attr.add(attribute)
		else:
			raise ValueError('route: unknown command "%s"' % command)

	changes = []
	while True:
		peeked_nlri = tokeniser.peek()
		if not peeked_nlri:
			break

		ipmask = prefix(tokeniser)
		new = Change(
			nlri.__class__(
				nlri.afi,
				nlri.safi,
				OUT.UNSET
			),
			attr
		)
		new.nlri.cidr = CIDR(ipmask.pack(),ipmask.mask)
		if labels:
			new.nlri.labels = labels
		if rd:
			new.nlri.rd = rd
		new.nlri.nexthop = nlri.nexthop
		changes.append(new)

	return changes
Exemplo n.º 27
0
 def __init__(self, afi, safi, action=None):
     Message.__init__(self)
     self.nlris = [
         EOR.NLRI(afi, safi, action),
     ]
     self.attributes = Attributes()
Exemplo n.º 28
0
    def unpack_message(cls, data, negotiated):
        logger = Logger()

        length = len(data)

        # This could be speed up massively by changing the order of the IF
        if length == 23:
            return EOR(AFI.ipv4, SAFI.unicast, IN.announced)
        if length == 30 and data.startswith(EOR.NLRI.PREFIX):
            return EOR.unpack_message(data)

        withdrawn, _attributes, announced = cls.split(data)
        attributes = Attributes.unpack(_attributes, negotiated)

        if not withdrawn:
            logger.parser("no withdrawn NLRI")
        if not announced:
            logger.parser("no announced NLRI")

            # Is the peer going to send us some Path Information with the route (AddPath)
        addpath = negotiated.addpath.receive(AFI(AFI.ipv4), SAFI(SAFI.unicast))

        # empty string for NoIP, the packed IP otherwise (without the 3/4 bytes of attributes headers)
        nexthop = attributes.get(Attribute.ID.NEXT_HOP, NoIP).packed

        nlris = []
        while withdrawn:
            length, nlri = NLRI.unpack(AFI.ipv4, SAFI.unicast, withdrawn, addpath, nexthop, IN.withdrawn)
            logger.parser(LazyFormat("parsed withdraw nlri %s payload " % nlri, od, withdrawn[: len(nlri)]))
            withdrawn = withdrawn[length:]
            nlris.append(nlri)

        while announced:
            length, nlri = NLRI.unpack(AFI.ipv4, SAFI.unicast, announced, addpath, nexthop, IN.announced)
            logger.parser(LazyFormat("parsed announce nlri %s payload " % nlri, od, announced[: len(nlri)]))
            announced = announced[length:]
            nlris.append(nlri)

            # required for 'is' comparaison
        UNREACH = [EMPTY_MPURNLRI]
        REACH = [EMPTY_MPRNLRI]

        unreach = attributes.pop(MPURNLRI.ID, UNREACH)
        reach = attributes.pop(MPRNLRI.ID, REACH)

        for mpr in unreach:
            nlris.extend(mpr.nlris)

        for mpr in reach:
            nlris.extend(mpr.nlris)

        if not attributes and not nlris:
            # Careful do not use == or != as the comparaison does not work
            if unreach is UNREACH and reach is REACH:
                return EOR(AFI(AFI.ipv4), SAFI(SAFI.unicast))
            if unreach is not UNREACH:
                return EOR(unreach[0].afi, unreach[0].safi)
            if reach is not REACH:
                return EOR(reach[0].afi, reach[0].safi)
            raise RuntimeError("This was not expected")

        return Update(nlris, attributes)