Пример #1
0
def redirect (tokeniser):
	data = tokeniser()
	count = data.count(':')
	if count == 0:
		return IP.create(data), ExtendedCommunities().add(TrafficNextHopSimpson(False))
	if count == 1:
		prefix,suffix = data.split(':',1)
		if prefix.count('.'):
			raise ValueError('this format has been deprecated as it does not make sense and it is not supported by other vendors')

		asn = int(prefix)
		route_target = int(suffix)

		if asn >= pow(2, 32):
			raise ValueError('asn is a 32 bits number, value too large %s' % asn)
		if asn >= pow(2,16):
			if route_target >= pow(2, 16):
				raise ValueError('asn is a 32 bits number, route target can only be 16 bit %s' % route_target)
			return NoNextHop, ExtendedCommunities().add(TrafficRedirectASN4(asn, route_target))
		if route_target >= pow(2,32):
			raise ValueError('route target is a 32 bits number, value too large %s' % route_target)
		return NoNextHop,ExtendedCommunities().add(TrafficRedirect(asn,route_target))
	else:
		elements = data.split(':')
		ip = ':'.join(elements[:-1])
		asn = int(elements[-1])
		return IP.create(ip), ExtendedCommunities().add(TrafficRedirectIPv6(ip,asn))
Пример #2
0
    def test99_EVPNMACCreatePackUnpack(self):
        '''Test pack/unpack for E-VPN MAC routes'''
        nlri = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                       ESI(),
                       EthernetTag(111),
                       MAC("01:02:03:04:05:06"), 6*8,
                       Labels([42], True),
                       IP.create("1.1.1.1"))

        packed = nlri.pack()

        unpacked,leftover = EVPN.unpack_nlri(AFI(AFI.l2vpn), SAFI(SAFI.evpn),
                                             packed, OUT.UNSET, None)

        self.assertEqual(0, len(leftover))

        # TODO: compare packed with a reference encoding verified 
        # as conformant with RFC7432

        self.assertTrue(isinstance(unpacked, EVPNMAC))

        self.assertEqual("42.42.42.42:5", unpacked.rd._str())
        self.assertEqual(ESI.DEFAULT, unpacked.esi.esi)
        self.assertEqual(EthernetTag(111), unpacked.etag)
        self.assertEqual(MAC("01:02:03:04:05:06"), unpacked.mac)

        self.assertEqual(IP.create("1.1.1.1"), unpacked.ip)

        self.assertEqual(1, len(unpacked.label.labels))
        self.assertEqual(42, unpacked.label.labels[0])
Пример #3
0
 def listen_on(self, local_addr, remote_addr, port, md5_password,
               md5_base64, ttl_in):
     try:
         if not remote_addr:
             remote_addr = IP.create(
                 '0.0.0.0') if local_addr.ipv4() else IP.create('::')
         self._listen(local_addr, remote_addr, port, md5_password,
                      md5_base64, ttl_in)
         self.logger.debug(
             'listening for BGP session(s) on %s:%d%s' %
             (local_addr, port, ' with MD5' if md5_password else ''),
             'network')
         return True
     except NetworkError as exc:
         if os.geteuid() != 0 and port <= 1024:
             self.logger.critical(
                 'can not bind to %s:%d, you may need to run ExaBGP as root'
                 % (local_addr, port), 'network')
         else:
             self.logger.critical(
                 'can not bind to %s:%d (%s)' %
                 (local_addr, port, str(exc)), 'network')
         self.logger.critical(
             'unset exabgp.tcp.bind if you do not want listen for incoming connections',
             'network')
         self.logger.critical(
             'and check that no other daemon is already binding to port %d'
             % port, 'network')
         return False
Пример #4
0
    def test99_EVPNPrefixCreatePackUnpack(self):
        '''Test pack/unpack for E-VPN Prefix routes'''

        nlri = EVPNPrefix(RouteDistinguisher.fromElements("42.42.42.42", 5),
                          ESI(),
                          EthernetTag(111),
                          Labels([42], True),
                          IP.create("1.1.1.0"),24,
                          IP.create("2.2.2.2"),
                          )

        packed = nlri.pack()

        unpacked,leftover = EVPN.unpack_nlri(AFI.l2vpn, SAFI.evpn,
                                             packed, OUT.UNSET, None)

        self.assertEqual(0, len(leftover))

        # TODO: compare packed with a reference encoding verified
        # as conformant with RFC7432

        self.assertTrue(isinstance(unpacked, EVPNPrefix))

        self.assertEqual("42.42.42.42:5", unpacked.rd._str())
        self.assertEqual(ESI.DEFAULT, unpacked.esi.esi)
        self.assertEqual(EthernetTag(111), unpacked.etag)
        self.assertEqual(IP.create("1.1.1.0"), unpacked.ip)
        self.assertEqual(24, unpacked.iplen)
        self.assertEqual(IP.create("2.2.2.2"), unpacked.gwip)
        self.assertEqual(1, len(unpacked.label.labels))
        self.assertEqual(42, unpacked.label.labels[0])
Пример #5
0
    def test100_EVPNMACHashEqual(self):
        '''
        Two indistinct EVPN NLRI should
        hash to the same value, and be equal
        '''

        nlri1 = EVPNMAC(
            RouteDistinguisher.fromElements("42.42.42.42", 5),
            ESI(),
            EthernetTag(111),
            MAC("01:02:03:04:05:06"),
            6 * 8,
            Labels([42], True),
            IP.create("1.1.1.1"),
        )

        nlri2 = EVPNMAC(
            RouteDistinguisher.fromElements("42.42.42.42", 5),
            ESI(),
            EthernetTag(111),
            MAC("01:02:03:04:05:06"),
            6 * 8,
            Labels([42], True),
            IP.create("1.1.1.1"),
        )

        self.assertEqual(hash(nlri1), hash(nlri2))
        self.assertEqual(nlri1, nlri2)
