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