Skip to content

Commit

Permalink
Merge pull request #17207 from louis-6wind/bmpserver-log
Browse files Browse the repository at this point in the history
tests: add bmpserver logging
  • Loading branch information
ton31337 authored Oct 25, 2024
2 parents ba3836c + c8ed08b commit 2606f84
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 26 deletions.
21 changes: 17 additions & 4 deletions tests/topotests/lib/bmp_collector/bmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
- XXX: more bmp messages types to dissect
- XXX: complete bgp message dissection
"""
import datetime
import ipaddress
import json
import os
import struct
import sys

from datetime import datetime

from bgp.update import BGPUpdate
from bgp.update.rd import RouteDistinguisher
Expand Down Expand Up @@ -48,6 +50,13 @@ def log2file(logs, log_file):
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:
"""
Expand Down Expand Up @@ -196,14 +205,18 @@ def dissect(cls, data, log_file=None):
data = data[msglen:]

if version != BMPCodes.VERSION:
# XXX: log something
timestamp_print(
f"Expected BMP version {BMPCodes.VERSION} but got version {version}."
)
return data

msg_cls = cls.lookup_msg_type(msgtype)
if msg_cls == cls.UNKNOWN_TYPE:
# XXX: log something
timestamp_print(f"Got unknown message type ")
return data

timestamp_print(f"Got message type: {msg_cls}")

msg_cls.MSG_LEN = msglen - cls.MIN_LEN
logs = msg_cls.dissect(msg_data)
logs["seq"] = SEQ
Expand Down Expand Up @@ -281,7 +294,7 @@ def dissect(cls, data):
"peer_distinguisher": str(RouteDistinguisher(peer_distinguisher)),
"peer_asn": peer_asn,
"peer_bgp_id": peer_bgp_id,
"timestamp": str(datetime.datetime.fromtimestamp(timestamp)),
"timestamp": str(datetime.fromtimestamp(timestamp)),
}
)

Expand Down
92 changes: 77 additions & 15 deletions tests/topotests/lib/bmp_collector/bmpserver
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,105 @@
# Authored by Farid Mihoub <farid.mihoub@6wind.com>
#
import argparse

# XXX: something more reliable should be used "Twisted" a great choice.
import signal
import socket
import sys

from datetime import datetime

from bmp import BMPMsg

BGP_MAX_SIZE = 4096

# Global variable to track shutdown signal
shutdown = False


parser = argparse.ArgumentParser()
parser.add_argument("-a", "--address", type=str, default="0.0.0.0")
parser.add_argument("-p", "--port", type=int, default=1789)
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():
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()
ADDRESS, PORT = args.address, args.port
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:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((ADDRESS, PORT))
s.listen()
connection, _ = s.accept()

try:
while True:
data = connection.recv(BGP_MAX_SIZE)
while len(data) > BMPMsg.MIN_LEN:
data = BMPMsg.dissect(data, log_file=LOG_FILE)
s.bind((ADDRESS, PORT))
s.listen()
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:
while not shutdown: # Check for shutdown signal
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:
data = BMPMsg.dissect(data, log_file=LOG_FILE)

timestamp_print(
f"Finished dissecting data from {client_address}"
)

except Exception as e:
timestamp_print(f"{e}")
pass
except KeyboardInterrupt:
timestamp_print(f"Got Keyboard Interrupt.")
pass
finally:
timestamp_print(f"TCP session closed with {client_address}")
connection.close()
except socket.error as sock_err:
timestamp_print(f"Socket error: {e}")
except Exception as e:
# XXX: do something
pass
except KeyboardInterrupt:
# XXX: do something
pass
timestamp_print(f"{e}")
finally:
connection.close()
timestamp_print(f"Server shutting down on {ADDRESS}:{PORT}")


if __name__ == "__main__":
sys.exit(main())
try:
sys.exit(main())
except KeyboardInterrupt:
logging.info("BMP server was interrupted and is shutting down.")
sys.exit(0)
22 changes: 15 additions & 7 deletions tests/topotests/lib/topogen.py
Original file line number Diff line number Diff line change
Expand Up @@ -1273,16 +1273,24 @@ def __str__(self):
return gear

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 ""
self.run(
"{}/bmp_collector/bmpserver -a {} -p {} {}&".format(
CWD, self.ip, self.port, log_arg
),
stdout=None,
)

with open(log_err, "w") as err:
self.run(
"{}/bmp_collector/bmpserver -a {} -p {} {}&".format(
CWD, self.ip, self.port, log_arg
),
stdout=None,
stderr=err,
)

def stop(self):
self.run("pkill -9 -f bmpserver")
self.run("pkill -f bmpserver")
return ""


Expand Down

0 comments on commit 2606f84

Please sign in to comment.