Пример #6
0
    def test99_EVPNMACCreatePackUnpack(self):
        '''Test pack/unpack for E-VPN MAC routes'''
        nlri = EVPNMAC(
            RouteDistinguisher.fromElements("42.42.42.42", 5),
            ESI(),
            EthernetTag(111),
            MAC("01:02:03:04:05:06"),
            6 * 8,
            Labels([42], True),
            IP.create("1.1.1.1"),
        )

        packed = nlri.pack()

        unpacked, leftover = EVPN.unpack_nlri(AFI.l2vpn, SAFI.evpn, packed,
                                              OUT.UNSET, None)

        self.assertEqual(0, len(leftover))

        # TODO: compare packed with a reference encoding verified
        # as conformant with RFC7432

        self.assertTrue(isinstance(unpacked, EVPNMAC))

        self.assertEqual("42.42.42.42:5", unpacked.rd._str())
        self.assertEqual(ESI.DEFAULT, unpacked.esi.esi)
        self.assertEqual(EthernetTag(111), unpacked.etag)
        self.assertEqual(MAC("01:02:03:04:05:06"), unpacked.mac)

        self.assertEqual(IP.create("1.1.1.1"), unpacked.ip)

        self.assertEqual(1, len(unpacked.label.labels))
        self.assertEqual(42, unpacked.label.labels[0])
Пример #7
0
def redirect(tokeniser):
    data = tokeniser()
    count = data.count(':')
    if count == 0:
        return IP.create(data), ExtendedCommunities().add(
            TrafficNextHopSimpson(False))
    if count == 1:
        prefix, suffix = data.split(':', 1)
        if prefix.count('.'):
            raise ValueError(
                'this format has been deprecated as it does not make sense and it is not supported by other vendors'
            )

        asn = int(prefix)
        route_target = int(suffix)

        if asn >= pow(2, 32):
            raise ValueError('asn is a 32 bits number, value too large %s' %
                             asn)
        if asn >= pow(2, 16):
            if route_target >= pow(2, 16):
                raise ValueError(
                    'asn is a 32 bits number, route target can only be 16 bit %s'
                    % route_target)
            return NoNextHop, ExtendedCommunities().add(
                TrafficRedirectASN4(asn, route_target))
        if route_target >= pow(2, 32):
            raise ValueError(
                'route target is a 32 bits number, value too large %s' %
                route_target)
        return NoNextHop, ExtendedCommunities().add(
            TrafficRedirect(asn, route_target))
    else:
        explicit_v6 = ']:' in data

        # ipv4
        if not explicit_v6 and data.count(':') == 1:
            return IP.create(data), ExtendedCommunities().add(
                TrafficNextHopSimpson(False))

        # ipv6 using []: notation
        if explicit_v6:
            ip, asn = data.split(']:')
            ip = ip.replace('[', '', 1)
            # FIXME: should this be 2^16 ??
            if asn >= pow(2, 32):
                raise ValueError(
                    'asn is a 32 bits number, value too large %s' % asn)
            return IP.create(ip), ExtendedCommunities().add(
                TrafficRedirectIPv6(ip, asn))

        raise ValueError(
            'it looks like you tried to use an IPv6 but did not enclose it in []'
        )
Пример #8
0
	def listen_on (self, local_addr, remote_addr, port, md5_password, md5_base64, ttl_in):
		try:
			if not remote_addr:
				remote_addr = IP.create('0.0.0.0') if local_addr.ipv4() else IP.create('::')
			self._listen(local_addr, remote_addr, port, md5_password, md5_base64, ttl_in)
			self.logger.debug('listening for BGP session(s) on %s:%d%s' % (local_addr, port,' with MD5' if md5_password else ''),'network')
			return True
		except NetworkError as exc:
			if os.geteuid() != 0 and port <= 1024:
				self.logger.critical('can not bind to %s:%d, you may need to run ExaBGP as root' % (local_addr, port),'network')
			else:
				self.logger.critical('can not bind to %s:%d (%s)' % (local_addr, port,str(exc)),'network')
			self.logger.critical('unset exabgp.tcp.bind if you do not want listen for incoming connections','network')
			self.logger.critical('and check that no other daemon is already binding to port %d' % port,'network')
			return False
Пример #9
0
	def connect (self):
		# allows to test the protocol code using modified StringIO with a extra 'pending' function
		if not self.connection:
			local = self.neighbor.md5_ip.top() if not self.neighbor.auto_discovery else None
			peer = self.neighbor.peer_address.top()
			afi = self.neighbor.peer_address.afi
			md5 = self.neighbor.md5_password
			md5_base64 = self.neighbor.md5_base64
			ttl_out = self.neighbor.ttl_out
			self.connection = Outgoing(afi,peer,local,self.port,md5,md5_base64,ttl_out)
			if not local and self.connection.init:
				self.neighbor.local_address = IP.create(self.connection.local)
				if self.neighbor.router_id is None and self.neighbor.local_address.afi == AFI.ipv4:
					self.neighbor.router_id = self.neighbor.local_address

			try:
				generator = self.connection.establish()
				while True:
					connected = six.next(generator)
					if not connected:
						yield False
						continue
					if self.peer.neighbor.api['neighbor-changes']:
						self.peer.reactor.processes.connected(self.peer.neighbor)
					yield True
					return
			except StopIteration:
				# close called by the caller
				# self.close('could not connect to remote end')
				yield False
				return
