Skip to content

Commit

Permalink
topotests: apply black on bmp collector
Browse files Browse the repository at this point in the history
Apply black on bmp collector

Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
  • Loading branch information
louis-6wind committed Feb 29, 2024
1 parent a5da98a commit 9208e16
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 81 deletions.
167 changes: 89 additions & 78 deletions tests/topotests/lib/bmp_collector/bmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,30 +33,33 @@
if not os.path.exists(LOG_DIR):
os.makedirs(LOG_DIR)


def bin2str_ipaddress(ip_bytes, is_ipv6=False):
if is_ipv6:
return str(ipaddress.IPv6Address(ip_bytes))
return str(ipaddress.IPv4Address(ip_bytes[-4:]))


def log2file(logs, log_file):
"""
XXX: extract the useful information and save it in a flat dictionnary
"""
with open(log_file, 'a') as f:
with open(log_file, "a") as f:
f.write(json.dumps(logs) + "\n")


#------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
class BMPCodes:
"""
XXX: complete the list, provide RFCs.
"""

VERSION = 0x3

BMP_MSG_TYPE_ROUTE_MONITORING = 0x00
BMP_MSG_TYPE_STATISTICS_REPORT = 0x01
BMP_MSG_TYPE_PEER_DOWN_NOTIFICATION = 0x02
BMP_MSG_TYPE_PEER_UP_NOTIFICATION = 0x03
BMP_MSG_TYPE_PEER_DOWN_NOTIFICATION = 0x02
BMP_MSG_TYPE_PEER_UP_NOTIFICATION = 0x03
BMP_MSG_TYPE_INITIATION = 0x04
BMP_MSG_TYPE_TERMINATION = 0x05
BMP_MSG_TYPE_ROUTE_MIRRORING = 0x06
Expand Down Expand Up @@ -107,15 +110,15 @@ class BMPCodes:

# peer down reason code
BMP_PEER_DOWN_LOCAL_NOTIFY = 0x01
BMP_PEER_DOWN_LOCAL_NO_NOTIFY = 0X02
BMP_PEER_DOWN_REMOTE_NOTIFY = 0X03
BMP_PEER_DOWN_REMOTE_NO_NOTIFY = 0X04
BMP_PEER_DOWN_LOCAL_NO_NOTIFY = 0x02
BMP_PEER_DOWN_REMOTE_NOTIFY = 0x03
BMP_PEER_DOWN_REMOTE_NO_NOTIFY = 0x04
BMP_PEER_DOWN_INFO_NO_LONGER = 0x05
BMP_PEER_DOWN_SYSTEM_CLOSED = 0X06
BMP_PEER_DOWN_SYSTEM_CLOSED = 0x06

# termincation message types
BMP_TERM_TYPE_STRING = 0x00
BMP_TERM_TYPE_REASON = 0X01
BMP_TERM_TYPE_REASON = 0x01

# termination reason code
BMP_TERM_REASON_ADMIN_CLOSE = 0x00
Expand All @@ -126,38 +129,40 @@ class BMPCodes:

# policy route tlv
BMP_ROUTE_POLICY_TLV_VRF = 0x00
BMP_ROUTE_POLICY_TLV_POLICY= 0x01
BMP_ROUTE_POLICY_TLV_POLICY = 0x01
BMP_ROUTE_POLICY_TLV_PRE_POLICY = 0x02
BMP_ROUTE_POLICY_TLV_POST_POLICY = 0x03
BMP_ROUTE_POLICY_TLV_STRING = 0x04


#------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
class BMPMsg:
"""
XXX: should we move register_msg_type and look_msg_type
to generic Type class.
"""

