Example #1
0
 def all(self, tokeniser):
     if self._all or self._seen:
         return self.error.set('all can not be used with any other options')
     self._all = True
     for pair in NLRI.known_families():
         self._seen.append(pair)
Example #2
0
	def post (self):
		local = self.scope.pop_context(self.name)
		neighbor = Neighbor()

		# XXX: use the right class for the data type
		# XXX: we can use the scope.nlri interface ( and rename it ) to set some values
		neighbor.router_id        = local.get('router-id',None)
		neighbor.peer_address     = local.get('peer-address',None)
		neighbor.local_address    = local.get('local-address',None)
		neighbor.local_as         = local.get('local-as',None)
		neighbor.peer_as          = local.get('peer-as',None)
		neighbor.passive          = local.get('passive',False)
		neighbor.listen           = local.get('listen',0)
		neighbor.hold_time        = local.get('hold-time',HoldTime(180))
		neighbor.host_name        = local.get('host-name',_hostname())
		neighbor.domain_name      = local.get('domain-name',_domainname())
		neighbor.md5              = local.get('md5',None)
		neighbor.description      = local.get('description','')
		neighbor.flush            = local.get('auto-flush',True)
		neighbor.adjribout        = local.get('adj-rib-out',True)
		neighbor.aigp             = local.get('aigp',None)
		neighbor.ttl              = local.get('ttl-security',None)
		neighbor.group_updates    = local.get('group-updates',True)
		neighbor.manual_eor       = local.get('manual-eor', False)

		neighbor.api              = ParseAPI.extract()

		# capabilities
		capability = local.get('capability',{})
		neighbor.graceful_restart = capability.get('graceful-restart',0) or int(neighbor.hold_time)
		neighbor.add_path         = capability.get('add-path',0)
		neighbor.asn4             = capability.get('asn4',True)
		neighbor.multisession     = capability.get('multi-session',False)
		neighbor.operational      = capability.get('operational',False)
		neighbor.route_refresh    = capability.get('route-refresh',0)

		families = []
		for family in ParseFamily.convert.keys():
			for pair in local.get('family',{}).get(family,[]):
				families.append(pair)

		families = families or NLRI.known_families()

		if (AFI.ipv4,SAFI.unicast) not in families:
			families.append((AFI(AFI.ipv4),SAFI(SAFI.unicast)))

		for family in families:
			neighbor.add_family(family)

		neighbor.changes = []

		for section in ('static','l2vpn','flow'):
			routes = local.get(section,{}).get('routes',[])
			for route in routes:
				route.nlri.action = OUT.ANNOUNCE
			neighbor.changes.extend(routes)

		messages = local.get('operational',{}).get('routes',[])

		if not neighbor.router_id:
			neighbor.router_id = neighbor.local_address

		if neighbor.graceful_restart is None:
			neighbor.graceful_restart = int(neighbor.hold_time)

		if neighbor.route_refresh:
			if neighbor.adjribout:
				self.logger.configuration('route-refresh requested, enabling adj-rib-out')

		missing = neighbor.missing()
		if missing:
			return self.error.set('incomplete neighbor, missing %s' % missing)

		if neighbor.local_address.afi != neighbor.peer_address.afi:
			return self.error.set('local-address and peer-address must be of the same family')

		if neighbor.peer_address.top() in self._neighbors:
			return self.error.set('duplicate peer definition %s' % neighbor.peer_address.top())
		self._neighbors.append(neighbor.peer_address.top())

		# check we are not trying to announce routes without the right MP announcement
		for change in neighbor.changes:
			family = change.nlri.family()
			if family not in families and family != (AFI.ipv4,SAFI.unicast):
				return self.error.set('Trying to announce a route of type %s,%s when we are not announcing the family to our peer' % change.nlri.family())

		def _init_neighbor (neighbor):
			families = neighbor.families()
			for change in neighbor.changes:
				if change.nlri.family() in families:
					# This add the family to neighbor.families()
					neighbor.rib.outgoing.insert_announced_watchdog(change)
			for message in messages:
				if message.family() in families:
					if message.name == 'ASM':
						neighbor.asm[message.family()] = message
					else:
						neighbor.messages.append(message)
			self.neighbors[neighbor.name()] = neighbor

		# create one neighbor object per family for multisession
		if neighbor.multisession and len(neighbor.families()) > 1:
			for family in neighbor.families():
				# XXX: FIXME: Ok, it works but it takes LOTS of memory ..
				m_neighbor = deepcopy(neighbor)
				m_neighbor.make_rib()
				m_neighbor.rib.outgoing.families = [family]
				_init_neighbor(m_neighbor)
		else:
			neighbor.make_rib()
			_init_neighbor(neighbor)

		return True
