Add a script to generate up-to-date NDN testbed topologies for Mini-NDN
Change-Id: I9686c65fe2f38fbc980c5fb54d876ebb3d9e7ede
diff --git a/util/testbed_topo_generator.py b/util/testbed_topo_generator.py
new file mode 100755
index 0000000..4730587
--- /dev/null
+++ b/util/testbed_topo_generator.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python3
+# -*- Mode:bash; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2020, The University of Memphis,
+# Arizona Board of Regents,
+# Regents of the University of California.
+#
+# This file is part of Mini-NDN.
+# See AUTHORS.md for a complete list of Mini-NDN authors and contributors.
+#
+# Mini-NDN is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Mini-NDN is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Mini-NDN, e.g., in COPYING.md file.
+# If not, see <http://www.gnu.org/licenses/>.
+
+# This script generates a testbed topology based on current data. Note
+# that this topology is memory intensive and can have issues on lower specced
+# systems due to its size.
+# To use, run with python3
+
+import argparse
+import datetime
+import json
+import logging
+from os import path
+from urllib.request import urlopen
+
+def testbedGen():
+ """Returns a string with the Mini-NDN topology version of the testbed"""
+ topology = None
+ connections = None
+ hosts = []
+ links = []
+ try:
+ with urlopen("https://ndndemo.arl.wustl.edu/testbedNodes.json") as url:
+ topology = json.loads(url.read().decode())
+ with urlopen("https://ndndemo.arl.wustl.edu/links.json") as url:
+ connections = json.loads(url.read().decode())
+ except:
+ logging.error("Failed to retrieve testbed info from WUSTL servers")
+ if __name__ == '__main__':
+ from sys import exit
+ exit(1)
+ raise
+
+ logging.info("Generating testbed topology...")
+ for node_name in topology:
+ node = topology[node_name]
+ if node['neighbors']:
+ radius = node['hr_radius']
+ angle = node['hr_angle']
+ host_str = "{}: _ radius={} angle={}\n".format(node_name, radius, angle)
+ hosts.append(host_str)
+ logging.debug("Add node: {}".format(host_str)[:-1])
+ else:
+ # A node without neighbors shouldn't be considered part of the testbed
+ # for testing purposes
+ logging.debug("Node {} has no neighbors, passing...".format(node_name))
+ for link in connections:
+ node1 = link['start']
+ node2 = link['end']
+ # This value is equivalent to RTT in the testbed
+ delay = link['nlsr_weight']
+ link_str = "{}:{} delay={}ms\n".format(node1, node2, delay)
+ logging.debug("Add link: {}".format(link_str)[:-1])
+ links.append(link_str.strip())
+
+ topo_str = "[nodes]\n"
+ for host in hosts:
+ topo_str = topo_str + host
+ topo_str = topo_str + "[links]\n"
+ for link in links:
+ topo_str = topo_str + link
+ return topo_str.strip()
+
+if __name__ == '__main__':
+ default_path = path.dirname(__file__) + '/../topologies/testbed{}.conf'.format(str(datetime.date.today()))
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-l", "--log_level", help="Log level to output", default="info", choices=["debug", "info", "warning", "error"])
+ parser.add_argument("-o", "--output_dir", help="File output location", default=default_path)
+ args = parser.parse_args()
+ log_level = getattr(logging, args.log_level.upper())
+ topologies_path = path.abspath(args.output_dir)
+ logging.basicConfig(format="%(levelname)s: %(message)s", level=log_level)
+ topo = testbedGen()
+ logging.info("Testbed generated, writing to file...")
+ with open(topologies_path, "w") as file:
+ file.writelines(topo)
+ logging.info("Finished")
\ No newline at end of file