TYPES = {}
UNKNOWN_TYPE = None
HDR_STR = '!BIB'
HDR_STR = "!BIB"
MIN_LEN = struct.calcsize(HDR_STR)
TYPES_STR = {
BMPCodes.BMP_MSG_TYPE_INITIATION: 'initiation',
BMPCodes.BMP_MSG_TYPE_PEER_DOWN_NOTIFICATION: 'peer down notification',
BMPCodes.BMP_MSG_TYPE_PEER_UP_NOTIFICATION: 'peer up notification',
BMPCodes.BMP_MSG_TYPE_ROUTE_MONITORING: 'route monitoring',
BMPCodes.BMP_MSG_TYPE_STATISTICS_REPORT: 'statistics report',
BMPCodes.BMP_MSG_TYPE_TERMINATION: 'termination',
BMPCodes.BMP_MSG_TYPE_ROUTE_MIRRORING: 'route mirroring',
BMPCodes.BMP_MSG_TYPE_ROUTE_POLICY: 'route policy',
BMPCodes.BMP_MSG_TYPE_INITIATION: "initiation",
BMPCodes.BMP_MSG_TYPE_PEER_DOWN_NOTIFICATION: "peer down notification",
BMPCodes.BMP_MSG_TYPE_PEER_UP_NOTIFICATION: "peer up notification",
BMPCodes.BMP_MSG_TYPE_ROUTE_MONITORING: "route monitoring",
BMPCodes.BMP_MSG_TYPE_STATISTICS_REPORT: "statistics report",
BMPCodes.BMP_MSG_TYPE_TERMINATION: "termination",
BMPCodes.BMP_MSG_TYPE_ROUTE_MIRRORING: "route mirroring",
BMPCodes.BMP_MSG_TYPE_ROUTE_POLICY: "route policy",
}

@classmethod
def register_msg_type(cls, msgtype):
def _register_type(subcls):
cls.TYPES[msgtype] = subcls
return subcls

return _register_type

@classmethod
Expand All @@ -179,15 +184,15 @@ def dissect_header(cls, data):
if len(data) < cls.MIN_LEN:
pass
else:
_version, _len, _type = struct.unpack(cls.HDR_STR, data[0:cls.MIN_LEN])
_version, _len, _type = struct.unpack(cls.HDR_STR, data[0 : cls.MIN_LEN])
return _version, _len, _type

@classmethod
def dissect(cls, data, log_file=None):
global SEQ
version, msglen, msgtype = cls.dissect_header(data)

msg_data = data[cls.MIN_LEN:msglen]
msg_data = data[cls.MIN_LEN : msglen]
data = data[msglen:]

if version != BMPCodes.VERSION:
Expand All @@ -208,7 +213,7 @@ def dissect(cls, data, log_file=None):
return data


