def setUp(self): self.table = Table() self.table.update(routes) self.neighbor = Neighbor() self.neighbor.local_as = ASN(65000) self.neighbor.peer_as = ASN(65000) self.neighbor.peer_address = InetIP('1.2.3.4') self.neighbor.local_address = InetIP('5.6.7.8')
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
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
0x75, 0x18, 0x67, 0x5, 0x74, 0x18, 0x67, 0x3, 0x10, 0x13, 0x65, 0x37, 0xc0, 0x11, 0x65, 0x32, 0x80, 0x18, 0x65, 0x0, 0x1f, 0x18, 0x65, 0x0, 0x1e, 0x18, 0x65, 0x0, 0x1d, 0x18, 0x65, 0x0, 0x1c, 0xf, 0x24, 0x2, 0x11, 0x1b, 0x79, 0x80, 0x13, 0x1b, 0x60, 0x20, 0x15, 0x1b, 0x60, 0x10, 0x10, 0x1, 0x15, 0x16, 0x1, 0x0, 0x1c, 0x17, 0x1, 0x0, 0x1a ] route = header + body from StringIO import StringIO from exabgp.reactor.protocol import Protocol from exabgp.reactor.peer import Peer from exabgp.bgp.neighbor import Neighbor class Connection(StringIO): def pending(self, **argv): return True cnx = Connection(''.join([chr(_) for _ in route])) neibor = Neighbor() peer = Peer(neibor, None) #import pdb #pdb.set_trace() proto = Protocol(peer, cnx) proto._asn4 = True print proto.UpdateFactory(body)
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): 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 setUp(self): self.neighbor = Neighbor() self.neighbor.local_as = ASN(65000) self.neighbor.peer_as = ASN(65000)
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
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
def setUp(self): self.neighbor = Neighbor() self.neighbor.local_as = ASN(65000) self.neighbor.peer_as = ASN(65000) self.neighbor.peer_address = InetIP('1.2.3.4') self.neighbor.local_address = InetIP('5.6.7.8')
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