Example #3
0
    def post(self):
        local = self.scope.pop_context(self.name)
        neighbor = Neighbor()

        # XXX: use the right class for the data type
        # XXX: we can use the scope.nlri interface ( and rename it ) to set some values
        neighbor.router_id = local.get('router-id', None)
        neighbor.peer_address = local.get('peer-address', None)
        neighbor.local_address = local.get('local-address', None)
        neighbor.local_as = local.get('local-as', None)
        neighbor.peer_as = local.get('peer-as', None)
        neighbor.passive = local.get('passive', False)
        neighbor.listen = local.get('listen', 0)
        neighbor.hold_time = local.get('hold-time', HoldTime(180))
        neighbor.host_name = local.get('host-name', _hostname())
        neighbor.domain_name = local.get('domain-name', _domainname())
        neighbor.md5 = local.get('md5', None)
        neighbor.description = local.get('description', '')
        neighbor.flush = local.get('auto-flush', True)
        neighbor.adjribout = local.get('adj-rib-out', True)
        neighbor.aigp = local.get('aigp', None)
        neighbor.ttl = local.get('ttl-security', None)
        neighbor.group_updates = local.get('group-updates', True)
        neighbor.manual_eor = local.get('manual-eor', False)

        neighbor.api = ParseAPI.extract()

        # capabilities
        capability = local.get('capability', {})

        neighbor.add_path = capability.get('add-path', 0)
        neighbor.asn4 = capability.get('asn4', True)
        neighbor.multisession = capability.get('multi-session', False)
        neighbor.operational = capability.get('operational', False)
        neighbor.route_refresh = capability.get('route-refresh', 0)

        if capability.get('graceful-restart', False) is not False:
            neighbor.graceful_restart = capability.get(
                'graceful-restart', 0) or int(neighbor.hold_time)

        families = []
        for family in ParseFamily.convert.keys():
            for pair in local.get('family', {}).get(family, []):
                families.append(pair)

        families = families or NLRI.known_families()

        if (AFI.ipv4, SAFI.unicast) not in families:
            families.append((AFI(AFI.ipv4), SAFI(SAFI.unicast)))

        for family in families:
            neighbor.add_family(family)

        neighbor.changes = []

        for section in ('static', 'l2vpn', 'flow'):
            routes = local.get(section, {}).get('routes', [])
            for route in routes:
                route.nlri.action = OUT.ANNOUNCE
            neighbor.changes.extend(routes)

        messages = local.get('operational', {}).get('routes', [])

        if not neighbor.router_id:
            neighbor.router_id = neighbor.local_address

        if neighbor.route_refresh:
            if neighbor.adjribout:
                self.logger.configuration(
                    'route-refresh requested, enabling adj-rib-out')

        missing = neighbor.missing()
        if missing:
            return self.error.set('incomplete neighbor, missing %s' % missing)

        if neighbor.local_address.afi != neighbor.peer_address.afi:
            return self.error.set(
                'local-address and peer-address must be of the same family')

        if neighbor.peer_address.top() in self._neighbors:
            return self.error.set('duplicate peer definition %s' %
                                  neighbor.peer_address.top())
        self._neighbors.append(neighbor.peer_address.top())

        # check we are not trying to announce routes without the right MP announcement
        for change in neighbor.changes:
            family = change.nlri.family()
            if family not in families and family != (AFI.ipv4, SAFI.unicast):
                return self.error.set(
                    'Trying to announce a route of type %s,%s when we are not announcing the family to our peer'
                    % change.nlri.family())

        def _init_neighbor(neighbor):
            families = neighbor.families()
            for change in neighbor.changes:
                if change.nlri.family() in families:
                    # This add the family to neighbor.families()
                    neighbor.rib.outgoing.insert_announced_watchdog(change)
            for message in messages:
                if message.family() in families:
                    if message.name == 'ASM':
                        neighbor.asm[message.family()] = message
                    else:
                        neighbor.messages.append(message)
            self.neighbors[neighbor.name()] = neighbor

        # create one neighbor object per family for multisession
        if neighbor.multisession and len(neighbor.families()) > 1:
            for family in neighbor.families():
                # XXX: FIXME: Ok, it works but it takes LOTS of memory ..
                m_neighbor = deepcopy(neighbor)
                m_neighbor.make_rib()
                m_neighbor.rib.outgoing.families = [family]
                _init_neighbor(m_neighbor)
        else:
            neighbor.make_rib()
            _init_neighbor(neighbor)

        return True
    def post(self):
        for inherit in self.scope.pop('inherit', []):
            data = self.scope.template('neighbor', inherit)
            self.scope.inherit(data)
        local = self.scope.get()

        neighbor = Neighbor()

        # XXX: use the right class for the data type
        # XXX: we can use the scope.nlri interface ( and rename it ) to set some values
        neighbor.router_id = local.get('router-id', None)
        neighbor.peer_address = local.get('peer-address', None)
        neighbor.local_address = local.get('local-address', None)
        neighbor.local_as = local.get('local-as', None)
        neighbor.peer_as = local.get('peer-as', None)
        neighbor.passive = local.get('passive', False)
        neighbor.listen = local.get('listen', 0)
        neighbor.connect = local.get('connect', 0)
        neighbor.hold_time = local.get('hold-time', HoldTime(180))
        neighbor.host_name = local.get('host-name', host())
        neighbor.domain_name = local.get('domain-name', domain())
        neighbor.md5_password = local.get('md5-password', None)
        neighbor.md5_base64 = local.get('md5-base64', None)
        neighbor.md5_ip = local.get('md5-ip', neighbor.local_address)
        neighbor.description = local.get('description', '')
        neighbor.flush = local.get('auto-flush', True)
        neighbor.adj_rib_out = local.get('adj-rib-out', True)
        neighbor.adj_rib_in = local.get('adj-rib-in', True)
        neighbor.aigp = local.get('aigp', None)
        neighbor.ttl_out = local.get('outgoing-ttl', None)
        neighbor.ttl_in = local.get('incoming-ttl', None)
        neighbor.group_updates = local.get('group-updates', True)
        neighbor.manual_eor = local.get('manual-eor', False)

        capability = local.get('capability', {})
        neighbor.add_path = capability.get('add-path', 0)
        neighbor.asn4 = capability.get('asn4', True)
        neighbor.extended_message = capability.get('extended-message', True)
        neighbor.multisession = capability.get('multi-session', False)
        neighbor.operational = capability.get('operational', False)
        neighbor.route_refresh = capability.get('route-refresh', 0)

        if capability.get('graceful-restart', False) is not False:
            neighbor.graceful_restart = capability.get(
                'graceful-restart', 0) or int(neighbor.hold_time)

        neighbor.api = ParseAPI.flatten(local.pop('api', {}))

        families = []
        for family in ParseFamily.convert:
            for pair in local.get('family', {}).get(family, []):
                families.append(pair)

        families = families or NLRI.known_families()

        for family in families:
            neighbor.add_family(family)

        if neighbor.add_path:
            add_path = local.get('add-path', {})
            if add_path:
                for family in ParseAddPath.convert:
                    for pair in add_path.get(family, []):
                        if pair not in families:
                            self.logger.debug(
                                'skipping add-path family %s as it is not negotiated'
                                % pair, 'configuration')
                            continue
                        neighbor.add_addpath(pair)
            else:
                for family in families:
                    neighbor.add_addpath(family)

        neighbor.changes = []
        neighbor.changes.extend(self.scope.pop_routes())

        # old format
        for section in ('static', 'l2vpn', 'flow'):
            routes = local.get(section, {}).get('routes', [])
            for route in routes:
                route.nlri.action = OUT.ANNOUNCE
            neighbor.changes.extend(routes)

        routes = local.get('routes', [])
        for route in routes:
            route.nlri.action = OUT.ANNOUNCE
        neighbor.changes.extend(routes)

        messages = local.get('operational', {}).get('routes', [])

        if neighbor.local_address is None:
            neighbor.auto_discovery = True
            neighbor.local_address = None
            neighbor.md5_ip = None

        if not neighbor.router_id and neighbor.peer_address.afi == AFI.ipv4 and not neighbor.auto_discovery:
            neighbor.router_id = neighbor.local_address

        if neighbor.route_refresh:
            if neighbor.adj_rib_out:
                self.logger.debug(
                    'route-refresh requested, enabling adj-rib-out',
                    'configuration')

        missing = neighbor.missing()
        if missing:
            return self.error.set('incomplete neighbor, missing %s' % missing)

        if not neighbor.auto_discovery and neighbor.local_address.afi != neighbor.peer_address.afi:
            return self.error.set(
                'local-address and peer-address must be of the same family')
        neighbor.range_size = neighbor.peer_address.mask.size()

        if neighbor.range_size > 1 and not neighbor.passive:
            return self.error.set(
                'can only use ip ranges for the peer address with passive neighbors'
            )

        if neighbor.peer_address.top() in self._neighbors:
            return self.error.set('duplicate peer definition %s' %
                                  neighbor.peer_address.top())
        self._neighbors.append(neighbor.peer_address.top())

        if neighbor.md5_password:
            try:
                md5 = base64.b64decode(
                    neighbor.md5_password
                ) if neighbor.md5_base64 else neighbor.md5_password
            except TypeError as e:
                return self.error.set(
                    "Invalid base64 encoding of MD5 password.")
            else:
                if len(md5) > 80:
                    return self.error.set(
                        'MD5 password must be no larger than 80 characters')

        # check we are not trying to announce routes without the right MP announcement
        for change in neighbor.changes:
            family = change.nlri.family()
            if family not in families and family != (AFI.ipv4, SAFI.unicast):
                return self.error.set(
                    'Trying to announce a route of type %s,%s when we are not announcing the family to our peer'
                    % change.nlri.family())

        def _init_neighbor(neighbor):
            families = neighbor.families()
            for change in neighbor.changes:
                if change.nlri.family() in families:
                    # This add the family to neighbor.families()
                    neighbor.rib.outgoing.add_to_rib_watchdog(change)
            for message in messages:
                if message.family() in families:
                    if message.name == 'ASM':
                        neighbor.asm[message.family()] = message
                    else:
                        neighbor.messages.append(message)
            self.neighbors[neighbor.name()] = neighbor

        # create one neighbor object per family for multisession
        if neighbor.multisession and len(neighbor.families()) > 1:
            for family in neighbor.families():
                # XXX: FIXME: Ok, it works but it takes LOTS of memory ..
                m_neighbor = deepcopy(neighbor)
                m_neighbor.make_rib()
                m_neighbor.rib.outgoing.families = [family]
                _init_neighbor(m_neighbor)
        else:
            neighbor.make_rib()
            _init_neighbor(neighbor)

        return True