#------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
class BMPPerPeerMessage:
"""
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
Expand All @@ -229,68 +234,71 @@ class BMPPerPeerMessage:
| Timestamp (microseconds) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""
PEER_UNPACK_STR = '!BB8s16sI4sII'

PEER_UNPACK_STR = "!BB8s16sI4sII"
PEER_TYPE_STR = {
BMPCodes.BMP_PEER_GLOBAL_INSTANCE: 'global instance',
BMPCodes.BMP_PEER_RD_INSTANCE: 'route distinguisher instance',
BMPCodes.BMP_PEER_LOCAL_INSTANCE: 'local instance',
BMPCodes.BMP_PEER_LOC_RIB_INSTANCE: 'loc-rib instance',
BMPCodes.BMP_PEER_GLOBAL_INSTANCE: "global instance",
BMPCodes.BMP_PEER_RD_INSTANCE: "route distinguisher instance",
BMPCodes.BMP_PEER_LOCAL_INSTANCE: "local instance",
BMPCodes.BMP_PEER_LOC_RIB_INSTANCE: "loc-rib instance",
}

@classmethod
def dissect(cls, data):
(peer_type,
peer_flags,
peer_distinguisher,
peer_address,
peer_asn,
peer_bgp_id,
timestamp_secs,
timestamp_microsecs) = struct.unpack_from(cls.PEER_UNPACK_STR, data)

msg = {'peer_type': cls.PEER_TYPE_STR[peer_type]}
(
peer_type,
peer_flags,
peer_distinguisher,
peer_address,
peer_asn,
peer_bgp_id,
timestamp_secs,
timestamp_microsecs,
) = struct.unpack_from(cls.PEER_UNPACK_STR, data)

msg = {"peer_type": cls.PEER_TYPE_STR[peer_type]}

if peer_type == 0x03:
msg['is_filtered'] = bool(peer_flags & IS_FILTERED)
msg['policy'] = 'loc-rib'
msg["is_filtered"] = bool(peer_flags & IS_FILTERED)
msg["policy"] = "loc-rib"
else:
# peer_flags = 0x0000 0000
# ipv6, post-policy, as-path, adj-rib-out, reserverdx4
is_adj_rib_out = bool(peer_flags & IS_ADJ_RIB_OUT)
is_as_path = bool(peer_flags & IS_AS_PATH)
is_post_policy = bool(peer_flags & IS_POST_POLICY)
is_ipv6 = bool(peer_flags & IS_IPV6)
msg['policy'] = 'post-policy' if is_post_policy else 'pre-policy'
msg['ipv6'] = is_ipv6
msg['peer_ip'] = bin2str_ipaddress(peer_address, is_ipv6)

msg["policy"] = "post-policy" if is_post_policy else "pre-policy"
msg["ipv6"] = is_ipv6
msg["peer_ip"] = bin2str_ipaddress(peer_address, is_ipv6)

peer_bgp_id = bin2str_ipaddress(peer_bgp_id)
timestamp = float(timestamp_secs) + timestamp_microsecs * (10 ** -6)

data = data[struct.calcsize(cls.PEER_UNPACK_STR):]
msg.update({
'peer_distinguisher': str(RouteDistinguisher(peer_distinguisher)),
'peer_asn': peer_asn,
'peer_bgp_id': peer_bgp_id,
'timestamp': str(datetime.datetime.fromtimestamp(timestamp)),
})
timestamp = float(timestamp_secs) + timestamp_microsecs * (10**-6)

data = data[struct.calcsize(cls.PEER_UNPACK_STR) :]
msg.update(
{
"peer_distinguisher": str(RouteDistinguisher(peer_distinguisher)),
"peer_asn": peer_asn,
"peer_bgp_id": peer_bgp_id,
"timestamp": str(datetime.datetime.fromtimestamp(timestamp)),
}
)

return data, msg


#------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
@BMPMsg.register_msg_type(BMPCodes.BMP_MSG_TYPE_ROUTE_MONITORING)
class BMPRouteMonitoring(BMPPerPeerMessage):

@classmethod
def dissect(cls, data):
data, peer_msg = super().dissect(data)
data, update_msg = BGPUpdate.dissect(data)
return {**peer_msg, **update_msg}


#------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
class BMPStatisticsReport:
"""
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
Expand All @@ -303,10 +311,11 @@ class BMPStatisticsReport:
~ ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""

pass


#------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
class BMPPeerDownNotification:
"""
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
Expand All @@ -316,10 +325,11 @@ class BMPPeerDownNotification:
| Data (present if Reason = 1, 2 or 3) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""

pass


#------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
@BMPMsg.register_msg_type(BMPCodes.BMP_MSG_TYPE_PEER_UP_NOTIFICATION)
class BMPPeerUpNotification(BMPPerPeerMessage):
"""
Expand All @@ -336,24 +346,23 @@ class BMPPeerUpNotification(BMPPerPeerMessage):
~ ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""
UNPACK_STR = '!16sHH'

UNPACK_STR = "!16sHH"
MIN_LEN = struct.calcsize(UNPACK_STR)
MSG_LEN = None

@classmethod
def dissect(cls, data):
data, peer_msg = super().dissect(data)

