def test_parse_construct_l2vpn_evpn(self): data_dict = { "attr": { 1: 0, 2: [], 5: 100, 14: { "afi_safi": (25, 70), "nexthop": "10.75.44.254", "nlri": [{ "type": 2, "value": { "eth_tag_id": 108, "ip": "11.11.11.1", "label": [0], "rd": "172.17.0.3:2", "mac": "00-11-22-33-44-55", "esi": 0 } }] }, 16: [[1536, 1, 500]] } } self.assertEqual( data_dict['attr'], Update.parse( None, Update.construct(msg_dict=data_dict)[HDR_LEN:])['attr'])
def test_parse_construct_l2vpn_evpn(self): data_bin = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x63\x02\x00\x00\x00' \ b'\x4c\xc0\x10\x08\x06\x00\x01\x00\x00\x00\x01\xf4\x40\x01\x01\x00\x40\x02\x00\x40\x05\x04' \ b'\x00\x00\x00\x64\x80\x0e\x30\x00\x19\x46\x04\x0a\x4b\x2c\xfe\x00\x02\x25\x00\x01\xac\x11' \ b'\x00\x03\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x6c\x30\x00\x11\x22' \ b'\x33\x44\x55\x20\x0b\x0b\x0b\x01\x00\x00\x00' data_dict = { "attr": { 1: 0, 2: [], 5: 100, 14: { "afi_safi": (25, 70), "nexthop": "10.75.44.254", "nlri": [{ "type": 2, "value": { "eth_tag_id": 108, "ip": "11.11.11.1", "label": [0], "rd": "172.17.0.3:2", "mac": "00-11-22-33-44-55", "esi": 0 } }] }, 16: [[1536, 1, 500]] } } self.assertEqual(data_bin, Update.construct(msg_dict=data_dict)) self.assertEqual(data_dict['attr'], Update.parse(None, data_bin[HDR_LEN:])['attr'])
def test_parse_and_construct_ipv6_unicast_update(self): value_parse = { 'attr': { 1: 0, 2: [(2, [65502])], 4: 0, 14: { 'afi_safi': (2, 1), 'linklocal_nexthop': 'fe80::c002:bff:fe7e:0', 'nexthop': '2001:db8::2', 'nlri': [ '::2001:db8:2:2/64', '::2001:db8:2:1/64', '::2001:db8:2:0/64' ] } } } self.assertEqual( value_parse['attr'], Update.parse( None, Update.construct(msg_dict=value_parse, asn4=True)[HDR_LEN:], True)['attr'], True)
def test_parse_construct_l2vpn_evpn(self): data_bin = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x63\x02\x00\x00\x00' \ b'\x4c\xc0\x10\x08\x06\x00\x01\x00\x00\x00\x01\xf4\x40\x01\x01\x00\x40\x02\x00\x40\x05\x04' \ b'\x00\x00\x00\x64\x80\x0e\x30\x00\x19\x46\x04\x0a\x4b\x2c\xfe\x00\x02\x25\x00\x01\xac\x11' \ b'\x00\x03\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x6c\x30\x00\x11\x22' \ b'\x33\x44\x55\x20\x0b\x0b\x0b\x01\x00\x00\x00' data_dict = { "attr": { 1: 0, 2: [], 5: 100, 14: { "afi_safi": (25, 70), "nexthop": "10.75.44.254", "nlri": [ { "type": 2, "value": { "eth_tag_id": 108, "ip": "11.11.11.1", "label": [0], "rd": "172.17.0.3:2", "mac": "00-11-22-33-44-55", "esi": 0}}] }, 16: [[1536, 1, 500]] }} self.assertEqual(data_bin, Update.construct(msg_dict=data_dict)) self.assertEqual(data_dict['attr'], Update.parse(None, data_bin[HDR_LEN:])['attr'])
def test_parse_and_construct_ipv4_mpls_vpn_update(self): data_bin = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00' \ b'\x74\x02\x00\x00\x00\x5d\x40\x01\x01\x02\x40\x02\x00\x80\x04\x04\x00' \ b'\x00\x00\x00\x40\x05\x04\x00\x00\x00\x64\xc0\x10\x08\x00\x02\x00\x02' \ b'\x00\x00\x00\x02\x80\x0a\x10\xc0\xa8\x01\x01\xc0\xa8\x01\x02\xc0\xa8' \ b'\x01\x03\xc0\xa8\x01\x04\x80\x09\x04\xc0\xa8\x01\x06\x80\x0e\x20\x00' \ b'\x01\x80\x0c\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8\x01\x06\x00\x70' \ b'\x00\x01\xd1\x00\x00\x00\x02\x00\x00\x00\x02\xc0\xa8\xc9' data_hoped = { 'attr': {1: 2, 2: [], 4: 0, 5: 100, 9: '192.168.1.6', 10: ['192.168.1.1', '192.168.1.2', '192.168.1.3', '192.168.1.4'], 14: {'afi_safi': (1, 128), 'nexthop': {'rd': '0:0', 'str': '192.168.1.6'}, 'nlri': [{'label': [29], 'rd': '2:2', 'prefix': '192.168.201.0/24'}]}, 16: [[2, '2:2']] } } self.maxDiff = None self.assertEqual(data_hoped['attr'], Update.parse(None, data_bin[HDR_LEN:], True)['attr']) self.assertEqual(data_hoped['attr'], Update.parse(None, Update.construct(msg_dict=data_hoped)[HDR_LEN:], True)['attr'])
def test_parse_and_construct_pmsi_tunnel_evpn_overlay(self): data_dict = { 'attr': { 1: 0, 5: 100, 14: { 'afi_safi': (25, 70), 'nexthop': '192.168.1.10', 'nlri': [{ 'type': 3, 'value': { 'eth_tag_id': 0, 'ip': '192.168.1.10', 'rd': '65527:36802' } }] }, 16: [[2, '65527:36802'], [780, 8]], 22: { 'mpls_label': [60001], 'tunnel_id': '192.168.1.10', 'tunnel_type': 6, 'leaf_info_required': 0 } } } self.assertEqual( data_dict['attr'], Update.parse( None, Update.construct(msg_dict=data_dict)[HDR_LEN:])['attr'])
def test_construct_prefix_v4(self): nlri = [ '184.157.224.1/32', '32.65.243.12/30', '89.232.254.0/23', '69.179.221.0/24', '61.172.0.0/16', '202.223.128.0/17', '156.152.0.0/15', '15.0.0.0/8', '209.102.178.0/24', '66.112.100.0/22', '208.54.194.0/24' ] nlri_hex = Update.construct_prefix_v4(nlri) self.assertEqual(nlri, Update.parse_prefix_list(nlri_hex))
def test_parse_and_construct_ipv4_mpls_vpn_withdraw(self): data_bin = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00' \ b'\x2c\x02\x00\x00\x00\x15\x80\x0f\x12\x00\x01\x80\x70\x80\x00\x00\x00' \ b'\x00\x00\x02\x00\x00\x00\x02\xc0\xa8\xc9' data_hoped = {'attr': {15: {'afi_safi': (1, 128), 'withdraw': [{'label': [524288], 'rd': '2:2', 'prefix': '192.168.201.0/24'}]}}} self.assertEqual(data_hoped['attr'], Update.parse(None, data_bin[HDR_LEN:], True)['attr']) self.assertEqual(data_bin, Update.construct(msg_dict=data_hoped))
def test_parse_and_construct_ipv4_unicast_2byteas(self): # 2 bytes asn msg_hex = b'\x00\x00\x00\x28\x40\x01\x01\x02\x40\x02\x0a\x02\x01\x00\x1e\x01\x02\x00\x0a\x00\x14\x40\x03\x04' \ b'\x0a\x00\x00\x09\x80\x04\x04\x00\x00\x00\x00\xc0\x07\x06\x00\x1e\x0a\x00\x00\x09\x15\xac\x10\x00' update = Update.parse([None, False, msg_hex]) attributes = {1: 2, 2: [(2, [30]), (1, [10, 20])], 3: '10.0.0.9', 4: 0, 7: (30, '10.0.0.9')} self.assertEqual(attributes, update['attr']) self.assertEqual([], update['withdraw']) self.assertEqual(['172.16.0.0/21'], update['nlri']) self.assertEqual(msg_hex, Update.construct(msg_dict=update, asn4=False)[HDR_LEN:])
def test_construct_attributes_ipv4(self): attr = { 1: 2, 2: [(2, [701, 71])], 3: '219.158.1.204', 5: 100, 6: b'', 7: (71, '16.96.243.103'), 8: ['4837:701', '4837:2100'], 9: '219.158.1.204', 10: ['219.158.1.209', '0.0.0.30']} attr_hex = Update.construct_attributes(attr, asn4=True) self.assertEqual(attr, Update.parse_attributes(attr_hex, asn4=True))
def test_construct_attributes_ipv4(self): attr = { 1: 2, 2: [(2, [701, 71])], 3: '219.158.1.204', 5: 100, 6: b'', 7: (71, '16.96.243.103'), 8: ['4837:701', '4837:2100'], 9: '219.158.1.204', 10: ['219.158.1.209', '0.0.0.30'] } attr_hex = Update.construct_attributes(attr, asn4=True) self.assertEqual(attr, Update.parse_attributes(attr_hex, asn4=True))
def test_parse_ipv4_addpath_withdraw(self): msg_hex = b'\x00\x09\x00\x00\x00\x01\x20\x63\x63\x63\x63\x00\x00' update = Update.parse(None, msg_hex, True, True) self.assertEqual([{ 'path_id': 1, 'prefix': '99.99.99.99/32' }], update['withdraw'])
def test_parse_prefix_list_with_addpath(self): prefix_hex = b'\x00\x00\x00\x01\x20\x05\x05\x05\x05\x00\x00\x00\x01\x20\xc0\xa8\x01\x05' nlri = [ {'prefix': '5.5.5.5/32', 'path_id': 1}, {'prefix': '192.168.1.5/32', 'path_id': 1} ] self.assertEqual(nlri, Update.parse_prefix_list(prefix_hex, True))
def test_parse_prefix_list(self): prefix_hex = b'\x13\xb8\x9d\xe0\x18E\xb3\xdd\x18E\xb3\xdc\x18\xd1f\xb2\x16Bpd\x18\xd06\xc2' nlri = [ '184.157.224.0/19', '69.179.221.0/24', '69.179.220.0/24', '209.102.178.0/24', '66.112.100.0/22', '208.54.194.0/24' ] self.assertEqual(nlri, Update.parse_prefix_list(prefix_hex))
def test_parse_and_construct_ipv6_unicast_update(self): value_parse = { 'attr': { 1: 0, 2: [(2, [65502])], 4: 0, 14: { 'afi_safi': (2, 1), 'linklocal_nexthop': 'fe80::c002:bff:fe7e:0', 'nexthop': '2001:db8::2', 'nlri': ['::2001:db8:2:2/64', '::2001:db8:2:1/64', '::2001:db8:2:0/64']} }} self.assertEqual(value_parse['attr'], Update.parse( None, Update.construct( msg_dict=value_parse, asn4=True)[HDR_LEN:], True)['attr'], True)
def test_parse_and_construct_ipv4_unicast_2byteas(self): # 2 bytes asn msg_hex = b'\x00\x00\x00\x28\x40\x01\x01\x02\x40\x02\x0a\x02\x01\x00\x1e\x01\x02\x00\x0a\x00\x14\x40\x03\x04' \ b'\x0a\x00\x00\x09\x80\x04\x04\x00\x00\x00\x00\xc0\x07\x06\x00\x1e\x0a\x00\x00\x09\x15\xac\x10\x00' update = Update.parse(None, msg_hex) attributes = { 1: 2, 2: [(2, [30]), (1, [10, 20])], 3: '10.0.0.9', 4: 0, 7: (30, '10.0.0.9') } self.assertEqual(attributes, update['attr']) self.assertEqual([], update['withdraw']) self.assertEqual(['172.16.0.0/21'], update['nlri']) self.assertEqual( msg_hex, Update.construct(msg_dict=update, asn4=False)[HDR_LEN:])
def test_parse_and_construct_ipv4_mpls_vpn_withdraw(self): data_hoped = { 'attr': { 15: { 'afi_safi': (1, 128), 'withdraw': [{ 'label': [524288], 'rd': '2:2', 'prefix': '192.168.201.0/24' }] } } } self.assertEqual( data_hoped['attr'], Update.parse(None, Update.construct(msg_dict=data_hoped)[HDR_LEN:], True)['attr'])
def test_parse_and_construct_ipv4_mpls_vpn_withdraw(self): data_bin = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00' \ b'\x2c\x02\x00\x00\x00\x15\x80\x0f\x12\x00\x01\x80\x70\x80\x00\x00\x00' \ b'\x00\x00\x02\x00\x00\x00\x02\xc0\xa8\xc9' data_hoped = { 'attr': { 15: { 'afi_safi': (1, 128), 'withdraw': [{ 'label': [524288], 'rd': '2:2', 'prefix': '192.168.201.0/24' }] } } } self.assertEqual(data_hoped['attr'], Update.parse(None, data_bin[HDR_LEN:], True)['attr']) self.assertEqual(data_bin, Update.construct(msg_dict=data_hoped))
def test_parse_ipv4_4byteas(self): # 4 bytes asn msg_hex = b'\x00\x00\x00\x30\x40\x01\x01\x02\x40\x02\x10\x02\x01\x00\x00\x00\x1e\x01\x02\x00\x00\x00\x0a\x00' \ b'\x00\x00\x14\x40\x03\x04\x0a\x00\x00\x09\x80\x04\x04\x00\x00\x00\x00\xc0\x07\x08\x00\x00\x00' \ b'\x1e\x0a\x00\x00\x09\x15\xac\x10\x00' update = Update.parse([None, True, msg_hex]) attributes = {1: 2, 2: [(2, [30]), (1, [10, 20])], 3: '10.0.0.9', 4: 0, 7: (30, '10.0.0.9')} self.assertEqual(attributes, update['attr']) self.assertEqual([], update['withdraw']) self.assertEqual(['172.16.0.0/21'], update['nlri'])
def test_parse_prefix_list_with_addpath(self): prefix_hex = b'\x00\x00\x00\x01\x20\x05\x05\x05\x05\x00\x00\x00\x01\x20\xc0\xa8\x01\x05' nlri = [{ 'prefix': '5.5.5.5/32', 'path_id': 1 }, { 'prefix': '192.168.1.5/32', 'path_id': 1 }] self.assertEqual(nlri, Update.parse_prefix_list(prefix_hex, True))
def test_construct_prefix_v4(self): nlri = [ "184.157.224.0/19", "69.179.221.0/24", "69.179.220.0/24", "209.102.178.0/24", "66.112.100.0/22", "208.54.194.0/24", ] nlri_hex = Update().construct_prefix_v4(nlri) self.assertEqual(nlri, Update.parse_prefix_list(nlri_hex))
def test_parse_attributes_ipv4(self): attr_hex = b'@\x01\x01\x00@\x02\x08\x02\x03\x00\x01\x00\x02\x00\x03@\x03\x04\xac\x10\x01\x0e\x80\x04\x04' \ b'\x00\x00\x00\x00@\x05\x04\x00\x00\x00d\x80\t\x04\xac\x10\x01\x0e\x80\n\x08\x02\x02\x02\x02dddd' attributes = {1: 0, 2: [(2, [1, 2, 3])], 3: '172.16.1.14', 4: 0, 5: 100, 9: '172.16.1.14', 10: ['2.2.2.2', '100.100.100.100']} self.assertEqual(attributes, Update.parse_attributes(attr_hex, False)) self.assertRaises(UpdateMessageError, Update.parse_attributes, attr_hex, True)
def test_parse_ipv4_addpath_update(self): msg_hex = b'\x00\x00\x00\x30\x40\x01\x01\x00\x40\x02\x06\x02\x01\x00\x00\xfb\xff\x40\x03\x04\x0a\x00\x0e' \ b'\x01\x80\x04\x04\x00\x00\x00\x00\x40\x05\x04\x00\x00\x00\x64\x80\x0a\x04\x0a\x00\x22' \ b'\x04\x80\x09\x04\x0a\x00\x0f\x01\x00\x00\x00\x01\x20\x05\x05\x05\x05\x00\x00\x00\x01' \ b'\x20\xc0\xa8\x01\x05' update = Update.parse(None, msg_hex, True, True) attributes = {1: 0, 2: [(2, [64511])], 3: '10.0.14.1', 4: 0, 5: 100, 9: '10.0.15.1', 10: ['10.0.34.4']} self.assertEqual(attributes, update['attr']) self.assertEqual([], update['withdraw']) self.assertEqual([ {'path_id': 1, 'prefix': '5.5.5.5/32'}, {'path_id': 1, 'prefix': '192.168.1.5/32'}], update['nlri'])
def test_parse_and_construct_ipv4_mpls_vpn_update(self): data_bin = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00' \ b'\x74\x02\x00\x00\x00\x5d\x40\x01\x01\x02\x40\x02\x00\x80\x04\x04\x00' \ b'\x00\x00\x00\x40\x05\x04\x00\x00\x00\x64\xc0\x10\x08\x00\x02\x00\x02' \ b'\x00\x00\x00\x02\x80\x0a\x10\xc0\xa8\x01\x01\xc0\xa8\x01\x02\xc0\xa8' \ b'\x01\x03\xc0\xa8\x01\x04\x80\x09\x04\xc0\xa8\x01\x06\x80\x0e\x20\x00' \ b'\x01\x80\x0c\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8\x01\x06\x00\x70' \ b'\x00\x01\xd1\x00\x00\x00\x02\x00\x00\x00\x02\xc0\xa8\xc9' data_hoped = { 'attr': { 1: 2, 2: [], 4: 0, 5: 100, 9: '192.168.1.6', 10: ['192.168.1.1', '192.168.1.2', '192.168.1.3', '192.168.1.4'], 14: { 'afi_safi': (1, 128), 'nexthop': { 'rd': '0:0', 'str': '192.168.1.6' }, 'nlri': [{ 'label': [29], 'rd': '2:2', 'prefix': '192.168.201.0/24' }] }, 16: [[2, '2:2']] } } self.maxDiff = None self.assertEqual(data_hoped['attr'], Update.parse(None, data_bin[HDR_LEN:], True)['attr']) self.assertEqual( data_hoped['attr'], Update.parse(None, Update.construct(msg_dict=data_hoped)[HDR_LEN:], True)['attr'])
def update_received(self, timestamp, msg): """Called when a BGP Update message was received.""" result = Update().parse(timestamp, msg, self.fourbytesas, self.add_path_ipv4_receive, self.add_path_ipv4_send) if result['sub_error']: msg = { 'attr': result['attr'], 'nlri': result['nlri'], 'withdraw': result['withdraw'], 'hex': repr(result['hex']) } self.factory.write_msg( timestamp=result['time'], msg_type=6, msg={'msg': msg}, flush=True ) LOG.error('[%s] Update message error: sub error=%s', self.factory.peer_addr, result['sub_error']) self.msg_recv_stat['Updates'] += 1 self.fsm.update_received() return afi_safi = None # process messages if result['nlri'] or result['withdraw']: afi_safi = 'ipv4' elif result['attr'].get(14): afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][14]['afi_safi']] elif result['attr'].get(15): afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][15]['afi_safi']] msg = { 'attr': result['attr'], 'nlri': result['nlri'], 'withdraw': result['withdraw'], 'afi_safi': afi_safi } # write message to disk self.factory.write_msg( timestamp=result['time'], msg_type=bgp_cons.MSG_UPDATE, msg={"msg": msg} ) self.factory.flush_and_check_file_size() # check channel filter if not CONF.standalone and self.factory.tag in \ [channel_cons.SOURCE_ROUTER_TAG, channel_cons.SOURCE_AND_TARGET_ROUTER_TAG]: self.channel_filter(msg=msg) # update rib self.update_rib(msg) self.msg_recv_stat['Updates'] += 1 self.fsm.update_received()
def _update_received(self, timestamp, msg): # if self.msg_recv_stat['Updates'] % 1000 == 0: # LOG.info(self.msg_recv_stat['Updates']) # LOG.info(time.time()) """Called when a BGP Update message was received.""" result = Update().parse(timestamp, msg, self.fourbytesas, self.add_path_ipv4_receive, self.add_path_ipv4_send) if result['sub_error']: msg = { 'attr': result['attr'], 'nlri': result['nlri'], 'withdraw': result['withdraw'], 'hex': repr(result['hex']) } self.handler.on_update_error(self, timestamp, msg) LOG.error('[%s] Update message error: sub error=%s', self.factory.peer_addr, result['sub_error']) self.msg_recv_stat['Updates'] += 1 self.fsm.update_received() return afi_safi = None # process messages if result['nlri'] or result['withdraw']: afi_safi = 'ipv4' elif result['attr'].get(14): afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][14]['afi_safi']] elif result['attr'].get(15): afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][15]['afi_safi']] msg = { 'attr': result['attr'], 'nlri': result['nlri'], 'withdraw': result['withdraw'], 'afi_safi': afi_safi } self.update_receive_verion(result['attr'], result['nlri'], result['withdraw']) if CONF.bgp.rib: # try to update bgp rib in if msg.get('afi_safi') == 'ipv4': self.update_rib_in_ipv4(msg) # LOG.info(msg) self.handler.update_received(self, timestamp, msg) self.msg_recv_stat['Updates'] += 1 self.fsm.update_received()
def construct_update_to_bin(self, msg): """ construct update message to binary :param msg: message dictionary :return: """ try: msg_update = Update().construct(msg, self.fourbytesas, self.add_path_ipv4_send) return msg_update except Exception as e: LOG.error(e) return "construct failed"
def test_parse_and_construct_pmsi_tunnel_evpn_overlay(self): data_bin = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' \ b'\x00`\x02\x00\x00\x00I\xc0\x10\x10\x00\x02\xff\xf7\x00\x00\x8f' \ b'\xc2\x03\x0c\x00\x00\x00\x00\x00\x08@\x01\x01\x00\xc0\x16\t\x00' \ b'\x06\x00\xeaa\xc0\xa8\x01\n@\x05\x04\x00\x00\x00d\x80\x0e\x1c\x00' \ b'\x19F\x04\xc0\xa8\x01\n\x00\x03\x11\x00\x00\xff\xf7\x00\x00\x8f\xc2' \ b'\x00\x00\x00\x00 \xc0\xa8\x01\n' data_dict = { 'attr': { 1: 0, 5: 100, 14: { 'afi_safi': (25, 70), 'nexthop': '192.168.1.10', 'nlri': [{ 'type': 3, 'value': { 'eth_tag_id': 0, 'ip': '192.168.1.10', 'rd': '65527:36802' } }] }, 16: [[2, '65527:36802'], [780, 8]], 22: { 'mpls_label': [60001], 'tunnel_id': '192.168.1.10', 'tunnel_type': 6, 'leaf_info_required': 0 } } } self.maxDiff = None self.assertEqual(data_dict['attr'], Update.parse(None, data_bin[HDR_LEN:])['attr']) self.assertEqual(data_bin, Update.construct(msg_dict=data_dict))
def send_update(self, msg): """ send update message to the peer :param msg: message dictionary :return: """ try: msg_update = Update().construct(msg, self.fourbytesas, self.add_path_ipv4_send) reactor.callFromThread(self.write_tcp_thread, msg_update) self.msg_sent_stat['Updates'] += 1 return True except Exception as e: LOG.error(e) return False
def send_update(self, msg): """ send update message to the peer :param msg: message dictionary :return: """ try: msg_update = Update().construct(msg, self.fourbytesas) self.transport.write(msg_update) self.msg_sent_stat['Updates'] += 1 return True except Exception as e: LOG.error(e) return False
def test_parse_attributes_ipv4(self): attr_hex = b'@\x01\x01\x00@\x02\x08\x02\x03\x00\x01\x00\x02\x00\x03@\x03\x04\xac\x10\x01\x0e\x80\x04\x04' \ b'\x00\x00\x00\x00@\x05\x04\x00\x00\x00d\x80\t\x04\xac\x10\x01\x0e\x80\n\x08\x02\x02\x02\x02dddd' attributes = { 1: 0, 2: [(2, [1, 2, 3])], 3: '172.16.1.14', 4: 0, 5: 100, 9: '172.16.1.14', 10: ['2.2.2.2', '100.100.100.100'] } self.assertEqual(attributes, Update.parse_attributes(attr_hex, False)) self.assertRaises(UpdateMessageError, Update.parse_attributes, attr_hex, True)
def test_parse_ipv4_4byteas(self): # 4 bytes asn msg_hex = b'\x00\x00\x00\x30\x40\x01\x01\x02\x40\x02\x10\x02\x01\x00\x00\x00\x1e\x01\x02\x00\x00\x00\x0a\x00' \ b'\x00\x00\x14\x40\x03\x04\x0a\x00\x00\x09\x80\x04\x04\x00\x00\x00\x00\xc0\x07\x08\x00\x00\x00' \ b'\x1e\x0a\x00\x00\x09\x15\xac\x10\x00' update = Update.parse(None, msg_hex, True) attributes = { 1: 2, 2: [(2, [30]), (1, [10, 20])], 3: '10.0.0.9', 4: 0, 7: (30, '10.0.0.9') } self.assertEqual(attributes, update['attr']) self.assertEqual([], update['withdraw']) self.assertEqual(['172.16.0.0/21'], update['nlri'])
def update_received(self, timestamp, msg): """Called when a BGP Update message was received.""" result = Update().parse(timestamp, msg, self.fourbytesas, self.add_path_ipv4_receive, self.add_path_ipv4_send) if result['sub_error']: msg = { 'attr': result['attr'], 'nlri': result['nlri'], 'withdraw': result['withdraw'], 'hex': repr(result['hex']) } self.factory.write_msg( timestamp=result['time'], msg_type=6, msg={'msg': msg}, flush=True ) LOG.error('[%s] Update message error: sub error=%s', self.factory.peer_addr, result['sub_error']) self.msg_recv_stat['Updates'] += 1 self.fsm.update_received() return # process messages msg = { 'attr': result['attr'], 'nlri': result['nlri'], 'withdraw': result['withdraw'] } # write message to disk self.factory.write_msg( timestamp=result['time'], msg_type=bgp_cons.MSG_UPDATE, msg={"msg": msg} ) if self.factory.flush_and_check_file_size(): for afi, safi in CONF.bgp.running_config[self.factory.peer_addr]['capability']['remote']['afi_safi']: self.send_route_refresh(afi=afi, safi=safi) # check channel filter if not CONF.standalone and self.factory.tag in \ [channel_cons.SOURCE_ROUTER_TAG, channel_cons.SOURCE_AND_TARGET_ROUTER_TAG]: self.channel_filter(msg=msg) # update rib self.update_rib(msg) self.msg_recv_stat['Updates'] += 1 self.fsm.update_received()
def update_received(self, timestamp, msg): """Called when a BGP Update message was received.""" result = Update().parse(timestamp, msg, self.fourbytesas, self.add_path_ipv4_receive, self.add_path_ipv4_send) if result['sub_error']: msg = { 'attr': result['attr'], 'nlri': result['nlri'], 'withdraw': result['withdraw'], 'hex': repr(result['hex']) } self.factory.write_msg(timestamp=result['time'], msg_type=6, msg=msg, flush=True) LOG.error('[%s] Update message error: sub error=%s', self.factory.peer_addr, result['sub_error']) self.msg_recv_stat['Updates'] += 1 self.fsm.update_received() return afi_safi = None # process messages if result['nlri'] or result['withdraw']: afi_safi = 'ipv4' elif result['attr'].get(14): afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][14]['afi_safi']] elif result['attr'].get(15): afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][15]['afi_safi']] msg = { 'attr': result['attr'], 'nlri': result['nlri'], 'withdraw': result['withdraw'], 'afi_safi': afi_safi } # write message to disk self.factory.write_msg(timestamp=result['time'], msg_type=bgp_cons.MSG_UPDATE, msg=msg) self.factory.flush_and_check_file_size() self.msg_recv_stat['Updates'] += 1 self.fsm.update_received()
def test_parse_ipv6_unicast(self): data_bin = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' \ b'\x00\x55\x02\x00\x00\x00\x3e\x80\x0e\x26\x00\x02\x01\x10\x00\x00' \ b'\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xac\x1f\x22\xaa\x00\x80' \ b'\x20\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' \ b'\x40\x01\x01\x00\x40\x02\x00\x80\x04\x04\x00\x00\x00\x00\x40\x05\x04\x00\x00\x00\x64' data_hoped = { 1: 0, 2: [], 4: 0, 5: 100, 14: { 'afi_safi': (2, 1), 'nexthop': '::ffff:172.31.34.170', 'nlri': ['2001::1/128'] } } self.maxDiff = None self.assertEqual(data_hoped, Update.parse(None, data_bin[HDR_LEN:], True)['attr'])
def _update_received(self, timestamp, msg): """Called when a BGP Update message was received.""" result = Update().parse(timestamp, msg, self.fourbytesas, self.add_path_ipv4_receive, self.add_path_ipv4_send) if result['sub_error']: msg = { 'attr': result['attr'], 'nlri': result['nlri'], 'withdraw': result['withdraw'], 'hex': repr(result['hex']) } self.handler.on_update_error(self, timestamp, msg) LOG.error('[%s] Update message error: sub error=%s', self.factory.peer_addr, result['sub_error']) self.msg_recv_stat['Updates'] += 1 self.fsm.update_received() return afi_safi = None # process messages if result['nlri'] or result['withdraw']: afi_safi = 'ipv4' elif result['attr'].get(14): afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][14]['afi_safi']] elif result['attr'].get(15): afi_safi = bgp_cons.AFI_SAFI_DICT[result['attr'][15]['afi_safi']] msg = { 'attr': result['attr'], 'nlri': result['nlri'], 'withdraw': result['withdraw'], 'afi_safi': afi_safi } self.handler.update_received(self, timestamp, msg) self.msg_recv_stat['Updates'] += 1 self.fsm.update_received()
def update_received(self, timestamp, msg): """Called when a BGP Update message was received.""" result = Update().parse([timestamp, self.fourbytesas, msg]) if result['sub_error']: self.factory.write_msg( timestamp=result['time'], msg_type=6, msg={ 'attr': result['attr'], 'nlri': result['nlri'], 'withdraw': result['withdraw'] }, flush=True ) LOG.error('[%s] Update message error: sub error=%s', self.factory.peer_addr, result['sub_error']) else: msg = { 'attr': result['attr'], 'nlri': result['nlri'], 'withdraw': result['withdraw'] } self.factory.write_msg( timestamp=result['time'], msg_type=bgp_cons.MSG_UPDATE, msg=msg, flush=True ) # update rib in ipv4 for prefix in msg['nlri']: self._adj_rib_in['ipv4'][prefix] = msg['attr'] for prefix in msg['withdraw']: if prefix in self._adj_rib_in['ipv4']: self._adj_rib_in['ipv4'].pop(prefix) else: LOG.warning('withdraw prefix which does not exist in rib table!') if not CONF.standalone: self.factory.channel.send_message(exchange='', routing_key=self.factory.peer_addr, message=str(msg)) self.msg_recv_stat['Updates'] += 1 self.fsm.update_received()
def parse_route_monitoring_msg(msg): """ Route Monitoring messages are used for initial synchronization of ADJ-RIBs-In. They are also used for ongoing monitoring of received advertisements and withdraws. Following the common BMP header and per-peer header is a BGP Update PDU. :param msg: :return: """ LOG.debug('decode route monitoring message') bgp_msg_type = struct.unpack('!B', msg[18])[0] LOG.debug('bgp message type=%s' % bgp_msg_type) msg = msg[bgp_cons.HDR_LEN:] if bgp_msg_type == 2: # decode update message results = Update().parse(None, msg, asn4=True) if results['sub_error']: LOG.error( 'error: decode update message error!, error code: %s' % results['sub_error']) LOG.error('Raw data: %s' % repr(results['hex'])) return None return_result = { 'attr': results['attr'], 'nlri': results['nlri'], 'withdraw': results['withdraw'] } LOG.debug('bgp update message: %s' % return_result) return bgp_msg_type, return_result elif bgp_msg_type == 5: bgp_route_refresh_msg = RouteRefresh().parse(msg=msg) 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])) return bgp_msg_type, { 'afi': bgp_route_refresh_msg[0], 'sub_type': bgp_route_refresh_msg[1], 'safi': bgp_route_refresh_msg[2] }
def test_parse_ipv4_addpath_update(self): msg_hex = b'\x00\x00\x00\x30\x40\x01\x01\x00\x40\x02\x06\x02\x01\x00\x00\xfb\xff\x40\x03\x04\x0a\x00\x0e' \ b'\x01\x80\x04\x04\x00\x00\x00\x00\x40\x05\x04\x00\x00\x00\x64\x80\x0a\x04\x0a\x00\x22' \ b'\x04\x80\x09\x04\x0a\x00\x0f\x01\x00\x00\x00\x01\x20\x05\x05\x05\x05\x00\x00\x00\x01' \ b'\x20\xc0\xa8\x01\x05' update = Update.parse(None, msg_hex, True, True) attributes = { 1: 0, 2: [(2, [64511])], 3: '10.0.14.1', 4: 0, 5: 100, 9: '10.0.15.1', 10: ['10.0.34.4'] } self.assertEqual(attributes, update['attr']) self.assertEqual([], update['withdraw']) self.assertEqual([{ 'path_id': 1, 'prefix': '5.5.5.5/32' }, { 'path_id': 1, 'prefix': '192.168.1.5/32' }], update['nlri'])
def test_parse_prefix_list(self): prefix_hex = b'\x13\xb8\x9d\xe0\x18E\xb3\xdd\x18E\xb3\xdc\x18\xd1f\xb2\x16Bpd\x18\xd06\xc2' nlri = ['184.157.224.0/19', '69.179.221.0/24', '69.179.220.0/24', '209.102.178.0/24', '66.112.100.0/22', '208.54.194.0/24'] self.assertEqual(nlri, Update.parse_prefix_list(prefix_hex))
def test_construct_prefix_v4_addpath(self): nlri = [{'path_id': 1, 'prefix': '99.99.99.99/32'}] nlri_hex = Update.construct_prefix_v4(nlri, add_path=True) self.assertEqual(b'\x00\x00\x00\x01\x20\x63\x63\x63\x63', nlri_hex)
def test_parse_ipv4_addpath_withdraw(self): msg_hex = b'\x00\x09\x00\x00\x00\x01\x20\x63\x63\x63\x63\x00\x00' update = Update.parse(None, msg_hex, True, True) self.assertEqual([{'path_id': 1, 'prefix': '99.99.99.99/32'}], update['withdraw'])
def test_construct_prefix_v4(self): nlri = ['184.157.224.1/32', '32.65.243.12/30', '89.232.254.0/23', '69.179.221.0/24', '61.172.0.0/16', '202.223.128.0/17', '156.152.0.0/15', '15.0.0.0/8', '209.102.178.0/24', '66.112.100.0/22', '208.54.194.0/24'] nlri_hex = Update.construct_prefix_v4(nlri) self.assertEqual(nlri, Update.parse_prefix_list(nlri_hex))
def test_parse_link_state(self): self.maxDiff = None data_bin = b"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \ b"\x00\xb3\x02\x00\x00\x00\x9c\x90\x0e\x00\x62\x40\x04\x47\x04\x0a" \ b"\x7c\x01\x7e\x00\x00\x02\x00\x55\x02\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x01\x00\x00\x1a\x02\x00\x00\x04\x00\x00\xff\xfe\x02\x01\x00" \ b"\x04\x00\x00\x00\x00\x02\x03\x00\x06\x00\x00\x00\x00\x00\x01\x01" \ b"\x01\x00\x1a\x02\x00\x00\x04\x00\x00\xff\xfe\x02\x01\x00\x04\x00" \ b"\x00\x00\x00\x02\x03\x00\x06\x00\x00\x00\x00\x00\x03\x01\x03\x00" \ b"\x04\x01\x03\x00\x01\x01\x04\x00\x04\x01\x03\x00\x02\x40\x01\x01" \ b"\x00\x40\x02\x00\x40\x05\x04\x00\x00\x00\x64\x80\x1d\x25\x04\x44" \ b"\x00\x04\x00\x00\x00\x0a\x04\x47\x00\x03\x00\x00\x0a\x04\x4b\x00" \ b"\x07\x70\x00\x00\x00\x00\x61\xaa\x04\x4b\x00\x07\x30\x00\x00\x00" \ b"\x00\x61\xab" data_dict = { 1: 0, 2: [], 5: 100, 14: { 'afi_safi': (16388, 71), 'nexthop': '10.124.1.126', 'nlri': [{ 'type': 'link', 'protocol_id': 2, 'instances_id': 0, 'descriptors': [{ 'type': 'local_node', 'value': { 'as_num': 65534, 'bgpls_id': '0.0.0.0', 'igp_router_id': { 'pseudonode': False, 'iso_node_id': b"0000.0000.0001" } } }, { 'type': 'remote_node', 'value': { 'as_num': 65534, 'bgpls_id': '0.0.0.0', 'igp_router_id': { 'pseudonode': False, 'iso_node_id': b"0000.0000.0003" } } }, { 'type': 'link_local_ipv4', 'value': '1.3.0.1' }, { 'type': 'link_remote_ipv4', 'value': '1.3.0.2' }] }] }, 29: [{ 'type': 'te_metric', 'value': 10 }, { 'type': 'igp_metric', 'value': 10 }, { 'type': 'adj_sid', 'value': { 'flags': { 'B': 1, 'F': 0, 'L': 1, 'P': 0, 'S': 0, 'V': 1 }, 'value': 25002, 'weight': 0 } }, { 'type': 'adj_sid', 'value': { 'flags': { 'B': 0, 'F': 0, 'L': 1, 'P': 0, 'S': 0, 'V': 1 }, 'value': 25003, 'weight': 0 } }] } self.assertEqual(data_dict, Update.parse(None, data_bin[HDR_LEN:])['attr'])