def test_ipv6_unicast_construct(self): nlri_dict = { 'afi_safi': (2, 1), 'withdraw': [ '2001:3232::1/128', '::2001:3232:1:0/64', '2001:4837:1632::2/127' ] } self.assertEqual( nlri_dict, MpUnReachNLRI.parse(MpUnReachNLRI.construct(nlri_dict)[4:]))
def test_ipv4_mpls_vpn_construct(self): data_hoped = { 'afi_safi': (1, 128), 'withdraw': [{ 'rd': '2:2', 'label': [524288], 'prefix': '192.168.201.0/24' }] } self.assertEqual( data_hoped, MpUnReachNLRI.parse(MpUnReachNLRI.construct(data_hoped)[4:]))
def test_ipv6_mpls_vpn_parse_construct(self): data_dict = { 'afi_safi': (2, 128), 'withdraw': [ {'label': [524288], 'rd': '100:10', 'prefix': '2001:3232::1/128'}, {'label': [524288], 'rd': '100:11', 'prefix': '2001:4837:1632::2/127'} ] } self.assertEqual( data_dict, MpUnReachNLRI.parse( value=MpUnReachNLRI.construct(value=data_dict)[3:] ))
def test_l2vpn_evpn_route_type_1_parse_construct(self): data_dict = { "afi_safi": (25, 70), "withdraw": [{ "type": 1, "value": { "rd": "1.1.1.1:32867", "esi": 0, "eth_tag_id": 100, "label": [10] } }]} self.assertEqual(data_dict, MpUnReachNLRI.parse(MpUnReachNLRI.construct(data_dict)[3:]))
def test_ipv4_labeled_unicast_parse_construct(self): data_dict = { "afi_safi": (1, 4), "withdraw": [{ 'prefix': '34.1.41.0/24', 'label': [321] }, { 'prefix': '34.1.42.0/24', 'label': [322] }] } self.assertEqual( data_dict, MpUnReachNLRI.parse(MpUnReachNLRI.construct(data_dict)[3:]))
def test_l2vpn_evpn_route_type_3_parse_construct(self): data_dict = { "afi_safi": (25, 70), "withdraw": [{ "type": 3, "value": { "rd": "172.16.0.1:5904", "eth_tag_id": 100, "ip": "192.168.0.1" } }] } self.assertEqual( data_dict, MpUnReachNLRI.parse(MpUnReachNLRI.construct(data_dict)[3:]))
def test_l2vpn_evpn_route_type_4_parse_construct(self): data_dict = { "afi_safi": (25, 70), "withdraw": [{ "type": 4, "value": { "rd": "172.16.0.1:8888", "esi": 0, "ip": "192.168.0.1" } }] } self.assertEqual( data_dict, MpUnReachNLRI.parse(MpUnReachNLRI.construct(data_dict)[4:]))
def test_l2vpn_evpn_route_type_4_parse_construct(self): data_dict = { "afi_safi": (25, 70), "withdraw": [ { "type": 4, "value": { "rd": "172.16.0.1:8888", "esi": 0, "ip": "192.168.0.1" } } ] } self.assertEqual(data_dict, MpUnReachNLRI.parse(MpUnReachNLRI.construct(data_dict)[3:]))
def test_l2vpn_evpn_route_type_2_parse_construct(self): data_dict = { 'afi_safi': (25, 70), 'withdraw': [ { '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, MpUnReachNLRI.parse(MpUnReachNLRI.construct(data_dict)[3:]))
def test_ipv4_mpls_vpn_parse(self): data_bin = b'\x80\x0f\x12\x00\x01\x80\x70\x80\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\xc0\xa8\xc9' data_hoped = {'afi_safi': (1, 128), 'withdraw': [{'label': [524288], 'rd': '2:2', 'prefix': '192.168.201.0/24'}]} self.assertEqual(data_hoped, MpUnReachNLRI.parse(data_bin[3:]))
def test_ipv6_labeled_unicast_parse_construct(self): data_dict = { 'afi_safi': (2, 4), 'withdraw': [{ '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, MpUnReachNLRI.parse(MpUnReachNLRI.construct(data_dict)[3:]))
def test_ipv4_flowspec_construct(self): data_bin = b'\x00\x01\x85\x0a\x01\x18\xc0\x55\x02\x02\x18\xc0\x55\x01' nlri_dict = { 'afi_safi': (1, 133), 'withdraw': [{ 1: '192.85.2.0/24', 2: '192.85.1.0/24' }] } self.assertEqual(data_bin, MpUnReachNLRI.construct(nlri_dict)[4:])
def test_ipv4_mpls_vpn_construct(self): data_bin = b'\x80\x0f\x12\x00\x01\x80\x70\x80\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\xc0\xa8\xc9' data_hoped = { 'afi_safi': (1, 128), 'withdraw': [{ 'rd': '2:2', 'prefix': '192.168.201.0/24' }] } self.assertEqual(data_bin, MpUnReachNLRI.construct(data_hoped))
def test_ipv4_srte_construct(self): data_bin = b'\x00\x01\x49\x60\x00\x00\x00\x00\x00\x00\x00\x0a\xc0\xa8\x05\x07' nlri_dict = { 'afi_safi': (1, 73), 'withdraw': { 'distinguisher': 0, 'color': 10, 'endpoint': '192.168.5.7' } } self.assertEqual(data_bin, MpUnReachNLRI.construct(nlri_dict)[4:])
def test_ipv4_flowspec_parse(self): data_bin = b'\x00\x01\x85\x0a\x01\x18\xc0\x55\x02\x02\x18\xc0\x55\x01' nlri_dict = { 'afi_safi': (1, 133), 'withdraw': [{ 1: '192.85.2.0/24' }, { 2: '192.85.1.0/24' }] } self.assertEqual(nlri_dict, MpUnReachNLRI.parse(data_bin))
def test_ipv4_flowspec_parse(self): data_bin = b'\x00\x01\x85\x0a\x01\x18\xc0\x55\x02\x02\x18\xc0\x55\x01' nlri_dict = {'afi_safi': (1, 133), 'withdraw': [{1: '192.85.2.0/24'}, {2: '192.85.1.0/24'}]} self.assertEqual(nlri_dict, MpUnReachNLRI.parse(data_bin))
def test_ipv6_unicast_parse(self): data_bin = b"\x00\x02\x01\x80\x20\x01\x48\x37\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20" data_hoped = {'afi_safi': (2, 1), 'withdraw': ['2001:4837::20/128']} self.assertEqual(data_hoped, MpUnReachNLRI.parse(data_bin))
def test_ipv4_mpls_vpn_construct(self): data_bin = b'\x80\x0f\x12\x00\x01\x80\x70\x80\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\xc0\xa8\xc9' data_hoped = {'afi_safi': (1, 128), 'withdraw': [{'rd': '2:2', 'prefix': '192.168.201.0/24'}]} self.assertEqual(data_bin, MpUnReachNLRI.construct(data_hoped))
def construct_attributes(attr_dict, asn4=False): """ construts BGP Update attirubte. :param attr_dict: bgp attribute dictionary :param asn4: support 4 bytes asn or not """ attr_raw_hex = b'' for type_code, value in attr_dict.items(): if type_code == bgp_cons.BGPTYPE_ORIGIN: origin_hex = Origin.construct(value=value) attr_raw_hex += origin_hex elif type_code == bgp_cons.BGPTYPE_AS_PATH: aspath_hex = ASPath.construct(value=value, asn4=asn4) attr_raw_hex += aspath_hex elif type_code == bgp_cons.BGPTYPE_NEXT_HOP: nexthop_hex = NextHop.construct(value=value) attr_raw_hex += nexthop_hex elif type_code == bgp_cons.BGPTYPE_MULTI_EXIT_DISC: med_hex = MED.construct(value=value) attr_raw_hex += med_hex elif type_code == bgp_cons.BGPTYPE_LOCAL_PREF: localpre_hex = LocalPreference.construct(value=value) attr_raw_hex += localpre_hex elif type_code == bgp_cons.BGPTYPE_ATOMIC_AGGREGATE: atomicaggregate_hex = AtomicAggregate.construct(value=value) attr_raw_hex += atomicaggregate_hex elif type_code == bgp_cons.BGPTYPE_AGGREGATOR: aggregator_hex = Aggregator.construct(value=value, asn4=asn4) attr_raw_hex += aggregator_hex elif type_code == bgp_cons.BGPTYPE_COMMUNITIES: community_hex = Community.construct(value=value) attr_raw_hex += community_hex elif type_code == bgp_cons.BGPTYPE_ORIGINATOR_ID: originatorid_hex = OriginatorID.construct(value=value) attr_raw_hex += originatorid_hex elif type_code == bgp_cons.BGPTYPE_CLUSTER_LIST: clusterlist_hex = ClusterList.construct(value=value) attr_raw_hex += clusterlist_hex elif type_code == bgp_cons.BGPTYPE_MP_REACH_NLRI: mpreach_hex = MpReachNLRI().construct(value=value) attr_raw_hex += mpreach_hex elif type_code == bgp_cons.BGPTYPE_MP_UNREACH_NLRI: mpunreach_hex = MpUnReachNLRI.construct(value=value) attr_raw_hex += mpunreach_hex elif type_code == bgp_cons.BGPTYPE_EXTENDED_COMMUNITY: community_ext_hex = ExtCommunity.construct(value=value) attr_raw_hex += community_ext_hex return attr_raw_hex
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
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 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): nlri_dict = { 'afi_safi': (2, 1), 'withdraw': ['2001:3232::1/128', '::2001:3232:1:0/64', '2001:4837:1632::2/127']} self.assertEqual(nlri_dict, MpUnReachNLRI.parse(MpUnReachNLRI.construct(nlri_dict)[3:]))
def test_ipv4_flowspec_construct(self): data_bin = b'\x00\x01\x85\x0a\x01\x18\xc0\x55\x02\x02\x18\xc0\x55\x01' nlri_dict = {'afi_safi': (1, 133), 'withdraw': [{1: '192.85.2.0/24', 2: '192.85.1.0/24'}]} self.assertEqual(data_bin, MpUnReachNLRI.construct(nlri_dict)[3:])