Example #5
0
	def post (self):
		for inherit in self.scope.pop('inherit',[]):
			data = self.scope.template('neighbor',inherit)
			self.scope.inherit(data)
		local = self.scope.get()

		neighbor = Neighbor()

		# XXX: use the right class for the data type
		# XXX: we can use the scope.nlri interface ( and rename it ) to set some values
		neighbor.router_id        = local.get('router-id',None)
		neighbor.peer_address     = local.get('peer-address',None)
		neighbor.local_address    = local.get('local-address',None)
		neighbor.local_as         = local.get('local-as',None)
		neighbor.peer_as          = local.get('peer-as',None)
		neighbor.passive          = local.get('passive',False)
		neighbor.listen           = local.get('listen',0)
		neighbor.connect          = local.get('connect',0)
		neighbor.hold_time        = local.get('hold-time',HoldTime(180))
		neighbor.host_name        = local.get('host-name',host())
		neighbor.domain_name      = local.get('domain-name',domain())
		neighbor.md5_password     = local.get('md5-password',None)
		neighbor.md5_base64       = local.get('md5-base64', None)
		neighbor.md5_ip           = local.get('md5-ip',neighbor.local_address)
		neighbor.description      = local.get('description','')
		neighbor.flush            = local.get('auto-flush',True)
		neighbor.adj_rib_out      = local.get('adj-rib-out',True)
		neighbor.adj_rib_in       = local.get('adj-rib-in',True)
		neighbor.aigp             = local.get('aigp',None)
		neighbor.ttl_out          = local.get('outgoing-ttl',None)
		neighbor.ttl_in           = local.get('incoming-ttl',None)
		neighbor.group_updates    = local.get('group-updates',True)
		neighbor.manual_eor       = local.get('manual-eor', False)

		capability = local.get('capability',{})
		neighbor.add_path         = capability.get('add-path',0)
		neighbor.asn4             = capability.get('asn4',True)
		neighbor.extended_message = capability.get('extended-message',True)
		neighbor.multisession     = capability.get('multi-session',False)
		neighbor.operational      = capability.get('operational',False)
		neighbor.route_refresh    = capability.get('route-refresh',0)

		if capability.get('graceful-restart',False) is not False:
			neighbor.graceful_restart = capability.get('graceful-restart',0) or int(neighbor.hold_time)

		neighbor.api              = ParseAPI.flatten(local.pop('api',{}))

		families = []
		for family in ParseFamily.convert:
			for pair in local.get('family',{}).get(family,[]):
				families.append(pair)

		families = families or NLRI.known_families()

		for family in families:
			neighbor.add_family(family)

		if neighbor.add_path:
			add_path = local.get('add-path',{})
			if add_path:
				for family in ParseAddPath.convert:
					for pair in add_path.get(family,[]):
						if pair not in families:
							self.logger.debug('skipping add-path family %s as it is not negotiated' % pair,'configuration')
							continue
						neighbor.add_addpath(pair)
			else:
				for family in families:
					neighbor.add_addpath(family)

		neighbor.changes = []
		neighbor.changes.extend(self.scope.pop_routes())

		# old format
		for section in ('static','l2vpn','flow'):
			routes = local.get(section,{}).get('routes',[])
			for route in routes:
				route.nlri.action = OUT.ANNOUNCE
			neighbor.changes.extend(routes)

		routes = local.get('routes',[])
		for route in routes:
			route.nlri.action = OUT.ANNOUNCE
		neighbor.changes.extend(routes)

		messages = local.get('operational',{}).get('routes',[])

		if neighbor.local_address is None:
			neighbor.auto_discovery = True
			neighbor.local_address = None
			neighbor.md5_ip = None

		if not neighbor.router_id:
			if neighbor.peer_address.afi == AFI.ipv4 and not neighbor.auto_discovery:
				neighbor.router_id = neighbor.local_address
			else:
				return self.error.set('missing router-id for the peer, it can not be set using the local-ip')

		if neighbor.route_refresh:
			if neighbor.adj_rib_out:
				self.logger.debug('route-refresh requested, enabling adj-rib-out','configuration')

		missing = neighbor.missing()
		if missing:
			return self.error.set('incomplete neighbor, missing %s' % missing)

		if not neighbor.auto_discovery and neighbor.local_address.afi != neighbor.peer_address.afi:
			return self.error.set('local-address and peer-address must be of the same family')
		neighbor.range_size = neighbor.peer_address.mask.size()

		if neighbor.range_size > 1 and not neighbor.passive:
			return self.error.set('can only use ip ranges for the peer address with passive neighbors')

		if neighbor.peer_address.top() in self._neighbors:
			return self.error.set('duplicate peer definition %s' % neighbor.peer_address.top())
		self._neighbors.append(neighbor.peer_address.top())

		if neighbor.md5_password:
			try:
				md5 = base64.b64decode(neighbor.md5_password) if neighbor.md5_base64 else neighbor.md5_password
			except TypeError as e:
				return self.error.set("Invalid base64 encoding of MD5 password.")
			else:
				if len(md5) > 80:
					return self.error.set('MD5 password must be no larger than 80 characters')

		# check we are not trying to announce routes without the right MP announcement
		for change in neighbor.changes:
			family = change.nlri.family()
			if family not in families and family != (AFI.ipv4,SAFI.unicast):
				return self.error.set('Trying to announce a route of type %s,%s when we are not announcing the family to our peer' % change.nlri.family())

		def _init_neighbor (neighbor):
			families = neighbor.families()
			for change in neighbor.changes:
				if change.nlri.family() in families:
					# This add the family to neighbor.families()
					neighbor.rib.outgoing.add_to_rib_watchdog(change)
			for message in messages:
				if message.family() in families:
					if message.name == 'ASM':
						neighbor.asm[message.family()] = message
					else:
						neighbor.messages.append(message)
			self.neighbors[neighbor.name()] = neighbor

		# create one neighbor object per family for multisession
		if neighbor.multisession and len(neighbor.families()) > 1:
			for family in neighbor.families():
				# XXX: FIXME: Ok, it works but it takes LOTS of memory ..
				m_neighbor = deepcopy(neighbor)
				m_neighbor.make_rib()
				m_neighbor.rib.outgoing.families = [family]
				_init_neighbor(m_neighbor)
		else:
			neighbor.make_rib()
			_init_neighbor(neighbor)

		return True