Пример #10
0
    def connect(self):
        # allows to test the protocol code using modified StringIO with a extra 'pending' function
        if not self.connection:
            local = self.neighbor.md5_ip.top(
            ) if not self.neighbor.auto_discovery else None
            peer = self.neighbor.peer_address.top()
            afi = self.neighbor.peer_address.afi
            md5 = self.neighbor.md5_password
            md5_base64 = self.neighbor.md5_base64
            ttl_out = self.neighbor.ttl_out
            self.connection = Outgoing(afi, peer, local, self.port, md5,
                                       md5_base64, ttl_out)
            if not self.connection.init:
                yield False
                return
            if not local:
                self.neighbor.local_address = IP.create(self.connection.local)
                if self.neighbor.router_id is None and self.neighbor.local_address.afi == AFI.ipv4:
                    self.neighbor.router_id = self.neighbor.local_address

            for connected in self.connection.establish():
                if not connected:
                    yield False
                    continue
                if self.peer.neighbor.api['neighbor-changes']:
                    self.peer.reactor.processes.connected(self.peer.neighbor)
                yield True
                return
Пример #11
0
	def _multi_neighbor (self, scope, name, command, tokens):
		if len(tokens) != 1:
			return self.error.set('syntax: neighbor <ip> { <options> }')

		address = tokens[0]
		scope.append({})
		try:
			scope[-1]['peer-address'] = IP.create(address)
		except (IndexError,ValueError,socket.error):
			return self.error.set('"%s" is not a valid IP address' % address)

		while True:
			r = self._dispatch(
				scope,name,'neighbor',
				[
					'static','flow','l2vpn',
					'process','family','capability','operational'
				],
				self._command['neighbor']
			)
			# XXX: THIS SHOULD ALLOW CAPABILITY AND NOT THE INDIVIDUAL SUB KEYS
			if r is False:
				return False
			if r is None:
				return True
Пример #12
0
	def redirect (self, scope, name, command, tokens):
		try:
			if tokens[0].count(':') == 1:
				prefix,suffix = tokens[0].split(':',1)
				if prefix.count('.'):
					raise ValueError('this format has been deprecaded as it does not make sense and it is not supported by other vendors')
				else:
					asn = int(prefix)
					route_target = int(suffix)
					if asn >= pow(2,16):
						raise ValueError('asn is a 32 bits number, it can only be 16 bit %s' % route_target)
					if route_target >= pow(2,32):
						raise ValueError('route target is a 32 bits number, value too large %s' % route_target)
					scope[-1]['announce'][-1].attributes[Attribute.CODE.EXTENDED_COMMUNITY].add(TrafficRedirect(asn,route_target))
					return True
			else:
				change = scope[-1]['announce'][-1]
				if change.nlri.nexthop is not NoNextHop:
					return self.error.set(self.syntax)

				nh = IP.create(tokens.pop(0))
				change.nlri.nexthop = nh
				change.attributes[Attribute.CODE.EXTENDED_COMMUNITY].add(TrafficNextHop(False))
				return True

		except (IndexError,ValueError):
			return self.error.set(self.syntax)
Пример #13
0
	def connect (self):
		# allows to test the protocol code using modified StringIO with a extra 'pending' function
		if not self.connection:
			local = self.neighbor.md5_ip.top() if not self.neighbor.auto_discovery else None
			peer = self.neighbor.peer_address.top()
			afi = self.neighbor.peer_address.afi
			md5 = self.neighbor.md5_password
			md5_base64 = self.neighbor.md5_base64
			ttl_out = self.neighbor.ttl_out
			self.connection = Outgoing(afi,peer,local,self.port,md5,md5_base64,ttl_out)
			if not self.connection.init:
				yield False
				return
			if not local:
				self.neighbor.local_address = IP.create(self.connection.local)
				if self.neighbor.router_id is None and self.neighbor.local_address.afi == AFI.ipv4:
					self.neighbor.router_id = self.neighbor.local_address

			for connected in self.connection.establish():
				if not connected:
					yield False
					continue
				if self.peer.neighbor.api['neighbor-changes']:
					self.peer.reactor.processes.connected(self.peer.neighbor)
				yield True
				return
Пример #14
0
	def next_hop (self, scope, name, command, tokens):
		if scope[-1]['announce'][-1].attributes.has(Attribute.CODE.NEXT_HOP):
			return self.error.set(self.syntax)

		try:
			# next-hop self is unsupported
			ip = tokens.pop(0)
			if ip.lower() == 'self':
				if 'local-address' in scope[-1]:
					la = scope[-1]['local-address']
				elif self._nexthopself:
					la = self._nexthopself
				else:
					return self.error.set('next-hop self can only be specified with a neighbor')
				nh = IP.unpack(la.pack())
			else:
				nh = IP.create(ip)

			change = scope[-1]['announce'][-1]
			nlri = change.nlri
			afi = nlri.afi
			safi = nlri.safi

			nlri.nexthop = nh

			if afi == AFI.ipv4 and safi in (SAFI.unicast,SAFI.multicast):
				change.attributes.add(Attribute.unpack(NextHop.ID,NextHop.FLAG,nh.packed,None))
				# NextHop(nh.ip,nh.packed) does not cache the result, using unpack does
				# change.attributes.add(NextHop(nh.ip,nh.packed))

			return True
		except Exception:
			return self.error.set(self.syntax)
