def test_ipv6_unicast_with_locallink_nexthop_construct(self): data_hoped = { '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(data_hoped, MpReachNLRI.parse(MpReachNLRI.construct(data_hoped)[3:]))
def test_linkstate(self): self.maxDiff = None data = b"\x90\x0e\x00\x62\x40\x04\x47\x04\x0a\x7c\x01\x7e\x00\x00\x02\x00" \ b"\x55\x02\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x1a\x02\x00" \ b"\x00\x04\x00\x00\xff\xfe\x02\x01\x00\x04\x00\x00\x00\x00\x02\x03" \ b"\x00\x06\x00\x00\x00\x00\x00\x01\x01\x01\x00\x1a\x02\x00\x00\x04" \ b"\x00\x00\xff\xfe\x02\x01\x00\x04\x00\x00\x00\x00\x02\x03\x00\x06" \ b"\x00\x00\x00\x00\x00\x03\x01\x03\x00\x04\x01\x03\x00\x01\x01\x04" \ b"\x00\x04\x01\x03\x00\x02" data_dict = { 'afi_safi': (16388, 71), 'nexthop': '10.124.1.126', 'nlri': [ { 'type': 'link', 'value': [ { 'type': 'local-node', 'value': { 'as': 65534, 'bgpls-id': '0.0.0.0', 'igp-id': '0.0.0.1'}}, { 'type': 'remote-node', 'value': { 'as': 65534, 'bgpls-id': '0.0.0.0', 'igp-id': '0.0.0.3'}}, {'type': 'link-local-ipv4', 'value': '1.3.0.1'}, {'type': 'link-remote-ipv4', 'value': '1.3.0.2'}]}]} self.assertEqual(data_dict, MpReachNLRI.parse(data[4:]))
def test_ipv4_mpls_vpn_parse(self): data_bin = b'\x80\x0e\x21\x00\x01\x80\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x02\x02\x02\x02' \ b'\x00\x78\x00\x01\x91\x00\x00\x00\x64\x00\x00\x00\x64\xaa\x00\x00\x00' data_hoped = {'afi_safi': (1, 128), 'nexthop': {'rd': '0:0', 'str': '2.2.2.2'}, 'nlri': [{'label': [25], 'rd': '100:100', 'prefix': '170.0.0.0/32'}]} self.assertEqual(data_hoped, MpReachNLRI.parse(data_bin[3:]))
def test_ipv6_unicast(self): data_bin = b"\x00\x02\x01\x10\x20\x01\x32\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x01\x00\x80\x20\x01\x32\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" \ b"\x40\x20\x01\x32\x32\x00\x01\x00\x00\x7f\x20\x01\x48\x37\x16\x32\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x02" data_hoped = { 'afi_safi': (2, 1), 'nexthop': '2001:3232::1', 'nlri': ['2001:3232::1/128', '::2001:3232:1:0/64', '2001:4837:1632::2/127']} self.assertEqual(data_hoped, MpReachNLRI.parse(data_bin))
def test_ipv4_flowspec_construct_multi_nlri(self): data_dict = { 'afi_safi': (1, 133), 'nexthop': '', 'nlri': [ {1: '192.88.3.0/24', 2: '192.89.3.0/24'}, {1: '192.88.4.0/24', 2: '192.89.4.0/24'} ]} data_bin_cons = MpReachNLRI.construct(data_dict) self.assertEqual(data_dict, MpReachNLRI.parse(data_bin_cons[3:]))
def test_ipv6_unicast_with_linklocal_nexthop(self): data_bin = b"\x00\x02\x01\x20\x20\x01\x0d\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x02\xfe\x80\x00\x00\x00\x00\x00\x00\xc0\x02\x0b\xff\xfe\x7e\x00\x00\x00\x40" \ b"\x20\x01\x0d\xb8\x00\x02\x00\x02\x40\x20\x01\x0d\xb8\x00\x02\x00\x01\x40\x20" \ b"\x01\x0d\xb8\x00\x02\x00\x00" data_hoped = { '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(data_hoped, MpReachNLRI.parse(data_bin))
def test_ipv4_flowspec_parse_multi_nlri_with_nexthop(self): data_bin = b'\x0e\x00\x1b\x00\x01\x85\x00\x00\x0a\x01\x18\xc0\x58\x03\x02\x18\xc0\x59\x03\x0a' \ b'\x01\x18\xc0\x58\x04\x02\x18\xc0\x59\x04' data_dict = { 'afi_safi': (1, 133), 'nexthop': '', 'nlri': [ {1: '192.88.3.0/24', 2: '192.89.3.0/24'}, {1: '192.88.4.0/24', 2: '192.89.4.0/24'} ]} self.assertEqual(data_dict, MpReachNLRI.parse(data_bin[3:]))
def test_ipv6_unicast_construct(self): data_parsed = { 'afi_safi': (2, 1), 'nexthop': '2001:3232::1', 'nlri': [ '2001:3232::1/128', '::2001:3232:1:0/64', '2001:4837:1632::2/127' ] } self.assertEqual( data_parsed, MpReachNLRI.parse(MpReachNLRI.construct(data_parsed)[3:]))
def test_ipv6_mpls_vpn_parse(self): data_bin = b'\x80\x0e\x45\x00\x02\x80\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' \ b'\x00\x00\x00\x00\x00\x00\xff\xff\xac\x10\x04\x0c\x00\x98\x00\x03\x61\x00\x00' \ b'\x00\x64\x00\x00\x00\x0c\x20\x10\x00\x00\x00\x12\x00\x04\x98\x00\x03\x71\x00' \ b'\x00\x00\x64\x00\x00\x00\x0c\x20\x10\x00\x01\x00\x12\x00\x00' data_hoped = { 'afi_safi': (2, 128), 'nexthop': {'rd': '0:0', 'str': '::ffff:172.16.4.12'}, 'nlri': [ {'label': [54], 'rd': '100:12', 'prefix': '2010:0:12:4::/64'}, {'label': [55], 'rd': '100:12', 'prefix': '2010:1:12::/64'} ] } self.assertEqual(data_hoped, MpReachNLRI.parse(data_bin[3:]))
def test_l2vpn_evpn_parse_construct_route_type1(self): data_dict = { "afi_safi": (25, 70), "nexthop": "10.75.44.254", "nlri": [{ "type": 1, "value": { "rd": "1.1.1.1:32867", "esi": 0, "eth_tag_id": 100, "label": [10] } }] } self.assertEqual(data_dict, MpReachNLRI.parse(MpReachNLRI.construct(data_dict)[3:]))
def test_ipv4_labeled_unicast_parse_construct(self): data_dict = { 'afi_safi': (1, 4), 'nexthop': "10.75.44.254", 'nlri': [{ 'prefix': '34.1.41.0/24', 'label': [321] }, { 'prefix': '34.1.42.0/24', 'label': [322] }] } self.assertEqual( data_dict, MpReachNLRI.parse(MpReachNLRI.construct(data_dict)[3:]))
def test_l2vpn_evpn_parse_construct_route_type4(self): data_dict = { "afi_safi": (25, 70), "nexthop": "10.75.44.254", "nlri": [ { "type": 4, "value": { "rd": "172.16.0.1:8888", "esi": 0, "ip": "192.168.0.1" } } ] } self.assertEqual(data_dict, MpReachNLRI.parse(MpReachNLRI.construct(data_dict)[3:]))
def test_ipv6_labeled_unicast_parse_construct(self): data_dict = { 'afi_safi': (2, 4), 'nexthop': '::ffff:20.1.1.18', 'nlri': [{ 'label': [91], 'prefix': '2001:2121::1/128' }, { 'label': [92], 'prefix': '::2001:2121:1:0/64' }, { 'label': [93], 'prefix': '2001:4837:1821::2/127' }] } self.assertEqual( data_dict, MpReachNLRI.parse(MpReachNLRI.construct(data_dict)[3:]))
def test_l2vpn_evpn_parse_route_type2(self): data_bin = b'\x80\x0e\x30\x00\x19\x46\x04\xac\x11\x00\x03\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' \ b'\x30\x00\x11\x22\x33\x44\x55\x20\x0b\x0b\x0b\x01\x00\x00\x01' data_dict = { 'afi_safi': (25, 70), 'nexthop': '172.17.0.3', '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}}] } self.assertEqual(data_dict, MpReachNLRI.parse(data_bin[3:]))
def test_ipv4_flowspec_parse(self): data_bin = b'\x80\x0e\x10\x00\x01\x85\x00\x00\x0a\x01\x18\xc0\x55\x02\x02\x18\xc0\x55\x01' data_dict = {'afi_safi': (1, 133), 'nexthop': '', 'nlri': [{1: '192.85.2.0/24'}, {2: '192.85.1.0/24'}]} self.assertEqual(data_dict, MpReachNLRI.parse(data_bin[3:]))
def parse_attributes(data, asn4=False): """ Parses an RFC4271 encoded blob of BGP attributes into a list :param data: :param asn4: support 4 bytes asn or not :return: """ attributes = {} postfix = data bgpls_pro_id = None bgpls_attr = None while len(postfix) > 0: try: flags, type_code = struct.unpack('!BB', postfix[:2]) if flags & AttributeFlag.EXTENDED_LENGTH: attr_len = struct.unpack('!H', postfix[2:4])[0] attr_value = postfix[4:4 + attr_len] postfix = postfix[4 + attr_len:] # Next attribute else: # standard 1-octet length if isinstance(postfix[2], int): attr_len = postfix[2] else: attr_len = ord(postfix[2]) attr_value = postfix[3:3 + attr_len] postfix = postfix[3 + attr_len:] # Next attribute except Exception as e: LOG.error(e) error_str = traceback.format_exc() LOG.debug(error_str) raise excep.UpdateMessageError( sub_error=bgp_cons.ERR_MSG_UPDATE_MALFORMED_ATTR_LIST, data='') if type_code == bgp_cons.BGPTYPE_ORIGIN: decode_value = Origin.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_AS_PATH: decode_value = ASPath.parse(value=attr_value, asn4=asn4) elif type_code == bgp_cons.BGPTYPE_NEXT_HOP: decode_value = NextHop.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_MULTI_EXIT_DISC: decode_value = MED.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_LOCAL_PREF: decode_value = LocalPreference.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_ATOMIC_AGGREGATE: decode_value = AtomicAggregate.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_AGGREGATOR: decode_value = Aggregator.parse(value=attr_value, asn4=asn4) elif type_code == bgp_cons.BGPTYPE_COMMUNITIES: decode_value = Community.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_ORIGINATOR_ID: decode_value = OriginatorID.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_CLUSTER_LIST: decode_value = ClusterList.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_NEW_AS_PATH: decode_value = ASPath.parse(value=attr_value, asn4=True) elif type_code == bgp_cons.BGPTYPE_NEW_AGGREGATOR: decode_value = Aggregator.parse(value=attr_value, asn4=True) elif type_code == bgp_cons.BGPTYPE_LARGE_COMMUNITY: decode_value = LargeCommunity.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_MP_REACH_NLRI: decode_value = MpReachNLRI.parse(value=attr_value) if decode_value['nlri'][0] and type( decode_value['nlri'][0]) is dict: if decode_value['nlri'][0].get("protocol_id"): bgpls_pro_id = decode_value['nlri'][0]["protocol_id"] elif type_code == bgp_cons.BGPTYPE_MP_UNREACH_NLRI: decode_value = MpUnReachNLRI.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_EXTENDED_COMMUNITY: decode_value = ExtCommunity.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_PMSI_TUNNEL: decode_value = PMSITunnel.parse(value=attr_value) pmsi_hex = attr_value elif type_code == bgp_cons.BGPTYPE_LINK_STATE: if bgpls_pro_id: attributes.update( LinkState.unpack(bgpls_pro_id=bgpls_pro_id, data=attr_value).dict()) else: bgpls_attr = attr_value continue else: decode_value = binascii.b2a_hex(attr_value) attributes[type_code] = decode_value if bgpls_attr: attributes.update( LinkState.unpack(bgpls_pro_id=bgpls_pro_id, data=attr_value).dict()) evpn_overlay = EVPN.signal_evpn_overlay(attributes) if evpn_overlay['evpn'] and evpn_overlay['encap_ec']: if bgp_cons.BGPTYPE_PMSI_TUNNEL in attributes: attributes[bgp_cons.BGPTYPE_PMSI_TUNNEL] = PMSITunnel.parse( value=pmsi_hex, evpn_overlay=evpn_overlay) return attributes
def test_ipv6_unicast_construct(self): data_parsed = { 'afi_safi': (2, 1), 'nexthop': '2001:3232::1', 'nlri': ['2001:3232::1/128', '::2001:3232:1:0/64', '2001:4837:1632::2/127']} self.assertEqual(data_parsed, MpReachNLRI.parse(MpReachNLRI.construct(data_parsed)[3:]))
def parse_attributes(data, asn4=False): """ Parses an RFC4271 encoded blob of BGP attributes into a list :param data: :param asn4: support 4 bytes asn or not :return: """ attributes = {} postfix = data while len(postfix) > 0: try: flags, type_code = struct.unpack('!BB', postfix[:2]) if flags & AttributeFlag.EXTENDED_LENGTH: attr_len = struct.unpack('!H', postfix[2:4])[0] attr_value = postfix[4:4 + attr_len] postfix = postfix[4 + attr_len:] # Next attribute else: # standard 1-octet length if isinstance(postfix[2], int): attr_len = postfix[2] else: attr_len = ord(postfix[2]) attr_value = postfix[3:3 + attr_len] postfix = postfix[3 + attr_len:] # Next attribute except Exception as e: LOG.error(e) error_str = traceback.format_exc() LOG.debug(error_str) raise excep.UpdateMessageError( sub_error=bgp_cons.ERR_MSG_UPDATE_MALFORMED_ATTR_LIST, data='') if type_code == bgp_cons.BGPTYPE_ORIGIN: decode_value = Origin.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_AS_PATH: decode_value = ASPath.parse(value=attr_value, asn4=asn4) elif type_code == bgp_cons.BGPTYPE_NEXT_HOP: decode_value = NextHop.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_MULTI_EXIT_DISC: decode_value = MED.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_LOCAL_PREF: decode_value = LocalPreference.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_ATOMIC_AGGREGATE: decode_value = AtomicAggregate.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_AGGREGATOR: decode_value = Aggregator.parse(value=attr_value, asn4=asn4) elif type_code == bgp_cons.BGPTYPE_COMMUNITIES: decode_value = Community.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_ORIGINATOR_ID: decode_value = OriginatorID.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_CLUSTER_LIST: decode_value = ClusterList.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_NEW_AS_PATH: decode_value = ASPath.parse(value=attr_value, asn4=True) elif type_code == bgp_cons.BGPTYPE_NEW_AGGREGATOR: decode_value = Aggregator.parse(value=attr_value, asn4=True) elif type_code == bgp_cons.BGPTYPE_MP_REACH_NLRI: decode_value = MpReachNLRI.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_MP_UNREACH_NLRI: decode_value = MpUnReachNLRI.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_EXTENDED_COMMUNITY: decode_value = ExtCommunity.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_PMSI_TUNNEL: decode_value = PMSITunnel.parse(value=attr_value) else: decode_value = repr(attr_value) attributes[type_code] = decode_value return attributes
def parse_attributes(data, asn4=False): """ Parses an RFC4271 encoded blob of BGP attributes into a list :param data: :param asn4: support 4 bytes asn or not :return: """ attributes = {} postfix = data while len(postfix) > 0: try: flags, type_code = struct.unpack('!BB', postfix[:2]) if flags & AttributeFlag.EXTENDED_LENGTH: attr_len = struct.unpack('!H', postfix[2:4])[0] attr_value = postfix[4:4 + attr_len] postfix = postfix[4 + attr_len:] # Next attribute else: # standard 1-octet length if isinstance(postfix[2], int): attr_len = postfix[2] else: attr_len = ord(postfix[2]) attr_value = postfix[3:3 + attr_len] postfix = postfix[3 + attr_len:] # Next attribute except Exception as e: LOG.error(e) error_str = traceback.format_exc() LOG.debug(error_str) raise excep.UpdateMessageError( sub_error=bgp_cons.ERR_MSG_UPDATE_MALFORMED_ATTR_LIST, data='') if type_code == bgp_cons.BGPTYPE_ORIGIN: decode_value = Origin.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_AS_PATH: decode_value = ASPath.parse(value=attr_value, asn4=asn4) elif type_code == bgp_cons.BGPTYPE_NEXT_HOP: decode_value = NextHop.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_MULTI_EXIT_DISC: decode_value = MED.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_LOCAL_PREF: decode_value = LocalPreference.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_ATOMIC_AGGREGATE: decode_value = AtomicAggregate.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_AGGREGATOR: decode_value = Aggregator.parse(value=attr_value, asn4=asn4) elif type_code == bgp_cons.BGPTYPE_COMMUNITIES: decode_value = Community.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_ORIGINATOR_ID: decode_value = OriginatorID.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_CLUSTER_LIST: decode_value = ClusterList.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_LINK_STATE: decode_value = LinkState.parse(value=attr_value).dict()[29] elif type_code == bgp_cons.BGPTYPE_NEW_AS_PATH: decode_value = ASPath.parse(value=attr_value, asn4=True) elif type_code == bgp_cons.BGPTYPE_NEW_AGGREGATOR: decode_value = Aggregator.parse(value=attr_value, asn4=True) elif type_code == bgp_cons.BGPTYPE_MP_REACH_NLRI: decode_value = MpReachNLRI.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_MP_UNREACH_NLRI: decode_value = MpUnReachNLRI.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_EXTENDED_COMMUNITY: decode_value = ExtCommunity.parse(value=attr_value) elif type_code == bgp_cons.BGPTYPE_PMSI_TUNNEL: decode_value = PMSITunnel.parse(value=attr_value) else: decode_value = binascii.b2a_hex(attr_value) attributes[type_code] = decode_value return attributes