Example #6
0
	def _make_neighbor (self, scope):
		# we have local_scope[-2] as the group template and local_scope[-1] as the peer specific
		if len(scope) > 1:
			for key,content in scope[-2].iteritems():
				if key not in scope[-1]:
					scope[-1][key] = deepcopy(content)
				elif key == 'announce':
					scope[-1][key].extend(scope[-2][key])

		neighbor = Neighbor()
		for local_scope in scope:
			value = local_scope.get('router-id','')
			if value:
				neighbor.router_id = value
			value = local_scope.get('peer-address','')
			if value:
				neighbor.peer_address = value
			value = local_scope.get('local-address','')
			if value:
				neighbor.local_address = value
			value = local_scope.get('local-as','')
			if value:
				neighbor.local_as = value
			value = local_scope.get('peer-as','')
			if value:
				neighbor.peer_as = value
			value = local_scope.get('passive',False)
			if value:
				neighbor.passive = value
			value = local_scope.get('listen',0)
			if value:
				neighbor.listen = value
			value = local_scope.get('hold-time','')
			if value:
				neighbor.hold_time = value

			neighbor.host_name = local_scope.get('host-name',hostname())
			neighbor.domain_name = local_scope.get('domain-name',domainname())

			neighbor.changes = local_scope.get('announce',[])
			messages = local_scope.get('operational-message',[])

		# we want to have a socket for the cli
		if self.fifo:
			_cli_name = 'CLI'
			self.processes[_cli_name] = {
				'neighbor': '*',
				'encoder': 'json',
				'run': [sys.executable, sys.argv[0]],

				'neighbor-changes': False,

				'receive-consolidate': False,
				'receive-packets': False,
				'receive-parsed': False,

				'send-consolidate': False,
				'send-packets': False,
				'send-parsed': False,
			}

			for direction in ['send','receive']:
				for message in [
					Message.CODE.NOTIFICATION,
					Message.CODE.OPEN,
					Message.CODE.KEEPALIVE,
					Message.CODE.UPDATE,
					Message.CODE.ROUTE_REFRESH,
					Message.CODE.OPERATIONAL
				]:
					self.processes[_cli_name]['%s-%d' % (direction,message)] = False

		for name in self.processes.keys():
			process = self.processes[name]

			neighbor.api.set('neighbor-changes',process.get('neighbor-changes',False))

			for direction in ['send','receive']:
				for option in ['packets','consolidate','parsed']:
					neighbor.api.set_value(direction,option,process.get('%s-%s' % (direction,option),False))

				for message in [
					Message.CODE.NOTIFICATION,
					Message.CODE.OPEN,
					Message.CODE.KEEPALIVE,
					Message.CODE.UPDATE,
					Message.CODE.ROUTE_REFRESH,
					Message.CODE.OPERATIONAL
				]:
					neighbor.api.set_message(direction,message,process.get('%s-%d' % (direction,message),False))

		if not neighbor.router_id:
			neighbor.router_id = neighbor.local_address

		local_scope = scope[-1]
		neighbor.description = local_scope.get('description','')

		neighbor.md5 = local_scope.get('md5',None)
		neighbor.ttl = local_scope.get('ttl-security',None)
		neighbor.group_updates = local_scope.get('group-updates',None)

		neighbor.route_refresh = local_scope.get('route-refresh',0)
		neighbor.graceful_restart = local_scope.get('graceful-restart',0)
		if neighbor.graceful_restart is None:
			# README: Should it be a subclass of int ?
			neighbor.graceful_restart = int(neighbor.hold_time)
		neighbor.multisession = local_scope.get('multi-session',False)
		neighbor.operational = local_scope.get('capa-operational',False)
		neighbor.add_path = local_scope.get('add-path',0)
		neighbor.flush = local_scope.get('auto-flush',True)
		neighbor.adjribout = local_scope.get('adj-rib-out',True)
		neighbor.asn4 = local_scope.get('asn4',True)
		neighbor.aigp = local_scope.get('aigp',None)

		if neighbor.route_refresh and not neighbor.adjribout:
			return self.error.set('incomplete option route-refresh and no adj-rib-out')

		# XXX: check that if we have any message, we have parsed/packets
		# XXX: and vice-versa

		missing = neighbor.missing()
		if missing:
			return self.error.set('incomplete neighbor, missing %s' % missing)

		if neighbor.local_address.afi != neighbor.peer_address.afi:
			return self.error.set('local-address and peer-address must be of the same family')

		if neighbor.peer_address.ip in self._neighbors:
			return self.error.set('duplicate peer definition %s' % neighbor.peer_address.ip)

		openfamilies = local_scope.get('families','everything')
		# announce every family we known
		if neighbor.multisession and openfamilies == 'everything':
			# announce what is needed, and no more, no need to have lots of TCP session doing nothing
			_families = set()
			for change in neighbor.changes:
				_families.add((change.nlri.afi,change.nlri.safi))
			families = list(_families)
		elif openfamilies in ('all','everything'):
			families = NLRI.known_families()
		# only announce what you have as routes
		elif openfamilies == 'minimal':
			_families = set()
			for change in neighbor.changes:
				_families.add((change.nlri.afi,change.nlri.safi))
			families = list(_families)
		else:
			families = openfamilies

		# check we are not trying to announce routes without the right MP announcement
		for family in neighbor.families():
			if family not in families:
				afi,safi = family
				return self.error.set('Trying to announce a route of type %s,%s when we are not announcing the family to our peer' % (afi,safi))

		# add the families to the list of families known
		initial_families = list(neighbor.families())
		for family in families:
			if family not in initial_families	:
				# we are modifying the data used by .families() here
				neighbor.add_family(family)

		if neighbor.group_updates is None:
			neighbor.group_updates = True

		def _init_neighbor (neighbor):
			families = neighbor.families()
			for change in neighbor.changes:
				if change.nlri.family() in families:
					# This add the family to neighbor.families()
					neighbor.rib.outgoing.insert_announced_watchdog(change)
			for message in messages:
				if message.family() in families:
					if message.name == 'ASM':
						neighbor.asm[message.family()] = message
					else:
						neighbor.messages.append(message)
			self._neighbors[neighbor.name()] = neighbor

		# create one neighbor object per family for multisession
		if neighbor.multisession and len(neighbor.families()) > 1:
			for family in neighbor.families():
				# XXX: FIXME: Ok, it works but it takes LOTS of memory ..
				m_neighbor = deepcopy(neighbor)
				m_neighbor.make_rib()
				m_neighbor.rib.outgoing.families = [family]
				_init_neighbor(m_neighbor)
		else:
			neighbor.make_rib()
			_init_neighbor(neighbor)

		# display configuration
		for line in str(neighbor).split('\n'):
			self.logger.configuration(line)
		self.logger.configuration("\n")

		# ...
		scope.pop(-1)
		return True