Пример #15
0
    def connect(self):
        # allows to test the protocol code using modified StringIO with a extra 'pending' function
        if self.connection:
            return

        local = self.neighbor['md5-ip'].top(
        ) if not self.neighbor.auto_discovery else None
        peer = self.neighbor['peer-address'].top()
        afi = self.neighbor['peer-address'].afi
        md5 = self.neighbor['md5-password']
        md5_base64 = self.neighbor['md5-base64']
        ttl_out = self.neighbor['outgoing-ttl']
        self.connection = Outgoing(afi, peer, local, self.port, md5,
                                   md5_base64, ttl_out)

        for connected in self.connection.establish():
            yield False

        if self.peer.neighbor.api['neighbor-changes']:
            self.peer.reactor.processes.connected(self.peer.neighbor)

        if not local:
            self.neighbor['local-address'] = IP.create(self.connection.local)
            if self.neighbor['router-id'] is None and self.neighbor[
                    'local-address'].afi == AFI.ipv4:
                self.neighbor['router-id'] = self.neighbor['local-address']

        yield True
Пример #16
0
    def connect(self):
        # allows to test the protocol code using modified StringIO with a extra 'pending' function
        if not self.connection:
            local = self.neighbor.md5_ip.top(
            ) if not self.neighbor.auto_discovery else None
            peer = self.neighbor.peer_address.top()
            afi = self.neighbor.peer_address.afi
            md5 = self.neighbor.md5_password
            md5_base64 = self.neighbor.md5_base64
            ttl_out = self.neighbor.ttl_out
            self.connection = Outgoing(afi, peer, local, self.port, md5,
                                       md5_base64, ttl_out)
            if not local and self.connection.init:
                self.neighbor.local_address = IP.create(self.connection.local)
                if self.neighbor.router_id is None and self.neighbor.local_address.afi == AFI.ipv4:
                    self.neighbor.router_id = self.neighbor.local_address

            try:
                generator = self.connection.establish()
                while True:
                    connected = six.next(generator)
                    if not connected:
                        yield False
                        continue
                    if self.peer.neighbor.api['neighbor-changes']:
                        self.peer.reactor.processes.connected(
                            self.peer.neighbor)
                    yield True
                    return
            except StopIteration:
                # close called by the caller
                # self.close('could not connect to remote end')
                yield False
                return
Пример #17
0
	def _multi_neighbor (self, scope, tokens):
		if len(tokens) != 1:
			return self.error.set('syntax: neighbor <ip> { <options> }')

		address = tokens[0]
		scope.append({})
		try:
			scope[-1]['peer-address'] = IP.create(address)
		except (IndexError,ValueError,socket.error):
			return self.error.set('"%s" is not a valid IP address' % address)

		while True:
			r = self._dispatch(
				scope,'neighbor',
				[
					'static','flow','l2vpn',
					'process','family','capability','operational'
				],
				[
					'description','router-id','local-address','local-as','peer-as',
					'host-name','domain-name',
					'passive','listen','hold-time','add-path','graceful-restart','md5',
					'ttl-security','multi-session','group-updates','asn4','aigp',
					'auto-flush','adj-rib-out'
				]
			)
			# XXX: THIS SHOULD ALLOW CAPABILITY AND NOT THE INDIVIDUAL SUB KEYS
			if r is False:
				return False
			if r is None:
				return True
Пример #18
0
def next_hop(tokeniser):
    value = tokeniser()

    if value.lower() == 'self':
        return IPSelf(tokeniser.afi), NextHopSelf(tokeniser.afi)
    else:
        ip = IP.create(value)
        return ip, NextHop(ip.top())
Пример #19
0
	def ip (self, scope, command, tokens):
		try:
			ip = IP.create(tokens[0])
		except (IndexError,ValueError):
			return self.error.set('"%s" is an invalid IP address' % ' '.join(tokens))

		scope[-1][command] = ip
		return True
Пример #20
0
def next_hop(tokeniser):
    value = tokeniser()

    if value.lower() == 'self':
        return NextHopSelf(AFI.ipv4)
    else:
        ip = IP.create(value)
        return NextHop(ip.top(), ip.pack())
Пример #21
0
def next_hop (tokeniser):
	value = tokeniser()

	if value.lower() == 'self':
		return NextHopSelf(AFI.ipv4)
	else:
		ip = IP.create(value)
		return NextHop(ip.string,ip.pack())
Пример #22
0
	def new (cls, afi, safi, packed, mask, labels, rd, nexthop=None, action=OUT.UNSET):
		instance = cls(afi,safi,action)
		instance.cidr = CIDR(packed, mask)
		instance.labels = labels
		instance.rd = rd
		instance.nexthop = IP.create(nexthop) if nexthop else NoNextHop
		instance.action = action
		return instance
Пример #23
0
def ip(tokeniser):
    if not tokeniser.tokens:
        raise ValueError('an ip address is required')

    value = tokeniser()
    try:
        return IP.create(value)
    except (IndexError, ValueError, socket.error):
        raise ValueError('"%s" is an invalid IP address' % value)
Пример #24
0
    def ip(self, scope, name, command, tokens):
        try:
            ip = IP.create(tokens[0])
        except (IndexError, ValueError):
            return self.error.set('"%s" is an invalid IP address' %
                                  ' '.join(tokens))

        scope[-1][command] = ip
        return True
