def open_received(self, timestamp, msg): """ porcess open message :param timestamp: timestamp that received this message :param msg: binary raw message data :return: """ self.msg_recv_stat['Opens'] += 1 open_msg = Open() parse_result = open_msg.parse(msg) if self.fsm.bgp_peering.peer_asn != open_msg.asn: raise excep.OpenMessageError( sub_error=bgp_cons.ERR_MSG_OPEN_BAD_PEER_AS) # Open message Capabilities negotiation cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability'][ 'remote'] = open_msg.capa_dict LOG.info("[%s]A BGP Open message was received", self.factory.peer_addr) LOG.info('--version = %s', open_msg.version) LOG.info('--ASN = %s', open_msg.asn) LOG.info('--hold time = %s', open_msg.hold_time) LOG.info('--id = %s', open_msg.bgp_id) LOG.info("[%s]Neighbor's Capabilities:", self.factory.peer_addr) for key in cfg.CONF.bgp.running_config[ self.factory.peer_addr]['capability']['remote']: if key == 'four_bytes_as': self.fourbytesas = True elif key == 'add_path': if cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability']['remote']['add_path'] in \ ['ipv4_send', 'ipv4_both']: if cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability']['local']['add_path'] in \ ['ipv4_receive', 'ipv4_both']: self.add_path_ipv4_receive = True LOG.info( "--%s = %s", key, cfg.CONF.bgp.running_config[ self.factory.peer_addr]['capability']['remote'][key]) # write bgp message self.factory.write_msg(timestamp=timestamp, msg_type=1, msg=parse_result, flush=True) self.peer_id = open_msg.bgp_id self.bgp_peering.set_peer_id(open_msg.bgp_id) self.negotiate_hold_time(open_msg.hold_time) self.fsm.open_received()
def parse_peer_up_notification(msg, peer_flag): """ The Peer Up message is used to indicate that a peering session has come up (i.e., has transitioned into ESTABLISHED state). Following the common BMP header and per-peer header is the following: :param msg: :param peer_flag: see parse_per_peer_header :return: """ # 0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Local Address (16 bytes) | # ~ ~ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Local Port | Remote Port | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Sent OPEN Message #| # ~ ~ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Received OPEN Message | # ~ ~ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ LOG.info('decode peer up notification') ip_value = int(binascii.b2a_hex(msg[0:16]), 16) if int(peer_flag['V']): # ipv6 address ip_address = str(netaddr.IPAddress(ip_value, version=6)) else: ip_address = str(netaddr.IPAddress(ip_value, version=4)) LOG.info('local address: %s' % ip_address) local_port = int(binascii.b2a_hex(msg[16:18]), 16) LOG.info('local port: %s' % local_port) remote_port = int(binascii.b2a_hex(msg[18:20]), 16) LOG.info('remote port: %s' % remote_port) # decode sent and received open message open_msg_data = msg[20:] length = struct.unpack('!H', open_msg_data[16:18])[0] sent_open_msg = Open().parse(open_msg_data[bgp_cons.HDR_LEN:length]) open_msg_data = open_msg_data[length:] received_open_msg = Open().parse(open_msg_data[bgp_cons.HDR_LEN:]) LOG.info('sent open: %s' % sent_open_msg) LOG.info('received open: %s' % received_open_msg) return { 'local_address': ip_address, 'local_port': local_port, 'remote_port': remote_port, 'sent_open_msg': sent_open_msg, 'received_open_msg': received_open_msg }
def open_received(self, timestamp, msg): """ porcess open message :param timestamp: timestamp that received this message :param msg: binary raw message data :return: """ self.msg_recv_stat['Opens'] += 1 open_msg = Open() parse_result = open_msg.parse(msg) if self.fsm.bgp_peering.peer_asn != open_msg.asn: raise excep.OpenMessageError(sub_error=bgp_cons.ERR_MSG_OPEN_BAD_PEER_AS) # Open message Capabilities negotiation cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability']['remote'] = open_msg.capa_dict LOG.info("[%s]A BGP Open message was received", self.factory.peer_addr) LOG.info('--version = %s', open_msg.version) LOG.info('--ASN = %s', open_msg.asn) LOG.info('--hold time = %s', open_msg.hold_time) LOG.info('--id = %s', open_msg.bgp_id) LOG.info("[%s]Neighbor's Capabilities:", self.factory.peer_addr) for key in cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability']['remote']: if key == 'four_bytes_as': self.fourbytesas = True elif key == 'add_path': if cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability']['remote']['add_path'] in \ ['ipv4_send', 'ipv4_both']: if cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability']['local']['add_path'] in \ ['ipv4_receive', 'ipv4_both']: self.add_path_ipv4_receive = True CONF.bgp.rib = False LOG.info("--%s = %s", key, cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability']['remote'][key]) # write bgp message self.factory.write_msg( timestamp=timestamp, msg_type=1, msg={"msg": parse_result}, flush=True ) self.peer_id = open_msg.bgp_id self.bgp_peering.set_peer_id(open_msg.bgp_id) self.negotiate_hold_time(open_msg.hold_time) self.fsm.open_received() self.reset_rib_in()
def send_open(self): """ send open message :return: """ # construct Open message self.capability_negotiate() open_msg = Open( version=bgp_cons.VERSION, asn=self.factory.my_asn, hold_time=self.fsm.hold_time, bgp_id=self.factory.bgp_id). \ construct(cfg.CONF.bgp.running_config['capability']['local']) if 'add_path' in cfg.CONF.bgp.running_config['capability']['local']: # check add path feature, send add path condition: # local support send or both # remote support receive or both if cfg.CONF.bgp.running_config['capability']['local']['add_path'] in \ ['ipv4_send', 'ipv4_both']: if cfg.CONF.bgp.running_config['capability']['remote'].get('add_path') in \ ['ipv4_receive', 'ipv4_both']: self.add_path_ipv4_send = True # send message self.transport.write(open_msg) self.msg_sent_stat['Opens'] += 1 LOG.info("[%s]Send a BGP Open message to the peer.", self.factory.peer_addr) LOG.info("[%s]Probe's Capabilities:", self.factory.peer_addr) for key in cfg.CONF.bgp.running_config['capability']['local']: LOG.info("--%s = %s", key, cfg.CONF.bgp.running_config['capability']['local'][key])
def open_received(self, timestamp, msg): """ porcess open message :param timestamp: timestamp that received this message :param msg: binary raw message data :return: """ self.msg_recv_stat['Opens'] += 1 open_msg = Open() parse_result = open_msg.parse(msg) if self.fsm.bgp_peering.peer_asn != open_msg.asn: raise excep.OpenMessageError(sub_error=bgp_cons.ERR_MSG_OPEN_BAD_PEER_AS) # Open message Capabilities negotiation cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability']['remote'] = open_msg.capa_dict LOG.info("[%s]A BGP Open message was received", self.factory.peer_addr) LOG.info('--version = %s', open_msg.version) LOG.info('--ASN = %s', open_msg.asn) LOG.info('--hold time = %s', open_msg.hold_time) LOG.info('--id = %s', open_msg.bgp_id) LOG.info("[%s]Neighbor's Capabilities:", self.factory.peer_addr) for key in cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability']['remote']: LOG.info("--%s = %s", key, cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability']['remote'][key]) # write bgp message self.factory.write_msg( timestamp=timestamp, msg_type=1, msg=parse_result, afi_safi=(0, 0), flush=True ) self.peer_id = open_msg.bgp_id self.bgp_peering.set_peer_id(open_msg.bgp_id) self.negotiate_hold_time(open_msg.hold_time) self.fsm.open_received()
class TestOpen(unittest.TestCase): def setUp(self): self.open = Open() self.maxDiff = None def test_parse(self): msg_hex = '\x04\x5b\xa0\x00\xb4\x03\x03\x03\x09\x25\x02\x06\x01\x04\x00\x01\x00\x80' \ '\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80\x00\x02\x02\x02\x00\x02\x03' \ '\x83\x01\x00\x02\x06\x41\x04\x00\x01\x04\x6a' open_msg = self.open.parse(msg_hex) results = {'bgpID': '3.3.3.9', 'Version': 4, 'holdTime': 180, 'ASN': 66666, 'Capabilities': { 'cisco_multi_session': True, 'cisco_route_refresh': True, 'four_bytes_as': True, 'afi_safi': [(1, 128), (1, 1)], 'route_refresh': True}} self.assertEqual(results, open_msg) def test_construct(self): self.open.version = VERSION self.open.asn = 66666 self.open.hold_time = 180 self.open.bgp_id = int(ipaddr.IPv4Address('1.1.1.1')) my_capa = { 'graceful_restart': False, 'cisco_multi_session': True, 'cisco_route_refresh': True, 'four_bytes_as': True, 'afi_safi': [(1, 128), (1, 1)], 'route_refresh': True} msg_hex = self.open.construct(my_capa) hope_hex = '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00=\x01\x04[\xa0\x00\xb4\x01' \ '\x01\x01\x01 \x02\x06\x01\x04\x00\x01\x00\x80\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80\x00' \ '\x02\x02\x02\x00\x02\x06A\x04\x00\x01\x04j' self.assertEqual(hope_hex, msg_hex)
def send_open(self): """ send open message :return: """ # construct Open message self.capability_negotiate() open_msg = Open(version=bgp_cons.VERSION, asn=self.factory.my_asn, hold_time=self.fsm.hold_time, bgp_id=self.factory.bgp_id). \ construct(cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability']['local']) # send message self.transport.write(open_msg) self.msg_sent_stat['Opens'] += 1 LOG.info("[%s]Send a BGP Open message to the peer.", self.factory.peer_addr) LOG.info("[%s]Probe's Capabilities:", self.factory.peer_addr) for key in cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability']['local']: LOG.info("--%s = %s", key, cfg.CONF.bgp.running_config[self.factory.peer_addr]['capability']['local'][key])
def setUp(self): self.open = Open() self.maxDiff = None
class TestOpen(unittest.TestCase): def setUp(self): self.open = Open() self.maxDiff = None def test_parse(self): msg_hex = b'\x04\x5b\xa0\x00\xb4\x03\x03\x03\x09\x25\x02\x06\x01\x04\x00\x01\x00\x80' \ b'\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80\x00\x02\x02\x02\x00\x02\x03' \ b'\x83\x01\x00\x02\x06\x41\x04\x00\x01\x04\x6a' open_msg = self.open.parse(msg_hex) results = { 'bgp_id': '3.3.3.9', 'version': 4, 'hold_time': 180, 'asn': 66666, 'capabilities': { 'cisco_multi_session': True, 'cisco_route_refresh': True, 'four_bytes_as': True, 'afi_safi': [(1, 128), (1, 1)], 'route_refresh': True } } self.assertEqual(results, open_msg) def test_construct(self): self.open.version = VERSION self.open.asn = 66666 self.open.hold_time = 180 self.open.bgp_id = int(netaddr.IPAddress('1.1.1.1')) my_capa = { 'graceful_restart': False, 'cisco_multi_session': True, 'cisco_route_refresh': True, 'four_bytes_as': True, 'afi_safi': [(1, 128), (1, 1)], 'route_refresh': True } msg_hex = self.open.construct(my_capa) hope_hex = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00=\x01\x04[\xa0\x00\xb4\x01' \ b'\x01\x01\x01 \x02\x06\x01\x04\x00\x01\x00\x80\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80\x00' \ b'\x02\x02\x02\x00\x02\x06A\x04\x00\x01\x04j' self.assertEqual(hope_hex, msg_hex) def test_construct_add_path(self): self.open.version = VERSION self.open.asn = 64512 self.open.hold_time = 180 self.open.bgp_id = int(netaddr.IPAddress('10.0.0.6')) my_capa = { 'cisco_route_refresh': True, 'route_refresh': True, 'add_path': 'ipv4_receive', 'four_bytes_as': True, 'afi_safi': [(1, 1)], 'enhanced_route_refresh': True } msg_hex = self.open.construct(my_capa) hope_hex = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00A\x01\x04' \ b'\xfc\x00\x00\xb4\n\x00\x00\x06$\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80' \ b'\x00\x02\x02\x02\x00\x02\x06A\x04\x00\x00\xfc\x00\x02\x06E\x04\x00\x01\x01\x01\x02\x02F\x00' self.assertEqual(hope_hex, msg_hex) def test_parser_add_path(self): msg_hex = b'\x04\xfc\x00\x00\xb4\x0a\x00\x00\x06\x24\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80\x00\x02' \ b'\x02\x02\x00\x02\x02\x46\x00\x02\x06\x45\x04\x00\x01\x01\x03\x02\x06\x41\x04\x00\x00\xfc\x00' open_msg = self.open.parse(msg_hex) results = { 'bgp_id': '10.0.0.6', 'version': 4, 'hold_time': 180, 'asn': 64512, 'capabilities': { 'cisco_route_refresh': True, 'route_refresh': True, 'add_path': [{ 'afi_safi': 'ipv4', 'send/receive': 'both' }], 'four_bytes_as': True, 'afi_safi': [(1, 1)], 'enhanced_route_refresh': True } } self.assertEqual(results, open_msg) def test_parse_llgr(self): msg_hex = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x4e\x01' \ b'\x04\x01\x2c\x00\xb4\x03\x03\x03\x03\x31\x02\x06\x01\x04\x00\x01\x00\x01\x02' \ b'\x06\x01\x04\x00\x01\x00\x85\x02\x02\x80\x00\x02\x02\x02\x00\x02\x06\x41\x04' \ b'\x00\x00\x01\x2c\x02\x04\x40\x02\x80\x78\x02\x09\x47\x07\x00\x01\x85\x80\x00\x01\x68' results = { 'asn': 300, 'bgp_id': '3.3.3.3', 'capabilities': { 'LLGR': [{ 'afi_safi': [1, 133], 'time': 360 }], 'afi_safi': [(1, 1), (1, 133)], 'cisco_route_refresh': True, 'four_bytes_as': True, 'graceful_restart': True, 'route_refresh': True }, 'hold_time': 180, 'version': 4 } self.assertEqual(results, self.open.parse(msg_hex[HDR_LEN:])) def test_parse_add_path_llgr(self): msg_hex = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' \ b'\x00\x41\x01\x04\xfd\xe9\x00\xb4\x0a\x00\x00\x07\x24\x02\x22\x01' \ b'\x04\x00\x01\x00\x01\x01\x04\x00\x01\x00\x04\x02\x00\x40\x02\x01' \ b'\x2c\x41\x04\x00\x00\xfd\xe9\x45\x08\x00\x01\x01\x01\x00\x01\x04\x01' results = { 'asn': 65001, 'bgp_id': '10.0.0.7', 'capabilities': { 'add_path': [{ 'afi_safi': 'ipv4', 'send/receive': 'receive' }, { 'afi_safi': 'ipv4_lu', 'send/receive': 'receive' }], 'afi_safi': [(1, 1), (1, 4)], 'four_bytes_as': True, 'graceful_restart': True, 'route_refresh': True }, 'hold_time': 180, 'version': 4 } self.assertEqual(results, self.open.parse(msg_hex[HDR_LEN:]))
def parse_route_mirroring_msg(msg): """ Route Mirroring messages are used for verbatim duplication of messages as received. Following the common BMP header and per-peer header is a set of TLVs that contain information about a message or set of messages. :param msg: :return: """ LOG.debug('decode route mirroring message') msg_dict = {} open_l = [] update = [] notification = [] route_refresh = [] while msg: mirror_type, length = struct.unpack('!HH', msg[0:4]) mirror_value = msg[4:4 + length] msg = msg[4 + length:] if mirror_type == 0: # BGP message type bgp_msg_type = struct.unpack('!B', mirror_value[18])[0] LOG.debug('bgp message type=%s' % bgp_msg_type) bgp_msg_body = mirror_value[bgp_cons.HDR_LEN:] if bgp_msg_type == 2: # Update message bgp_update_msg = Update().parse(None, bgp_msg_body, asn4=True) if bgp_update_msg['sub_error']: LOG.error( 'error: decode update message error!, error code: %s' % bgp_update_msg['sub_error']) LOG.error('Raw data: %s' % repr(bgp_update_msg['hex'])) else: update.append(bgp_update_msg) elif bgp_msg_type == 5: # Route Refresh message bgp_route_refresh_msg = RouteRefresh().parse( msg=bgp_msg_body) LOG.debug( 'bgp route refresh message: afi=%s,res=%s,safi=%s' % (bgp_route_refresh_msg[0], bgp_route_refresh_msg[1], bgp_route_refresh_msg[2])) route_refresh.append(bgp_route_refresh_msg) elif bgp_msg_type == 1: # Open message open_msg = Open().parse(bgp_msg_body) open_l.append(open_msg) elif bgp_msg_type == 3: # Notification message notification_msg = Notification().parse(bgp_msg_body) notification.append(notification_msg) elif mirror_type == 1: # Information type. # Amount of this TLV is not specified but we can assume # only one per mirroring message is present. info_code_type = struct.unpack('!H', mirror_value)[0] msg_dict['1'] = info_code_type else: msg_dict[mirror_type] = binascii.unhexlify( binascii.hexlify(mirror_value)) LOG.info('unknow mirroring type, type = %s' % mirror_type) msg_dict['0'] = { 'update': update, 'route_refresh': route_refresh, 'open': open_l, 'notification': notification } return msg_dict
class TestOpen(unittest.TestCase): def setUp(self): self.open = Open() self.maxDiff = None def test_parse(self): msg_hex = b'\x04\x5b\xa0\x00\xb4\x03\x03\x03\x09\x25\x02\x06\x01\x04\x00\x01\x00\x80' \ b'\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80\x00\x02\x02\x02\x00\x02\x03' \ b'\x83\x01\x00\x02\x06\x41\x04\x00\x01\x04\x6a' open_msg = self.open.parse(msg_hex) results = {'bgp_id': '3.3.3.9', 'version': 4, 'hold_time': 180, 'asn': 66666, 'capabilities': { 'cisco_multi_session': True, 'cisco_route_refresh': True, 'four_bytes_as': True, 'afi_safi': [(1, 128), (1, 1)], 'route_refresh': True}} self.assertEqual(results, open_msg) def test_construct(self): self.open.version = VERSION self.open.asn = 66666 self.open.hold_time = 180 self.open.bgp_id = int(netaddr.IPAddress('1.1.1.1')) my_capa = { 'graceful_restart': False, 'cisco_multi_session': True, 'cisco_route_refresh': True, 'four_bytes_as': True, 'afi_safi': [(1, 128), (1, 1)], 'route_refresh': True} msg_hex = self.open.construct(my_capa) hope_hex = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00=\x01\x04[\xa0\x00\xb4\x01' \ b'\x01\x01\x01 \x02\x06\x01\x04\x00\x01\x00\x80\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80\x00' \ b'\x02\x02\x02\x00\x02\x06A\x04\x00\x01\x04j' self.assertEqual(hope_hex, msg_hex) def test_construct_add_path(self): self.open.version = VERSION self.open.asn = 64512 self.open.hold_time = 180 self.open.bgp_id = int(netaddr.IPAddress('10.0.0.6')) my_capa = { 'cisco_route_refresh': True, 'route_refresh': True, 'add_path': 'ipv4_receive', 'four_bytes_as': True, 'afi_safi': [(1, 1)], 'enhanced_route_refresh': True} msg_hex = self.open.construct(my_capa) hope_hex = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00A\x01\x04' \ b'\xfc\x00\x00\xb4\n\x00\x00\x06$\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80' \ b'\x00\x02\x02\x02\x00\x02\x06A\x04\x00\x00\xfc\x00\x02\x06E\x04\x00\x01\x01\x01\x02\x02F\x00' self.assertEqual(hope_hex, msg_hex) def test_parser_add_path(self): msg_hex = b'\x04\xfc\x00\x00\xb4\x0a\x00\x00\x06\x24\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80\x00\x02' \ b'\x02\x02\x00\x02\x02\x46\x00\x02\x06\x45\x04\x00\x01\x01\x03\x02\x06\x41\x04\x00\x00\xfc\x00' open_msg = self.open.parse(msg_hex) results = { 'bgp_id': '10.0.0.6', 'version': 4, 'hold_time': 180, 'asn': 64512, 'capabilities': { 'cisco_route_refresh': True, 'route_refresh': True, 'add_path': 'ipv4_both', 'four_bytes_as': True, 'afi_safi': [(1, 1)], 'enhanced_route_refresh': True}} self.assertEqual(results, open_msg)
class TestOpen(unittest.TestCase): def setUp(self): self.open = Open() self.maxDiff = None def test_parse(self): msg_hex = b'\x04\x5b\xa0\x00\xb4\x03\x03\x03\x09\x25\x02\x06\x01\x04\x00\x01\x00\x80' \ b'\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80\x00\x02\x02\x02\x00\x02\x03' \ b'\x83\x01\x00\x02\x06\x41\x04\x00\x01\x04\x6a' open_msg = self.open.parse(msg_hex) results = {'bgpID': '3.3.3.9', 'Version': 4, 'holdTime': 180, 'ASN': 66666, 'Capabilities': { 'cisco_multi_session': True, 'cisco_route_refresh': True, 'four_bytes_as': True, 'afi_safi': [(1, 128), (1, 1)], 'route_refresh': True}} self.assertEqual(results, open_msg) def test_construct(self): self.open.version = VERSION self.open.asn = 66666 self.open.hold_time = 180 self.open.bgp_id = int(netaddr.IPAddress('1.1.1.1')) my_capa = { 'graceful_restart': False, 'cisco_multi_session': True, 'cisco_route_refresh': True, 'four_bytes_as': True, 'afi_safi': [(1, 128), (1, 1)], 'route_refresh': True} msg_hex = self.open.construct(my_capa) hope_hex = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00=\x01\x04[\xa0\x00\xb4\x01' \ b'\x01\x01\x01 \x02\x06\x01\x04\x00\x01\x00\x80\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80\x00' \ b'\x02\x02\x02\x00\x02\x06A\x04\x00\x01\x04j' self.assertEqual(hope_hex, msg_hex) def test_construct_add_path(self): self.open.version = VERSION self.open.asn = 64512 self.open.hold_time = 180 self.open.bgp_id = int(netaddr.IPAddress('10.0.0.6')) my_capa = { 'cisco_route_refresh': True, 'route_refresh': True, 'add_path': True, 'four_bytes_as': True, 'afi_safi': [(1, 1)], 'enhanced_route_refresh': True} msg_hex = self.open.construct(my_capa) hope_hex = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00A\x01\x04' \ b'\xfc\x00\x00\xb4\n\x00\x00\x06$\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80' \ b'\x00\x02\x02\x02\x00\x02\x06A\x04\x00\x00\xfc\x00\x02\x06E\x04\x00\x01\x01\x01\x02\x02F\x00' self.assertEqual(hope_hex, msg_hex) def test_parser_add_path(self): msg_hex = b'\x04\xfc\x00\x00\xb4\x0a\x00\x00\x06\x24\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80\x00\x02' \ b'\x02\x02\x00\x02\x02\x46\x00\x02\x06\x45\x04\x00\x01\x01\x03\x02\x06\x41\x04\x00\x00\xfc\x00' open_msg = self.open.parse(msg_hex) results = { 'bgpID': '10.0.0.6', 'Version': 4, 'holdTime': 180, 'ASN': 64512, 'Capabilities': { 'cisco_route_refresh': True, 'route_refresh': True, 'add_path': True, 'four_bytes_as': True, 'afi_safi': [(1, 1)], 'enhanced_route_refresh': True}} self.assertEqual(results, open_msg)