Example #7
0
	def all (self, tokeniser):
		if self._all or self._seen:
			return self.error.set('all can not be used with any other options')
		self._all = True
		for pair in NLRI.known_families():
			self._seen.append(pair)
Example #8
0
    def post(self):
        for inherited in self.scope.pop('inherit', []):
            data = self.scope.template('neighbor', inherited)
            self.scope.inherit(data)
        local = self.scope.get()

        neighbor = Neighbor()

        for option in neighbor.defaults:
            conf = local.get(option, None)
            if conf is not None:
                neighbor[option] = conf

        # XXX: use the right class for the data type
        # XXX: we can use the scope.nlri interface ( and rename it ) to set some values

        capability = local.get('capability', {})
        for option in neighbor.Capability.defaults:
            conf = capability.get(option, None)
            if conf is not None:
                neighbor['capability'][option] = conf

        neighbor.api = ParseAPI.flatten(local.pop('api', {}))

        missing = neighbor.missing()
        if missing:
            return self.error.set(missing)
        neighbor.infer()

        families = []
        for family in ParseFamily.convert:
            for pair in local.get('family', {}).get(family, []):
                families.append(pair)

        families = families or NLRI.known_families()

        for family in families:
            neighbor.add_family(family)

        if neighbor['capability']['add-path']:
            add_path = local.get('add-path', {})
            if add_path:
                for family in ParseAddPath.convert:
                    for pair in add_path.get(family, []):
                        if pair not in families:
                            log.debug(
                                'skipping add-path family ' + str(pair) +
                                ' as it is not negotiated', 'configuration')
                            continue
                        neighbor.add_addpath(pair)
            else:
                for family in families:
                    neighbor.add_addpath(family)

        # The default is to auto-detect by the presence of the nexthop block
        # if this is manually set, then we honor it
        nexthop = local.get('nexthop', {})
        if neighbor['capability']['nexthop'] is None and nexthop:
            neighbor['capability']['nexthop'] = True

        if neighbor['capability']['nexthop']:
            nexthops = []
            for family in nexthop:
                nexthops.extend(nexthop[family])
            if nexthops:
                for afi, safi, nhafi in nexthops:
                    if (afi, safi) not in neighbor.families():
                        log.debug(
                            'skipping nexthop afi,safi ' + str(afi) + '/' +
                            str(safi) + ' as it is not negotiated',
                            'configuration',
                        )
                        continue
                    if (nhafi, safi) not in neighbor.families():
                        log.debug(
                            'skipping nexthop afi ' + str(nhafi) + '/' +
                            str(safi) + ' as it is not negotiated',
                            'configuration',
                        )
                        continue
                    neighbor.add_nexthop(afi, safi, nhafi)

        neighbor.changes = []
        neighbor.changes.extend(self.scope.pop_routes())

        # old format
        for section in ('static', 'l2vpn', 'flow'):
            routes = local.get(section, {}).get('routes', [])
            for route in routes:
                route.nlri.action = OUT.ANNOUNCE
            neighbor.changes.extend(routes)

        routes = local.get('routes', [])
        for route in routes:
            route.nlri.action = OUT.ANNOUNCE
        neighbor.changes.extend(routes)

        messages = local.get('operational', {}).get('routes', [])

        if neighbor['local-address'] is None:
            neighbor.auto_discovery = True
            neighbor['local-address'] = None
            neighbor['md5-ip'] = None

        if not neighbor['router-id']:
            if neighbor[
                    'peer-address'].afi == AFI.ipv4 and not neighbor.auto_discovery:
                neighbor['router-id'] = neighbor['local-address']
            else:
                return self.error.set(
                    'missing router-id for the peer, it can not be set using the local-ip'
                )

        if neighbor['capability']['route-refresh']:
            if neighbor['adj-rib-out']:
                log.debug('route-refresh requested, enabling adj-rib-out',
                          'configuration')

        missing = neighbor.missing()
        if missing:
            return self.error.set('incomplete neighbor, missing %s' % missing)

        if not neighbor.auto_discovery and neighbor[
                'local-address'].afi != neighbor['peer-address'].afi:
            return self.error.set(
                'local-address and peer-address must be of the same family')
        neighbor.range_size = neighbor['peer-address'].mask.size()

        if neighbor.range_size > 1 and not (neighbor['passive']
                                            or getenv().bgp.passive):
            return self.error.set(
                'can only use ip ranges for the peer address with passive neighbors'
            )

        if neighbor.index() in self._neighbors:
            return self.error.set('duplicate peer definition %s' %
                                  neighbor['peer-address'].top())
        self._neighbors.append(neighbor.index())

        if neighbor['md5-password']:
            try:
                md5 = base64.b64decode(
                    neighbor['md5-password']
                ) if neighbor['md5-base64'] else neighbor['md5-password']
            except TypeError as e:
                return self.error.set(
                    f"Invalid base64 encoding of MD5 password ({e})")
            else:
                if len(md5) > 80:
                    return self.error.set(
                        'MD5 password must be no larger than 80 characters')

        # check we are not trying to announce routes without the right MP announcement
        for change in neighbor.changes:
            family = change.nlri.family()
            if family not in families and family != (AFI.ipv4, SAFI.unicast):
                return self.error.set(
                    'Trying to announce a route of type %s,%s when we are not announcing the family to our peer'
                    % change.nlri.family())

        def _init_neighbor(neighbor):
            families = neighbor.families()
            for change in neighbor.changes:
                if change.nlri.family() in families:
                    # This add the family to neighbor.families()
                    neighbor.rib.outgoing.add_to_rib_watchdog(change)
            for message in messages:
                if message.family() in families:
                    if message.name == 'ASM':
                        neighbor.asm[message.family()] = message
                    else:
                        neighbor.messages.append(message)
            self.neighbors[neighbor.name()] = neighbor

        # create one neighbor object per family for multisession
        if neighbor['capability']['multi-session'] and len(
                neighbor.families()) > 1:
            for family in neighbor.families():
                # XXX: FIXME: Ok, it works but it takes LOTS of memory ..
                m_neighbor = deepcopy(neighbor)
                m_neighbor.make_rib()
                m_neighbor.rib.outgoing.families = [family]
                _init_neighbor(m_neighbor)
        else:
            neighbor.make_rib()
            _init_neighbor(neighbor)

        local.clear()
        return True
