diff options
Diffstat (limited to 'tests/topotests/lib/bmp_collector/bgp')
6 files changed, 142 insertions, 131 deletions
diff --git a/tests/topotests/lib/bmp_collector/bgp/open/__init__.py b/tests/topotests/lib/bmp_collector/bgp/open/__init__.py index 6c814ee..e1e6b51 100644 --- a/tests/topotests/lib/bmp_collector/bgp/open/__init__.py +++ b/tests/topotests/lib/bmp_collector/bgp/open/__init__.py @@ -8,27 +8,29 @@ import struct class BGPOpen: - UNPACK_STR = '!16sHBBHH4sB' + UNPACK_STR = "!16sHBBHH4sB" @classmethod def dissect(cls, data): - (marker, - length, - open_type, - version, - my_as, - hold_time, - bgp_id, - optional_params_len) = struct.unpack_from(cls.UNPACK_STR, data) + ( + marker, + length, + open_type, + version, + my_as, + hold_time, + bgp_id, + optional_params_len, + ) = struct.unpack_from(cls.UNPACK_STR, data) - data = data[struct.calcsize(cls.UNPACK_STR) + optional_params_len:] + data = data[struct.calcsize(cls.UNPACK_STR) + optional_params_len :] # XXX: parse optional parameters return data, { - 'version': version, - 'my_as': my_as, - 'hold_time': hold_time, - 'bgp_id': ipaddress.ip_address(bgp_id), - 'optional_params_len': optional_params_len, + "version": version, + "my_as": my_as, + "hold_time": hold_time, + "bgp_id": ipaddress.ip_address(bgp_id), + "optional_params_len": optional_params_len, } diff --git a/tests/topotests/lib/bmp_collector/bgp/update/__init__.py b/tests/topotests/lib/bmp_collector/bgp/update/__init__.py index d079b35..629e175 100644 --- a/tests/topotests/lib/bmp_collector/bgp/update/__init__.py +++ b/tests/topotests/lib/bmp_collector/bgp/update/__init__.py @@ -10,45 +10,47 @@ from .nlri import NlriIPv4Unicast from .path_attributes import PathAttribute -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class BGPUpdate: - UNPACK_STR = '!16sHBH' + UNPACK_STR = "!16sHBH" STATIC_SIZE = 23 @classmethod def dissect(cls, data): - msg = {'bmp_log_type': 'update'} + msg = {"bmp_log_type": "update"} common_size = struct.calcsize(cls.UNPACK_STR) - (marker, - length, - update_type, - withdrawn_routes_len) = struct.unpack_from(cls.UNPACK_STR, data) + (marker, length, update_type, withdrawn_routes_len) = struct.unpack_from( + cls.UNPACK_STR, data + ) # get withdrawn routes - withdrawn_routes = '' + withdrawn_routes = "" if withdrawn_routes_len: withdrawn_routes = NlriIPv4Unicast.parse( - data[common_size:common_size + withdrawn_routes_len] + data[common_size : common_size + withdrawn_routes_len] ) - msg['bmp_log_type'] = 'withdraw' + msg["bmp_log_type"] = "withdraw" msg.update(withdrawn_routes) # get path attributes (total_path_attrs_len,) = struct.unpack_from( - '!H', data[common_size+withdrawn_routes_len:]) + "!H", data[common_size + withdrawn_routes_len :] + ) if total_path_attrs_len: offset = cls.STATIC_SIZE + withdrawn_routes_len - path_attrs_data = data[offset:offset + total_path_attrs_len] + path_attrs_data = data[offset : offset + total_path_attrs_len] while path_attrs_data: path_attrs_data, pattr = PathAttribute.dissect(path_attrs_data) if pattr: msg = {**msg, **pattr} # get nlri - nlri_len = length - cls.STATIC_SIZE - withdrawn_routes_len - total_path_attrs_len + nlri_len = ( + length - cls.STATIC_SIZE - withdrawn_routes_len - total_path_attrs_len + ) if nlri_len > 0: - nlri = NlriIPv4Unicast.parse(data[length - nlri_len:length]) + nlri = NlriIPv4Unicast.parse(data[length - nlri_len : length]) msg.update(nlri) return data[length:], msg diff --git a/tests/topotests/lib/bmp_collector/bgp/update/af.py b/tests/topotests/lib/bmp_collector/bgp/update/af.py index 01af1ae..200b15a 100644 --- a/tests/topotests/lib/bmp_collector/bgp/update/af.py +++ b/tests/topotests/lib/bmp_collector/bgp/update/af.py @@ -19,7 +19,7 @@ SAFI_IP_FLOWSPEC = 133 SAFI_VPN_FLOWSPEC = 134 -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class AddressFamily: def __init__(self, afi, safi): self.afi = afi @@ -31,13 +31,13 @@ class AddressFamily: return (self.afi, self.safi) == (other.afi, other.safi) def __str__(self): - return f'afi: {self.afi}, safi: {self.safi}' + return f"afi: {self.afi}, safi: {self.safi}" def __hash__(self): return hash((self.afi, self.safi)) -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class AF: IPv4_UNICAST = AddressFamily(AFI_IP, SAFI_UNICAST) IPv6_UNICAST = AddressFamily(AFI_IP6, SAFI_UNICAST) diff --git a/tests/topotests/lib/bmp_collector/bgp/update/nlri.py b/tests/topotests/lib/bmp_collector/bgp/update/nlri.py index c1720f1..b362520 100644 --- a/tests/topotests/lib/bmp_collector/bgp/update/nlri.py +++ b/tests/topotests/lib/bmp_collector/bgp/update/nlri.py @@ -13,7 +13,8 @@ from .rd import RouteDistinguisher def decode_label(label): # from frr # frr encode just one label - return (label[0] << 12) | (label[1] << 4) | (label[2] & 0xf0) >> 4 + return (label[0] << 12) | (label[1] << 4) | (label[2] & 0xF0) >> 4 + def padding(databin, len_): """ @@ -23,7 +24,8 @@ def padding(databin, len_): """ if len(databin) >= len_: return databin - return databin + b'\0' * (len_ - len(databin)) + return databin + b"\0" * (len_ - len(databin)) + def dissect_nlri(nlri_data, afi, safi): """ @@ -37,35 +39,34 @@ def dissect_nlri(nlri_data, afi, safi): elif addr_family == AF.IPv6_UNICAST: return NlriIPv6Unicast.parse(nlri_data) - return {'ip_prefix': 'Unknown'} + return {"ip_prefix": "Unknown"} -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv4Unicast: - @staticmethod def parse(data): """parses prefixes from withdrawn_routes or nrli data""" - (prefix_len,) = struct.unpack_from('!B', data) + (prefix_len,) = struct.unpack_from("!B", data) prefix = padding(data[1:], 4) - return {'ip_prefix': f'{ipaddress.IPv4Address(prefix)}/{prefix_len}'} + return {"ip_prefix": f"{ipaddress.IPv4Address(prefix)}/{prefix_len}"} -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv6Unicast: @staticmethod def parse(data): """parses prefixes from withdrawn_routes or nrli data""" - (prefix_len,) = struct.unpack_from('!B', data) + (prefix_len,) = struct.unpack_from("!B", data) prefix = padding(data[1:], 16) - return {'ip_prefix': f'{ipaddress.IPv6Address(prefix)}/{prefix_len}'} + return {"ip_prefix": f"{ipaddress.IPv6Address(prefix)}/{prefix_len}"} -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv4Vpn: - UNPACK_STR = '!B3s8s' + UNPACK_STR = "!B3s8s" @classmethod def parse(cls, data): @@ -74,17 +75,17 @@ class NlriIPv4Vpn: ipv4 = padding(data[offset:], 4) # prefix_len = total_bits_len - label_bits_len - rd_bits_len - prefix_len = bit_len - 3*8 - 8*8 + prefix_len = bit_len - 3 * 8 - 8 * 8 return { - 'label': decode_label(label), - 'rd': str(RouteDistinguisher(rd)), - 'ip_prefix': f'{ipaddress.IPv4Address(ipv4)}/{prefix_len}', + "label": decode_label(label), + "rd": str(RouteDistinguisher(rd)), + "ip_prefix": f"{ipaddress.IPv4Address(ipv4)}/{prefix_len}", } -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv6Vpn: - UNPACK_STR = '!B3s8s' + UNPACK_STR = "!B3s8s" @classmethod def parse(cls, data): @@ -93,48 +94,49 @@ class NlriIPv6Vpn: offset = struct.calcsize(cls.UNPACK_STR) ipv6 = padding(data[offset:], 16) - prefix_len = bit_len - 3*8 - 8*8 + prefix_len = bit_len - 3 * 8 - 8 * 8 return { - 'label': decode_label(label), - 'rd': str(RouteDistinguisher(rd)), - 'ip_prefix': f'{ipaddress.IPv6Address(ipv6)}/{prefix_len}', + "label": decode_label(label), + "rd": str(RouteDistinguisher(rd)), + "ip_prefix": f"{ipaddress.IPv6Address(ipv6)}/{prefix_len}", } -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv4Mpls: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv6Mpls: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv4FlowSpec: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv6FlowSpec: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriVpn4FlowSpec: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriVpn6FlowSpec: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriL2EVPN: pass -#------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ class NlriL2VPNFlowSpec: pass diff --git a/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py b/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py index 6e82e9c..3694cb4 100644 --- a/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py +++ b/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py @@ -38,17 +38,18 @@ ORIGIN_EGP = 0x01 ORIGIN_INCOMPLETE = 0x02 -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttribute: PATH_ATTRS = {} UNKNOWN_ATTR = None - UNPACK_STR = '!BB' + UNPACK_STR = "!BB" @classmethod def register_path_attr(cls, path_attr): def _register_path_attr(subcls): cls.PATH_ATTRS[path_attr] = subcls return subcls + return _register_path_attr @classmethod @@ -61,7 +62,7 @@ class PathAttribute: offset = struct.calcsize(cls.UNPACK_STR) # get attribute length - attr_len_str = '!H' if (flags & PATH_ATTR_FLAG_EXTENDED_LENGTH) else '!B' + attr_len_str = "!H" if (flags & PATH_ATTR_FLAG_EXTENDED_LENGTH) else "!B" (attr_len,) = struct.unpack_from(attr_len_str, data[offset:]) @@ -69,32 +70,34 @@ class PathAttribute: path_attr_cls = cls.lookup_path_attr(type_code) if path_attr_cls == cls.UNKNOWN_ATTR: - return data[offset + attr_len:], None + return data[offset + attr_len :], None - return data[offset+attr_len:], path_attr_cls.dissect(data[offset:offset+attr_len]) + return data[offset + attr_len :], path_attr_cls.dissect( + data[offset : offset + attr_len] + ) -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ @PathAttribute.register_path_attr(PATH_ATTR_TYPE_ORIGIN) class PathAttrOrigin: ORIGIN_STR = { - ORIGIN_IGP: 'IGP', - ORIGIN_EGP: 'EGP', - ORIGIN_INCOMPLETE: 'INCOMPLETE', + ORIGIN_IGP: "IGP", + ORIGIN_EGP: "EGP", + ORIGIN_INCOMPLETE: "INCOMPLETE", } @classmethod def dissect(cls, data): - (origin,) = struct.unpack_from('!B', data) + (origin,) = struct.unpack_from("!B", data) - return {'origin': cls.ORIGIN_STR.get(origin, 'UNKNOWN')} + return {"origin": cls.ORIGIN_STR.get(origin, "UNKNOWN")} -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ @PathAttribute.register_path_attr(PATH_ATTR_TYPE_AS_PATH) class PathAttrAsPath: AS_PATH_TYPE_SET = 0x01 - AS_PATH_TYPE_SEQUENCE= 0x02 + AS_PATH_TYPE_SEQUENCE = 0x02 @staticmethod def get_asn_len(asns): @@ -103,34 +106,34 @@ class PathAttrAsPath: @classmethod def dissect(cls, data): - (_type, _len) = struct.unpack_from('!BB', data) + (_type, _len) = struct.unpack_from("!BB", data) data = data[2:] - _type_str = 'Ordred' if _type == cls.AS_PATH_TYPE_SEQUENCE else 'Raw' + _type_str = "Ordred" if _type == cls.AS_PATH_TYPE_SEQUENCE else "Raw" segment = [] while data: - (asn,) = struct.unpack_from('!I', data) + (asn,) = struct.unpack_from("!I", data) segment.append(asn) data = data[4:] - return {'as_path': ' '.join(str(a) for a in segment)} + return {"as_path": " ".join(str(a) for a in segment)} -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ @PathAttribute.register_path_attr(PATH_ATTR_TYPE_NEXT_HOP) class PathAttrNextHop: @classmethod def dissect(cls, data): - (nexthop,) = struct.unpack_from('!4s', data) - return {'bgp_nexthop': str(ipaddress.IPv4Address(nexthop))} + (nexthop,) = struct.unpack_from("!4s", data) + return {"bgp_nexthop": str(ipaddress.IPv4Address(nexthop))} -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrMultiExitDisc: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ @PathAttribute.register_path_attr(PATH_ATTR_TYPE_MP_REACH_NLRI) class PathAttrMpReachNLRI: """ @@ -162,7 +165,8 @@ class PathAttrMpReachNLRI: | Network Layer Reachability Information (variable) | +---------------------------------------------------------+ """ - UNPACK_STR = '!HBB' + + UNPACK_STR = "!HBB" NLRI_RESERVED_LEN = 1 @staticmethod @@ -170,35 +174,35 @@ class PathAttrMpReachNLRI: msg = {} if nexthop_len == 4: # IPv4 - (ipv4,) = struct.unpack_from('!4s', nexthop_data) - msg['nxhp_ip'] = str(ipaddress.IPv4Address(ipv4)) + (ipv4,) = struct.unpack_from("!4s", nexthop_data) + msg["nxhp_ip"] = str(ipaddress.IPv4Address(ipv4)) elif nexthop_len == 12: # RD + IPv4 - (rd, ipv4) = struct.unpack_from('!8s4s', nexthop_data) - msg['nxhp_ip'] = str(ipaddress.IPv4Address(ipv4)) - msg['nxhp_rd'] = str(RouteDistinguisher(rd)) + (rd, ipv4) = struct.unpack_from("!8s4s", nexthop_data) + msg["nxhp_ip"] = str(ipaddress.IPv4Address(ipv4)) + msg["nxhp_rd"] = str(RouteDistinguisher(rd)) elif nexthop_len == 16: # IPv6 - (ipv6,) = struct.unpack_from('!16s', nexthop_data) - msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6)) + (ipv6,) = struct.unpack_from("!16s", nexthop_data) + msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6)) elif nexthop_len == 24: # RD + IPv6 - (rd, ipv6) = struct.unpack_from('!8s16s', nexthop_data) - msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6)) - msg['nxhp_rd'] = str(RouteDistinguisher(rd)) + (rd, ipv6) = struct.unpack_from("!8s16s", nexthop_data) + msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6)) + msg["nxhp_rd"] = str(RouteDistinguisher(rd)) elif nexthop_len == 32: # IPv6 + IPv6 link-local - (ipv6, link_local)= struct.unpack_from('!16s16s', nexthop_data) - msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6)) - msg['nxhp_link-local'] = str(ipaddress.IPv6Address(link_local)) + (ipv6, link_local) = struct.unpack_from("!16s16s", nexthop_data) + msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6)) + msg["nxhp_link-local"] = str(ipaddress.IPv6Address(link_local)) elif nexthop_len == 48: # RD + IPv6 + RD + IPv6 link-local - u_str = '!8s16s8s16s' - (rd1, ipv6, rd2, link_local)= struct.unpack_from(u_str, nexthop_data) - msg['nxhp_rd1'] = str(RouteDistinguisher(rd1)) - msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6)) - msg['nxhp_rd2'] = str(RouteDistinguisher(rd2)) - msg['nxhp_link-local'] = str(ipaddress.IPv6Address(link_local)) + u_str = "!8s16s8s16s" + (rd1, ipv6, rd2, link_local) = struct.unpack_from(u_str, nexthop_data) + msg["nxhp_rd1"] = str(RouteDistinguisher(rd1)) + msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6)) + msg["nxhp_rd2"] = str(RouteDistinguisher(rd2)) + msg["nxhp_link-local"] = str(ipaddress.IPv6Address(link_local)) return msg @@ -210,10 +214,10 @@ class PathAttrMpReachNLRI: def dissect(cls, data): (afi, safi, nexthop_len) = struct.unpack_from(cls.UNPACK_STR, data) offset = struct.calcsize(cls.UNPACK_STR) - msg = {'afi': afi, 'safi': safi} + msg = {"afi": afi, "safi": safi} # dissect nexthop - nexthop_data = data[offset: offset + nexthop_len] + nexthop_data = data[offset : offset + nexthop_len] nexthop = cls.dissect_nexthop(nexthop_data, nexthop_len) msg.update(nexthop) @@ -227,7 +231,7 @@ class PathAttrMpReachNLRI: return msg -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ @PathAttribute.register_path_attr(PATH_ATTR_TYPE_MP_UNREACH_NLRI) class PathAttrMpUnReachNLRI: """ @@ -239,13 +243,14 @@ class PathAttrMpUnReachNLRI: | Withdrawn Routes (variable) | +---------------------------------------------------------+ """ - UNPACK_STR = '!HB' + + UNPACK_STR = "!HB" @classmethod def dissect(cls, data): (afi, safi) = struct.unpack_from(cls.UNPACK_STR, data) offset = struct.calcsize(cls.UNPACK_STR) - msg = {'bmp_log_type': 'withdraw','afi': afi, 'safi': safi} + msg = {"bmp_log_type": "withdraw", "afi": afi, "safi": safi} if data[offset:]: # dissect withdrawn_routes @@ -254,51 +259,51 @@ class PathAttrMpUnReachNLRI: return msg -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrLocalPref: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrAtomicAgregate: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrAggregator: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrCommunities: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrOriginatorID: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrClusterList: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrExtendedCommunities: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrPMSITunnel: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrLinkState: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrLargeCommunities: pass diff --git a/tests/topotests/lib/bmp_collector/bgp/update/rd.py b/tests/topotests/lib/bmp_collector/bgp/update/rd.py index c382fa8..3f08de5 100644 --- a/tests/topotests/lib/bmp_collector/bgp/update/rd.py +++ b/tests/topotests/lib/bmp_collector/bgp/update/rd.py @@ -7,7 +7,7 @@ import ipaddress import struct -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class RouteDistinguisher: """ type 0: @@ -28,32 +28,32 @@ class RouteDistinguisher: + | 4-bytes AS number (4 bytes)| Service Provider 2 bytes)| +-------------------------------------------------------------------------+ """ + def __init__(self, rd): self.rd = rd self.as_number = None self.admin_ipv4 = None self.four_bytes_as = None self.assigned_sp = None - self.repr_str = '' + self.repr_str = "" self.dissect() def dissect(self): - (rd_type,) = struct.unpack_from('!H', self.rd) + (rd_type,) = struct.unpack_from("!H", self.rd) if rd_type == 0: - (self.as_number, - self.assigned_sp) = struct.unpack_from('!HI', self.rd[2:]) - self.repr_str = f'{self.as_number}:{self.assigned_sp}' + (self.as_number, self.assigned_sp) = struct.unpack_from("!HI", self.rd[2:]) + self.repr_str = f"{self.as_number}:{self.assigned_sp}" elif rd_type == 1: - (self.admin_ipv4, - self.assigned_sp) = struct.unpack_from('!IH', self.rd[2:]) + (self.admin_ipv4, self.assigned_sp) = struct.unpack_from("!IH", self.rd[2:]) ipv4 = str(ipaddress.IPv4Address(self.admin_ipv4)) - self.repr_str = f'{self.as_number}:{self.assigned_sp}' + self.repr_str = f"{self.as_number}:{self.assigned_sp}" elif rd_type == 2: - (self.four_bytes_as, - self.assigned_sp) = struct.unpack_from('!IH', self.rd[2:]) - self.repr_str = f'{self.four_bytes_as}:{self.assigned_sp}' + (self.four_bytes_as, self.assigned_sp) = struct.unpack_from( + "!IH", self.rd[2:] + ) + self.repr_str = f"{self.four_bytes_as}:{self.assigned_sp}" def __str__(self): return self.repr_str |