Merge pull request #17207 from louis-6wind/bmpserver-log

tests: add bmpserver logging
This commit is contained in:
Donatas Abraitis 2024-10-25 09:58:57 +03:00 committed by GitHub
commit 2606f84b31
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 109 additions and 26 deletions

View File

@ -10,11 +10,13 @@ BMP main module:
- XXX: more bmp messages types to dissect - XXX: more bmp messages types to dissect
- XXX: complete bgp message dissection - XXX: complete bgp message dissection
""" """
import datetime
import ipaddress import ipaddress
import json import json
import os import os
import struct import struct
import sys
from datetime import datetime
from bgp.update import BGPUpdate from bgp.update import BGPUpdate
from bgp.update.rd import RouteDistinguisher from bgp.update.rd import RouteDistinguisher
@ -48,6 +50,13 @@ def log2file(logs, log_file):
f.write(json.dumps(logs) + "\n") f.write(json.dumps(logs) + "\n")
def timestamp_print(message, file=sys.stderr):
"""Helper function to timestamp_print messages with timestamps."""
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"[{current_time}] {message}", file=file)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
class BMPCodes: class BMPCodes:
""" """
@ -196,14 +205,18 @@ class BMPMsg:
data = data[msglen:] data = data[msglen:]
if version != BMPCodes.VERSION: if version != BMPCodes.VERSION:
# XXX: log something timestamp_print(
f"Expected BMP version {BMPCodes.VERSION} but got version {version}."
)
return data return data
msg_cls = cls.lookup_msg_type(msgtype) msg_cls = cls.lookup_msg_type(msgtype)
if msg_cls == cls.UNKNOWN_TYPE: if msg_cls == cls.UNKNOWN_TYPE:
# XXX: log something timestamp_print(f"Got unknown message type ")
return data return data
timestamp_print(f"Got message type: {msg_cls}")
msg_cls.MSG_LEN = msglen - cls.MIN_LEN msg_cls.MSG_LEN = msglen - cls.MIN_LEN
logs = msg_cls.dissect(msg_data) logs = msg_cls.dissect(msg_data)
logs["seq"] = SEQ logs["seq"] = SEQ
@ -281,7 +294,7 @@ class BMPPerPeerMessage:
"peer_distinguisher": str(RouteDistinguisher(peer_distinguisher)), "peer_distinguisher": str(RouteDistinguisher(peer_distinguisher)),
"peer_asn": peer_asn, "peer_asn": peer_asn,
"peer_bgp_id": peer_bgp_id, "peer_bgp_id": peer_bgp_id,
"timestamp": str(datetime.datetime.fromtimestamp(timestamp)), "timestamp": str(datetime.fromtimestamp(timestamp)),
} }
) )

View File

@ -5,43 +5,105 @@
# Authored by Farid Mihoub <farid.mihoub@6wind.com> # Authored by Farid Mihoub <farid.mihoub@6wind.com>
# #
import argparse import argparse
# XXX: something more reliable should be used "Twisted" a great choice. # XXX: something more reliable should be used "Twisted" a great choice.
import signal
import socket import socket
import sys import sys
from datetime import datetime
from bmp import BMPMsg from bmp import BMPMsg
BGP_MAX_SIZE = 4096 BGP_MAX_SIZE = 4096
# Global variable to track shutdown signal
shutdown = False
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("-a", "--address", type=str, default="0.0.0.0") parser.add_argument("-a", "--address", type=str, default="0.0.0.0")
parser.add_argument("-p", "--port", type=int, default=1789) parser.add_argument("-p", "--port", type=int, default=1789)
parser.add_argument("-l", "--logfile", type=str, default="/var/log/bmp.log") parser.add_argument("-l", "--logfile", type=str, default="/var/log/bmp.log")
def handle_signal(signum, frame):
global shutdown
timestamp_print(f"Received signal {signum}, shutting down.")
shutdown = True
def timestamp_print(message, file=sys.stderr):
"""Helper function to timestamp_print messages with timestamps."""
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"[{current_time}] {message}", file=file)
def main(): def main():
global shutdown
# Set up signal handling for SIGTERM and SIGINT
signal.signal(signal.SIGTERM, handle_signal)
signal.signal(signal.SIGINT, handle_signal)
args = parser.parse_args() args = parser.parse_args()
ADDRESS, PORT = args.address, args.port ADDRESS, PORT = args.address, args.port
LOG_FILE = args.logfile LOG_FILE = args.logfile
timestamp_print(f"Starting bmpserver on {args.address}:{args.port}")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
s.bind((ADDRESS, PORT)) s.bind((ADDRESS, PORT))
s.listen() s.listen()
connection, _ = s.accept() timestamp_print(f"Listening on TCP {args.address}:{args.port}")
connection, client_address = s.accept()
timestamp_print(f"TCP session opened from {client_address}")
try: try:
while True: while not shutdown: # Check for shutdown signal
data = connection.recv(BGP_MAX_SIZE) data = connection.recv(BGP_MAX_SIZE)
if shutdown:
break
if not data:
# connection closed
break
timestamp_print(
f"Data received from {client_address}: length {len(data)}"
)
while len(data) > BMPMsg.MIN_LEN: while len(data) > BMPMsg.MIN_LEN:
data = BMPMsg.dissect(data, log_file=LOG_FILE) data = BMPMsg.dissect(data, log_file=LOG_FILE)
timestamp_print(
f"Finished dissecting data from {client_address}"
)
except Exception as e: except Exception as e:
# XXX: do something timestamp_print(f"{e}")
pass pass
except KeyboardInterrupt: except KeyboardInterrupt:
# XXX: do something timestamp_print(f"Got Keyboard Interrupt.")
pass pass
finally: finally:
timestamp_print(f"TCP session closed with {client_address}")
connection.close() connection.close()
except socket.error as sock_err:
timestamp_print(f"Socket error: {e}")
except Exception as e:
timestamp_print(f"{e}")
finally:
timestamp_print(f"Server shutting down on {ADDRESS}:{PORT}")
if __name__ == "__main__": if __name__ == "__main__":
try:
sys.exit(main()) sys.exit(main())
except KeyboardInterrupt:
logging.info("BMP server was interrupted and is shutting down.")
sys.exit(0)

View File

@ -1273,16 +1273,24 @@ class TopoBMPCollector(TopoHost):
return gear return gear
def start(self, log_file=None): def start(self, log_file=None):
log_dir = os.path.join(self.logdir, self.name)
self.run("chmod 777 {}".format(log_dir))
log_err = os.path.join(log_dir, "bmpserver.log")
log_arg = "-l {}".format(log_file) if log_file else "" log_arg = "-l {}".format(log_file) if log_file else ""
with open(log_err, "w") as err:
self.run( self.run(
"{}/bmp_collector/bmpserver -a {} -p {} {}&".format( "{}/bmp_collector/bmpserver -a {} -p {} {}&".format(
CWD, self.ip, self.port, log_arg CWD, self.ip, self.port, log_arg
), ),
stdout=None, stdout=None,
stderr=err,
) )
def stop(self): def stop(self):
self.run("pkill -9 -f bmpserver") self.run("pkill -f bmpserver")
return "" return ""