def updates(self, grouped): attr_af_nlri = self._new_attr_af_nlri new_attr = self._new_attribute # Get ready to accept more data self._new_nlri = {} self._new_attr_af_nlri = {} self._new_attribute = {} # if we need to perform a route-refresh, sending the message # to indicate the start of the announcements rr_announced = [] for afi, safi in self._enhanced_refresh_start: rr_announced.append((afi, safi)) yield Update(RouteRefresh(afi, safi, RouteRefresh.start), Attributes()) # generating Updates from what is in the RIB for attr_index, per_family in attr_af_nlri.items(): for family, changes in per_family.items(): if not changes: continue # only yield once we have a consistent state, otherwise it will go wrong # as we will try to modify things we are iterating over and using attributes = new_attr[attr_index] if family == (AFI.ipv4, SAFI.unicast) and grouped: yield Update([change.nlri for change in changes.values()], attributes) else: for change in changes.values(): yield Update( [ change.nlri, ], attributes, ) # If we are performing a route-refresh, indicating that the # update were all sent if rr_announced: for afi, safi in rr_announced: self._enhanced_refresh_start.remove((afi, safi)) yield Update(RouteRefresh(afi, safi, RouteRefresh.end), Attributes()) for change in self._enhanced_refresh_delay: self.add_to_rib(change, True) self._enhanced_refresh_delay = [] for update in self.updates(grouped): yield update
def send (self,raw): if self.neighbor.api.get('send-%s' % Message.CODE.short(ord(raw[18])),False): message = Update.unpack_message(raw[19:],self.negotiated) self._to_api('send',message,raw) for boolean in self.connection.writer(raw): yield boolean
def send (self,raw): if self.neighbor.api.get('send-%s' % Message.CODE.short(ord(raw[19])),False): message = Update.unpack_message(raw[19:],self.negotiated) self._to_api('send',message,raw) for boolean in self.connection.writer(raw): yield boolean
def check_update (neighbor, raw): logger = Logger() logger._option.parser = True logger.parser('\ndecoding routes in configuration') neighbor = neighbor[neighbor.keys()[0]] path = {} for f in NLRI.known_families(): if neighbor.add_path: path[f] = neighbor.add_path capa = Capabilities().new(neighbor,False) capa[Capability.CODE.ADD_PATH] = path capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families() # capa[Capability.CODE.FOUR_BYTES_ASN] = True routerid_1 = str(neighbor.router_id) routerid_2 = '.'.join(str((int(_)+1) % 250) for _ in str(neighbor.router_id).split('.',-1)) o1 = Open(4,neighbor.local_as,routerid_1,capa,180) o2 = Open(4,neighbor.peer_as,routerid_2,capa,180) negotiated = Negotiated(neighbor) negotiated.sent(o1) negotiated.received(o2) # grouped = False while raw: if raw.startswith('\xff'*16): kind = ord(raw[18]) size = (ord(raw[16]) << 16) + (ord(raw[17])) injected,raw = raw[19:size],raw[size:] if kind == 2: logger.parser('the message is an update') decoding = 'update' else: logger.parser('the message is not an update (%d) - aborting' % kind) return False else: logger.parser('header missing, assuming this message is ONE update') decoding = 'update' injected,raw = raw,'' try: # This does not take the BGP header - let's assume we will not break that :) update = Update.unpack_message(injected,negotiated) except KeyboardInterrupt: raise except Notify,exc: logger.parser('could not parse the message') logger.parser(str(exc)) return False except Exception,exc: logger.parser('could not parse the message') logger.parser(str(exc)) return False
def send (self, raw): code = 'send-%s' % Message.CODE.short(ordinal(raw[18])) self.peer.stats[code] = self.peer.stats.get(code,0) + 1 if self.neighbor.api.get(code,False): message = Update.unpack_message(raw[19:],self.negotiated) self._to_api('send',message,raw) for boolean in self.connection.writer(raw): yield boolean
def send(self, raw): code = 'send-%s' % Message.CODE.short(ordinal(raw[18])) self.peer.stats[code] = self.peer.stats.get(code, 0) + 1 if self.neighbor.api.get(code, False): message = Update.unpack_message(raw[19:], self.negotiated) self._to_api('send', message, raw) for boolean in self.connection.writer(raw): yield boolean
def check_update(neighbor, raw): option.enabled['parser'] = True negotiated = _negotiated(neighbor) while raw: if raw.startswith(b'\xff' * 16): kind = raw[18] size = (raw[16] << 16) + raw[17] injected, raw = raw[19:size], raw[size:] if kind == 2: log.debug('the message is an update', 'parser') decoding = 'update' else: log.debug( 'the message is not an update (%d) - aborting' % kind, 'parser') return False else: log.debug('header missing, assuming this message is ONE update', 'parser') decoding = 'update' injected, raw = raw, '' try: # This does not take the BGP header - let's assume we will not break that :) update = Update.unpack_message(injected, Direction.IN, negotiated) except Notify: import traceback log.error('could not parse the message', 'parser') log.error(traceback.format_exc(), 'parser') if getenv().debug.pdb: raise return False except Exception: import traceback log.error('could not parse the message', 'parser') log.error(traceback.format_exc(), 'parser') if getenv().debug.pdb: raise return False log.debug('', 'parser') # new line for number in range(len(update.nlris)): change = Change(update.nlris[number], update.attributes) log.info( 'decoded %s %s %s' % (decoding, change.nlri.action, change.extensive()), 'parser') log.info( 'update json %s' % Response.JSON(json_version).update( neighbor, 'in', update, None, '', ''), 'parser') return True
def _route (self, header): bgp_header = self._read_data(19) if bgp_header is None: self.close() return length = unpack('!H',bgp_header[16:18])[0] - 19 bgp_body = self._read_data(length) if bgp_body is None: self.close() return negotiated = FakeNegotiated(header,self.asn4) update = Update.unpack_message(bgp_body,negotiated) if self.use_json: print >> self.fd, self.json.bmp(self.ip,update) else: for route in update.routes: print >> self.fd, route.extensive()
def _route(self, header): bgp_header = self._read_data(19) if bgp_header is None: self.close() return length = unpack('!H', bgp_header[16:18])[0] - 19 bgp_body = self._read_data(length) if bgp_body is None: self.close() return negotiated = FakeNegotiated(header, self.asn4) update = Update.unpack_message(bgp_body, negotiated) if self.use_json: print(self.json.bmp(self.ip, update), file=self.fd) else: for route in update.routes: print(route.extensive(), file=self.fd)
def check_update (neighbor, raw): logger = Logger() logger._option.parser = True logger.parser('\ndecoding routes in configuration') neighbor = neighbor[neighbor.keys()[0]] path = {} for f in NLRI.known_families(): if neighbor.add_path: path[f] = neighbor.add_path capa = Capabilities().new(neighbor,False) capa[Capability.CODE.ADD_PATH] = path capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families() # capa[Capability.CODE.FOUR_BYTES_ASN] = True routerid_1 = str(neighbor.router_id) routerid_2 = '.'.join(str((int(_)+1) % 250) for _ in str(neighbor.router_id).split('.',-1)) o1 = Open(Version(4),ASN(neighbor.local_as),HoldTime(180),RouterID(routerid_1),capa) o2 = Open(Version(4),ASN(neighbor.peer_as),HoldTime(180),RouterID(routerid_2),capa) negotiated = Negotiated(neighbor) negotiated.sent(o1) negotiated.received(o2) # grouped = False while raw: if raw.startswith('\xff'*16): kind = ord(raw[18]) size = (ord(raw[16]) << 16) + (ord(raw[17])) injected,raw = raw[19:size],raw[size:] if kind == 2: logger.parser('the message is an update') decoding = 'update' else: logger.parser('the message is not an update (%d) - aborting' % kind) return False else: logger.parser('header missing, assuming this message is ONE update') decoding = 'update' injected,raw = raw,'' try: # This does not take the BGP header - let's assume we will not break that :) update = Update.unpack_message(injected,negotiated) except KeyboardInterrupt: raise except Notify: logger.parser('could not parse the message','error') logger.parser(traceback.format_exc(),'error') return False except StandardError: logger.parser('could not parse the message','error') logger.parser(traceback.format_exc(),'error') return False logger.parser('') # new line for number in range(len(update.nlris)): change = Change(update.nlris[number],update.attributes) logger.parser('decoded %s %s %s' % (decoding,change.nlri.action,change.extensive())) logger.parser('update json %s' % Response.JSON(json_version).update(neighbor,'in',update,'','')) return True
def test_decoding_udpate_asn4 (self): for asn4,body in bodies: if not asn4: continue Update.unpack_message(''.join(chr(_) for _ in body),self.negotiated[asn4])
def test_decoding_udpate_asn4(self): for asn4, body in bodies: if not asn4: continue Update.unpack_message(data_from_body(body), self.negotiated[asn4])
def check_update(neighbor, raw): logger = Logger() logger._option.parser = True logger.parser('\ndecoding routes in configuration') neighbor = neighbor[neighbor.keys()[0]] path = {} for f in NLRI.known_families(): if neighbor.add_path: path[f] = neighbor.add_path capa = Capabilities().new(neighbor, False) capa[Capability.CODE.ADD_PATH] = path capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families() # capa[Capability.CODE.FOUR_BYTES_ASN] = True routerid_1 = str(neighbor.router_id) routerid_2 = '.'.join( str((int(_) + 1) % 250) for _ in str(neighbor.router_id).split('.', -1)) o1 = Open(Version(4), ASN(neighbor.local_as), HoldTime(180), RouterID(routerid_1), capa) o2 = Open(Version(4), ASN(neighbor.peer_as), HoldTime(180), RouterID(routerid_2), capa) negotiated = Negotiated(neighbor) negotiated.sent(o1) negotiated.received(o2) # grouped = False while raw: if raw.startswith('\xff' * 16): kind = ord(raw[18]) size = (ord(raw[16]) << 16) + (ord(raw[17])) injected, raw = raw[19:size], raw[size:] if kind == 2: logger.parser('the message is an update') decoding = 'update' else: logger.parser('the message is not an update (%d) - aborting' % kind) return False else: logger.parser( 'header missing, assuming this message is ONE update') decoding = 'update' injected, raw = raw, '' try: # This does not take the BGP header - let's assume we will not break that :) update = Update.unpack_message(injected, negotiated) except KeyboardInterrupt: raise except Notify: logger.parser('could not parse the message', 'error') logger.parser(traceback.format_exc(), 'error') return False except StandardError: logger.parser('could not parse the message', 'error') logger.parser(traceback.format_exc(), 'error') return False logger.parser('') # new line for number in range(len(update.nlris)): change = Change(update.nlris[number], update.attributes) logger.parser('decoded %s %s %s' % (decoding, change.nlri.action, change.extensive())) logger.parser( 'update json %s' % Response.JSON(json_version).update(neighbor, 'in', update, '', '')) return True
def check_generation(neighbors): option.enabled['parser'] = True for name in neighbors.keys(): neighbor = copy.deepcopy(neighbors[name]) neighbor['local-as'] = neighbor['peer-as'] path = {} for f in NLRI.known_families(): if neighbor['capability']['add-path']: path[f] = neighbor['capability']['add-path'] capa = Capabilities().new(neighbor, False) if path: capa[Capability.CODE.ADD_PATH] = path capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families() routerid_1 = str(neighbor['router-id']) routerid_2 = '.'.join( str((int(_) + 1) % 250) for _ in str(neighbor['router-id']).split('.', -1)) o1 = Open(Version(4), ASN(neighbor['local-as']), HoldTime(180), RouterID(routerid_1), capa) o2 = Open(Version(4), ASN(neighbor['peer-as']), HoldTime(180), RouterID(routerid_2), capa) negotiated = Negotiated(neighbor) negotiated.sent(o1) negotiated.received(o2) # grouped = False for _ in neighbor.rib.outgoing.updates(False): pass for change1 in neighbor.rib.outgoing.cached_changes(): str1 = change1.extensive() packed = list( Update([change1.nlri], change1.attributes).messages(negotiated)) pack1 = packed[0] log.debug('parsed route requires %d updates' % len(packed), 'parser') log.debug('update size is %d' % len(pack1), 'parser') log.debug('parsed route %s' % str1, 'parser') log.debug('parsed hex %s' % od(pack1), 'parser') # This does not take the BGP header - let's assume we will not break that :) try: log.debug('') # new line pack1s = pack1[19:] if pack1.startswith(b'\xFF' * 16) else pack1 update = Update.unpack_message(pack1s, negotiated) change2 = Change(update.nlris[0], update.attributes) str2 = change2.extensive() pack2 = list( Update([update.nlris[0]], update.attributes).messages(negotiated))[0] log.debug('recoded route %s' % str2, 'parser') log.debug('recoded hex %s' % od(pack2), 'parser') str1 = str1.replace('attribute [ 0x04 0x80 0x00000064 ]', 'med 100') str1r = (str1.lower().replace(' med 100', '').replace( ' local-preference 100', '').replace(' origin igp', '')) str2r = (str2.lower().replace(' med 100', '').replace( ' local-preference 100', '').replace(' origin igp', '')) str2r = str2r.replace( 'large-community [ 1:2:3 10:11:12 ]', 'attribute [ 0x20 0xc0 0x0000000100000002000000030000000a0000000b0000000c ]', ) if 'next-hop self' in str1r: if ':' in str1r: str1r = str1r.replace('next-hop self', 'next-hop ::1') else: str1r = str1r.replace( 'next-hop self', 'next-hop %s' % neighbor['local-address']) if ' name ' in str1r: parts = str1r.split(' ') pos = parts.index('name') str1r = ' '.join(parts[:pos] + parts[pos + 2:]) skip = False if str1r != str2r: if 'attribute [' in str1r and ' 0x00 ' in str1r: # we do not decode non-transitive attributes log.debug( 'skipping string check on update with non-transitive attribute(s)', 'parser') skip = True else: log.debug('strings are different:', 'parser') log.debug('[%s]' % (str1r), 'parser') log.debug('[%s]' % (str2r), 'parser') return False else: log.debug('strings are fine', 'parser') if skip: log.debug( 'skipping encoding for update with non-transitive attribute(s)', 'parser') elif pack1 != pack2: log.debug('encoding are different', 'parser') log.debug('[%s]' % (od(pack1)), 'parser') log.debug('[%s]' % (od(pack2)), 'parser') return False else: log.debug('encoding is fine', 'parser') log.debug('----------------------------------------', 'parser') log.debug('JSON nlri %s' % change1.nlri.json(), 'parser') log.debug('JSON attr %s' % change1.attributes.json(), 'parser') except Notify as exc: log.debug('----------------------------------------', 'parser') log.debug(str(exc), 'parser') log.debug('----------------------------------------', 'parser') return False neighbor.rib.clear() return True
def updates(self, grouped): if self._changes: dict_nlri = self._modify_nlri for family in self._seen: for change in self._seen[family].itervalues(): if change.index() not in self._modify_nlri: change.nlri.action = OUT.WITHDRAW self.insert_announced(change, True) for new in self._changes: self.insert_announced(new, True) self._changes = None # end of changes rr_announced = [] for afi, safi in self._enhanced_refresh_start: rr_announced.append((afi, safi)) yield Update(RouteRefresh(afi, safi, RouteRefresh.start), Attributes()) dict_sorted = self._modify_sorted dict_nlri = self._modify_nlri dict_attr = self._cache_attribute for attr_index, full_dict_change in dict_sorted.items(): if self.cache: dict_change = {} for nlri_index, change in full_dict_change.iteritems(): family = change.nlri.family() announced = self._seen.get(family, {}) if change.nlri.action == OUT.ANNOUNCE: if nlri_index in announced: old_change = announced[nlri_index] # it is a duplicate route if old_change.attributes.index( ) == change.attributes.index( ) and old_change.nlri.nexthop.index( ) == change.nlri.nexthop.index(): continue elif change.nlri.action == OUT.WITHDRAW: if nlri_index not in announced: if dict_nlri[ nlri_index].nlri.action == OUT.ANNOUNCE: continue dict_change[nlri_index] = change else: dict_change = full_dict_change if not dict_change: continue attributes = dict_attr[attr_index].attributes # we NEED the copy provided by list() here as insert_announced can be called while we iterate changed = list(dict_change.itervalues()) if grouped: updates = [] nlris = [] for change in dict_change.values(): if change.nlri.afi == AFI.ipv4: nlris.append(change.nlri) continue updates.append(Update([change.nlri], attributes)) if nlris: updates.append(Update(nlris, attributes)) nlris = [] for change in changed: nlri_index = change.index() del dict_sorted[attr_index][nlri_index] del dict_nlri[nlri_index] # only yield once we have a consistent state, otherwise it will go wrong # as we will try to modify things we are using for update in updates: yield update else: updates = [] for change in changed: updates.append(Update([ change.nlri, ], attributes)) nlri_index = change.index() del dict_sorted[attr_index][nlri_index] del dict_nlri[nlri_index] # only yield once we have a consistent state, otherwise it will go wrong # as we will try to modify things we are using for update in updates: yield update if self.cache: announced = self._seen for change in changed: if change.nlri.action == OUT.ANNOUNCE: announced.setdefault(change.nlri.family(), {})[change.index()] = change else: family = change.nlri.family() if family in announced: announced[family].pop(change.index(), None) if rr_announced: for afi, safi in rr_announced: self._enhanced_refresh_start.remove((afi, safi)) yield Update(RouteRefresh(afi, safi, RouteRefresh.end), Attributes()) for change in self._enhanced_refresh_delay: self.insert_announced(change, True) self.enhanced_refresh_delay = [] for update in self.updates(grouped): yield update
def test_decoding_udpate_asn4 (self): for asn4,body in bodies: if not asn4: continue Update.unpack_message(data_from_body(body),self.negotiated[asn4])
def check_neighbor(neighbors): logger = Logger() logger._option.parser = True if not neighbors: logger.parser('\ncould not find neighbor(s) to check') return False logger.parser('\ndecoding routes in configuration') for name in neighbors.keys(): neighbor = neighbors[name] path = {} for f in NLRI.known_families(): if neighbor.add_path: path[f] = neighbor.add_path capa = Capabilities().new(neighbor, False) if path: capa[Capability.CODE.ADD_PATH] = path capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families() o1 = Open(4, neighbor.local_as, str(neighbor.local_address), capa, 180) o2 = Open(4, neighbor.peer_as, str(neighbor.peer_address), capa, 180) negotiated = Negotiated(neighbor) negotiated.sent(o1) negotiated.received(o2) # grouped = False for _ in neighbor.rib.outgoing.updates(False): pass for change1 in neighbor.rib.outgoing.sent_changes(): str1 = change1.extensive() packed = list( Update([change1.nlri], change1.attributes).messages(negotiated)) pack1 = packed[0] logger.parser('parsed route requires %d updates' % len(packed)) logger.parser('parsed route requires %d updates' % len(packed)) logger.parser('update size is %d' % len(pack1)) logger.parser('parsed route %s' % str1) logger.parser('parsed hex %s' % od(pack1)) # This does not take the BGP header - let's assume we will not break that :) try: logger.parser('') # new line pack1s = pack1[19:] if pack1.startswith('\xFF' * 16) else pack1 update = Update.unpack_message(pack1s, negotiated) change2 = Change(update.nlris[0], update.attributes) str2 = change2.extensive() pack2 = list( Update([update.nlris[0]], update.attributes).messages(negotiated))[0] logger.parser('recoded route %s' % str2) logger.parser('recoded hex %s' % od(pack2)) str1r = str1.replace(' med 100', '').replace( ' local-preference 100', '').replace(' origin igp', '') str2r = str2.replace(' med 100', '').replace( ' local-preference 100', '').replace(' origin igp', '') if ' name ' in str1r: parts = str1r.split(' ') pos = parts.index('name') str1r = ' '.join(parts[:pos] + parts[pos + 2:]) skip = False if str1r != str2r: if 'attribute [' in str1r and ' 0x00 ' in str1r: # we do not decode non-transitive attributes logger.parser( 'skipping string check on update with non-transitive attribute(s)' ) skip = True else: logger.parser('strings are different:') logger.parser('[%s]' % (str1r)) logger.parser('[%s]' % (str2r)) return False else: logger.parser('strings are fine') if skip: logger.parser( 'skipping encoding for update with non-transitive attribute(s)' ) elif pack1 != pack2: logger.parser('encoding are different') logger.parser('[%s]' % (od(pack1))) logger.parser('[%s]' % (od(pack2))) return False else: logger.parser('encoding is fine') logger.parser('----------------------------------------') logger.parser('JSON nlri %s' % change1.nlri.json()) logger.parser('JSON attr %s' % change1.attributes.json()) except Notify, exc: logger.parser('----------------------------------------') logger.parser(str(exc)) logger.parser('----------------------------------------') return False neighbor.rib.clear()
def check_update(neighbor, raw): logger = Logger() logger._option.parser = True logger.parser('\ndecoding routes in configuration') neighbor = neighbor[neighbor.keys()[0]] path = {} for f in NLRI.known_families(): if neighbor.add_path: path[f] = neighbor.add_path capa = Capabilities().new(neighbor, False) capa[Capability.CODE.ADD_PATH] = path capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families() # capa[Capability.CODE.FOUR_BYTES_ASN] = True routerid_1 = str(neighbor.router_id) routerid_2 = '.'.join( str((int(_) + 1) % 250) for _ in str(neighbor.router_id).split('.', -1)) o1 = Open(4, neighbor.local_as, routerid_1, capa, 180) o2 = Open(4, neighbor.peer_as, routerid_2, capa, 180) negotiated = Negotiated(neighbor) negotiated.sent(o1) negotiated.received(o2) # grouped = False while raw: if raw.startswith('\xff' * 16): kind = ord(raw[18]) size = (ord(raw[16]) << 16) + (ord(raw[17])) injected, raw = raw[19:size], raw[size:] if kind == 2: logger.parser('the message is an update') decoding = 'update' else: logger.parser('the message is not an update (%d) - aborting' % kind) return False else: logger.parser( 'header missing, assuming this message is ONE update') decoding = 'update' injected, raw = raw, '' try: # This does not take the BGP header - let's assume we will not break that :) update = Update.unpack_message(injected, negotiated) except KeyboardInterrupt: raise except Notify, exc: logger.parser('could not parse the message') logger.parser(str(exc)) return False except Exception, exc: logger.parser('could not parse the message') logger.parser(str(exc)) return False
def updates (self, grouped): if self._changes: dict_nlri = self._modify_nlri for family in self._seen: for change in six.itervalues(self._seen[family]): if change.index() not in self._modify_nlri: change.nlri.action = OUT.WITHDRAW self.insert_announced(change,True) for new in self._changes: self.insert_announced(new,True) self._changes = None # end of changes rr_announced = [] for afi,safi in self._enhanced_refresh_start: rr_announced.append((afi,safi)) yield Update(RouteRefresh(afi,safi,RouteRefresh.start),Attributes()) dict_sorted = self._modify_sorted dict_nlri = self._modify_nlri dict_attr = self._cache_attribute for attr_index,dict_change in dict_sorted.items(): if not dict_change: continue updates = {} changed = dict_change.values() attributes = dict_attr[attr_index].attributes for change in dict_change.values(): updates.setdefault(change.nlri.family(),[]).append(change.nlri) nlri_index = change.index() # only yield once we have a consistent state, otherwise it will go wrong # as we will try to modify things we are iterating over and using if grouped: for nlris in six.itervalues(updates): yield Update(nlris, attributes) else: for nlris in six.itervalues(updates): for nlri in nlris: yield Update([nlri,], attributes) if self.cache: announced = self._seen for change in changed: if change.nlri.action == OUT.ANNOUNCE: announced.setdefault(change.nlri.family(),{})[change.index()] = change else: family = change.nlri.family() if family in announced: announced[family].pop(change.index(),None) self._modify_sorted = {} self._modify_nlri = {} if rr_announced: for afi,safi in rr_announced: self._enhanced_refresh_start.remove((afi,safi)) yield Update(RouteRefresh(afi,safi,RouteRefresh.end),Attributes()) for change in self._enhanced_refresh_delay: self.insert_announced(change,True) self.enhanced_refresh_delay = [] for update in self.updates(grouped): yield update
def check_neighbor (neighbors): logger = Logger() logger._option.parser = True logger.parser('\ndecoding routes in configuration') for name in neighbors.keys(): neighbor = neighbors[name] path = {} for f in NLRI.known_families(): if neighbor.add_path: path[f] = neighbor.add_path capa = Capabilities().new(neighbor,False) if path: capa[Capability.CODE.ADD_PATH] = path capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families() routerid_1 = str(neighbor.router_id) routerid_2 = '.'.join(str((int(_)+1) % 250) for _ in str(neighbor.router_id).split('.',-1)) o1 = Open(Version(4),ASN(neighbor.local_as),HoldTime(180),RouterID(routerid_1),capa) o2 = Open(Version(4),ASN(neighbor.peer_as),HoldTime(180),RouterID(routerid_2),capa) negotiated = Negotiated(neighbor) negotiated.sent(o1) negotiated.received(o2) # grouped = False for _ in neighbor.rib.outgoing.updates(False): pass for change1 in neighbor.rib.outgoing.sent_changes(): str1 = change1.extensive() packed = list(Update([change1.nlri],change1.attributes).messages(negotiated)) pack1 = packed[0] logger.parser('parsed route requires %d updates' % len(packed)) logger.parser('update size is %d' % len(pack1)) logger.parser('parsed route %s' % str1) logger.parser('parsed hex %s' % od(pack1)) # This does not take the BGP header - let's assume we will not break that :) try: logger.parser('') # new line pack1s = pack1[19:] if pack1.startswith('\xFF'*16) else pack1 update = Update.unpack_message(pack1s,negotiated) change2 = Change(update.nlris[0],update.attributes) str2 = change2.extensive() pack2 = list(Update([update.nlris[0]],update.attributes).messages(negotiated))[0] logger.parser('recoded route %s' % str2) logger.parser('recoded hex %s' % od(pack2)) str1 = str1.replace('attribute [ 0x04 0x80 0x00000064 ]','med 100') str1r = str1.lower().replace(' med 100','').replace(' local-preference 100','').replace(' origin igp','') str2r = str2.lower().replace(' med 100','').replace(' local-preference 100','').replace(' origin igp','') if 'next-hop self' in str1r: if ':' in str1r: str1r = str1r.replace('next-hop self','next-hop ::1') else: str1r = str1r.replace('next-hop self','next-hop %s' % neighbor.local_address) if ' name ' in str1r: parts = str1r.split(' ') pos = parts.index('name') str1r = ' '.join(parts[:pos] + parts[pos+2:]) skip = False if str1r != str2r: if 'attribute [' in str1r and ' 0x00 ' in str1r: # we do not decode non-transitive attributes logger.parser('skipping string check on update with non-transitive attribute(s)') skip = True else: logger.parser('strings are different:') logger.parser('[%s]' % (str1r)) logger.parser('[%s]' % (str2r)) return False else: logger.parser('strings are fine') if skip: logger.parser('skipping encoding for update with non-transitive attribute(s)') elif pack1 != pack2: logger.parser('encoding are different') logger.parser('[%s]' % (od(pack1))) logger.parser('[%s]' % (od(pack2))) return False else: logger.parser('encoding is fine') logger.parser('----------------------------------------') logger.parser('JSON nlri %s' % change1.nlri.json()) logger.parser('JSON attr %s' % change1.attributes.json()) except Notify,exc: logger.parser('----------------------------------------') logger.parser(str(exc)) logger.parser('----------------------------------------') return False neighbor.rib.clear()
from exabgp.bgp.message import Operational from exabgp.bgp.message.direction import IN from exabgp.bgp.message.direction import Direction from exabgp.bgp.message.update.attribute import Attribute from exabgp.protocol.ip import IP from exabgp.reactor.api.processes import ProcessError from exabgp.logger import log # This is the number of chuncked message we are willing to buffer, not the number of routes MAX_BACKLOG = 15000 _UPDATE = Update([], b'') _OPERATIONAL = Operational(0x00) class Protocol(object): decode = True def __init__(self, peer): self.peer = peer self.neighbor = peer.neighbor self.negotiated = Negotiated(self.neighbor) self.connection = None if self.neighbor['connect']: self.port = self.neighbor['connect'] elif os.environ.get('exabgp.tcp.port', '').isdigit():
def check_update(neighbor, raw): option.enabled['parser'] = True neighbor = neighbor[list(neighbor)[0]] path = {} for f in NLRI.known_families(): if neighbor['capability']['add-path']: path[f] = neighbor['capability']['add-path'] capa = Capabilities().new(neighbor, False) capa[Capability.CODE.ADD_PATH] = path capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families() # capa[Capability.CODE.FOUR_BYTES_ASN] = True routerid_1 = str(neighbor['router-id']) routerid_2 = '.'.join( str((int(_) + 1) % 250) for _ in str(neighbor['router-id']).split('.', -1)) o1 = Open(Version(4), ASN(neighbor['local-as']), HoldTime(180), RouterID(routerid_1), capa) o2 = Open(Version(4), ASN(neighbor['peer-as']), HoldTime(180), RouterID(routerid_2), capa) negotiated = Negotiated(neighbor) negotiated.sent(o1) negotiated.received(o2) # grouped = False while raw: if raw.startswith(b'\xff' * 16): kind = raw[18] size = (raw[16] << 16) + raw[17] injected, raw = raw[19:size], raw[size:] if kind == 2: log.debug('the message is an update', 'parser') decoding = 'update' else: log.debug( 'the message is not an update (%d) - aborting' % kind, 'parser') return False else: log.debug('header missing, assuming this message is ONE update', 'parser') decoding = 'update' injected, raw = raw, '' try: # This does not take the BGP header - let's assume we will not break that :) update = Update.unpack_message(injected, negotiated) except Notify: import traceback log.error('could not parse the message', 'parser') log.error(traceback.format_exc(), 'parser') return False except Exception: import traceback log.error('could not parse the message', 'parser') log.error(traceback.format_exc(), 'parser') return False log.debug('', 'parser') # new line for number in range(len(update.nlris)): change = Change(update.nlris[number], update.attributes) log.info( 'decoded %s %s %s' % (decoding, change.nlri.action, change.extensive()), 'parser') log.info( 'update json %s' % Response.JSON(json_version).update( neighbor, 'in', update, None, '', ''), 'parser') return True
def test_decoding_udpate_asn4(self): for asn4, body in bodies: if not asn4: continue Update.unpack_message(bytes(body), Direction.IN, self.negotiated[asn4])
from exabgp.bgp.message import Update from exabgp.bgp.message import EOR from exabgp.bgp.message import KeepAlive from exabgp.bgp.message import Notification from exabgp.bgp.message import Notify from exabgp.bgp.message import Operational from exabgp.reactor.api.processes import ProcessError from exabgp.logger import Logger from exabgp.logger import FakeLogger # This is the number of chuncked message we are willing to buffer, not the number of routes MAX_BACKLOG = 15000 _UPDATE = Update([], '') _OPERATIONAL = Operational(0x00) class Protocol(object): decode = True def __init__(self, peer): try: self.logger = Logger() except RuntimeError: self.logger = FakeLogger() self.peer = peer self.neighbor = peer.neighbor self.negotiated = Negotiated(self.neighbor) self.connection = None
def check_generation(neighbors): option.enabled['parser'] = True for name in neighbors.keys(): neighbor = copy.deepcopy(neighbors[name]) neighbor['local-as'] = neighbor['peer-as'] negotiated = _negotiated(neighbor) for _ in neighbor.rib.outgoing.updates(False): pass for change1 in neighbor.rib.outgoing.cached_changes(): str1 = change1.extensive() packed = list(Update([change1.nlri], change1.attributes).messages(negotiated)) pack1 = packed[0] log.debug('parsed route requires %d updates' % len(packed), 'parser') log.debug('update size is %d' % len(pack1), 'parser') log.debug('parsed route %s' % str1, 'parser') log.debug('parsed hex %s' % od(pack1), 'parser') # This does not take the BGP header - let's assume we will not break that :) try: log.debug('') # new line pack1s = pack1[19:] if pack1.startswith(b'\xFF' * 16) else pack1 update = Update.unpack_message(pack1s, Direction.IN, negotiated) change2 = Change(update.nlris[0], update.attributes) str2 = change2.extensive() pack2 = list(Update([update.nlris[0]], update.attributes).messages(negotiated))[0] log.debug('recoded route %s' % str2, 'parser') log.debug('recoded hex %s' % od(pack2), 'parser') str1 = str1.replace('attribute [ 0x04 0x80 0x00000064 ]', 'med 100') str1r = ( str1.lower().replace(' med 100', '').replace(' local-preference 100', '').replace(' origin igp', '') ) str2r = ( str2.lower().replace(' med 100', '').replace(' local-preference 100', '').replace(' origin igp', '') ) str2r = str2r.replace( 'large-community [ 1:2:3 10:11:12 ]', 'attribute [ 0x20 0xc0 0x0000000100000002000000030000000a0000000b0000000c ]', ) if 'next-hop self' in str1r: if ':' in str1r: str1r = str1r.replace('next-hop self', 'next-hop ::1') else: str1r = str1r.replace('next-hop self', 'next-hop %s' % neighbor['local-address']) if ' name ' in str1r: parts = str1r.split(' ') pos = parts.index('name') str1r = ' '.join(parts[:pos] + parts[pos + 2 :]) skip = False if str1r != str2r: if 'attribute [' in str1r and ' 0x00 ' in str1r: # we do not decode non-transitive attributes log.debug('skipping string check on update with non-transitive attribute(s)', 'parser') skip = True else: log.debug('strings are different:', 'parser') log.debug('[%s]' % (str1r), 'parser') log.debug('[%s]' % (str2r), 'parser') return False else: log.debug('strings are fine', 'parser') if skip: log.debug('skipping encoding for update with non-transitive attribute(s)', 'parser') elif pack1 != pack2: log.debug('encoding are different', 'parser') log.debug('[%s]' % (od(pack1)), 'parser') log.debug('[%s]' % (od(pack2)), 'parser') return False else: log.debug('encoding is fine', 'parser') log.debug('----------------------------------------', 'parser') log.debug('JSON nlri %s' % change1.nlri.json(), 'parser') log.debug('JSON attr %s' % change1.attributes.json(), 'parser') except Notify as exc: log.debug('----------------------------------------', 'parser') log.debug(str(exc), 'parser') log.debug('----------------------------------------', 'parser') return False neighbor.rib.clear() return True