Пример #25
0
def ip(tokeniser):
    if not tokeniser.tokens:
        raise ValueError("an ip address is required")

    value = tokeniser()
    try:
        return IP.create(value)
    except (IndexError, ValueError, socket.error):
        raise ValueError('"%s" is an invalid IP address' % value)
Пример #26
0
def next_hop (tokeniser):
	value = tokeniser()

	if value.lower() == 'self':
		return IPSelf(tokeniser.afi),NextHopSelf(tokeniser.afi)
	else:
		ip = IP.create(value)
		if ip.afi == AFI.ipv4:
			return ip,NextHop(ip.top())
		return ip,None
Пример #27
0
	def ip_list (_):
		ips = []
		for ip in _.split(' '):
			if not ip:
				continue
			elif isip(ip):
				ips.append(IP.create(ip))
			else:
				raise TypeError('ip %s is invalid' % ip)
		return ips
Пример #28
0
 def ip_list(_):
     ips = []
     for ip in _.split(' '):
         if not ip:
             continue
         elif isip(ip):
             ips.append(IP.create(ip))
         else:
             raise TypeError('ip %s is invalid' % ip)
     return ips
Пример #29
0
def next_hop(tokeniser):
    value = tokeniser()

    if value.lower() == 'self':
        return IPSelf(AFI.undefined), NextHopSelf(AFI.undefined)
    else:
        ip = IP.create(value)
        if ip.afi == AFI.ipv4:
            return ip, NextHop(ip.top())
        return ip, None
Пример #30
0
def local_address(tokeniser):
    if not tokeniser.tokens:
        raise ValueError("an ip address  or 'auto' is required")

    value = tokeniser()
    if value == 'auto':
        return value
    try:
        return IP.create(value)
    except (IndexError, ValueError, socket.error):
        raise ValueError('"%s" is an invalid IP address' % value)
Пример #31
0
def local_address(tokeniser):
	if not tokeniser.tokens:
		raise ValueError("an ip address  or 'auto' is required")

	value = tokeniser()
	if value == 'auto':
		return None
	try:
		return IP.create(value)
	except (IndexError,ValueError,socket.error):
		raise ValueError('"%s" is an invalid IP address' % value)
Пример #32
0
	def next_hop (self, scope, name, command, tokens):
		try:
			change = scope[-1]['announce'][-1]

			if change.nlri.nexthop is not NoNextHop:
				return self.error.set(self.syntax)

			change.nlri.nexthop = IP.create(tokens.pop(0))
			return True

		except (IndexError,ValueError):
			return self.error.set(self.syntax)
Пример #33
0
    def next_hop(self, scope, name, command, tokens):
        try:
            change = scope[-1]['announce'][-1]

            if change.nlri.nexthop is not NoNextHop:
                return self.error.set(self.syntax)

            change.nlri.nexthop = IP.create(tokens.pop(0))
            return True

        except (IndexError, ValueError):
            return self.error.set(self.syntax)
Пример #34
0
    def test99_EVPNMulticastCreatePackUnpack(self):
        '''Test pack/unpack for E-VPN Multicast routes'''

        nlri = EVPNMulticast(RouteDistinguisher.fromElements("42.42.42.42", 5),
                             EthernetTag(111), IP.create("1.1.1.1"))

        packed = nlri.pack()

        unpacked, leftover = EVPN.unpack_nlri(AFI.l2vpn, SAFI.evpn, packed,
                                              OUT.UNSET, None)

        self.assertEqual(0, len(leftover))

        # TODO: compare packed with a reference encoding verified
        # as conformant with RFC7432

        self.assertTrue(isinstance(unpacked, EVPNMulticast))

        self.assertEqual("42.42.42.42:5", unpacked.rd._str())
        self.assertEqual(EthernetTag(111), unpacked.etag)
        self.assertEqual(IP.create("1.1.1.1"), unpacked.ip)
Пример #35
0
	def copy (self, scope, name, command, tokens):
		# README: We are setting the ASN as zero as that what Juniper (and Arbor) did when we created a local flow route
		try:
			if scope[-1]['announce'][-1].attributes.has(Attribute.CODE.NEXT_HOP):
				return self.error.set(self.syntax)

			change = scope[-1]['announce'][-1]
			change.nlri.nexthop = IP.create(tokens.pop(0))
			change.attributes[Attribute.CODE.EXTENDED_COMMUNITY].add(TrafficNextHop(True))
			return True

		except (IndexError,ValueError):
			return self.error.set(self.syntax)
Пример #36
0
    def test100_EVPNMACHashEqual(self):
        '''
        Two indistinct EVPN NLRI should
        hash to the same value, and be equal
        '''

        nlri1 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(0),
                        EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6*8,
                        Labels([42], True),
                        IP.create("1.1.1.1"))

        nlri2 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(0),
                        EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6*8,
                        Labels([42], True),
                        IP.create("1.1.1.1"))

        self.assertEqual(hash(nlri1), hash(nlri2))
        self.assertEqual(nlri1, nlri2)
Пример #37
0
    def test99_EVPNMulticastCreatePackUnpack(self):
        '''Test pack/unpack for E-VPN Multicast routes'''

        nlri = EVPNMulticast(RouteDistinguisher.fromElements("42.42.42.42", 5),
                             EthernetTag(111),
                             IP.create("1.1.1.1"))

        packed = nlri.pack()

        unpacked,leftover = EVPN.unpack_nlri(AFI(AFI.l2vpn), SAFI(SAFI.evpn),
                                             packed, OUT.UNSET, None)

        self.assertEqual(0, len(leftover))

        # TODO: compare packed with a reference encoding verified 
        # as conformant with RFC7432

        self.assertTrue(isinstance(unpacked, EVPNMulticast))

        self.assertEqual("42.42.42.42:5", unpacked.rd._str())
        self.assertEqual(EthernetTag(111), unpacked.etag)
        self.assertEqual(IP.create("1.1.1.1"), unpacked.ip)
