summaryrefslogtreecommitdiffstats
path: root/tests/topotests/lib
diff options
context:
space:
mode:
Diffstat (limited to 'tests/topotests/lib')
-rw-r--r--tests/topotests/lib/bgp.py19
-rw-r--r--tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py6
-rwxr-xr-xtests/topotests/lib/bmp_collector/bmpserver.py (renamed from tests/topotests/lib/bmp_collector/bmpserver)84
-rw-r--r--tests/topotests/lib/snmptest.py6
-rw-r--r--tests/topotests/lib/topogen.py7
5 files changed, 114 insertions, 8 deletions
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index bcd1c7481..329c2b54f 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -5638,3 +5638,22 @@ def configure_bgp_soft_configuration(tgen, dut, neighbor_dict, direction):
)
)
return True
+
+
+def bgp_configure_prefixes(router, asn, safi, prefixes, vrf=None, update=True):
+ """
+ Configure the bgp prefixes.
+ """
+ withdraw = "no " if not update else ""
+ vrf = " vrf {}".format(vrf) if vrf else ""
+ for p in prefixes:
+ ip = ipaddress.ip_network(p)
+ cmd = [
+ "conf t\n",
+ f"router bgp {asn}{vrf}\n"
+ f"address-family ipv{ip.version} {safi}\n"
+ f"{withdraw}network {ip}\n".format(withdraw, ip),
+ "exit-address-family\n",
+ ]
+ logger.debug(f"setting prefix: ipv{ip.version} {safi} {ip}")
+ router.vtysh_cmd("".join(cmd))
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 3694cb4fe..ca49c405d 100644
--- a/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py
+++ b/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py
@@ -72,6 +72,12 @@ class PathAttribute:
if path_attr_cls == cls.UNKNOWN_ATTR:
return data[offset + attr_len :], None
+ # RFC1771, 4.3 UPDATE Message Format
+ # The path segment length is a 1-octet long field containing
+ # the number of ASs in the path segment value field.
+ if type_code == PATH_ATTR_TYPE_AS_PATH and attr_len == 0:
+ return data[offset:], path_attr_cls.dissect(data[offset : offset + 2])
+
return data[offset + attr_len :], path_attr_cls.dissect(
data[offset : offset + attr_len]
)
diff --git a/tests/topotests/lib/bmp_collector/bmpserver b/tests/topotests/lib/bmp_collector/bmpserver.py
index 56d85fc74..c42c38756 100755
--- a/tests/topotests/lib/bmp_collector/bmpserver
+++ b/tests/topotests/lib/bmp_collector/bmpserver.py
@@ -5,8 +5,11 @@
# Authored by Farid Mihoub <farid.mihoub@6wind.com>
#
import argparse
+import errno
+import logging
# XXX: something more reliable should be used "Twisted" a great choice.
+import os
import signal
import socket
import sys
@@ -20,11 +23,11 @@ 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")
+parser.add_argument("-r", "--pidfile", type=str, default="/var/run/bmp.pid")
def handle_signal(signum, frame):
@@ -40,6 +43,74 @@ def timestamp_print(message, file=sys.stderr):
print(f"[{current_time}] {message}", file=file)
+def check_pid(pid):
+ if pid < 0: # user input error
+ return False
+ if pid == 0: # all processes
+ return False
+ try:
+ os.kill(pid, 0)
+ return True
+ except OSError as err:
+ if err.errno == errno.EPERM: # a process we were denied access to
+ return True
+ if err.errno == errno.ESRCH: # No such process
+ return False
+ # should never happen
+ return False
+
+
+def savepid():
+ ownid = os.getpid()
+
+ flags = os.O_CREAT | os.O_EXCL | os.O_WRONLY
+ mode = ((os.R_OK | os.W_OK) << 6) | (os.R_OK << 3) | os.R_OK
+
+ try:
+ fd = os.open(pid_file, flags, mode)
+ except OSError:
+ try:
+ pid = open(pid_file, "r").readline().strip()
+ if check_pid(int(pid)):
+ timestamp_print(
+ "PID file already exists and program still running %s\n" % pid_file
+ )
+ return False
+ else:
+ # If pid is not running, reopen file without O_EXCL
+ fd = os.open(pid_file, flags ^ os.O_EXCL, mode)
+ except (OSError, IOError, ValueError):
+ timestamp_print(
+ "issue accessing PID file %s (most likely permission or ownership)\n"
+ % pid_file
+ )
+ return False
+
+ try:
+ f = os.fdopen(fd, "w")
+ line = "%d\n" % ownid
+ f.write(line)
+ f.close()
+ saved_pid = True
+ except IOError:
+ timestamp_print("Can not create PID file %s\n" % pid_file)
+ return False
+ timestamp_print("Created PID file %s with value %d\n" % (pid_file, ownid))
+ return True
+
+
+def removepid():
+ try:
+ os.remove(pid_file)
+ except OSError as exc:
+ if exc.errno == errno.ENOENT:
+ pass
+ else:
+ timestamp_print("Can not remove PID file %s\n" % pid_file)
+ return
+ timestamp_print("Removed PID file %s\n" % pid_file)
+
+
def main():
global shutdown
@@ -51,8 +122,13 @@ def main():
ADDRESS, PORT = args.address, args.port
LOG_FILE = args.logfile
+ global pid_file
+ pid_file = args.pidfile
+
timestamp_print(f"Starting bmpserver on {args.address}:{args.port}")
+ savepid()
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
@@ -80,9 +156,7 @@ def main():
while len(data) > BMPMsg.MIN_LEN:
data = BMPMsg.dissect(data, log_file=LOG_FILE)
- timestamp_print(
- f"Finished dissecting data from {client_address}"
- )
+ timestamp_print(f"Finished dissecting data from {client_address}")
except Exception as e:
timestamp_print(f"{e}")
@@ -99,6 +173,7 @@ def main():
timestamp_print(f"{e}")
finally:
timestamp_print(f"Server shutting down on {ADDRESS}:{PORT}")
+ removepid()
if __name__ == "__main__":
@@ -106,4 +181,5 @@ if __name__ == "__main__":
sys.exit(main())
except KeyboardInterrupt:
logging.info("BMP server was interrupted and is shutting down.")
+ removepid()
sys.exit(0)
diff --git a/tests/topotests/lib/snmptest.py b/tests/topotests/lib/snmptest.py
index 8e2e76d15..6d586cee5 100644
--- a/tests/topotests/lib/snmptest.py
+++ b/tests/topotests/lib/snmptest.py
@@ -104,12 +104,16 @@ class SnmpTester(object):
return None
return self._get_snmp_value(result)
- def walk(self, oid):
+ def walk(self, oid, raw=False):
cmd = "snmpwalk {0} {1} 2>&1 | grep -v SNMPv2-PDU".format(
self._snmp_config(), oid
)
result = self.router.cmd(cmd)
+
+ if raw:
+ return result
+
return self._parse_multiline(result)
def parse_notif_ipv4(self, notif):
diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py
index 4d7c56423..0a9a84a4b 100644
--- a/tests/topotests/lib/topogen.py
+++ b/tests/topotests/lib/topogen.py
@@ -1293,18 +1293,19 @@ class TopoBMPCollector(TopoHost):
log_err = os.path.join(log_dir, "bmpserver.log")
log_arg = "-l {}".format(log_file) if log_file else ""
+ self.pid_file = os.path.join(log_dir, "bmpserver.pid")
with open(log_err, "w") as err:
self.run(
- "{}/bmp_collector/bmpserver -a {} -p {} {}&".format(
- CWD, self.ip, self.port, log_arg
+ "{}/bmp_collector/bmpserver.py -a {} -p {} -r {} {}&".format(
+ CWD, self.ip, self.port, self.pid_file, log_arg
),
stdout=None,
stderr=err,
)
def stop(self):
- self.run("pkill -f bmpserver")
+ self.run(f"kill $(cat {self.pid_file}")
return ""