Example #9
0
    def make(self, scope, configuration):
        # we have local_scope[-2] as the group template and local_scope[-1] as the peer specific
        if len(scope) > 1:
            for key, content in scope[-2].iteritems():
                if key not in scope[-1]:
                    scope[-1][key] = deepcopy(content)
                elif key == 'announce':
                    scope[-1][key].extend(scope[-2][key])

        neighbor = Neighbor()
        for local_scope in scope:
            value = local_scope.get('router-id', '')
            if value:
                neighbor.router_id = value
            value = local_scope.get('peer-address', '')
            if value:
                neighbor.peer_address = value
            value = local_scope.get('local-address', '')
            if value:
                neighbor.local_address = value
            value = local_scope.get('local-as', '')
            if value:
                neighbor.local_as = value
            value = local_scope.get('peer-as', '')
            if value:
                neighbor.peer_as = value
            value = local_scope.get('passive', False)
            if value:
                neighbor.passive = value
            value = local_scope.get('listen', 0)
            if value:
                neighbor.listen = value
            value = local_scope.get('hold-time', '')
            if value:
                neighbor.hold_time = value

            neighbor.host_name = local_scope.get('host-name', hostname())
            neighbor.domain_name = local_scope.get('domain-name', domainname())

            neighbor.changes = local_scope.get('announce', [])
            messages = local_scope.get('operational-message', [])

        # we want to have a socket for the cli
        if self.fifo:
            _cli_name = 'CLI'
            configuration.processes[_cli_name] = {
                'neighbor': '*',
                'encoder': 'json',
                'run': [sys.executable, sys.argv[0]],
                'neighbor-changes': False,
                'receive-consolidate': False,
                'receive-packets': False,
                'receive-parsed': False,
                'send-consolidate': False,
                'send-packets': False,
                'send-parsed': False,
            }

            for direction in ['send', 'receive']:
                for message in [
                        Message.CODE.NOTIFICATION, Message.CODE.OPEN,
                        Message.CODE.KEEPALIVE, Message.CODE.UPDATE,
                        Message.CODE.ROUTE_REFRESH, Message.CODE.OPERATIONAL
                ]:
                    configuration.processes[_cli_name]['%s-%d' %
                                                       (direction,
                                                        message)] = False

        for name in configuration.processes.keys():
            process = configuration.processes[name]

            neighbor.api.set('neighbor-changes',
                             process.get('neighbor-changes', False))

            for direction in ['send', 'receive']:
                for option in ['packets', 'consolidate', 'parsed']:
                    neighbor.api.set_value(
                        direction, option,
                        process.get('%s-%s' % (direction, option), False))

                for message in [
                        Message.CODE.NOTIFICATION, Message.CODE.OPEN,
                        Message.CODE.KEEPALIVE, Message.CODE.UPDATE,
                        Message.CODE.ROUTE_REFRESH, Message.CODE.OPERATIONAL
                ]:
                    neighbor.api.set_message(
                        direction, message,
                        process.get('%s-%d' % (direction, message), False))

        if not neighbor.router_id:
            neighbor.router_id = neighbor.local_address

        local_scope = scope[-1]
        neighbor.description = local_scope.get('description', '')

        neighbor.md5 = local_scope.get('md5', None)
        neighbor.ttl = local_scope.get('ttl-security', None)
        neighbor.group_updates = local_scope.get('group-updates', None)

        neighbor.route_refresh = local_scope.get('route-refresh', 0)
        neighbor.graceful_restart = local_scope.get('graceful-restart', 0)
        if neighbor.graceful_restart is None:
            # README: Should it be a subclass of int ?
            neighbor.graceful_restart = int(neighbor.hold_time)
        neighbor.multisession = local_scope.get('multi-session', False)
        neighbor.operational = local_scope.get('operational', False)
        neighbor.add_path = local_scope.get('add-path', 0)
        neighbor.flush = local_scope.get('auto-flush', True)
        neighbor.adjribout = local_scope.get('adj-rib-out', True)
        neighbor.asn4 = local_scope.get('asn4', True)
        neighbor.aigp = local_scope.get('aigp', None)

        if neighbor.route_refresh and not neighbor.adjribout:
            return self.error.set(
                'incomplete option route-refresh and no adj-rib-out')

        # XXX: check that if we have any message, we have parsed/packets
        # XXX: and vice-versa

        missing = neighbor.missing()
        if missing:
            return self.error.set('incomplete neighbor, missing %s' % missing)

        if neighbor.local_address.afi != neighbor.peer_address.afi:
            return self.error.set(
                'local-address and peer-address must be of the same family')

        if neighbor.peer_address.ip in self._neighbors:
            return self.error.set('duplicate peer definition %s' %
                                  neighbor.peer_address.ip)

        openfamilies = local_scope.get('families', 'everything')
        # announce every family we known
        if neighbor.multisession and openfamilies == 'everything':
            # announce what is needed, and no more, no need to have lots of TCP session doing nothing
            _families = set()
            for change in neighbor.changes:
                _families.add((change.nlri.afi, change.nlri.safi))
            families = list(_families)
        elif openfamilies in ('all', 'everything'):
            families = NLRI.known_families()
        # only announce what you have as routes
        elif openfamilies == 'minimal':
            _families = set()
            for change in neighbor.changes:
                _families.add((change.nlri.afi, change.nlri.safi))
            families = list(_families)
        else:
            families = openfamilies

        # check we are not trying to announce routes without the right MP announcement
        for family in neighbor.families():
            if family not in families:
                afi, safi = family
                return self.error.set(
                    'Trying to announce a route of type %s,%s when we are not announcing the family to our peer'
                    % (afi, safi))

        # add the families to the list of families known
        initial_families = list(neighbor.families())
        for family in families:
            if family not in initial_families:
                # we are modifying the data used by .families() here
                neighbor.add_family(family)

        if neighbor.group_updates is None:
            neighbor.group_updates = True

        def _init_neighbor(neighbor):
            families = neighbor.families()
            for change in neighbor.changes:
                if change.nlri.family() in families:
                    # This add the family to neighbor.families()
                    neighbor.rib.outgoing.insert_announced_watchdog(change)
            for message in messages:
                if message.family() in families:
                    if message.name == 'ASM':
                        neighbor.asm[message.family()] = message
                    else:
                        neighbor.messages.append(message)
            self._neighbors[neighbor.name()] = neighbor

        # create one neighbor object per family for multisession
        if neighbor.multisession and len(neighbor.families()) > 1:
            for family in neighbor.families():
                # XXX: FIXME: Ok, it works but it takes LOTS of memory ..
                m_neighbor = deepcopy(neighbor)
                m_neighbor.make_rib()
                m_neighbor.rib.outgoing.families = [family]
                _init_neighbor(m_neighbor)
        else:
            neighbor.make_rib()
            _init_neighbor(neighbor)

        # display configuration
        for line in str(neighbor).split('\n'):
            self.logger.configuration(line)
        self.logger.configuration("\n")

        # ...
        scope.pop(-1)
        return True