Пример #38
0
    def test101_EVPNHashEqual_somefieldsvary(self):
        '''
        Two EVPN MAC NLRIs differing by their ESI or label or RD,
        or nexthop, but otherwise identical should hash to the same value,
        and be equal
        '''

        nlri0 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42",
                                                        5), ESI(),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([42], True), IP.create("1.1.1.1"))

        # Esi
        nlri1 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(['1' for _ in range(0, 10)]), EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6 * 8, Labels([42], True),
                        IP.create("1.1.1.1"))

        # label
        nlri2 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42",
                                                        5), ESI(),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([4444], True), IP.create("1.1.1.1"))

        # IP: different IPs, but same MACs: different route
        nlri3 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42",
                                                        5), ESI(),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([42], True), IP.create("2.2.2.2"))

        # with a next hop...
        nlri4 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42",
                                                        5), ESI(),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([42], True), IP.create("1.1.1.1"),
                        IP.pton("10.10.10.10"))
        nlri5 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42",
                                                        5), ESI(),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([42], True), IP.create("1.1.1.1"),
                        IP.pton("11.11.11.11"))

        self.assertEqual(hash(nlri0), hash(nlri1))
        self.assertEqual(hash(nlri0), hash(nlri2))
        self.assertEqual(hash(nlri0), hash(nlri4))
        self.assertEqual(nlri0, nlri1)
        self.assertEqual(nlri0, nlri2)
        self.assertEqual(nlri0, nlri4)
        self.assertEqual(nlri1, nlri2)
        self.assertEqual(nlri1, nlri4)
        self.assertEqual(nlri2, nlri4)
        self.assertEqual(nlri4, nlri5)

        self.assertNotEqual(hash(nlri0), hash(nlri3))
        self.assertNotEqual(nlri0, nlri3)
        self.assertNotEqual(nlri1, nlri3)
        self.assertNotEqual(nlri2, nlri3)
        self.assertNotEqual(nlri3, nlri4)
Пример #39
0
    def copy(self, scope, name, command, tokens):
        # README: We are setting the ASN as zero as that what Juniper (and Arbor) did when we created a local flow route
        try:
            if scope[-1]['announce'][-1].attributes.has(
                    Attribute.CODE.NEXT_HOP):
                return self.error.set(self.syntax)

            change = scope[-1]['announce'][-1]
            change.nlri.nexthop = IP.create(tokens.pop(0))
            change.attributes[Attribute.CODE.EXTENDED_COMMUNITY].add(
                TrafficNextHop(True))
            return True

        except (IndexError, ValueError):
            return self.error.set(self.syntax)
Пример #40
0
def redirect (tokeniser):
	data = tokeniser()
	if data.count(':') == 1:
		prefix,suffix = data.split(':',1)
		if prefix.count('.'):
			raise ValueError('this format has been deprecaded as it does not make sense and it is not supported by other vendors')

		asn = int(prefix)
		route_target = int(suffix)
		if asn >= pow(2,16):
			raise ValueError('asn is a 32 bits number, it can only be 16 bit %s' % route_target)
		if route_target >= pow(2,32):
			raise ValueError('route target is a 32 bits number, value too large %s' % route_target)
		return NoNextHop,ExtendedCommunities().add(TrafficRedirect(asn,route_target))
	else:
		return IP.create(data),ExtendedCommunities().add(TrafficNextHop(False))
Пример #41
0
def redirect (tokeniser):
	data = tokeniser()
	if data.count(':') == 1:
		prefix,suffix = data.split(':',1)
		if prefix.count('.'):
			raise ValueError('this format has been deprecaded as it does not make sense and it is not supported by other vendors')

		asn = int(prefix)
		route_target = int(suffix)
		if asn >= pow(2,16):
			raise ValueError('asn is a 32 bits number, it can only be 16 bit %s' % route_target)
		if route_target >= pow(2,32):
			raise ValueError('route target is a 32 bits number, value too large %s' % route_target)
		return None,ExtendedCommunities().add(TrafficRedirect(asn,route_target))
	else:
		return IP.create(data),ExtendedCommunities().add(TrafficNextHop(False))
Пример #42
0
    def redirect(self, scope, name, command, tokens):
        try:
            if tokens[0].count(':') == 1:
                prefix, suffix = tokens[0].split(':', 1)
                if prefix.count('.'):
                    raise ValueError(
                        'this format has been deprecaded as it does not make sense and it is not supported by other vendors'
                    )
                else:
                    asn = int(prefix)
                    route_target = int(suffix)
                    if asn >= pow(2, 16):
                        raise ValueError(
                            'asn is a 32 bits number, it can only be 16 bit %s'
                            % route_target)
                    if route_target >= pow(2, 32):
                        raise ValueError(
                            'route target is a 32 bits number, value too large %s'
                            % route_target)
                    scope[-1]['announce'][-1].attributes[
                        Attribute.CODE.EXTENDED_COMMUNITY].add(
                            TrafficRedirect(asn, route_target))
                    return True
            else:
                change = scope[-1]['announce'][-1]
                if change.nlri.nexthop is not NoNextHop:
                    return self.error.set(self.syntax)

                nh = IP.create(tokens.pop(0))
                change.nlri.nexthop = nh
                change.attributes[Attribute.CODE.EXTENDED_COMMUNITY].add(
                    TrafficNextHop(False))
                return True

        except (IndexError, ValueError):
            return self.error.set(self.syntax)