(local_addr,
local_port,
remote_port) = struct.unpack_from(cls.UNPACK_STR, data)
(local_addr, local_port, remote_port) = struct.unpack_from(cls.UNPACK_STR, data)

msg = {
**peer_msg,
**{
'local_ip': bin2str_ipaddress(local_addr, peer_msg.get('ipv6')),
'local_port': int(local_port),
'remote_port': int(remote_port),
"local_ip": bin2str_ipaddress(local_addr, peer_msg.get("ipv6")),
"local_port": int(local_port),
"remote_port": int(remote_port),
},
}

Expand All @@ -362,7 +371,7 @@ def dissect(cls, data):
return msg


#------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
@BMPMsg.register_msg_type(BMPCodes.BMP_MSG_TYPE_INITIATION)
class BMPInitiation:
"""
Expand All @@ -374,30 +383,31 @@ class BMPInitiation:
~ ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""
TLV_STR = '!HH'

TLV_STR = "!HH"
MIN_LEN = struct.calcsize(TLV_STR)
FIELD_TO_STR = {
BMPCodes.BMP_INIT_INFO_STRING: 'information',
BMPCodes.BMP_INIT_ADMIN_LABEL: 'admin_label',
BMPCodes.BMP_INIT_SYSTEM_DESCRIPTION: 'system_description',
BMPCodes.BMP_INIT_SYSTEM_NAME: 'system_name',
BMPCodes.BMP_INIT_VRF_TABLE_NAME: 'vrf_table_name',
BMPCodes.BMP_INIT_INFO_STRING: "information",
BMPCodes.BMP_INIT_ADMIN_LABEL: "admin_label",
BMPCodes.BMP_INIT_SYSTEM_DESCRIPTION: "system_description",
BMPCodes.BMP_INIT_SYSTEM_NAME: "system_name",
BMPCodes.BMP_INIT_VRF_TABLE_NAME: "vrf_table_name",
}

@classmethod
def dissect(cls, data):
msg = {}
while len(data) > cls.MIN_LEN:
_type, _len = struct.unpack_from(cls.TLV_STR, data[0:cls.MIN_LEN])
_value = data[cls.MIN_LEN: cls.MIN_LEN + _len].decode()
_type, _len = struct.unpack_from(cls.TLV_STR, data[0 : cls.MIN_LEN])
_value = data[cls.MIN_LEN : cls.MIN_LEN + _len].decode()

msg[cls.FIELD_TO_STR[_type]] = _value
data = data[cls.MIN_LEN + _len:]
data = data[cls.MIN_LEN + _len :]

return msg


#------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
class BMPTermination:
"""
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
Expand All @@ -408,14 +418,15 @@ class BMPTermination:
~ ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""

pass


#------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
class BMPRouteMirroring:
pass


#------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
class BMPRoutePolicy:
pass
10 changes: 7 additions & 3 deletions tests/topotests/lib/topogen.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ def exacmd_version_ok(exacmd):
return False
version = m.group(1)
if topotest.version_cmp(version, "4.2.11") < 0:
logging.debug("found exabgp version < 4.2.11 in %s will keep looking", exacmd)
logging.debug(
"found exabgp version < 4.2.11 in %s will keep looking", exacmd
)
return False
logger.info("Using ExaBGP version %s in %s", version, exacmd)
return True
Expand Down Expand Up @@ -1254,9 +1256,11 @@ def __str__(self):
return gear

def start(self, log_file=None):
log_arg = "-l {}".format(log_file) if log_file else ""
log_arg = "-l {}".format(log_file) if log_file else ""
self.run(
"{}/bmp_collector/bmpserver -a {} -p {} {}&".format(CWD, self.ip, self.port, log_arg),
"{}/bmp_collector/bmpserver -a {} -p {} {}&".format(
CWD, self.ip, self.port, log_arg
),
stdout=None,
)

Expand Down

0 comments on commit 9208e16

Please sign in to comment.