Пример #43
0
    def next_hop(self, scope, name, command, tokens):
        if scope[-1]['announce'][-1].attributes.has(Attribute.CODE.NEXT_HOP):
            return self.error.set(self.syntax)

        try:
            # next-hop self is unsupported
            ip = tokens.pop(0)
            if ip.lower() == 'self':
                if 'local-address' in scope[-1]:
                    la = scope[-1]['local-address']
                elif self._nexthopself:
                    la = self._nexthopself
                else:
                    return self.error.set(
                        'next-hop self can only be specified with a neighbor')
                nh = IP.unpack(la.pack())
            else:
                nh = IP.create(ip)

            change = scope[-1]['announce'][-1]
            nlri = change.nlri
            afi = nlri.afi
            safi = nlri.safi

            nlri.nexthop = nh

            if afi == AFI.ipv4 and safi in (SAFI.unicast, SAFI.multicast):
                change.attributes.add(
                    Attribute.unpack(NextHop.ID, NextHop.FLAG, nh.packed,
                                     None))
                # NextHop(nh.ip,nh.packed) does not cache the result, using unpack does
                # change.attributes.add(NextHop(nh.ip,nh.packed))

            return True
        except Exception:
            return self.error.set(self.syntax)
Пример #44
0
def ls_unicast_ipv4_neighbor_address (tokeniser):
	value = tokeniser()
	return IP.create(value)
Пример #45
0
    def test101_EVPNHashEqual_somefieldsvary(self):
        '''
        Two EVPN MAC NLRIs differing by their ESI or label or RD,
        or nexthop, but otherwise identical should hash to the same value,
        and be equal
        '''

        nlri0 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(0),
                        EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6*8,
                        Labels([42], True),
                        IP.create("1.1.1.1"))

        # Esi
        nlri1 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(1),
                        EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6*8,
                        Labels([42], True),
                        IP.create("1.1.1.1"))

        # label
        nlri2 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(0),
                        EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6*8,
                        Labels([4444], True),
                        IP.create("1.1.1.1"))

        # IP: different IPs, but same MACs: different route
        nlri3 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(0),
                        EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6*8,
                        Labels([42], True),
                        IP.create("2.2.2.2"))

        # with a next hop...
        nlri4 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(0),
                        EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6*8,
                        Labels([42], True),
                        IP.create("1.1.1.1"),
                        IP.pton("10.10.10.10"))
        nlri5 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(0),
                        EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6*8,
                        Labels([42], True),
                        IP.create("1.1.1.1"),
                        IP.pton("11.11.11.11"))

        self.assertEqual(hash(nlri0), hash(nlri1))
        self.assertEqual(hash(nlri0), hash(nlri2))
        self.assertEqual(hash(nlri0), hash(nlri4))
        self.assertEqual(nlri0, nlri1)
        self.assertEqual(nlri0, nlri2)
        self.assertEqual(nlri0, nlri4)
        self.assertEqual(nlri1, nlri2)
        self.assertEqual(nlri1, nlri4)
        self.assertEqual(nlri2, nlri4)
        self.assertEqual(nlri4, nlri5)

        self.assertNotEqual(hash(nlri0), hash(nlri3))
        self.assertNotEqual(nlri0, nlri3)
        self.assertNotEqual(nlri1, nlri3)
        self.assertNotEqual(nlri2, nlri3)
        self.assertNotEqual(nlri3, nlri4)
Пример #46
0
def ip(tokeniser):
    value = tokeniser()
    try:
        return IP.create(value)
    except (IndexError, ValueError, SocketError):
        raise ValueError('"%s" is an invalid IP address' % value)
Пример #47
0
	def __init__ (self, ip, packed=None):
		# Need to conform to from IP interface
		self.ip = ip
		self.packed = packed if packed else IP.create(ip).pack()
Пример #48
0
def next_hop(tokeniser):
    value = tokeniser()

    if value.lower() == 'self':
        return NextHopSelf(AFI.ipv4)
    return IP.create(value)
Пример #49
0
def ls_unicast_ipv4_neighbor_address(tokeniser):
    value = tokeniser()
    return IP.create(value)
Пример #50
0
def copy(tokeniser):
    return IP.create(tokeniser()), ExtendedCommunities().add(TrafficNextHopSimpson(True))
Пример #51
0
def ls_unicast_ipv4_interface_address (tokeniser):
	value = tokeniser()
	return IP.create(value)
Пример #52
0
	def new_connections (self):
		if not self.serving:
			return
		yield None

		reactor = self._reactor
		ranged_neighbor = []

		for connection in self._connected():
			self.logger.debug('new connection received %s' % connection.name(),'network')
			for key in reactor.peers:
				peer = reactor.peers[key]
				neighbor = peer.neighbor

				connection_local = IP.create(connection.local).address()
				neighbor_peer_start = neighbor.peer_address.address()
				neighbor_peer_next = neighbor_peer_start + neighbor.range_size

				if not neighbor_peer_start <= connection_local < neighbor_peer_next:
					continue

				connection_peer = IP.create(connection.peer).address()
				neighbor_local = neighbor.local_address.address()

				if connection_peer != neighbor_local:
					if not neighbor.auto_discovery:
						continue

				# we found a range matching for this connection
				# but the peer may already have connected, so
				# we need to iterate all individual peers before
				# handling "range" peers
				if neighbor.range_size > 1:
					ranged_neighbor.append(peer.neighbor)
					continue

				denied = peer.handle_connection(connection)
				if denied:
					self.logger.debug('refused connection from %s due to the state machine' % connection.name(),'network')
					break
				self.logger.debug('accepted connection from %s' % connection.name(),'network')
				break
			else:
				# we did not break (and nothign was found/done or we have group match)
				matched = len(ranged_neighbor)
				if matched > 1:
					self.logger.debug('could not accept connection from %s (more than one neighbor match)' % connection.name(),'network')
					reactor.asynchronous.schedule(str(uuid.uuid1()), 'sending notification (6,5)', connection.notification(
						6, 5, 'could not accept the connection (more than one neighbor match)'))
					return
				if not matched:
					self.logger.debug('no session configured for %s' % connection.name(),'network')
					reactor.asynchronous.schedule(str(uuid.uuid1()), 'sending notification (6,3)', connection.notification(
						6, 3, 'no session configured for the peer'))
					return

				new_neighbor = copy.copy(ranged_neighbor[0])
				new_neighbor.range_size = 1
				new_neighbor.generated = True
				new_neighbor.local_address = IP.create(connection.peer)
				new_neighbor.peer_address = IP.create(connection.local)
				new_neighbor.router_id = RouterID.create(connection.local)

				new_peer = Peer(new_neighbor,self)
				denied = new_peer.handle_connection(connection)
				if denied:
					self.logger.debug('refused connection from %s due to the state machine' % connection.name(),'network')
					return

				reactor.peers[new_neighbor.name()] = new_peer
				return
Пример #53
0
    def new_connections(self):
        if not self.serving:
            return
        yield None

        reactor = self._reactor
        ranged_neighbor = []

        for connection in self._connected():
            for key in reactor.peers:
                peer = reactor.peers[key]
                neighbor = peer.neighbor

                connection_local = IP.create(connection.local).address()
                neighbor_peer_start = neighbor.peer_address.address()
                neighbor_peer_next = neighbor_peer_start + neighbor.range_size

                if not neighbor_peer_start <= connection_local < neighbor_peer_next:
                    continue

                connection_peer = IP.create(connection.peer).address()
                neighbor_local = neighbor.local_address.address()

                if connection_peer != neighbor_local:
                    if not neighbor.auto_discovery:
                        continue

                # we found a range matching for this connection
                # but the peer may already have connected, so
                # we need to iterate all individual peers before
                # handling "range" peers
                if neighbor.range_size > 1:
                    ranged_neighbor.append(peer.neighbor)
                    continue

                denied = peer.handle_connection(connection)
                if denied:
                    self.logger.debug(
                        'refused connection from %s due to the state machine' %
                        connection.name(), 'network')
                    break
                self.logger.debug(
                    'accepted connection from %s' % connection.name(),
                    'network')
                break
            else:
                # we did not break (and nothign was found/done or we have group match)
                matched = len(ranged_neighbor)
                if matched > 1:
                    self.logger.debug(
                        'could not accept connection from %s (more than one neighbor match)'
                        % connection.name(), 'network')
                    reactor. async .schedule(
                        str(uuid.uuid1()), 'sending notification (6,5)',
                        connection.notification(
                            6, 5,
                            b'could not accept the connection (more than one neighbor match)'
                        ))
                    return
                if not matched:
                    self.logger.debug(
                        'no session configured for %s' % connection.name(),
                        'network')
                    reactor. async .schedule(
                        str(uuid.uuid1()), 'sending notification (6,3)',
                        connection.notification(
                            6, 3, b'no session configured for the peer'))
                    return

                new_neighbor = copy.copy(ranged_neighbor[0])
                new_neighbor.range_size = 1
                new_neighbor.generated = True
                new_neighbor.local_address = IP.create(connection.peer)
                new_neighbor.peer_address = IP.create(connection.local)

                new_peer = Peer(new_neighbor, self)
                denied = new_peer.handle_connection(connection)
                if denied:
                    self.logger.debug(
                        'refused connection from %s due to the state machine' %
                        connection.name(), 'network')
                    return

                reactor.peers[new_neighbor.name()] = new_peer
                return
Пример #54
0
def copy (tokeniser):
	return IP.create(tokeniser()),ExtendedCommunities().add(TrafficNextHop(True))
Пример #55
0
 def __init__(self, ip, packed=None):
     # Need to conform to from IP interface
     self.ip = ip
     self.packed = packed if packed else IP.create(ip).pack()
Пример #56
0
def ls_unicast_remote_node (tokeniser):
	value = tokeniser()
	return IP.create(value)
Пример #57
0
def next_hop (tokeniser):
	value = tokeniser()

	if value.lower() == 'self':
		return NextHopSelf(AFI.ipv4)
	return IP.create(value)
Пример #58
0
def ip (tokeniser):
	value = tokeniser()
	try:
		return IP.create(value)
	except (IndexError,ValueError,SocketError):
		raise ValueError('"%s" is an invalid IP address' % value)
Пример #59
0
def redirect_next_hop_ietf(tokeniser):
    ip = IP.create(tokeniser())
    if ip.ipv4():
        return ExtendedCommunities().add(TrafficNextHopIPv4IETF(ip, False))
    else:
        return ExtendedCommunitiesIPv6().add(TrafficNextHopIPv6IETF(ip, False))