**breaking** mini-ndn: re-design
refs: #5062
Everything is now done through examples like Mininet.
bin/minindn no longer provided as a binary installed in the system
bin/minindnedit GUI: will no longer be maintained
Remove cluster edition, will be re-introduced later
Change-Id: Id4ef137cb2a04d1b0dd24d01941757363bbf7d26
diff --git a/.gitignore b/.gitignore
index 1ea55fa..e56d449 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,24 +1,19 @@
+# Python
build
-crypto
-ChronoSync
dist
-doc/html
-doc/latex
-.DS_Store
-examples
-infoedit
-jndn
Mini_NDN.egg-info
-mininet
-NFD
-NLSR
-ndn-cpp
-ndn-cxx
-ndn-js
-ndn-tools
-openflow
-PyNDN2
-PSync
-util
-.vagrant
*.pyc
+
+# Docs
+docs/html
+docs/latex
+docs/_build
+
+# Misc
+.DS_Store
+mininet
+ndn-src
+openflow
+
+# Vagrant
+.vagrant
diff --git a/INSTALL.md b/INSTALL.md
deleted file mode 100644
index f263972..0000000
--- a/INSTALL.md
+++ /dev/null
@@ -1,92 +0,0 @@
-Mini-NDN Installation Instructions
-================================
-
-### What equipment will I need?
-
-For this guide, you will need a laptop/desktop with a recent version
-of a Linux distro such as Ubuntu or any of its variants. Fedora is not
-officially supported but has also been reported to work for some
-users. For this guide, the _Ubuntu 18.04 LTS_ release was used.
-Also, note that you'll need administrative privileges in order to
-download and install extra packages and also to execute **Mini-NDN**.
-
-### Installing **Mini-NDN**
-
-NOTE: Mini-NDN, while providing a high level of emulation of hosts,
-requires programs to be installed onto your computer. It will not work
-if they are not installed. If you do not want NDN software installed
-onto your computer, you can use a virtual machine, which can be quite
-simply set up with the provided vagrantfile.
-
-If you have all the dependencies (see sections below) installed simply clone this repository and run:
-
- ./install.sh -i
-
-else if you don't have the dependencies, the following command will install them from source along with Mini-NDN:
-
- ./install.sh -a
-
-If you want to install the dependencies manually or from the Named Data PPA, follow the instructions below:
-
-### Installing NDN
-
-Each node in **Mini-NDN** will run the official implementation of NDN installed on your system. The following dependencies are needed:
-
-Mini-NDN uses NFD, NLSR, and ndn-tools.
-
-To install NFD:
-https://named-data.net/doc/NFD/current/INSTALL.html
-
-To install NLSR:
-https://named-data.net/doc/NLSR/current/INSTALL.html
-
-To install ndn-tools:
-https://github.com/named-data/ndn-tools
-
-Note that all three of these can be installed from the Named Data PPA. Instructions for setting it up can
-be found in the NFD insallation instructions. Note that PPA and installs from source **cannot** be mixed.
-
-###Special Instructions for PPA Installs
-
-If you are using a custom nfd.conf file in an experiment, you should place it in /usr/local/etc/ndn/
-rather than /etc/ndn/. This is to avoid a bug from the default configuration file for the PPA, which
-is incompatiable with Mini-NDN.
-
-### Installing Mininet
-
-**Mini-NDN** is based on Mininet. To install Mininet:
-
-First, clone Mininet from github:
-
- git clone --depth 1 https://github.com/mininet/mininet.git
-
-After Mininet source is on your system, run the following command to
-install Mininet core dependencies and Open vSwitch:
-
- ./util/install.sh -nv
-
-To check if Mininet is working correctly, run this test:
-
- sudo mn --test pingall
-
-This will print out a series of statements that show the test setup
-and the results of the test. Look for `Results:` two-thirds of the way
-down where it will indicate the percentage of dropped packets.
-Your results should show "0% dropped (2/2 received)".
-
-### Installing Infoedit
-
-Infoedit is used to edit configuration files such as NFD configuration
-file.
-
-To install infoedit:
-https://github.com/NDN-Routing/infoedit
-
-### Verification
-
-You can use these steps to verify your installation:
-
-1. Issue the command: `sudo minindn --experiment=pingall --nPings=50`
-2. When the `mini-ndn>` CLI prompt appears, the experiment has finished. On the Mini-NDN CLI, issue the command `exit` to exit the experiment.
-3. Issue the command: `grep -c content /tmp/minindn/*/ping-data/*.txt`. Each file should report a count of 50.
-4. Issue the command: `grep -c timeout /tmp/minindn/*/ping-data/*.txt`. Each file should report a count of 0.
\ No newline at end of file
diff --git a/README.md b/README.md
index 146d953..5a1d007 100644
--- a/README.md
+++ b/README.md
@@ -7,10 +7,9 @@
### What is Mini-NDN?
Mini-NDN is a lightweight networking emulation tool that enables testing, experimentation, and
-research on the NDN platform. Based on [Mini-CCNx](https://github.com/chesteve/mn-ccnx) which
-is a fork of [Mininet](https://github.com/mininet/mininet), Mini-NDN uses the NDN libraries,
-NFD, NLSR, and tools released by the [NDN project](http://named-data.net/codebase/platform/)
-to emulate an NDN network on a single system.
+research on the NDN platform based on [Mininet](https://github.com/mininet/mininet).
+Mini-NDN uses the NDN libraries, NFD, NLSR, and tools released by the
+[NDN project](http://named-data.net/codebase/platform/) to emulate an NDN network on a single system.
Mini-NDN is open and free software licensed under the GPL 3.0 license. Mini-NDN is free to all
users and developers. For more information about licensing details and limitations,
@@ -25,9 +24,9 @@
### Documentation
-* [Installation](INSTALL.md)
-* [Getting Started](docs/GETTING-STARTED.md)
-* [Mini-NDN Edit](docs/GUI.md)
-* [Running Experiments](docs/EXPERIMENTS.md)
-* [Mini-NDN Redmine](http://redmine.named-data.net/projects/mini-ndn)
-* [Contributor's Guide](https://github.com/named-data/NFD/blob/master/CONTRIBUTING.md)
+Please refer to http://minindn.memphis.edu/ or [docs/index.rst](docs/index.rst) for installation, usage, and other documentation.
+The documentation can be built using:
+
+ ./install.sh -d
+
+and is available under `docs/_build/html`.
diff --git a/Vagrantfile b/Vagrantfile
index 6083675..f3bb364 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -2,18 +2,27 @@
# vi: set ft=ruby :
$script = <<SCRIPT
+ln -s /vagrant /home/vagrant/mini-ndn
-git clone --depth 1 https://github.com/named-data/mini-ndn.git
-cd mini-ndn
+# Check if install.sh is present or someone just copied the Vagrantfile directly
+if [[ -f /home/vagrant/mini-ndn/install.sh ]]; then
+ pushd /home/vagrant/mini-ndn
+else
+ # Remove the symlink
+ rm /home/vagrant/mini-ndn
+ git clone --depth 1 https://github.com/named-data/mini-ndn.git
+ pushd mini-ndn
+fi
./install.sh -a
+
SCRIPT
Vagrant.configure(2) do |config|
- config.vm.box = "bento/ubuntu-16.04"
+ config.vm.box = "ubuntu/bionic64"
config.vm.provision "shell", privileged: false, inline: $script
config.vm.provider "virtualbox" do |vb|
vb.name = "mini-ndn_box"
- vb.memory = 2000
- vb.cpus = 2
+ vb.memory = 4096
+ vb.cpus = 4
end
end
diff --git a/bin/minindn b/bin/minindn
deleted file mode 100755
index e0b4446..0000000
--- a/bin/minindn
+++ /dev/null
@@ -1,462 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2019, 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 file incorporates work covered by the following copyright and
-# permission notice:
-#
-# Mininet 2.3.0d1 License
-#
-# Copyright (c) 2013-2016 Open Networking Laboratory
-# Copyright (c) 2009-2012 Bob Lantz and The Board of Trustees of
-# The Leland Stanford Junior University
-#
-# Original authors: Bob Lantz and Brandon Heller
-#
-# We are making Mininet available for public use and benefit with the
-# expectation that others will use, modify and enhance the Software and
-# contribute those enhancements back to the community. However, since we
-# would like to make the Software available for broadest use, with as few
-# restrictions as possible permission is hereby granted, free of charge, to
-# any person obtaining a copy of this Software to deal in the Software
-# under the copyrights without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# The name and trademarks of copyright holder(s) may NOT be used in
-# advertising or publicity pertaining to the Software or any derivatives
-# without specific, written prior permission.
-
-from mininet.topo import Topo
-from mininet.net import Mininet
-from mininet.log import setLogLevel, output, info, error, warn
-from mininet.link import TCLink
-from mininet.util import ipStr, ipParse
-
-from mininet.examples.cluster import MininetCluster, RoundRobinPlacer, ClusterCleanup
-from mininet.examples.clustercli import ClusterCLI
-
-from ndn import ExperimentManager
-from ndn.experiments.experiment import Experiment
-from ndn.ndn_host import NdnHost, CpuLimitedNdnHost, RemoteNdnHost
-from ndn.conf_parser import parse_hosts, parse_switches, parse_links
-from ndn.remote_ndn_link import RemoteNdnLink, RemoteGRENdnLink
-from ndn.placer import GuidedPlacer, PopulatePlacement
-from ndn.nfd import Nfd
-from ndn.util import ssh, scp, MiniNDNCLI, ProgramOptions
-
-import os.path, time
-import shutil
-import argparse
-import datetime
-from os.path import expanduser
-import sys
-import signal
-from subprocess import call
-import glob
-from functools import partial
-import re
-
-try:
- import argcomplete
-except ImportError:
- pass
-
-VERSION_NUMBER = "0.4.0"
-INSTALL_DIR='/usr/local/etc/mini-ndn/'
-
-class PrintExperimentNames(argparse.Action):
- def __init__(self, option_strings, dest, nargs=0, help=None):
- super(PrintExperimentNames, self).__init__(option_strings=option_strings, dest=dest, nargs=nargs, help=help)
-
- def __call__(self, parser, namespace, values, option_string=None):
- experimentNames = ExperimentManager.getExperimentNames()
-
- print("Mini-NDN experiments:")
- for experiment in experimentNames:
- print(" {}".format(experiment))
-
- sys.exit(0)
-
-def createResultsDir(resultDir, faces, rType):
- if faces == 0:
- faces = "all"
-
- routingChoice = "/{}/".format(rType)
-
- resultDir = "{}/{}/faces-{}".format(resultDir, routingChoice, faces)
- resultDir = os.path.abspath(resultDir)
-
- if not os.path.isdir(resultDir):
- os.makedirs(resultDir)
- else:
- warn("Results directory ({}) already exists!".format(resultDir))
- sys.exit(1)
-
- info("Results will be stored at: {}".format(resultDir))
- return resultDir
-
-def parse_args():
- parser = argparse.ArgumentParser(prog='minindn')
-
- # nargs='?' required here since optional argument
- parser.add_argument('tempfile', nargs='?', default=INSTALL_DIR + 'default-topology.conf',
- help="If no template_file is given, topologies/default-topology.conf (given sample file) will be used.")
-
- parser.add_argument("--ctime", type=int, default=60,
- help="Specify convergence time for the topology (Default: 60 seconds)")
-
- parser.add_argument("--experiment", choices=[experiment for experiment in ExperimentManager.getExperimentNames()],
- help="Runs the specified experiment")
-
- parser.add_argument("--faces", type=int, default=3,
- help="Specify number of max faces per prefix for NLSR 0-60")
-
- parser.add_argument("--routing", dest="routingType", default='link-state', choices=['link-state', 'hr', 'dry'],
- help="""choices for routing are 'link-state' for link state, 'hr' for hyperbolic, and 'dry'
- to test hyperbolic routing and compare with link state. Default is link-state.""")
-
- parser.add_argument("--no-nlsr", action="store_false", dest="isNlsrEnabled",
- help="Run mini-ndn without NLSR routing")
-
- parser.add_argument("--list-experiments", action=PrintExperimentNames,
- help="Lists the names of all available experiments")
-
- parser.add_argument("--no-cli", action="store_false", dest="isCliEnabled",
- help="Run experiments and exit without showing the command line interface")
-
- parser.add_argument("--nPings", type=int, default=300,
- help="Number of pings to perform between each node in the experiment")
-
- # store_true stores default value of False
- parser.add_argument("--nlsr-security", action="store_true", dest="nlsrSecurity",
- help="Enables NLSR security")
-
- parser.add_argument("-t", "--testbed", action="store_true", dest="testbed",
- help="Instantiates a snapshot of the NDN Testbed irrespective of the tempfile provided")
-
- parser.add_argument("--work-dir", action="store", dest="workDir", default="/tmp/minindn",
- help="Specify the working directory; default is /tmp/minindn")
-
- parser.add_argument("--result-dir", action="store", dest="resultDir", default=None,
- help="Specify the full path destination folder where experiment results will be moved")
-
- parser.add_argument("--pct-traffic", dest="pctTraffic", type=float, default=1.0,
- help="Specify the percentage of nodes each node should ping")
-
- parser.add_argument('--version', '-V', action='version', version='%(prog)s ' + VERSION_NUMBER,
- help='Displays version information')
-
- parser.add_argument("--cluster", metavar='localhost,server2,...',
- help="Run cluster edition")
-
- parser.add_argument("--placement", default='guided',
- choices=['roundRobin', 'guided'])
-
- parser.add_argument("--place-list", dest="placeList",
- help="""Provide corresponding number of nodes (comma separated) to put on
- each node respectively of --cluster when guided placement is used""")
-
- parser.add_argument("--tunnel-type", dest="tunnelType", default='ssh',
- choices=['ssh', 'gre'])
-
- parser.add_argument("--face-type", dest='faceType', default='udp', choices=['udp', 'tcp'])
-
- parser.add_argument("--cs-size", dest='csSize', type=int, default=65536,
- help="Set CS size in NFD's conf file")
-
- ExperimentManager.addExperimentArgs(parser)
-
- if "argcomplete" in sys.modules:
- argcomplete.autocomplete(parser)
-
- args = parser.parse_args()
-
- options = ProgramOptions()
- options.templateFile = args.tempfile
- options.ctime = args.ctime
- options.experimentName = args.experiment
- options.nFaces = args.faces
- options.routingType = args.routingType
- options.isNlsrEnabled = args.isNlsrEnabled
- options.isCliEnabled = args.isCliEnabled
- options.nlsrSecurity = args.nlsrSecurity
- options.nPings = args.nPings
-
- options.testbed = args.testbed
- options.workDir = args.workDir
- options.resultDir = args.resultDir
- options.pctTraffic = args.pctTraffic
- options.cluster = args.cluster
- options.placement = args.placement
- options.tunnelType = args.tunnelType
- options.placeList = args.placeList
- options.faceType = args.faceType
- options.csSize = args.csSize
- options.arguments = args
-
- if options.experimentName is not None and options.experimentName not in ExperimentManager.getExperimentNames():
- error("No experiment named {}\n".format(options.experimentName))
- sys.exit(1)
-
- if options.experimentName is not None and options.resultDir is None:
- warn("No results folder specified; experiment results will remain in the working directory\n")
-
- if options.cluster is not None:
- servers = options.cluster.split(',')
- for server in servers:
- ClusterCleanup.add(server)
- options.servers = servers
-
- if options.placement == "roundRobin":
- options.placement = RoundRobinPlacer
- elif options.placement == "guided":
- if options.placeList is None or not re.match("^[0-9,]+$", options.placeList):
- error("Please specify correctly how many nodes you want to place on each node!")
- sys.exit(1)
- else:
- try:
- options.placeList = map(int, options.placeList.split(","))
- except ValueError:
- error("Please specify the nodes correctly, no comma at the beginning/end!")
- sys.exit(1)
-
- PopulatePlacement(options.placeList)
- options.placement = GuidedPlacer
-
- if options.tunnelType == "ssh":
- options.tunnelType = RemoteNdnLink
- else:
- options.tunnelType = RemoteGRENdnLink
-
- return options
-
-class NdnTopo(Topo):
- def __init__(self, conf_arq, workDir, **opts):
- Topo.__init__(self, **opts)
-
- self.hosts_conf = parse_hosts(conf_arq)
- self.switches_conf = parse_switches(conf_arq)
- self.links_conf = parse_links(conf_arq)
-
- self.isTCLink = False
- self.isLimited = False
-
- for host in self.hosts_conf:
- if host.cpu != None and self.isLimited != True:
- self.isLimited = True
- self.addHost(host.name, app=host.app, params=host.params, cpu=host.cpu,
- cores=host.cores,cache=host.cache, workdir=workDir)
-
- for switch in self.switches_conf:
- self.addSwitch(switch.name)
-
- for link in self.links_conf:
- if len(link.linkDict) == 0:
- self.addLink(link.h1, link.h2)
- else:
- self.addLink(link.h1, link.h2, **link.linkDict)
- self.isTCLink = True
-
- info('Parse of ' + conf_arq + ' done.\n')
-
-def execute(options):
- "Create a network based on template_file"
-
- if options.testbed:
- options.templateFile = INSTALL_DIR + 'minindn.testbed.conf'
-
- if os.path.exists(options.templateFile) == False:
- error('Template file cannot be found. Exiting...\n')
- sys.exit(1)
-
- if options.cluster is not None and options.placement == GuidedPlacer:
- num_nodes = 0
- with open(options.templateFile, 'r') as topo:
- for line in topo:
- if ': _' in line:
- num_nodes += 1
-
- if sum(options.placeList) != num_nodes:
- error("Placement list sum is not equal to number of nodes!")
- sys.exit(1)
-
- # Copy nfd.conf to remote hosts - this assumes that NDN versions across
- # the cluster are at least compatible if not the same
- if options.cluster is not None:
- for server in options.servers:
- if server != "localhost":
- login = "mininet@{}".format(server)
- src = nfdConfFile
- dst = "{}:/tmp/nfd.conf".format(login)
- scp(src, dst)
- ssh(login, "sudo cp /tmp/nfd.conf {}".format(src))
-
- if options.resultDir is not None:
- options.resultDir = createResultsDir(options.resultDir, options.nFaces, options.routingType)
-
- topo = NdnTopo(options.templateFile, options.workDir)
-
- if topo.isTCLink == True and topo.isLimited == True:
- net = Mininet(topo,host=CpuLimitedNdnHost,link=TCLink)
- elif topo.isTCLink == True and topo.isLimited == False:
- if options.cluster is not None:
- mn = partial(MininetCluster, servers=options.servers, placement=options.placement)
- net = mn(topo=topo, host=RemoteNdnHost, link=options.tunnelType)
- else:
- net = Mininet(topo, host=NdnHost, link=TCLink)
- elif topo.isTCLink == False and topo.isLimited == True:
- net = Mininet(topo, host=CpuLimitedNdnHost)
- else:
- net = Mininet(topo, host=NdnHost)
-
- net.start()
-
- # Giving proper IPs to intf so neighbor nodes can communicate
- # This is one way of giving connectivity, another way could be
- # to insert a switch between each pair of neighbors
- ndnNetBase = "1.0.0.0"
- interfaces = []
- for host in net.hosts:
- for intf in host.intfList():
- link = intf.link
- node1, node2 = link.intf1.node, link.intf2.node
-
- if node1 in net.switches or node2 in net.switches:
- continue
-
- if link.intf1 not in interfaces and link.intf2 not in interfaces:
- interfaces.append(link.intf1)
- interfaces.append(link.intf2)
- node1.setIP(ipStr(ipParse(ndnNetBase) + 1) + '/30', intf=link.intf1)
- node2.setIP(ipStr(ipParse(ndnNetBase) + 2) + '/30', intf=link.intf2)
- ndnNetBase = ipStr(ipParse(ndnNetBase) + 4)
-
- time.sleep(2)
-
- info('Starting NFD on nodes\n')
- for host in net.hosts:
- host.nfd = Nfd(host, options.csSize)
- host.nfd.start()
-
- for host in net.hosts:
- if 'app' in host.params:
- if host.params['app'] != '':
- app = host.params['app']
- info("Starting {} on node {}".format(app, host.name))
- info(host.cmd(app))
-
- # Determine if each host is running NFD
- for host in net.hosts:
- nfdStatus = host.cmd("ps -g -U root | grep 'nfd --config {}/[n]fd.conf'".format(host.homeFolder))
- if not host.nfd.isRunning or not nfdStatus:
- error("NFD on host {} is not running. Printing log file and exiting...".format(host.name))
- info(host.cmd("tail {}/nfd.log".format(host.homeFolder)))
- net.stop()
- sys.exit(1)
-
- # Load experiment
- experimentName = options.experimentName
-
- experimentArgs = {
- "net": net,
- "options": options
- }
-
- if experimentName is not None:
- info("Loading experiment: {}\n".format(experimentName))
-
- experiment = ExperimentManager.create(experimentName, experimentArgs)
-
- if experiment is not None:
- experiment.start()
- else:
- error("Experiment '{}' does not exist\n".format(experimentName))
- return
- else:
- experiment = Experiment(experimentArgs)
- if options.isNlsrEnabled:
- experiment.startNlsr(checkConvergence = False)
-
- if options.isCliEnabled is True:
- MiniNDNCLI(net)
-
- net.stop()
-
- if options.resultDir is not None:
- info("Moving results to {}".format(options.resultDir))
- for file in glob.glob('{}/*'.format(options.workDir)):
- shutil.move(file, options.resultDir)
- if options.cluster is not None:
- for server in options.servers:
- if server != "localhost":
- login = "mininet@{}".format(server)
- src = "{}:{}/*".format(login, options.workDir)
- dst = options.resultDir
- scp(src, dst)
- info("Please clean work directories of other machines before running the cluster again")
-
-def signal_handler(signal, frame):
- info('Cleaning up...')
- call(["nfd-stop"])
- call(["sudo", "mn", "--clean"])
- sys.exit(1)
-
-def verify_dependencies():
- "Prevent MiniNDN from running without necessary dependencies"
- dependencies = ["nfd", "nlsr", "infoedit", "ndnping", "ndnpingserver"]
- devnull = open("/dev/null", "w")
- # Checks that each program is in the system path
- for program in dependencies:
- if call(["which", program], stdout=devnull):
- error("{} is missing from the system path! Exiting...".format(program))
- sys.exit(1)
- devnull.close()
-
-if __name__ == '__main__':
-
- signal.signal(signal.SIGQUIT, signal_handler)
-
- options = parse_args()
-
- setLogLevel('info')
- verify_dependencies()
-
- try:
- execute(options)
- except Exception as e:
- error("{}".format(e))
- call(["nfd-stop"])
- call(["sudo", "mn", "--clean"])
- sys.exit(1)
diff --git a/bin/minindnedit b/bin/minindnedit
deleted file mode 100755
index 0bdcb5d..0000000
--- a/bin/minindnedit
+++ /dev/null
@@ -1,1901 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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 file incorporates work covered by the following copyright and
-# permission notice:
-#
-# Mininet 2.2.1 License
-#
-# Copyright (c) 2013-2015 Open Networking Laboratory
-# Copyright (c) 2009-2012 Bob Lantz and The Board of Trustees of
-# The Leland Stanford Junior University
-#
-# Original authors: Bob Lantz and Brandon Heller
-#
-# We are making Mininet available for public use and benefit with the
-# expectation that others will use, modify and enhance the Software and
-# contribute those enhancements back to the community. However, since we
-# would like to make the Software available for broadest use, with as few
-# restrictions as possible permission is hereby granted, free of charge, to
-# any person obtaining a copy of this Software to deal in the Software
-# under the copyrights without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# The name and trademarks of copyright holder(s) may NOT be used in
-# advertising or publicity pertaining to the Software or any derivatives
-# without specific, written prior permission.
-
-"""
-MiniNDNEdit: a simple network editor for MiniNDN
-
-Based on miniccnxedit by:
-Carlos Cabral, Jan 2013
-Caio Elias, Nov 2014
-
-Based on miniedit by:
-Bob Lantz, April 2010
-Gregory Gee, July 2013
-
-"""
-
-MINIEDIT_VERSION = '2.2.0.1'
-
-from optparse import OptionParser
-from Tkinter import *
-from ttk import Notebook
-from tkMessageBox import showinfo, showerror, showwarning
-from subprocess import call, Popen
-import tkFont
-import csv
-import tkFileDialog
-import tkSimpleDialog
-import re
-import json
-from distutils.version import StrictVersion
-import os
-import sys
-import threading
-from functools import partial
-
-import pdb
-
-if 'PYTHONPATH' in os.environ:
- sys.path = os.environ[ 'PYTHONPATH' ].split( ':' ) + sys.path
-
-# someday: from ttk import *
-
-from mininet.log import info, error, debug, output, setLogLevel
-from mininet.net import Mininet, VERSION
-from mininet.util import ipStr, netParse, ipAdd, quietRun
-from mininet.util import buildTopo
-from mininet.util import custom
-from mininet.term import makeTerm, cleanUpScreens
-from mininet.node import Controller, RemoteController, NOX, OVSController
-from mininet.node import CPULimitedHost, Host, Node
-from mininet.node import OVSKernelSwitch, OVSSwitch, UserSwitch
-from mininet.link import TCLink, Intf, Link
-from mininet.cli import CLI
-from mininet.moduledeps import moduleDeps, pathCheck
-from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
-from mininet.topolib import TreeTopo
-
-print 'MiniNDNEdit running...' #+VERSION
-MININET_VERSION = re.sub(r'[^\d\.]', '', VERSION)
-if StrictVersion(MININET_VERSION) > StrictVersion('2.0'):
- from mininet.node import IVSSwitch
-
-
-from ndn.gui import NfdFrame, NlsrFrame
-
-TOPODEF = 'none'
-TOPOS = { 'minimal': lambda: SingleSwitchTopo( k=2 ),
- 'linear': LinearTopo,
- 'reversed': SingleSwitchReversedTopo,
- 'single': SingleSwitchTopo,
- 'none': None,
- 'tree': TreeTopo }
-LINKDEF = 'default'
-LINKS = { 'default': Link,
- 'tc': TCLink }
-HOSTDEF = 'proc'
-HOSTS = { 'proc': Host,
- 'rt': custom( CPULimitedHost, sched='rt' ),
- 'cfs': custom( CPULimitedHost, sched='cfs' ) }
-
-def runMiniNdn(window, template):
- # Hide window
- window.withdraw()
-
- proc = Popen("sudo minindn %s" % template, shell=True)
- proc.wait()
-
- # Restore window
- window.deiconify()
-
-class LegacyRouter( Node ):
-
- def __init__( self, name, inNamespace=True, **params ):
- Node.__init__( self, name, inNamespace, **params )
-
- def config( self, **_params ):
- if self.intfs:
- self.setParam( _params, 'setIP', ip='0.0.0.0' )
- r = Node.config( self, **_params )
- self.cmd('sysctl -w net.ipv4.ip_forward=1')
- return r
-
-class CustomDialog(object):
-
- # TODO: Fix button placement and Title and window focus lock
- def __init__(self, master, title):
- self.top=Toplevel(master)
-
- self.bodyFrame = Frame(self.top)
- self.bodyFrame.grid(row=0, column=0, sticky='nswe')
- self.body(self.bodyFrame)
-
- #return self.b # initial focus
- buttonFrame = Frame(self.top, relief='ridge', bd=3, bg='lightgrey')
- buttonFrame.grid(row=1 , column=0, sticky='nswe')
-
- okButton = Button(buttonFrame, width=8, text='OK', relief='groove',
- bd=4, command=self.okAction)
- okButton.grid(row=1, column=0, sticky=E)
-
- canlceButton = Button(buttonFrame, width=8, text='Cancel', relief='groove',
- bd=4, command=self.cancelAction)
- canlceButton.grid(row=1, column=1, sticky=W)
-
- def body(self, master):
- self.rootFrame = master
-
- def apply(self):
- self.top.destroy()
-
- def cancelAction(self):
- self.top.destroy()
-
- def okAction(self):
- self.apply()
- self.top.destroy()
-
-class HostDialog(CustomDialog):
-
- def __init__(self, master, title, prefDefaults, isRouter):
-
- self.prefValues = prefDefaults
- self.result = None
- self.isRouter = isRouter
- self.title = title
-
- CustomDialog.__init__(self, master, title)
-
- def body(self, master):
- self.rootFrame = master
- n = Notebook(self.rootFrame)
- self.propFrame = Frame(n)
-
- # NDN
- self.nfdFrame = NfdFrame(n, self.prefValues)
- self.nlsrFrame = NlsrFrame(n,self.prefValues)
-
- n.add(self.propFrame, text='Properties')
-
- n.add(self.nfdFrame, text=self.nfdFrame.frameLabel)
- n.add(self.nlsrFrame, text=self.nlsrFrame.frameLabel)
-
- n.pack()
-
- ### TAB 1
- # Field for Hostname
- Label(self.propFrame, text="Hostname:").grid(row=0, sticky=E)
- self.hostnameEntry = Entry(self.propFrame)
- self.hostnameEntry.grid(row=0, column=1)
- if 'hostname' in self.prefValues:
- self.hostnameEntry.insert(0, self.prefValues['hostname'])
-
- # Field for CPU
- Label(self.propFrame, text="Amount CPU:").grid(row=2, sticky=E)
- self.cpuEntry = Entry(self.propFrame)
- self.cpuEntry.grid(row=2, column=1)
- Label(self.propFrame, text="%").grid(row=2, column=2, sticky=W)
- if 'cpu' in self.prefValues:
- self.cpuEntry.insert(0, str(self.prefValues['cpu']))
-
- # Field for Memory
- Label(self.propFrame, text="Amount MEM:").grid(row=3, sticky=E)
- self.memEntry = Entry(self.propFrame)
- self.memEntry.grid(row=3, column=1)
- Label(self.propFrame, text="%").grid(row=3, column=2, sticky=W)
- if 'mem' in self.prefValues:
- self.memEntry.insert(0, str(self.prefValues['mem']))
-
- # Field for Cache
- Label(self.propFrame, text="Amount CACHE:").grid(row=4, sticky=E)
- self.cacheEntry = Entry(self.propFrame)
- self.cacheEntry.grid(row=4, column=1)
- Label(self.propFrame, text="KBytes").grid(row=4, column=2, sticky=W)
- if 'cache' in self.prefValues:
- self.cacheEntry.insert(0, str(self.prefValues['cache']))
-
- # Start command
- #print self.isRouter
- if self.isRouter == 'False':
- Label(self.propFrame, text="Start Command(s):").grid(row=5, sticky=E)
- self.scrollbar = Scrollbar(self.propFrame, orient="horizontal")
- self.startEntry = Entry(self.propFrame, xscrollcommand=self.scrollbar.set,)
- self.startEntry.grid(row=5, column=1)
- self.scrollbar.grid(row=6, column=1, sticky=N+S+E+W)
- self.scrollbar.config(command=self.startEntry.xview)
- Label(self.propFrame, text="[Use bash syntax]").grid(row=5, column=2, sticky=W)
- if 'startCommand' in self.prefValues:
- self.startEntry.insert(0, str(self.prefValues['startCommand']))
- else:
- self.startEntry= Entry(self.propFrame)
-
- def apply(self):
- results = {'cpu': self.cpuEntry.get(),
- 'cache': self.cacheEntry.get(),
- 'mem': self.memEntry.get(),
- 'hostname':self.hostnameEntry.get(),
- 'startCommand':self.startEntry.get(),
- 'nfd': self.nfdFrame.getValues(),
- 'nlsr': self.nlsrFrame.getValues()
- }
-
- self.result = results
-
-class VerticalScrolledTable(LabelFrame):
- """A pure Tkinter scrollable frame that actually works!
-
- * Use the 'interior' attribute to place widgets inside the scrollable frame
- * Construct and pack/place/grid normally
- * This frame only allows vertical scrolling
-
- """
- def __init__(self, parent, rows=2, columns=2, title=None, *args, **kw):
- LabelFrame.__init__(self, parent, text=title, padx=5, pady=5, *args, **kw)
-
- # create a canvas object and a vertical scrollbar for scrolling it
- vscrollbar = Scrollbar(self, orient=VERTICAL)
- vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
- canvas = Canvas(self, bd=0, highlightthickness=0,
- yscrollcommand=vscrollbar.set)
- canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
- vscrollbar.config(command=canvas.yview)
-
- # reset the view
- canvas.xview_moveto(0)
- canvas.yview_moveto(0)
-
- # create a frame inside the canvas which will be scrolled with it
- self.interior = interior = TableFrame(canvas, rows=rows, columns=columns)
- interior_id = canvas.create_window(0, 0, window=interior,
- anchor=NW)
-
- # track changes to the canvas and frame width and sync them,
- # also updating the scrollbar
- def _configure_interior(event):
- # update the scrollbars to match the size of the inner frame
- size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
- canvas.config(scrollregion="0 0 %s %s" % size)
- if interior.winfo_reqwidth() != canvas.winfo_width():
- # update the canvas's width to fit the inner frame
- canvas.config(width=interior.winfo_reqwidth())
- interior.bind('<Configure>', _configure_interior)
-
- def _configure_canvas(event):
- if interior.winfo_reqwidth() != canvas.winfo_width():
- # update the inner frame's width to fill the canvas
- canvas.itemconfigure(interior_id, width=canvas.winfo_width())
- canvas.bind('<Configure>', _configure_canvas)
-
- return
-
-class TableFrame(Frame):
- def __init__(self, parent, rows=2, columns=2):
-
- Frame.__init__(self, parent, background="black")
- self._widgets = []
- self.rows = rows
- self.columns = columns
- for row in range(rows):
- current_row = []
- for column in range(columns):
- label = Entry(self, borderwidth=0)
- label.grid(row=row, column=column, sticky="wens", padx=1, pady=1)
- current_row.append(label)
- self._widgets.append(current_row)
-
- def set(self, row, column, value):
- widget = self._widgets[row][column]
- widget.insert(0, value)
-
- def get(self, row, column):
- widget = self._widgets[row][column]
- return widget.get()
-
- def addRow( self, value=None, readonly=False ):
- #print "Adding row " + str(self.rows +1)
- current_row = []
- for column in range(self.columns):
- label = Entry(self, borderwidth=0)
- label.grid(row=self.rows, column=column, sticky="wens", padx=1, pady=1)
- if value is not None:
- label.insert(0, value[column])
- if (readonly == True):
- label.configure(state='readonly')
- current_row.append(label)
- self._widgets.append(current_row)
- self.update_idletasks()
- self.rows += 1
-
-class LinkDialog(tkSimpleDialog.Dialog):
-
- def __init__(self, parent, title, linkDefaults):
-
- self.linkValues = linkDefaults
-
- tkSimpleDialog.Dialog.__init__(self, parent, title)
-
- def body(self, master):
-
- self.var = StringVar(master)
- Label(master, text="Bandwidth:").grid(row=0, sticky=E)
- self.e1 = Entry(master)
- self.e1.grid(row=0, column=1)
- Label(master, text="[1-1000] Mbps").grid(row=0, column=2, sticky=W)
- if 'bw' in self.linkValues:
- self.e1.insert(0,str(self.linkValues['bw']))
-
- Label(master, text="Delay:").grid(row=1, sticky=E)
- self.e2 = Entry(master)
- self.e2.grid(row=1, column=1)
- Label(master, text="[0-1000] ms").grid(row=1, column=2, sticky=W)
- if 'delay' in self.linkValues:
- self.e2.insert(0, self.linkValues['delay'])
-
- Label(master, text="Loss:").grid(row=2, sticky=E)
- self.e3 = Entry(master)
- self.e3.grid(row=2, column=1)
- Label(master, text="%").grid(row=2, column=2, sticky=W)
- if 'loss' in self.linkValues:
- self.e3.insert(0, str(self.linkValues['loss']))
-
- return self.e1 # initial focus
-
- def apply(self):
- self.result = {}
- if (len(self.e1.get()) > 0):
- self.result['bw'] = int(self.e1.get())
- if (len(self.e2.get()) > 0):
- self.result['delay'] = self.e2.get()
- if (len(self.e3.get()) > 0):
- self.result['loss'] = int(self.e3.get())
-
-class ToolTip(object):
-
- def __init__(self, widget):
- self.widget = widget
- self.tipwindow = None
- self.id = None
- self.x = self.y = 0
-
- def showtip(self, text):
- "Display text in tooltip window"
- self.text = text
- if self.tipwindow or not self.text:
- return
- x, y, cx, cy = self.widget.bbox("insert")
- x = x + self.widget.winfo_rootx() + 27
- y = y + cy + self.widget.winfo_rooty() +27
- self.tipwindow = tw = Toplevel(self.widget)
- tw.wm_overrideredirect(1)
- tw.wm_geometry("+%d+%d" % (x, y))
- try:
- # For Mac OS
- tw.tk.call("::tk::unsupported::MacWindowStyle",
- "style", tw._w,
- "help", "noActivates")
- except TclError:
- pass
- label = Label(tw, text=self.text, justify=LEFT,
- background="#ffffe0", relief=SOLID, borderwidth=1,
- font=("tahoma", "8", "normal"))
- label.pack(ipadx=1)
-
- def hidetip(self):
- tw = self.tipwindow
- self.tipwindow = None
- if tw:
- tw.destroy()
-
-class MiniEdit( Frame ):
-
- "A simple network editor for MiniNDN."
-
- def __init__( self, parent=None, cheight=600, cwidth=1000, template_file='minindn.conf' ):
-
- self.template_file = template_file
-
- Frame.__init__( self, parent )
- self.action = None
- self.appName = 'MiniNDNEdit'
- self.fixedFont = tkFont.Font ( family="DejaVu Sans Mono", size="14" )
-
- # Style
- self.font = ( 'Geneva', 9 )
- self.smallFont = ( 'Geneva', 7 )
- self.bg = 'white'
-
- # Title
- self.top = self.winfo_toplevel()
- self.top.title( self.appName )
-
- # Menu bar
- self.createMenubar()
-
- # Editing canvas
- self.cheight, self.cwidth = cheight, cwidth
- self.cframe, self.canvas = self.createCanvas()
-
- # Toolbar
- self.controllers = {}
-
- # Toolbar
- self.images = miniEditImages()
- self.buttons = {}
- self.active = None
- self.tools = ( 'Select', 'Host', 'Switch', 'NetLink' )
- #self.customColors = { 'LegacyRouter': 'darkGreen', 'Host': 'blue' }
- self.toolbar = self.createToolbar()
-
- # Layout
- self.toolbar.grid( column=0, row=0, sticky='nsew')
- self.cframe.grid( column=1, row=0 )
- self.columnconfigure( 1, weight=1 )
- self.rowconfigure( 0, weight=1 )
- self.pack( expand=True, fill='both' )
-
- # About box
- self.aboutBox = None
-
- # Initialize node data
- self.nodeBindings = self.createNodeBindings()
- self.nodePrefixes = { 'LegacyRouter': 'r', 'Host': 'h', 'Switch': 's'}
- self.widgetToItem = {}
- self.itemToWidget = {}
-
- # Initialize link tool
- self.link = self.linkWidget = None
-
- # Selection support
- self.selection = None
-
- # Keyboard bindings
- self.bind( '<Control-q>', lambda event: self.quit() )
- self.bind( '<KeyPress-Delete>', self.deleteSelection )
- self.bind( '<KeyPress-BackSpace>', self.deleteSelection )
- self.focus()
-
- #Mouse bindings
- self.bind( '<Button-1>', lambda event: self.clearPopups )
-
- self.hostPopup = Menu(self.top, tearoff=0)
- self.hostPopup.add_command(label='Host Options', font=self.font, command=self.hostDetails)
- #self.hostPopup.add_separator()
- #self.hostPopup.add_command(label='Properties', font=self.font, command=self.hostDetails )
-
- self.legacyRouterPopup = Menu(self.top, tearoff=0)
- self.legacyRouterPopup.add_command(label='Router Options', font=self.font, command=self.hostDetails)
-
- self.linkPopup = Menu(self.top, tearoff=0)
- self.linkPopup.add_command(label='Link Options', font=self.font, command=self.linkDetails)
- #self.linkPopup.add_separator()
- #self.linkPopup.add_command(label='Properties', font=self.font, command=self.linkDetails )
-
- # Event handling initalization
- self.linkx = self.linky = self.linkItem = None
- self.lastSelection = None
-
- # Model initialization
- self.links = {}
- self.hostOpts = {}
- self.switchOpts = {}
- self.routerOpts = {}
- self.hostCount = 0
- self.switchCount = 0
- self.routerCount = 0
- self.net = None
-
- # Close window gracefully
- Wm.wm_protocol( self.top, name='WM_DELETE_WINDOW', func=self.quit )
-
- def quit( self ):
- "Stop our network, if any, then quit."
- #sself.stop()
- Frame.quit( self )
-
- def createMenubar( self ): # MODIFICADO - OK
- "Create our menu bar."
-
- font = self.font
-
- mbar = Menu( self.top, font=font )
- self.top.configure( menu=mbar )
-
- fileMenu = Menu( mbar, tearoff=False )
- mbar.add_cascade( label="File", font=font, menu=fileMenu )
- fileMenu.add_command( label="New", font=font, command=self.newTopology )
- fileMenu.add_command( label="Open", font=font, command=self.loadTopology )
- fileMenu.add_command( label="Save", font=font, command=self.saveTopology )
- fileMenu.add_command( label="Generate", font=font, command=self.doGenerate )
- fileMenu.add_command( label="Run", font=font, command=self.doRun )
- fileMenu.add_separator()
- fileMenu.add_command( label='Quit', command=self.quit, font=font )
-
- editMenu = Menu( mbar, tearoff=False )
- mbar.add_cascade( label="Edit", font=font, menu=editMenu )
- editMenu.add_command( label="Cut", font=font,
- command=lambda: self.deleteSelection( None ) )
-
- # Application menu
- appMenu = Menu( mbar, tearoff=False )
- mbar.add_cascade( label=self.appName, font=font, menu=appMenu )
- appMenu.add_command( label='About Mini-NDN', command=self.about,
- font=font)
- #appMenu.add_separator()
- #appMenu.add_command( label='Quit', command=self.quit, font=font )
-
- # Canvas - TUDO IGUAL - OK
-
- def createCanvas( self ):
- "Create and return our scrolling canvas frame."
- f = Frame( self )
-
- canvas = Canvas( f, width=self.cwidth, height=self.cheight,
- bg=self.bg )
-
- # Scroll bars
- xbar = Scrollbar( f, orient='horizontal', command=canvas.xview )
- ybar = Scrollbar( f, orient='vertical', command=canvas.yview )
- canvas.configure( xscrollcommand=xbar.set, yscrollcommand=ybar.set )
-
- # Resize box
- resize = Label( f, bg='white' )
-
- # Layout
- canvas.grid( row=0, column=1, sticky='nsew')
- ybar.grid( row=0, column=2, sticky='ns')
- xbar.grid( row=1, column=1, sticky='ew' )
- resize.grid( row=1, column=2, sticky='nsew' )
-
- # Resize behavior
- f.rowconfigure( 0, weight=1 )
- f.columnconfigure( 1, weight=1 )
- f.grid( row=0, column=0, sticky='nsew' )
- f.bind( '<Configure>', lambda event: self.updateScrollRegion() )
-
- # Mouse bindings
- canvas.bind( '<ButtonPress-1>', self.clickCanvas )
- canvas.bind( '<B1-Motion>', self.dragCanvas )
- canvas.bind( '<ButtonRelease-1>', self.releaseCanvas )
-
- return f, canvas
-
- def updateScrollRegion( self ):
- "Update canvas scroll region to hold everything."
- bbox = self.canvas.bbox( 'all' )
- if bbox is not None:
- self.canvas.configure( scrollregion=( 0, 0, bbox[ 2 ],
- bbox[ 3 ] ) )
-
- def canvasx( self, x_root ):
- "Convert root x coordinate to canvas coordinate."
- c = self.canvas
- return c.canvasx( x_root ) - c.winfo_rootx()
-
- def canvasy( self, y_root ):
- "Convert root y coordinate to canvas coordinate."
- c = self.canvas
- return c.canvasy( y_root ) - c.winfo_rooty()
-
- # Toolbar
-
- def activate( self, toolName ): #IGUAL - OK
- "Activate a tool and press its button."
- # Adjust button appearance
- if self.active:
- self.buttons[ self.active ].configure( relief='raised' )
- self.buttons[ toolName ].configure( relief='sunken' )
- # Activate dynamic bindings
- self.active = toolName
-
-
- def createToolTip(self, widget, text): #NOVA - CRIA HINTS E TIPS
- toolTip = ToolTip(widget)
- def enter(event):
- toolTip.showtip(text)
- def leave(event):
- toolTip.hidetip()
- widget.bind('<Enter>', enter)
- widget.bind('<Leave>', leave)
-
- def createToolbar( self ): #MODIFICADO - OK
- "Create and return our toolbar frame."
-
- toolbar = Frame( self )
-
- # Tools
- for tool in self.tools:
- cmd = ( lambda t=tool: self.activate( t ) )
- b = Button( toolbar, text=tool, font=self.smallFont, command=cmd)
- if tool in self.images:
- b.config( height=35, image=self.images[ tool ] )
- self.createToolTip(b, str(tool))
- # b.config( compound='top' )
- b.pack( fill='x' )
- self.buttons[ tool ] = b
- self.activate( self.tools[ 0 ] )
-
- # Spacer
- Label( toolbar, text='' ).pack()
-
- # abaixo copiado Mini-NDN para criar botao Generate
-
- for cmd, color in [ ( 'Generate', 'darkGreen' ) ]:
- doCmd = getattr( self, 'do' + cmd )
- b = Button( toolbar, text=cmd, font=self.smallFont,
- fg=color, command=doCmd )
- b.pack( fill='x', side='bottom' )
-
- return toolbar
-
- def doGenerate( self ): #COPIA Mini-NDN - GERA TEMPLATE
- "Generate template."
- self.activate( 'Select' )
- for tool in self.tools:
- self.buttons[ tool ].config( state='disabled' )
-
- self.buildTemplate()
-
- for tool in self.tools:
- self.buttons[ tool ].config( state='normal' )
-
- toplevel = Toplevel()
- label1 = Label(toplevel, text="Template file generated successfully", height=0, width=30)
- label1.pack()
- b=Button(toplevel, text="Ok", width=5, command=toplevel.destroy)
- b.pack(side='bottom', padx=0,pady=0)
-
- def doRun( self ):
- "Use current configuration to generate a template and run the topology"
-
- # Generate temporary template file
- old_template_file = self.template_file
- self.template_file = "/tmp/tmp.conf"
- self.doGenerate()
-
- thread = threading.Thread(target=runMiniNdn, args=(self.master, self.template_file))
- thread.start()
-
- self.template_file = old_template_file
-
- def buildTemplate( self ): #COPIA Mini-NDN para criar Template
- "Generate template"
-
- template = open(self.template_file, 'w')
-
- # hosts
- template.write('[nodes]\n')
- for widget in self.widgetToItem:
- name = widget[ 'text' ]
- tags = self.canvas.gettags( self.widgetToItem[ widget ] )
-
- if 'Host' in tags:
- hOpts=self.hostOpts[name]
- print hOpts
-
- template.write(name + ': ')
- if 'startCommand' in hOpts:
- cmds = hOpts['startCommand'].replace("\"", "\\\"")
- template.write('apps="%s" ' % cmds)
- else:
- template.write('_ ')
- if 'cache' in hOpts:
- template.write('cache=' + hOpts['cache'] + ' ')
- if 'cpu' in hOpts:
- cpu=float(hOpts['cpu'])/100
- template.write('cpu=' + repr(cpu) + ' ')
- if 'mem' in hOpts:
- mem=float(hOpts['mem'])/100
- template.write('mem=' + repr(mem) + ' ')
- if 'nlsr' in hOpts:
- values = hOpts['nlsr']
-
- template.write('hyperbolic-state=' + values['hyperbolic-state'] + ' ')
- template.write('radius=' + values['radius'] + ' ')
- template.write('angle=' + values['angle'] + ' ')
- template.write('network=' + values['network'] + ' ')
- template.write('router=' + values['router'] + ' ')
- template.write('site=' + values['site'] + ' ')
- template.write('nlsr-log-level=' + values['log-level'] + ' ')
- template.write('max-faces-per-prefix=' + values['max-faces-per-prefix'] + ' ')
- if 'nfd' in hOpts:
- values = hOpts['nfd']
-
- template.write('nfd-log-level=' + values['log-level'] + ' ')
-
- template.write('\n')
-
- # switches/routers
- #template.write('[routers]\n')
-
- for router in self.routerOpts.values():
-
- hasOpt='False'
- routerName=router['hostname']
- #nodetype=router['nodetype']
- #nodenum=router['nodenum']
-
- rOpts=self.routerOpts[routerName]
-
- template.write(routerName + ': ')
-
- if 'cpu' in rOpts:
- cpu=float(rOpts['cpu'])/100
- template.write('cpu=' + repr(cpu) + ' ')
- hasOpt='True'
- if 'mem' in rOpts:
- mem=float(rOpts['mem'])/100
- template.write('mem=' + repr(mem) + ' ')
- hasOpt='True'
- if 'cache' in rOpts:
- template.write('cache=' + rOpts['cache'] + ' ')
- hasOpt='True'
- if hasOpt == 'False':
- template.write('_')
-
- template.write('\n')
-
- # Write switches
- template.write('[switches]\n')
-
- for switch in self.switchOpts.values():
- print "Switch%s" % switch
-
- name = switch['hostname']
- template.write(name + ': _\n')
-
- # Make links
- template.write('[links]\n')
- for link in self.links.values():
- dst=link['dest']
- src=link['src']
- linkopts=link['linkOpts']
- linktype=link['type']
-
- srcName, dstName = src[ 'text' ], dst[ 'text' ]
- template.write(srcName + ':' + dstName + ' ')
- if 'bw' in linkopts:
- template.write('bw=' + str(linkopts['bw']) + ' ' )
- if 'loss' in linkopts:
- template.write('loss=' + repr(linkopts['loss']) + ' ' )
- if 'delay' in linkopts:
- template.write('delay=' + str(linkopts['delay'])+ 'ms' )
-
- template.write('\n')
-
- template.close()
-
- def addNode( self, node, nodeNum, x, y, name=None):
- "Add a new node to our canvas."
-
- if 'LegacyRouter' == node:
- self.routerCount += 1
- if 'Host' == node:
- self.hostCount += 1
- if 'Switch' == node:
- self.switchCount += 1
- if name is None:
- name = self.nodePrefixes[ node ] + nodeNum
- self.addNamedNode(node, name, x, y)
-
- def addNamedNode( self, node, name, x, y):
- "Add a new node to our canvas."
- c = self.canvas
- icon = self.nodeIcon( node, name )
- item = self.canvas.create_window( x, y, anchor='c', window=icon,
- tags=node )
- self.widgetToItem[ icon ] = item
- self.itemToWidget[ item ] = icon
- icon.links = {}
-
- def convertJsonUnicode(self, input):
- "Some part of Mininet don't like Unicode"
- if isinstance(input, dict):
- return {self.convertJsonUnicode(key): self.convertJsonUnicode(value) for key, value in input.iteritems()}
- elif isinstance(input, list):
- return [self.convertJsonUnicode(element) for element in input]
- elif isinstance(input, unicode):
- return input.encode('utf-8')
- else:
- return input
-
- def loadTopology( self ):
- "Load command."
- c = self.canvas
-
- myFormats = [
- ('MiniNDN Topology','*.mnndn'),
- ('All Files','*'),
- ]
- f = tkFileDialog.askopenfile(filetypes=myFormats, mode='rb')
- if f == None:
- return
- self.newTopology()
- loadedTopology = self.convertJsonUnicode(json.load(f))
-
- # Load hosts
- hosts = loadedTopology['hosts']
- for host in hosts:
- nodeNum = host['number']
- hostname = 'h'+nodeNum
- if 'hostname' in host['opts']:
- hostname = host['opts']['hostname']
- else:
- host['opts']['hostname'] = hostname
- if 'nodeNum' not in host['opts']:
- host['opts']['nodeNum'] = int(nodeNum)
-
- x = host['x']
- y = host['y']
-
- self.addNode('Host', nodeNum, float(x), float(y), name=hostname)
-
- # Fix JSON converting tuple to list when saving
- if 'privateDirectory' in host['opts']:
- newDirList = []
- for privateDir in host['opts']['privateDirectory']:
- if isinstance( privateDir, list ):
- newDirList.append((privateDir[0],privateDir[1]))
- else:
- newDirList.append(privateDir)
- host['opts']['privateDirectory'] = newDirList
- self.hostOpts[hostname] = host['opts']
- icon = self.findWidgetByName(hostname)
- icon.bind('<Button-3>', self.do_hostPopup )
-
- # Load routers
- routers = loadedTopology['routers']
- for router in routers:
- nodeNum = router['number']
- hostname = 'r'+nodeNum
- #print router
- if 'nodeType' not in router['opts']:
- router['opts']['nodeType'] = 'legacyRouter'
- if 'hostname' in router['opts']:
- hostname = router['opts']['hostname']
- else:
- router['opts']['hostname'] = hostname
- if 'nodeNum' not in router['opts']:
- router['opts']['nodeNum'] = int(nodeNum)
- x = router['x']
- y = router['y']
- if router['opts']['nodeType'] == "legacyRouter":
- self.addNode('LegacyRouter', nodeNum, float(x), float(y), name=hostname)
- icon = self.findWidgetByName(hostname)
- icon.bind('<Button-3>', self.do_legacyRouterPopup )
- self.routerOpts[hostname] = router['opts']
-
- # Load switches
- switches = loadedTopology['switches']
-
- for switch in switches:
- nodeNum = switch['number']
- hostname = 's' + nodeNum
-
- if 'hostname' in switch['opts']:
- hostname = switch['opts']['hostname']
- else:
- switch['opts']['hostname'] = hostname
-
- if 'nodeNum' not in switch['opts']:
- switch['opts']['nodeNum'] = int(nodeNum)
-
- x = switch['x']
- y = switch['y']
-
- self.addNode('Switch', nodeNum, float(x), float(y), name=hostname)
- icon = self.findWidgetByName(hostname)
-
- self.switchOpts[hostname] = switch['opts']
-
- # Load links
- links = loadedTopology['links']
- for link in links:
- srcNode = link['src']
- src = self.findWidgetByName(srcNode)
- sx, sy = self.canvas.coords( self.widgetToItem[ src ] )
-
- destNode = link['dest']
- dest = self.findWidgetByName(destNode)
- dx, dy = self.canvas.coords( self.widgetToItem[ dest ] )
-
- self.link = self.canvas.create_line( sx, sy, dx, dy, width=4,
- fill='blue', tag='link' )
- c.itemconfig(self.link, tags=c.gettags(self.link)+('data',))
- self.addLink( src, dest, linkopts=link['opts'] )
- self.createDataLinkBindings()
- self.link = self.linkWidget = None
-
- f.close
-
- def findWidgetByName( self, name ):
- for widget in self.widgetToItem:
- if name == widget[ 'text' ]:
- return widget
-
- def newTopology( self ):
- "New command."
- for widget in self.widgetToItem.keys():
- self.deleteItem( self.widgetToItem[ widget ] )
- self.hostCount = 0
- self.routerCount = 0
- self.switchCount = 0
- self.links = {}
- self.hostOpts = {}
- self.routerOpts = {}
-
- def saveTopology( self ):
- "Save command."
- myFormats = [
- ('MiniNDN Topology','*.mnndn'),
- ('All Files','*'),
- ]
-
- savingDictionary = {}
- fileName = tkFileDialog.asksaveasfilename(filetypes=myFormats ,title="Save the topology as...")
- if len(fileName ) > 0:
- # Save Application preferences
- savingDictionary['version'] = '2'
-
- # Save routers and Hosts
- hostsToSave = []
- routersToSave = []
- switchesToSave = []
-
- for widget in self.widgetToItem:
- name = widget[ 'text' ]
- tags = self.canvas.gettags( self.widgetToItem[ widget ] )
- x1, y1 = self.canvas.coords( self.widgetToItem[ widget ] )
- if 'LegacyRouter' in tags:
- nodeNum = self.routerOpts[name]['nodeNum']
- nodeToSave = {'number':str(nodeNum),
- 'x':str(x1),
- 'y':str(y1),
- 'opts':self.routerOpts[name] }
- routersToSave.append(nodeToSave)
- elif 'Host' in tags:
- nodeNum = self.hostOpts[name]['nodeNum']
- nodeToSave = {'number':str(nodeNum),
- 'x':str(x1),
- 'y':str(y1),
- 'opts':self.hostOpts[name] }
- hostsToSave.append(nodeToSave)
- elif 'Switch' in tags:
- nodeNum = self.switchOpts[name]['nodeNum']
- nodeToSave = {'number':str(nodeNum),
- 'x':str(x1),
- 'y':str(y1),
- 'opts':self.switchOpts[name] }
- switchesToSave.append(nodeToSave)
- else:
- raise Exception( "Cannot create mystery node: " + name )
- savingDictionary['hosts'] = hostsToSave
- savingDictionary['routers'] = routersToSave
- savingDictionary['switches'] = switchesToSave
-
- # Save Links
- linksToSave = []
- for link in self.links.values():
- src = link['src']
- dst = link['dest']
- linkopts = link['linkOpts']
-
- srcName, dstName = src[ 'text' ], dst[ 'text' ]
- linkToSave = {'src':srcName,
- 'dest':dstName,
- 'opts':linkopts}
- if link['type'] == 'data':
- linksToSave.append(linkToSave)
- savingDictionary['links'] = linksToSave
-
- # Save Application preferences
- #savingDictionary['application'] = self.appPrefs
-
- try:
- f = open(fileName, 'wb')
- f.write(json.dumps(savingDictionary, sort_keys=True, indent=4, separators=(',', ': ')))
- except Exception as er:
- print er
- finally:
- f.close()
-
- # Generic canvas handler
- #
- # We could have used bindtags, as in nodeIcon, but
- # the dynamic approach used here
- # may actually require less code. In any case, it's an
- # interesting introspection-based alternative to bindtags.
-
- def canvasHandle( self, eventName, event ):
- "Generic canvas event handler"
- if self.active is None:
- return
- toolName = self.active
- handler = getattr( self, eventName + toolName, None )
- if handler is not None:
- handler( event )
-
- def clickCanvas( self, event ):
- "Canvas click handler."
- self.canvasHandle( 'click', event )
-
- def dragCanvas( self, event ):
- "Canvas drag handler."
- self.canvasHandle( 'drag', event )
-
- def releaseCanvas( self, event ):
- "Canvas mouse up handler."
- self.canvasHandle( 'release', event )
-
- # Currently the only items we can select directly are
- # links. Nodes are handled by bindings in the node icon.
-
- def findItem( self, x, y ):
- "Find items at a location in our canvas."
- items = self.canvas.find_overlapping( x, y, x, y )
- if len( items ) == 0:
- return None
- else:
- return items[ 0 ]
-
- # Canvas bindings for Select, Host, Router and Link tools
-
- def clickSelect( self, event ):
- "Select an item."
- self.selectItem( self.findItem( event.x, event.y ) )
-
- def deleteItem( self, item ):
- "Delete an item."
- # Don't delete while network is running
- if self.buttons[ 'Select' ][ 'state' ] == 'disabled':
- return
- # Delete from model
- if item in self.links:
- self.deleteLink( item )
- if item in self.itemToWidget:
- self.deleteNode( item )
- # Delete from view
- self.canvas.delete( item )
-
- def deleteSelection( self, _event ):
- "Delete the selected item."
- if self.selection is not None:
- self.deleteItem( self.selection )
- self.selectItem( None )
-
- def clearPopups(self):
- print 'Entrou funcao clear_popups'
- if isHostPopup == True:
- print 'Hostpopup = true'
- self.hostPopup.unpost
- isHostPopup = False
- #if isRouterPopup == True
- #if isLinkPopup == True
-
- def nodeIcon( self, node, name ):
- "Create a new node icon."
- icon = Button( self.canvas, image=self.images[ node ],
- text=name, compound='top' )
- # Unfortunately bindtags wants a tuple
- bindtags = [ str( self.nodeBindings ) ]
- bindtags += list( icon.bindtags() )
- icon.bindtags( tuple( bindtags ) )
- return icon
-
- def newNode( self, node, event ):
- "Add a new node to our canvas."
- c = self.canvas
- x, y = c.canvasx( event.x ), c.canvasy( event.y )
- name = self.nodePrefixes[ node ]
-
- if 'LegacyRouter' == node:
- self.routerCount += 1
- name = self.nodePrefixes[ node ] + str( self.routerCount )
- self.routerOpts[name] = {}
- self.routerOpts[name]['nodeNum']=self.routerCount
- self.routerOpts[name]['hostname']=name
- self.routerOpts[name]['nodeType']='legacyRouter'
-
- if 'Host' == node:
- self.hostCount += 1
- name = self.nodePrefixes[ node ] + str( self.hostCount )
- self.hostOpts[name] = {'sched':'host'}
- self.hostOpts[name]['nodeNum']=self.hostCount
- self.hostOpts[name]['hostname']=name
-
- if 'Switch' == node:
- self.switchCount += 1
- name = self.nodePrefixes[ node ] + str( self.switchCount )
- self.switchOpts[name] = {}
- self.switchOpts[name]['nodeNum']=self.switchCount
- self.switchOpts[name]['hostname']=name
-
- icon = self.nodeIcon( node, name )
- item = self.canvas.create_window( x, y, anchor='c', window=icon,
- tags=node )
- self.widgetToItem[ icon ] = item
- self.itemToWidget[ item ] = icon
- self.selectItem( item )
- icon.links = {}
- if 'LegacyRouter' == node:
- icon.bind('<Button-3>', self.do_legacyRouterPopup )
- if 'Host' == node:
- icon.bind('<Button-3>', self.do_hostPopup )
-
- def clickHost( self, event ):
- "Add a new host to our canvas."
- self.newNode( 'Host', event )
-
- def clickSwitch( self, event ):
- "Add a new switch to the canvas."
- self.newNode( 'Switch', event )
-
- def clickLegacyRouter( self, event ):
- "Add a new router to our canvas."
- self.newNode( 'LegacyRouter', event )
-
- def dragNetLink( self, event ):
- "Drag a link's endpoint to another node."
- if self.link is None:
- return
- # Since drag starts in widget, we use root coords
- x = self.canvasx( event.x_root )
- y = self.canvasy( event.y_root )
- c = self.canvas
- c.coords( self.link, self.linkx, self.linky, x, y )
-
- def releaseNetLink( self, _event ):
- "Give up on the current link."
- if self.link is not None:
- self.canvas.delete( self.link )
- self.linkWidget = self.linkItem = self.link = None
-
- # Generic node handlers
-
- def createNodeBindings( self ):
- "Create a set of bindings for nodes."
- bindings = {
- '<ButtonPress-1>': self.clickNode,
- '<B1-Motion>': self.dragNode,
- '<ButtonRelease-1>': self.releaseNode,
- '<Enter>': self.enterNode,
- '<Leave>': self.leaveNode
- }
- l = Label() # lightweight-ish owner for bindings
- for event, binding in bindings.items():
- l.bind( event, binding )
- return l
-
- def selectItem( self, item ):
- "Select an item and remember old selection."
- self.lastSelection = self.selection
- self.selection = item
-
- def enterNode( self, event ):
- "Select node on entry."
- self.selectNode( event )
-
- def leaveNode( self, _event ):
- "Restore old selection on exit."
- self.selectItem( self.lastSelection )
-
- def clickNode( self, event ):
- "Node click handler."
- if self.active is 'NetLink':
- self.startLink( event )
- else:
- self.selectNode( event )
- return 'break'
-
- def dragNode( self, event ):
- "Node drag handler."
- if self.active is 'NetLink':
- self.dragNetLink( event )
- else:
- self.dragNodeAround( event )
-
- def releaseNode( self, event ):
- "Node release handler."
- if self.active is 'NetLink':
- self.finishLink( event )
-
- # Specific node handlers
-
- def selectNode( self, event ):
- "Select the node that was clicked on."
- item = self.widgetToItem.get( event.widget, None )
- self.selectItem( item )
-
- def dragNodeAround( self, event ):
- "Drag a node around on the canvas."
- c = self.canvas
- # Convert global to local coordinates;
- # Necessary since x, y are widget-relative
- x = self.canvasx( event.x_root )
- y = self.canvasy( event.y_root )
- w = event.widget
- # Adjust node position
- item = self.widgetToItem[ w ]
- c.coords( item, x, y )
- # Adjust link positions
- for dest in w.links:
- link = w.links[ dest ]
- item = self.widgetToItem[ dest ]
- x1, y1 = c.coords( item )
- c.coords( link, x, y, x1, y1 )
- self.updateScrollRegion()
-
- def createDataLinkBindings( self ):
- "Create a set of bindings for nodes."
- # Link bindings
- # Selection still needs a bit of work overall
- # Callbacks ignore event
-
- def select( _event, link=self.link ):
- "Select item on mouse entry."
- self.selectItem( link )
-
- def highlight( _event, link=self.link ):
- "Highlight item on mouse entry."
- self.selectItem( link )
- self.canvas.itemconfig( link, fill='green' )
-
- def unhighlight( _event, link=self.link ):
- "Unhighlight item on mouse exit."
- self.canvas.itemconfig( link, fill='blue' )
- #self.selectItem( None )
-
- self.canvas.tag_bind( self.link, '<Enter>', highlight )
- self.canvas.tag_bind( self.link, '<Leave>', unhighlight )
- self.canvas.tag_bind( self.link, '<ButtonPress-1>', select )
- self.canvas.tag_bind( self.link, '<Button-3>', self.do_linkPopup )
-
- def startLink( self, event ):
- "Start a new link."
- if event.widget not in self.widgetToItem:
- # Didn't click on a node
- return
-
- w = event.widget
- item = self.widgetToItem[ w ]
- x, y = self.canvas.coords( item )
- self.link = self.canvas.create_line( x, y, x, y, width=4,
- fill='blue', tag='link' )
- self.linkx, self.linky = x, y
- self.linkWidget = w
- self.linkItem = item
-
- def finishLink( self, event ):
- "Finish creating a link"
- if self.link is None:
- return
- source = self.linkWidget
- c = self.canvas
- # Since we dragged from the widget, use root coords
- x, y = self.canvasx( event.x_root ), self.canvasy( event.y_root )
- target = self.findItem( x, y )
- dest = self.itemToWidget.get( target, None )
- if ( source is None or dest is None or source == dest
- or dest in source.links or source in dest.links ):
- self.releaseNetLink( event )
- return
- # For now, don't allow hosts to be directly linked
- stags = self.canvas.gettags( self.widgetToItem[ source ] )
- dtags = self.canvas.gettags( target )
- #if (('Host' in stags and 'Host' in dtags)):
- #self.releaseNetLink( event )
- #return
-
- # Set link type
- linkType='data'
-
- self.createDataLinkBindings()
- c.itemconfig(self.link, tags=c.gettags(self.link)+(linkType,))
-
- x, y = c.coords( target )
- c.coords( self.link, self.linkx, self.linky, x, y )
- self.addLink( source, dest, linktype=linkType )
-
- # We're done
- self.link = self.linkWidget = None
-
- # Menu handlers
-
- def about( self ):
- "Display about box."
- about = self.aboutBox
- if about is None:
- bg = 'white'
- about = Toplevel( bg='white' )
- about.title( 'About' )
- info = self.appName + ': a simple network editor for MiniNDN - based on Miniedit'
- warning = 'Development version - not entirely functional!'
- #version = 'MiniEdit '+MINIEDIT_VERSION
- author = 'Vince Lehman, Jan 2015'
- author2 = 'Ashlesh Gawande, Jan 2015'
- author3 = 'Carlos Cabral, Jan 2013'
- author4 = 'Caio Elias, Nov 2014'
- author5 = 'Originally by: Bob Lantz <rlantz@cs>, April 2010'
- enhancements = 'Enhancements by: Gregory Gee, Since July 2013'
- www = 'http://gregorygee.wordpress.com/category/miniedit/'
- line1 = Label( about, text=info, font='Helvetica 10 bold', bg=bg )
- line2 = Label( about, text=warning, font='Helvetica 9', bg=bg )
- line3 = Label( about, text=author, font='Helvetica 9', bg=bg )
- line4 = Label( about, text=author2, font='Helvetica 9', bg=bg )
- line5 = Label( about, text=author3, font='Helvetica 9', bg=bg )
- line6 = Label( about, text=author4, font='Helvetica 9', bg=bg )
- line7 = Label( about, text=author5, font='Helvetica 9', bg=bg )
- line8 = Label( about, text=enhancements, font='Helvetica 9', bg=bg )
- line9 = Entry( about, font='Helvetica 9', bg=bg, width=len(www), justify=CENTER )
-
-
- line9.insert(0, www)
- line9.configure(state='readonly')
- line1.pack( padx=20, pady=10 )
- line2.pack(pady=10 )
- line3.pack(pady=10 )
- line4.pack(pady=10 )
- line5.pack(pady=10 )
- line6.pack(pady=10 )
- line7.pack(pady=10 )
- line8.pack(pady=10 )
- line9.pack(pady=10 )
- hide = ( lambda about=about: about.withdraw() )
- self.aboutBox = about
- # Hide on close rather than destroying window
- Wm.wm_protocol( about, name='WM_DELETE_WINDOW', func=hide )
- # Show (existing) window
- about.deiconify()
-
- def createToolImages( self ):
- "Create toolbar (and icon) images."
-
- def hostDetails( self, _ignore=None ):
- if ( self.selection is None or
- self.net is not None or
- self.selection not in self.itemToWidget ):
- return
- widget = self.itemToWidget[ self.selection ]
- name = widget[ 'text' ]
- tags = self.canvas.gettags( self.selection )
-
- #print tags
- if 'Host' in tags:
-
- prefDefaults = self.hostOpts[name]
- hostBox = HostDialog(self, title='Host Details', prefDefaults=prefDefaults, isRouter='False')
- self.master.wait_window(hostBox.top)
- if hostBox.result:
- newHostOpts = {'nodeNum':self.hostOpts[name]['nodeNum']}
-
- if len(hostBox.result['startCommand']) > 0:
- newHostOpts['startCommand'] = hostBox.result['startCommand']
- if hostBox.result['cpu']:
- newHostOpts['cpu'] = hostBox.result['cpu']
- if hostBox.result['mem']:
- newHostOpts['mem'] = hostBox.result['mem']
- if len(hostBox.result['hostname']) > 0:
- newHostOpts['hostname'] = hostBox.result['hostname']
- name = hostBox.result['hostname']
- widget[ 'text' ] = name
- if len(hostBox.result['cache']) > 0:
- newHostOpts['cache'] = hostBox.result['cache']
-
- newHostOpts['nlsr'] = hostBox.nlsrFrame.getValues()
- newHostOpts['nfd'] = hostBox.nfdFrame.getValues()
-
- self.hostOpts[name] = newHostOpts
-
- print 'New host details for ' + name + ' = ' + str(newHostOpts)
-
- elif 'LegacyRouter' in tags:
-
- prefDefaults = self.routerOpts[name]
- hostBox = HostDialog(self, title='Router Details', prefDefaults=prefDefaults, isRouter='True')
- self.master.wait_window(hostBox.top)
- if hostBox.result:
- newRouterOpts = {'nodeNum':self.routerOpts[name]['nodeNum']}
-
- if hostBox.result['cpu']:
- newRouterOpts['cpu'] = hostBox.result['cpu']
- if hostBox.result['mem']:
- newRouterOpts['mem'] = hostBox.result['mem']
- if len(hostBox.result['hostname']) > 0:
- newRouterOpts['hostname'] = hostBox.result['hostname']
- name = hostBox.result['hostname']
- widget[ 'text' ] = name
- if len(hostBox.result['cache']) > 0:
- newRouterOpts['cache'] = hostBox.result['cache']
- self.routerOpts[name] = newRouterOpts
-
- print 'New host details for ' + name + ' = ' + str(newRouterOpts)
-
- def linkDetails( self, _ignore=None ):
- if ( self.selection is None or
- self.net is not None):
- return
- link = self.selection
-
- linkDetail = self.links[link]
- src = linkDetail['src']
- dest = linkDetail['dest']
- linkopts = linkDetail['linkOpts']
- linkBox = LinkDialog(self, title='Link Details', linkDefaults=linkopts)
- if linkBox.result is not None:
- linkDetail['linkOpts'] = linkBox.result
- print 'New link details = ' + str(linkBox.result)
-
- # Model interface
- #
- # Ultimately we will either want to use a topo or
- # mininet object here, probably.
-
- def addLink( self, source, dest, linktype='data', linkopts={} ):
- "Add link to model."
- source.links[ dest ] = self.link
- dest.links[ source ] = self.link
- self.links[ self.link ] = {'type' :linktype,
- 'src':source,
- 'dest':dest,
- 'linkOpts':linkopts}
-
- def deleteLink( self, link ):
- "Delete link from model."
- pair = self.links.get( link, None )
- if pair is not None:
- source=pair['src']
- dest=pair['dest']
- del source.links[ dest ]
- del dest.links[ source ]
- stags = self.canvas.gettags( self.widgetToItem[ source ] )
- dtags = self.canvas.gettags( self.widgetToItem[ dest ] )
- ltags = self.canvas.gettags( link )
-
- if link is not None:
- del self.links[ link ]
-
- def deleteNode( self, item ):
- "Delete node (and its links) from model."
-
- widget = self.itemToWidget[ item ]
- tags = self.canvas.gettags(item)
-
- for link in widget.links.values():
- # Delete from view and model
- self.deleteItem( link )
- del self.itemToWidget[ item ]
- del self.widgetToItem[ widget ]
-
- def do_linkPopup(self, event):
- # display the popup menu
- if ( self.net is None ):
- try:
- self.linkPopup.tk_popup(event.x_root, event.y_root)
- finally:
- # make sure to release the grab (Tk 8.0a1 only)
- self.linkPopup.grab_release()
-
- def do_legacyRouterPopup(self, event):
- # display the popup menu
- if ( self.net is None ):
- try:
- self.legacyRouterPopup.tk_popup(event.x_root, event.y_root)
- finally:
- # make sure to release the grab (Tk 8.0a1 only)
- self.legacyRouterPopup.grab_release()
-
- def do_hostPopup(self, event):
- # display the popup menu
- if ( self.net is None ):
- try:
- self.hostPopup.tk_popup(event.x_root, event.y_root)
- isHostPopup = True
- finally:
- # make sure to release the grab (Tk 8.0a1 only)
- self.hostPopup.grab_release()
-
- def xterm( self, _ignore=None ):
- "Make an xterm when a button is pressed."
- if ( self.selection is None or
- self.net is None or
- self.selection not in self.itemToWidget ):
- return
- name = self.itemToWidget[ self.selection ][ 'text' ]
- if name not in self.net.nameToNode:
- return
- term = makeTerm( self.net.nameToNode[ name ], 'Host', term=self.appPrefs['terminalType'] )
- if StrictVersion(MININET_VERSION) > StrictVersion('2.0'):
- self.net.terms += term
- else:
- self.net.terms.append(term)
-
- def iperf( self, _ignore=None ):
- "Make an xterm when a button is pressed."
- if ( self.selection is None or
- self.net is None or
- self.selection not in self.itemToWidget ):
- return
- name = self.itemToWidget[ self.selection ][ 'text' ]
- if name not in self.net.nameToNode:
- return
- self.net.nameToNode[ name ].cmd( 'iperf -s -p 5001 &' )
-
- """ BELOW HERE IS THE TOPOLOGY IMPORT CODE """
-
- def parseArgs( self ):
- """Parse command-line args and return options object.
- returns: opts parse options dict"""
-
- if '--custom' in sys.argv:
- index = sys.argv.index( '--custom' )
- if len( sys.argv ) > index + 1:
- filename = sys.argv[ index + 1 ]
- self.parseCustomFile( filename )
- else:
- raise Exception( 'Custom file name not found' )
-
- desc = ( "The %prog utility creates Minindn network from the\n"
- "command line. It can create parametrized topologies,\n"
- "invoke the Minindn CLI, and run tests." )
-
- usage = ( '%prog [options] [template_file]\n'
- '\nIf no template_file is given, generated template will be written to the file minindn.conf in the current directory.\n'
- 'Type %prog -h for details)' )
-
- opts = OptionParser( description=desc, usage=usage )
-
- addDictOption( opts, TOPOS, TOPODEF, 'topo' )
- addDictOption( opts, LINKS, LINKDEF, 'link' )
-
- opts.add_option( '--custom', type='string', default=None,
- help='read custom topo and node params from .py' +
- 'file' )
-
- self.options, self.args = opts.parse_args()
- # We don't accept extra arguments after the options
- if self.args:
- if len(self.args) > 1:
- opts.print_help()
- exit()
- else:
- self.template_file=self.args[0]
-
- def setCustom( self, name, value ):
- "Set custom parameters for MininetRunner."
- if name in ( 'topos', 'switches', 'hosts', 'controllers' ):
- # Update dictionaries
- param = name.upper()
- globals()[ param ].update( value )
- elif name == 'validate':
- # Add custom validate function
- self.validate = value
- else:
- # Add or modify global variable or class
- globals()[ name ] = value
-
- def parseCustomFile( self, fileName ):
- "Parse custom file and add params before parsing cmd-line options."
- customs = {}
- if os.path.isfile( fileName ):
- execfile( fileName, customs, customs )
- for name, val in customs.iteritems():
- self.setCustom( name, val )
- else:
- raise Exception( 'could not find custom file: %s' % fileName )
-
- def importTopo( self ):
- print 'topo='+self.options.topo
- if self.options.topo == 'none':
- return
- self.newTopology()
- topo = buildTopo( TOPOS, self.options.topo )
- link = customConstructor( LINKS, self.options.link )
- importNet = Mininet(topo=topo, build=False, link=link)
- importNet.build()
-
- c = self.canvas
- rowIncrement = 100
- currentY = 100
-
- # Add switches
- print 'switches:'+str(len(importNet.switches))
- columnCount = 0
- for switch in importNet.switches:
- name = switch.name
- self.switchOpts[name] = {}
- self.switchOpts[name]['nodeNum']=self.switchCount
- self.switchOpts[name]['hostname']=name
- self.switchOpts[name]['switchType']='default'
- self.switchOpts[name]['controllers']=[]
-
- x = columnCount*100+100
- self.addNode('Switch', self.switchCount,
- float(x), float(currentY), name=name)
- icon = self.findWidgetByName(name)
- icon.bind('<Button-3>', self.do_switchPopup )
-
- if columnCount == 9:
- columnCount = 0
- currentY = currentY + rowIncrement
- else:
- columnCount =columnCount+1
-
- currentY = currentY + rowIncrement
- # Add hosts
- print 'hosts:'+str(len(importNet.hosts))
- columnCount = 0
- for host in importNet.hosts:
- name = host.name
- self.hostOpts[name] = {'sched':'host'}
- self.hostOpts[name]['nodeNum']=self.hostCount
- self.hostOpts[name]['hostname']=name
- #self.hostOpts[name]['ip']=host.IP()
-
- x = columnCount*100+100
- self.addNode('Host', self.hostCount,
- float(x), float(currentY), name=name)
- icon = self.findWidgetByName(name)
- icon.bind('<Button-3>', self.do_hostPopup )
- if columnCount == 9:
- columnCount = 0
- currentY = currentY + rowIncrement
- else:
- columnCount =columnCount+1
-
- print 'links:'+str(len(topo.links()))
- #[('h1', 's3'), ('h2', 's4'), ('s3', 's4')]
- for link in topo.links():
- print str(link)
- srcNode = link[0]
- src = self.findWidgetByName(srcNode)
- sx, sy = self.canvas.coords( self.widgetToItem[ src ] )
-
- destNode = link[1]
- dest = self.findWidgetByName(destNode)
- dx, dy = self.canvas.coords( self.widgetToItem[ dest] )
-
- params = topo.linkInfo( srcNode, destNode )
- print 'Link Parameters='+str(params)
-
- self.link = self.canvas.create_line( sx, sy, dx, dy, width=4,
- fill='blue', tag='link' )
- c.itemconfig(self.link, tags=c.gettags(self.link)+('data',))
- self.addLink( src, dest, linkopts=params )
- self.createDataLinkBindings()
- self.link = self.linkWidget = None
-
- importNet.stop()
-
-def miniEditImages():
- "Create and return images for MiniEdit."
-
- # Image data. Git will be unhappy. However, the alternative
- # is to keep track of separate binary files, which is also
- # unappealing.
-
- return {
- 'Select': BitmapImage(
- file='/usr/include/X11/bitmaps/left_ptr' ),
-
- 'LegacyRouter': PhotoImage( data=r"""
- R0lGODlhMgAYAPcAAAEBAXZ8gQNAgL29vQNctjl/xVSa4j1dfCF+
- 3QFq1DmL3wJMmAMzZZW11dnZ2SFrtyNdmTSO6gIZMUKa8gJVqEOH
- zR9Pf5W74wFjxgFx4jltn+np6Eyi+DuT6qKiohdtwwUPGWiq6ymF
- 4LHH3Rh11CV81kKT5AMoUA9dq1ap/mV0gxdXlytRdR1ptRNPjTt9
- vwNgvwJZsX+69gsXJQFHjTtjizF0tvHx8VOm9z2V736Dhz2N3QM2
- acPZ70qe8gFo0HS19wVRnTiR6hMpP0eP1i6J5iNlqAtgtktjfQFu
- 3TNxryx4xAMTIzOE1XqAh1uf5SWC4AcfNy1XgQJny93n8a2trRh3
- 12Gt+VGm/AQIDTmByAF37QJasydzvxM/ayF3zhdLf8zLywFdu4i5
- 6gFlyi2J4yV/1w8wUo2/8j+X8D2Q5Eee9jeR7Uia7DpeggFt2QNP
- m97e3jRong9bpziH2DuT7aipqQoVICmG45vI9R5720eT4Q1hs1er
- /yVVhwJJktPh70tfdbHP7Xev5xs5V7W1sz9jhz11rUVZcQ9WoCVV
- hQk7cRdtwWuw9QYOFyFHbSBnr0dznxtWkS18zKfP9wwcLAMHCwFF
- iS5UeqGtuRNNiwMfPS1hlQMtWRE5XzGM5yhxusLCwCljnwMdOFWh
- 7cve8pG/7Tlxp+Tr8g9bpXF3f0lheStrrYu13QEXLS1ppTV3uUuR
- 1RMjNTF3vU2X4TZupwRSolNne4nB+T+L2YGz4zJ/zYe99YGHjRdD
- cT95sx09XQldsgMLEwMrVc/X3yN3yQ1JhTRbggsdMQNfu9HPz6Wl
- pW2t7RctQ0GFyeHh4dvl8SBZklCb5kOO2kWR3Vmt/zdjkQIQHi90
- uvPz8wIVKBp42SV5zbfT7wtXpStVfwFWrBVvyTt3swFz5kGBv2+1
- /QlbrVFjdQM7d1+j54i67UmX51qn9i1vsy+D2TuR5zddhQsjOR1t
- u0GV6ghbsDVZf4+76RRisent8Xd9hQFBgwFNmwJLlcPDwwFr1z2T
- 5yH5BAEAAAAALAAAAAAyABgABwj/AAEIHEiQYJY7Qwg9UsTplRIb
- ENuxEiXJgpcz8e5YKsixY8Essh7JcbbOBwcOa1JOmJAmTY4cHeoI
- abJrCShI0XyB8YRso0eOjoAdWpciBZajJ1GuWcnSZY46Ed5N8hPA
- TqEBoRB9gVJsxRlhPwHI0kDkVywcRpGe9LF0adOnMpt8CxDnxg1o
- 9lphKoEACoIvmlxxvHOKVg0n/Tzku2WoVoU2J1P6WNkSrtwADuxC
- G/MOjwgRUEIjGG3FhaOBzaThiDSCil27G8Isc3LLjZwXsA6YYJmD
- jhTMmseoKQIFDx7RoxHo2abnwygAlUj1mV6tWjlelEpRwfd6gzI7
- VeJQ/2vZoVaDUqigqftXpH0R46H9Kl++zUo4JnKq9dGvv09RHFhc
- IUMe0NiFDyql0OJUHWywMc87TXRhhCRGiHAccvNZUR8JxpDTH38p
- 9HEUFhxgMSAvjbBjQge8PSXEC6uo0IsHA6gAAShmgCbffNtsQwIJ
- ifhRHX/TpUUiSijlUk8AqgQixSwdNBjCa7CFoVggmEgCyRf01WcF
- CYvYUgB104k4YlK5HONEXXfpokYdMrXRAzMhmNINNNzB9p0T57Ag
- yZckpKKPGFNgw06ZWKR10jTw6MAmFWj4AJcQQkQQwSefvFeGCemM
- IQggeaJywSQ/wgHOAmJskQEfWqBlFBEH1P/QaGY3QOpDZXA2+A6m
- 7hl3IRQKGDCIAj6iwE8yGKC6xbJv8IHNHgACQQybN2QiTi5NwdlB
- pZdiisd7vyanByOJ7CMGGRhgwE+qyy47DhnBPLDLEzLIAEQjBtCh
- RmVPNWgpr+Be+Nc9icARww9TkIEuDAsQ0O7DzGIQzD2QdDEJHTsI
- AROc3F7qWQncyHPPHN5QQAAG/vjzw8oKp8sPPxDH3O44/kwBQzLB
- xBCMOTzzHEMMBMBARgJvZJBBEm/4k0ACKydMBgwYoKNNEjJXbTXE
- 42Q9jtFIp8z0Dy1jQMA1AGziz9VoW7310V0znYDTGMQgwUDXLDBO
- 2nhvoTXbbyRk/XXL+pxWkAT8UJ331WsbnbTSK8MggDZhCTOMLQkc
- jvXeSPedAAw0nABWWARZIgEDfyTzxt15Z53BG1PEcEknrvgEelhZ
- MDHKCTwI8EcQFHBBAAFcgGPLHwLwcMIo12Qxu0ABAQA7
- """),
-
- 'Host': PhotoImage( data=r"""
- R0lGODlhIAAYAPcAMf//////zP//mf//Zv//M///AP/M///MzP/M
- mf/MZv/MM//MAP+Z//+ZzP+Zmf+ZZv+ZM/+ZAP9m//9mzP9mmf9m
- Zv9mM/9mAP8z//8zzP8zmf8zZv8zM/8zAP8A//8AzP8Amf8AZv8A
- M/8AAMz//8z/zMz/mcz/Zsz/M8z/AMzM/8zMzMzMmczMZszMM8zM
- AMyZ/8yZzMyZmcyZZsyZM8yZAMxm/8xmzMxmmcxmZsxmM8xmAMwz
- /8wzzMwzmcwzZswzM8wzAMwA/8wAzMwAmcwAZswAM8wAAJn//5n/
- zJn/mZn/Zpn/M5n/AJnM/5nMzJnMmZnMZpnMM5nMAJmZ/5mZzJmZ
- mZmZZpmZM5mZAJlm/5lmzJlmmZlmZplmM5lmAJkz/5kzzJkzmZkz
- ZpkzM5kzAJkA/5kAzJkAmZkAZpkAM5kAAGb//2b/zGb/mWb/Zmb/
- M2b/AGbM/2bMzGbMmWbMZmbMM2bMAGaZ/2aZzGaZmWaZZmaZM2aZ
- AGZm/2ZmzGZmmWZmZmZmM2ZmAGYz/2YzzGYzmWYzZmYzM2YzAGYA
- /2YAzGYAmWYAZmYAM2YAADP//zP/zDP/mTP/ZjP/MzP/ADPM/zPM
- zDPMmTPMZjPMMzPMADOZ/zOZzDOZmTOZZjOZMzOZADNm/zNmzDNm
- mTNmZjNmMzNmADMz/zMzzDMzmTMzZjMzMzMzADMA/zMAzDMAmTMA
- ZjMAMzMAAAD//wD/zAD/mQD/ZgD/MwD/AADM/wDMzADMmQDMZgDM
- MwDMAACZ/wCZzACZmQCZZgCZMwCZAABm/wBmzABmmQBmZgBmMwBm
- AAAz/wAzzAAzmQAzZgAzMwAzAAAA/wAAzAAAmQAAZgAAM+4AAN0A
- ALsAAKoAAIgAAHcAAFUAAEQAACIAABEAAADuAADdAAC7AACqAACI
- AAB3AABVAABEAAAiAAARAAAA7gAA3QAAuwAAqgAAiAAAdwAAVQAA
- RAAAIgAAEe7u7t3d3bu7u6qqqoiIiHd3d1VVVURERCIiIhEREQAA
- ACH5BAEAAAAALAAAAAAgABgAAAiNAAH8G0iwoMGDCAcKTMiw4UBw
- BPXVm0ixosWLFvVBHFjPoUeC9Tb+6/jRY0iQ/8iVbHiS40CVKxG2
- HEkQZsyCM0mmvGkw50uePUV2tEnOZkyfQA8iTYpTKNOgKJ+C3AhO
- p9SWVaVOfWj1KdauTL9q5UgVbFKsEjGqXVtP40NwcBnCjXtw7tx/
- C8cSBBAQADs=
- """ ),
-
- 'Switch': PhotoImage( data=r"""
- R0lGODlhMgAYAPcAAAEBAXmDjbe4uAE5cjF7xwFWq2Sa0S9biSlrrdTW1k2Ly02a5xUvSQFHjmep
- 6bfI2Q5SlQIYLwFfvj6M3Jaan8fHyDuFzwFp0Vah60uU3AEiRhFgrgFRogFr10N9uTFrpytHYQFM
- mGWt9wIwX+bm5kaT4gtFgR1cnJPF9yt80CF0yAIMGHmp2c/P0AEoUb/P4Fei7qK4zgpLjgFkyQlf
- t1mf5jKD1WWJrQ86ZwFAgBhYmVOa4MPV52uv8y+A0iR3ywFbtUyX5ECI0Q1UmwIcOUGQ3RBXoQI0
- aRJbpr3BxVeJvQUJDafH5wIlS2aq7xBmv52lr7fH12el5Wml3097ph1ru7vM3HCz91Ke6lid40KQ
- 4GSQvgQGClFnfwVJjszMzVCX3hljrdPT1AFLlBRnutPf6yd5zjeI2QE9eRBdrBNVl+3v70mV4ydf
- lwMVKwErVlul8AFChTGB1QE3bsTFxQImTVmAp0FjiUSM1k+b6QQvWQ1SlxMgLgFixEqU3xJhsgFT
- pn2Xs5OluZ+1yz1Xb6HN+Td9wy1zuYClykV5r0x2oeDh4qmvt8LDwxhuxRlLfyRioo2124mft9bi
- 71mDr7fT79nl8Z2hpQs9b7vN4QMQIOPj5XOPrU2Jx32z6xtvwzeBywFFikFnjwcPFa29yxJjuFmP
- xQFv3qGxwRc/Z8vb6wsRGBNqwqmpqTdvqQIbNQFPngMzZAEfP0mQ13mHlQFYsAFnznOXu2mPtQxj
- vQ1Vn4Ot1+/x8my0/CJgnxNNh8DT5CdJaWyx+AELFWmt8QxPkxBZpwMFB015pgFduGCNuyx7zdnZ
- 2WKm6h1xyOPp8aW70QtPkUmM0LrCyr/FyztljwFPm0OJzwFny7/L1xFjswE/e12i50iR2VR8o2Gf
- 3xszS2eTvz2BxSlloQdJiwMHDzF3u7bJ3T2I1WCp8+Xt80FokQFJklef6mORw2ap7SJ1y77Q47nN
- 3wFfu1Kb5cXJyxdhrdDR0wlNkTSF11Oa4yp4yQEuW0WQ3QIDBQI7dSH5BAEAAAAALAAAAAAyABgA
- Bwj/AAEIHDjKF6SDvhImPMHwhA6HOiLqUENRDYSLEIplxBcNHz4Z5GTI8BLKS5OBA1Ply2fDhxwf
- PlLITGFmmRkzP+DlVKHCmU9nnz45csSqKKsn9gileZKrVC4aRFACOGZu5UobNuRohRkzhc2b+36o
- qCaqrFmzZEV1ERBg3BOmMl5JZTBhwhm7ZyycYZnvJdeuNl21qkCHTiPDhxspTtKoQgUKCJ6wehMV
- 5QctWupeo6TkjOd8e1lmdQkTGbTTMaDFiDGINeskX6YhEicUiQa5A/kUKaFFwQ0oXzjZ8Tbcm3Hj
- irwpMtTSgg9QMJf5WEZ9375AiED19ImpSQSUB4Kw/8HFSMyiRWJaqG/xhf2X91+oCbmq1e/MFD/2
- EcApVkWVJhp8J9AqsywQxDfAbLJJPAy+kMkL8shjxTkUnhOJZ5+JVp8cKfhwxwdf4fQLgG4MFAwW
- KOZRAxM81EAPPQvoE0QQfrDhx4399OMBMjz2yCMVivCoCAWXKLKMTPvoUYcsKwi0RCcwYCAlFjU0
- A6OBM4pXAhsl8FYELYWFWZhiZCbRQgIC2AGTLy408coxAoEDx5wwtGPALTVg0E4NKC7gp4FsBKoA
- Ki8U+oIVmVih6DnZPMBMAlGwIARWOLiggSYC+ZNIOulwY4AkSZCyxaikbqHMqaeaIp4+rAaxQxBg
- 2P+IozuRzvLZIS4syYVAfMAhwhSC1EPCGoskIIYY9yS7Hny75OFnEIAGyiVvWkjjRxF11fXIG3WU
- KNA6wghDTCW88PKMJZOkm24Z7LarSjPtoIjFn1lKyyVmmBVhwRtvaDDMgFL0Eu4VhaiDwhXCXNFD
- D8QQw7ATEDsBw8RSxotFHs7CKJ60XWrRBj91EOGPQCA48c7J7zTjSTPctOzynjVkkYU+O9S8Axg4
- Z6BzBt30003Ps+AhNB5C4PCGC5gKJMMTZJBRytOl/CH1HxvQkMbVVxujtdZGGKGL17rsEfYQe+xR
- zNnFcGQCv7LsKlAtp8R9Sgd0032BLXjPoPcMffTd3YcEgAMOxOBA1GJ4AYgXAMjiHDTgggveCgRI
- 3RfcnffefgcOeDKEG3444osDwgEspMNiTQhx5FoOShxcrrfff0uQjOycD+554qFzMHrpp4cwBju/
- 5+CmVNbArnntndeCO+O689777+w0IH0o1P/TRJMohRA4EJwn47nyiocOSOmkn/57COxE3wD11Mfh
- fg45zCGyVF4Ufvvyze8ewv5jQK9++6FwXxzglwM0GPAfR8AeSo4gwAHCbxsQNCAa/kHBAVhwAHPI
- 4BE2eIRYeHAEIBwBP0Y4Qn41YWRSCQgAOw==
- """ ),
-
- 'NetLink': PhotoImage( data=r"""
- R0lGODlhFgAWAPcAMf//////zP//mf//Zv//M///AP/M///MzP/M
- mf/MZv/MM//MAP+Z//+ZzP+Zmf+ZZv+ZM/+ZAP9m//9mzP9mmf9m
- Zv9mM/9mAP8z//8zzP8zmf8zZv8zM/8zAP8A//8AzP8Amf8AZv8A
- M/8AAMz//8z/zMz/mcz/Zsz/M8z/AMzM/8zMzMzMmczMZszMM8zM
- AMyZ/8yZzMyZmcyZZsyZM8yZAMxm/8xmzMxmmcxmZsxmM8xmAMwz
- /8wzzMwzmcwzZswzM8wzAMwA/8wAzMwAmcwAZswAM8wAAJn//5n/
- zJn/mZn/Zpn/M5n/AJnM/5nMzJnMmZnMZpnMM5nMAJmZ/5mZzJmZ
- mZmZZpmZM5mZAJlm/5lmzJlmmZlmZplmM5lmAJkz/5kzzJkzmZkz
- ZpkzM5kzAJkA/5kAzJkAmZkAZpkAM5kAAGb//2b/zGb/mWb/Zmb/
- M2b/AGbM/2bMzGbMmWbMZmbMM2bMAGaZ/2aZzGaZmWaZZmaZM2aZ
- AGZm/2ZmzGZmmWZmZmZmM2ZmAGYz/2YzzGYzmWYzZmYzM2YzAGYA
- /2YAzGYAmWYAZmYAM2YAADP//zP/zDP/mTP/ZjP/MzP/ADPM/zPM
- zDPMmTPMZjPMMzPMADOZ/zOZzDOZmTOZZjOZMzOZADNm/zNmzDNm
- mTNmZjNmMzNmADMz/zMzzDMzmTMzZjMzMzMzADMA/zMAzDMAmTMA
- ZjMAMzMAAAD//wD/zAD/mQD/ZgD/MwD/AADM/wDMzADMmQDMZgDM
- MwDMAACZ/wCZzACZmQCZZgCZMwCZAABm/wBmzABmmQBmZgBmMwBm
- AAAz/wAzzAAzmQAzZgAzMwAzAAAA/wAAzAAAmQAAZgAAM+4AAN0A
- ALsAAKoAAIgAAHcAAFUAAEQAACIAABEAAADuAADdAAC7AACqAACI
- AAB3AABVAABEAAAiAAARAAAA7gAA3QAAuwAAqgAAiAAAdwAAVQAA
- RAAAIgAAEe7u7t3d3bu7u6qqqoiIiHd3d1VVVURERCIiIhEREQAA
- ACH5BAEAAAAALAAAAAAWABYAAAhIAAEIHEiwoEGBrhIeXEgwoUKG
- Cx0+hGhQoiuKBy1irChxY0GNHgeCDAlgZEiTHlFuVImRJUWXEGEy
- lBmxI8mSNknm1Dnx5sCAADs=
- """ )
- }
-
-def addDictOption( opts, choicesDict, default, name, helpStr=None ):
- """Convenience function to add choices dicts to OptionParser.
- opts: OptionParser instance
- choicesDict: dictionary of valid choices, must include default
- default: default choice key
- name: long option name
- help: string"""
- if default not in choicesDict:
- raise Exception( 'Invalid default %s for choices dict: %s' %
- ( default, name ) )
- if not helpStr:
- helpStr = ( '|'.join( sorted( choicesDict.keys() ) ) +
- '[,param=value...]' )
- opts.add_option( '--' + name,
- type='string',
- default = default,
- help = helpStr )
-
-if __name__ == '__main__':
- setLogLevel( 'info' )
- app = MiniEdit()
- """ import topology if specified """
- app.parseArgs()
- app.importTopo()
-
- global isHostPopup
- global isRouterPopup
- global isLinkPopup
-
- app.mainloop()
diff --git a/docs/CLUSTER.md b/docs/CLUSTER.md
deleted file mode 100644
index e1e52ad..0000000
--- a/docs/CLUSTER.md
+++ /dev/null
@@ -1,25 +0,0 @@
-Mini-NDN cluster edition
-========================
-
-Mini-NDN cluster edition uses the experimental Mininet cluster edition.
-**Make sure that you can run the Mininet cluster edition by following
-[these instructions](https://github.com/mininet/mininet/wiki/Cluster-Edition-Prototype)**.
-Mini-NDN will use the "mininet" username created in Mininet cluster edition setup.
-
-## Mini-NDN cluster options
-
-To run Mini-NDN cluster on `localhost` and another server `server1` with
-the guided node placement strategy (default), the following command can be used:
-
- sudo minindn --cluster=localhost,server1 --place-list=1,3
-
-Note that `place-list` specifies the number of nodes to be placed on the corresponding servers
-of the cluster.
-In the example, one node will be placed on `localhost` and three nodes on `server1`.
-Unless specified, the default 4 node topology is used.
-Another placement can be `roundRobin` placement algorithm from Mininet.
-This does not require a place-list.
-
- sudo minindn --cluster=localhost,server1 --placement roundRobin
-
-By default the tunnel type used is SSH, but GRE tunnel can be specified by `--tunnel-type=gre`
diff --git a/docs/CONFIG.md b/docs/CONFIG.md
deleted file mode 100644
index d2a5bf1..0000000
--- a/docs/CONFIG.md
+++ /dev/null
@@ -1,68 +0,0 @@
-Configuration
-=============
-
-Mini-NDN uses a configuration file describing the topology and its parameters to setup a network.
-It can be generated by the GUI or written by hand or scripts.
-
-## Configuration file format:
-
-### The [nodes] section:
-
-At the bare minimum, the node section describes the nodes present in the topology.
-
- [nodes]
- a: _
- b: _
-
-Additionally each node can take the following parameters:
-
-* app : Default application(s) to be started on a node (specify '_' if no app needs to be started - required).
-The app is the only parameter which needs double quotes (see example below).
-
-* cpu : Amount of cpu available to a node (0.00 - 1.00), optional
-
-* mem : Amount of memory available to a node in KB
-
-* cache : Amount of cache memory available to a node in KB
-
-* nfd-log-level: Set the log level of the NFD running on the node (ex: DEBUG). For finer control,
-nfd.conf or nfd.conf.sample needs to be modified in /usr/local/etc/ndn/
-
-* nlsr-log-level: Set the log level of the NLSR running on the node (ex: DEBUG).
-
- e.g.)
-
- [nodes]
- a: _ cpu=0.3 nfd-log-level=TRACE nlsr-log-level=NONE
- b: app="sample app 1; sampleapp2.sh" cpu=0.3
-
-### The [links] section:
-
-The links section describes the links in the topology.
-
- e.g.)
-
- [links]
- a:b delay=10ms
-
-This would create a link between a and b. 'b:a' would also result in the same.
-The following parameters can be configured for a node:
-
-* delay : Delay parameter is a required parameter which defines the delay of the link (1-1000ms)
-
-* bw : Bandwidth of a link (<1-1000> Mbps)
-
-* loss : Percentage of packet loss (<1-100>)
-
-### Example configuration file
-
- [nodes]
- a: _ cpu=0.3
- b: app="sampleApp1; ./sampleApp2.sh" cpu=0.3
- [links]
- a:b delay=10ms bw=100
-
-Note that `sampleApp1` and `sampleApp2` must be either installed in the system (ex: /usr/bin)
-or an absolute path needs to be given.
-
-See `topologies` for more sample files
diff --git a/docs/CONNECT-TO-OUTSIDE.md b/docs/CONNECT-TO-OUTSIDE.md
deleted file mode 100644
index eb3f5b6..0000000
--- a/docs/CONNECT-TO-OUTSIDE.md
+++ /dev/null
@@ -1,91 +0,0 @@
-Connect Mini-NDN nodes to an outside network
-============================================
-
-Mini-NDN nodes can be connected to an outside network indirectly by running NFD on the local machine:
-
- (Mini-NDN node) ------ (NFD running on the host machine where Mini-NDN is running) ------- (External Network)
-
-## Add a node in root namespace
-
-For this simple example, we use the default topology:
-
- c----a----b----d
-
-If we want node "a" to connect to the host machine, we need to add a "root" node which has a link with node "a."
-
-To do so, we need to add the following import statement at the top of `bin/minindn`:
-
-```python
-from mininet.node import Node
-```
-
-Then the following lines can be added to `bin/minindn` before net.start():
-
-```python
-root = Node( 'root', inNamespace=False )
-net.addLink(root, 'a')
-```
-
-Adding these before net.start() is important as node "root" would then be assigned an IP automatically.
-Re-install Mini-NDN by issuing the following command in the mini-ndn folder:
-
- sudo ./install.sh -i
-
-## Configuration
-
-Run Mini-NDN with the simple topology and issue ifconfig on the local machine to confirm the addition of
-the interface. You should be able to locate "root-eth0":
-
- root-eth0 Link encap:Ethernet HWaddr 3e:eb:77:d2:6f:1f
- inet addr:1.0.0.9 Bcast:1.0.0.11 Mask:255.255.255.252
- inet6 addr: fe80::3ceb:77ff:fed2:6f1f/64 Scope:Link
- UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
- RX packets:34 errors:0 dropped:0 overruns:0 frame:0
- TX packets:33 errors:0 dropped:0 overruns:0 carrier:0
- collisions:0 txqueuelen:1000
- RX bytes:2667 (2.6 KB) TX bytes:2797 (2.7 KB)
-
-To make the IP address associated with this interface persistent, add the following line to
-/etc/network/interfaces and reboot your machine:
-
- iface root-eth0 inet manual
-
-## Check connection
-
-After rebooting, run Mini-NDN and issue the following command:
-
- mini-ndn>net
- a a-eth0:b-eth0 a-eth1:c-eth0 a-eth2:root-eth0
-
-Node "a" is connected to "root-eth0". Now issue "ifconfig a-eth2" on node "a":
-
- mini-ndn>a ifconfig a-eth2
- a-eth2 Link encap:Ethernet HWaddr fa:76:d4:86:d3:ba
- inet addr:1.0.0.10 Bcast:1.0.0.11 Mask:255.255.255.252
-
-As learned from the previous step, the IP address of root-eth0 is 1.0.0.9.
-
- mini-ndn>a ping 1.0.0.9
- PING 1.0.0.9 (1.0.0.9) 56(84) bytes of data.
- 64 bytes from 1.0.0.9: icmp_seq=1 ttl=64 time=0.137 ms
- 64 bytes from 1.0.0.9: icmp_seq=2 ttl=64 time=0.123 ms
-
-The host machine will also be able to ping node "a":
-
- VirtualBox:~$ ping 1.0.0.10
- PING 1.0.0.10 (1.0.0.10) 56(84) bytes of data.
- 64 bytes from 1.0.0.10: icmp_seq=1 ttl=64 time=0.086 ms
-
-## Run NFD on local machine and register route
-
-Start NFD on the local machine by using:
-
- sudo nfd
-
-The "nfd-start" script cannot be used, since the script allows only one instance of NFD at a time.
-The NFD processes running on the Mini-NDN nodes will prevent the "nfd-start" script from working.
-
-Now, using "nfdc register", we can register a route from node "a" in Mini-NDN to the NFD process on the
-host machine and from the host machine to an external machine.
-
-Also, if the local machine has a public IP, Mini-NDN nodes can be reached via external machines.
diff --git a/docs/EXPERIMENTS.md b/docs/EXPERIMENTS.md
deleted file mode 100644
index a2191ac..0000000
--- a/docs/EXPERIMENTS.md
+++ /dev/null
@@ -1,207 +0,0 @@
-Experiments
-===========
-
-Mini-NDN includes an experimentation framework which allows a user to create and automate
-networking experiments. Users can run existing experiments, included with Mini-NDN, or define
-their own custom experiment.
-
-## Running existing experiments
-
-Mini-NDN includes three example experiments that can be used to test the network or as reference
-for custom experiment implementations. `ndn-tools` must be installed to run the example
-experiments as each experiment uses both `ndnpingserver` and `ndnping`. Please see
-[INSTALL.md](../INSTALL.md) for instructions on installing `ndn-tools`.
-
-To see a list of the available experiments, run Mini-NDN using the `--list-experiments` parameter:
-
- minindn --list-experiments
-
-To run an experiment, provide the experiment name as an argument to the `--experiment` parameter:
-
- sudo minindn --experiment=pingall
-
-Each experiment will run until completion or exit if there is an error setting up the
-test environment.
-
-The three included experiments are set up using the same starting
-configuration. Each node runs NFD, NLSR, and an ndnpingserver which advertises the node's
-site name. After a waiting period to allow the network to converge (default is 60 seconds),
-the convergence status of the network is checked. If each node's FIB does not have an entry
-for every other node's router name and advertised prefix, the experiment is aborted and an error
-is reported.
-
-#### Common experiment parameters
-
-The time allowed for convergence (in seconds) can be configured using the `--ctime` parameter:
-
- sudo minindn --ctime=30 ...
-
-After the experiment has finished running, the command-line interface (CLI) will be launched and the
-user can then interact with the test environment. To disable the CLI and instead exit Mini-NDN
-as soon as the experiment has finished, use the `--no-cli` parameter:
-
- sudo minindn --no-cli ...
-
-To ping only a percentage of nodes `--pct-traffic` can be set.
-
- sudo minindn --pct-traffic=0.5 ...
-
-The above command will ping only 50% of other nodes from each node.
-The default value is 1 i.e. ping every other node.
-
-To move the experiment results to a results directory from the working directory
-after the experiment is complete (either --no-cli or quit) the following option
-can be used:
-
- sudo minindn --result-dir /home/mydir/result-dir ...
-
-The included experiments are described in detail below along with additional
-parameters that can be provided to modify the execution of the experiments.
-
-### Pingall experiment
-
-**Scenario**: Each node in the network simultaneously pings every other node in the network at a
-one second interval.
-
-**Experiment ID**: `--pingall`
-
-The number of pings sent in the experiment can be configured using the `--nPings` parameter:
-
- sudo minindn --experiment=pingall --nPings=120
-
-By default, `--nPings` is 300 for the Pingall experiment.
-
-### Failure experiment
-
-**Scenario**: Each node in the network simultaneously pings every other node in the network at a
-one second interval. After 60 seconds, the node with the name "csu" is brought down. The node is
-left in a failed state for 120 seconds while the other nodes continue pinging. After this period,
-the failed node is recovered and pings are collected for an additional 90 seconds.
-
-**Experiment ID**: `--failure`
-
-`--nPings` is 300 for the Failure experiment and cannot be modified.
-
-### Multiple failure experiment
-
-**Scenario**: Each node in the network simultaneously pings every other node in the network at a
-one second interval. After 60 seconds, the first node in the network will be brought down and remain
-in failed state for 60 seconds. After the failure period, the node is recovered and the network
-is allowed to recover for 60 seconds. After the recovery period, the next node will go through this
-failure and recovery process. Once every node in the network has gone through the failure and
-recovery process, the experiment will end.
-
-**Experiment ID**: `--multiple-failure`
-
-`--nPings` is dependent on the size of the topology being tested. 120 pings are scheduled for
-each node's failure/recovery period as well as an additional 60 pings for the initial collection
-period.
-
-### MCN failure experiment
-
-**Scenario**: This is exactly like the failure experiment but instead of failing the node named "csu" it fails the most connected node (MCN) i.e the node with the most links.
-
-Experiment ID: `--mcn-failure`
-
-### Experiment data
-
-The ping data is stored at `/tmp/minindn/node-name/ping-data`.
-
-The ping server log is stored at `/tmp/minindn/node-name/ping-server`
-
-## Creating custom experiments
-
-Mini-NDN provides a simple Python based framework which allows a user to define their own experiment
-and run it from the command line.
-
-To create an experiment, follow these steps:
-
-1. Create a Python source file for the experiment in the `ndn/experiments` directory.
-
- e.g.) `ndn/experiments/example.py`
-
-2. Derive the experiment from the `Experiment` base class defined in
- `ndn/experiments/experiment.py`.
-
- #!/usr/bin/python
-
- from ndn.experiments.experiment import Experiment
-
- class ExampleExperiment(Experiment):
- def __init__(self, args):
- Experiment.__init__(self, args)
-
-3. Override `start()` if the experiments want to override NLSR setup and skip `setup()` and `run()`
-as described below. `start()` is the entry point for an experiment.
-
-4. Override the `setup()` method to define how the experiment should be initialized
-
- e.g.) Run an ndnping server in the background on each node
-
- def setup(self):
- for host in self.net.hosts:
- host.cmd("ndnpingserver host.name &")
-
-
-5. Override the `run()` method to define how the experiment should behave
-
- e.g.) Obtain the NFD status of each node and save it to file
-
- def run(self):
- for host in self.net.hosts:
- host.cmd("nfdc status report > status.txt")
-
-6. Register the experiment with the `ExperimentManager` to make the experiment runnable from the
-command line.
-
- Experiment.register("example-name", ExampleExperiment)
-
-The experiment can then be run from the command-line using the name registered.
-"example-name" in the above example:
-
- sudo minindn --experiment=example-name
-
-### Full example experiment code
-
- #!/usr/bin/python
-
- from ndn.experiments.experiment import Experiment
-
- class ExampleExperiment(Experiment):
- def __init__(self, args):
- Experiment.__init__(self, args)
-
- def setup(self):
- for host in self.net.hosts:
- host.cmd("ndnpingserver host.name &")
-
- def run(self):
- for host in self.net.hosts:
- # By default status.txt would be stored
- # at /tmp/minindn/host/status.txt
- host.cmd("nfdc status report > status.txt")
-
- Experiment.register("example-name", ExampleExperiment)
-
-## Passing arguments to experiments
-
-Mini-NDN has the capacity to pass arguments to experiments, insofar
-as they do not clash with those of Mini-NDN. This feature
-allows users to pass arguments to Mini-NDN and process them in an
-experiment without having to rewrite Mini-NDN's core.
-
-An example of an experiment implementing this functionality is given in
-`ndn/experiments/arguments_experiment.py`, which demonstrates how to
-write code which handles arguments. Documentation for these arguments
-appears when called with `sudo minindn -h`, as does documentation for
-fixed arguments defined in core code, so it is strongly recommended to
-differentiate those you write yourself. Note that Bash and Zsh users
-can make use of autocomplete functionality when calling these arguments.
-
-To run the experiment:
-
- sudo minindn --experiment arg-exp --ds 226 --logging
-
-The experiment will print out the supplied value for --ds and a boolean
-value for the presence of --logging. --experiment is a fixed argument of
-Mini-NDN.
\ No newline at end of file
diff --git a/docs/GETTING-STARTED.md b/docs/GETTING-STARTED.md
deleted file mode 100644
index d15e95f..0000000
--- a/docs/GETTING-STARTED.md
+++ /dev/null
@@ -1,115 +0,0 @@
-Getting Started
-===============
-
-## Installation
-Please see [INSTALL.md](../INSTALL.md) for instructions on installing Mini-NDN and its dependencies.
-
-## Running Mini-NDN
-
-To run Mini-NDN with the default topology, `ndn_utils/topologies/default-topology.conf`, type:
-
- sudo minindn
-
-A full list of options can be printed by using:
-
- sudo minindn --help
-
-To run Mini-NDN with a topology file, provide the filename as the first argument:
-
- sudo minindn my-topology.conf
-
-During set up, the list of nodes in the network will be listed as they are initialized:
-
- *** Adding hosts:
- a b c d
-
-After set up, the command-line interface (CLI) will display a prompt.
-
- mini-ndn>
-
-To interact with a node, first type the node's name and then the command to be executed:
-
- mini-ndn> a echo "Hello, world!"
- Hello, world!
-
-To see the status of the forwarder on the node:
-
- mini-ndn> a nfdc status report
-
-To see the status of routing on the node:
-
- mini-ndn> a nlsrc status
-
-To exit Mini-NDN, type `quit` in the CLI:
-
- mini-ndn> quit
-
-Another option to quit Mini-NDN is sending a SIGQUIT (ctrl+\). SIGINT (ctrl+c)
-is reserved for the purpose of stopping applications initiated on the minindn command
-line.
-
-For a more in depth explanation of the CLI, please see the
-[Mininet Walkthrough](http://mininet.org/walkthrough/).
-
-## Command-line options
-
-To run Mini-NDN with a replica of the NDN testbed, use the `--testbed` parameter:
-
- sudo minindn --testbed
-
-To change the working directory from default `/tmp/minindn` following option can be used:
-
- sudo minindn --work-dir /home/mydir/test
-
-Autocomplete of command-line options is available for users of Bash and Zsh.
-
-#### Routing options
-
-To run minindn without NLSR, use the `--no-nlsr` parameter:
-
- sudo minindn --no-nlsr
-
-To run NLSR with hyperbolic routing enabled, use the `--routing` parameter:
-
- sudo minindn --routing hr
-
-Topology files given under ndn_utils/topologies/minindn* have hyperbolic coordinates configured
-and can be used with this option.
-
-To run NLSR in dry-run mode, use the `--routing` parameter:
-
- sudo minindn --routing dry
-
-To configure the max number of faces added by NLSR to reach each name prefix, use the `--faces`
-parameter:
-
- sudo minindn --faces 3
-
-`--faces` can be an integer from 0 to 60; 0 indicates NLSR can add all available faces.
-
-To run Mini-NDN with NLSR security configured
-
- sudo minindn --nlsr-security
-
-## Working Directory Structure
-
-Currently Mini-NDN uses /tmp/minindn as the working directory if not specified otherwise by using
-the option --work-dir.
-
-Each node is given a HOME directory under /tmp/minindn/node-name
-where node-name is the name of the node specified in the [nodes] section of the conf file.
-
-### NFD
-NFD conf file is stored at `/tmp/minindn/node-name/node-name.conf`
-
-NFD log file is stored at `/tmp/minindn/node-name/node-name.log`
-
-`.ndn` folder is stored at `/tmp/minindn/node-name/.ndn`
-
-### NLSR
-NLSR conf file is stored at `/tmp/minindn/node-name/nlsr.conf`
-
-NLSR log file is stored at `/tmp/minindn/node-name/log/nlsr.log`
-
-When security is enabled, NLSR security certificates are stored in: `/tmp/minindn/node-name/security`
-Note that no NLSR publishes the root certificate, Mini-NDN installs root.cert in security folder for each NLSR.
diff --git a/docs/GUI.md b/docs/GUI.md
deleted file mode 100644
index b190eeb..0000000
--- a/docs/GUI.md
+++ /dev/null
@@ -1,81 +0,0 @@
-Mini-NDN Edit
-=============
-
-Mini-NDN Edit is a GUI program designed to simplify the creation of Mini-NDN topology
-configuration files. Mini-NDN Edit allows the user to build a topology, configure the hosts and
-links, and generate a topology file that can be used by Mini-NDN.
-
-![minindnedit](img/gui/minindnedit.png)
-
-## Working with topology files
-
-#### File formats
-
-There are two file formats used by Mini-NDN edit.
-
-* `.mnndn` files store topology information used by the GUI. Mini-NDN Edit can open and
-save `.mnndn` files.
-
-* `.conf` files are used by Mini-NDN to create and run topologies. Mini-NDN Edit can generate a
-`.conf` file from a `.mnndn` file. Mini-NDN edit cannot open `.conf` files. Please see
-[CONFIG-FILE.md](CONFIG.md) for more information on the content and format of `.conf` files.
-
-#### File menu
-
-![file-dropdown](img/gui/file-dropdown.png)
-
-* **New** - Erase the current canvas and provide a new empty topology
-* **Open** - Open a `.mnndn` topology file
-* **Save** - Save the current topology as a `.mnndn` topology file
-* **Generate** - Convert the current topology to a `.conf` file runnable by Mini-NDN
-* **Run** - Run the current topology in Mini-NDN. The GUI will disappear and Mini-NDN will run on
- the command-line.
-* **Quit** - Exit Mini-NDN edit
-
-## Tools
-
-### Cursor tool
-![cursor-tool](img/gui/cursor-tool.png)
-
-The *cursor tool* is used to select and move nodes in the topology. A selected node or link can be
-removed from the topology using the `backspace` key or by selecting `edit/cut`.
-
-### Host tool
-![host-tool](img/gui/host-tool.png)
-
-The *host tool* is used to add a host node to the topology. Click on the canvas to create a new host
-node at the mouse cursor's position.
-
-### Switch tool
-![switch-tool](img/gui/switch-tool.png)
-
-The *switch tool* is used to add a switch to the topology. Click on the canvas to create a new
-switch at the mouse cursor's position.
-
-### Link tool
-![link-tool](img/gui/link-tool.png)
-
-The *link tool* is used to connect two nodes with a network link. Click on a node and drag the mouse
-cursor to another node to create a link between the two nodes.
-
-## Configuration
-
-#### Editing host information
-
-To edit a host's information and configuration, right-click on the desired node and select
-`Host Options`.
-
-The *Host Options* window will include tabs to modify the node's properties as well as the
-configuration files for NFD and NLSR on that node.
-
-*Note: Network, Site, and Router in the NLSR tab are unused in v0.1.0*
-
-![host-config](img/gui/host-config.png)
-
-#### Editing link configuration
-
-To edit a link's configuration, right-click on the desired link and select `Link Options`.
-
-The *Link Options* window will allow configuration of the link's bandwidth, delay, and loss rate.
-
-![link-details](img/gui/link-details.png)
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..d4bb2cb
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = .
+BUILDDIR = _build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs/RELEASE-NOTES.md b/docs/RELEASE-NOTES.md
deleted file mode 100644
index 9a825d7..0000000
--- a/docs/RELEASE-NOTES.md
+++ /dev/null
@@ -1,176 +0,0 @@
-Release Notes
-=============
-
-Mini-NDN version 0.4.0 (changes since version 0.3.0)
-----------------------------------------------------
-
-Release date: January 10, 2018
-
-**New features**:
-
-- Use SIGQUIT to quit Mini-NDN, SIGINT to kill programs
-
-- Use Infoedit to edit NFD and NLSR configuration files
-
-- Use nlsr.conf installed in the system
-
-- Provide a Vagrantfile to setup Mini-NDN and NDN
-
-- Provide option to disable NLSR
-
-- Provide an option to run NLSR in dry-run mode
-
-- Add option to specify whether to use TCP or UDP face in nlsr.conf
-
-- Add option to specify arbitrary arguments to use in experiments
-
-- Include a single option to install Mini-NDN and all the dependencies
-
-**Bug fixes**:
-
-- Fix "key does not exist error" after NLSR starts
-
-- Update install.sh to call ldconfig after installing ChronoSync
-
-- Add hyperbolic coordinates to default topology
-
-**Misc changes**:
-
-- Add an experiment to test nlsrc
-
-- Create faces in NFD for each neighbor in NLSR
-
-- Update to latest ndn-cxx
-
-- Use /tmp/minindn folder as default work dir instead of /tmp
-
-Mini-NDN version 0.3.0 (changes since version 0.2.0)
-----------------------------------------------------
-
-Release date: March 3, 2017
-
-**New features**:
-
-- Mini-NDN cluster edition
-
-- New experiments for making NLSR testing easier
-
-**Bug fixes**:
-
-- Set site name correctly
-
-- Install missing certificates in NLSR security config
-
-- Fix quitting of NLSR due to key not found error
-
-**Misc changes**:
-
-- Removed nlsr.conf file, generate it within the code
-
-- Use argparse instead of deprecated optparse
-
-- Update security config section for NLSR
-
-- Change mininet prompt to mini-ndn
-
-- Set network name at one place
-
-- Update install.sh script to install openssl
-
-- Update install.sh script to install cryptopp from package instead of compiling from source
-
-- Update install.sh to clean build folder every time to get rid of removed files such as old experiments
-
-- Fix old code - use net.hosts instead of storing hosts in a variable
-
-- Use nfdc instead of deprecated nfd-status
-
-Mini-NDN version 0.2.0 (changes since version 0.1.1)
-----------------------------------------
-
-Release date: August 18, 2016
-
-**New features**:
-
-- Automatic security configuration for NLSR
-
-- Use /usr/local/etc/ndn/nfd.conf as default config file for NFD
-
-- Class to monitor /proc/$PID/stat file for PID
-
-- Mini-NDN exits gracefully on SIGINT and non-convergence
-
-- Faster Mini-NDN install script - does not do apt-get update everytime
-
-- NLSR is launched with explicit config file for easier process identification
-
-- Add and update more documentation
-
-**Bug fixes**:
-
-- NFD is killed correctly on exit
-
-- Best route strategy is set correctly
-
-Mini-NDN version 0.1.1 (changes since version 0.1.0)
-----------------------------------------
-
-Release date: November 4, 2015
-
-**New features**:
-
-- Use nfd.conf.sample from currently installed NFD
-
-- Add working directory option to allow execution environment outside of /tmp
-
-- Add results directory option to store experiment results after completion
-
-- Add support for switches in GUI and configuration file
-
-- Add failNode and recoverNode methods to Experiment class
-
-- Add most connected node (MCN) failure experiment
-
-- Add option to specify percentage of nodes pinged
-
-**Code changes**:
-
-- Refactor program options into container class
-
-- Remove unused "FIB Entries" option from NDN host options
-
-**Bug fixes**:
-
-- Abort start up if experiment name is invalid
-
-- Restart pings after recovery in failure experiment
-
-Mini-NDN version 0.1.0 (initial release)
-----------------------------------------
-
-Release date: July 15, 2015
-
-Mini-NDN is a lightweight networking emulation tool that enables testing, experimentation, and
-research on the NDN platform. Based on Mininet, Mini-NDN uses the NDN libraries, NFD, NLSR, and
-tools released by the [NDN project](http://named-data.net/codebase/platform/) to emulate
-an NDN network on a single system.
-
-**Included features**:
-
-- Run a complete NDN network on a single system
-
-- Automatic configuration of NLSR to provide a routable NDN network
-
-- Supports user created NDN applications
-
-- Create a topology using the included Mini-NDN Edit GUI application
-
-- Allows individual configuration of NFD and NLSR parameters for each node
-
-- Provides an experiment management framework for easy creation of custom networking experiments
-
-- Uses a simple topology file format to define hosts, links, and configuration values
-
-- Configure network link parameters including bandwidth, delay, and loss rate
-
-- Includes a pre-configured topology file to replicate the NDN testbed
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..54591c1
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,56 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# This file only contains a selection of the most common options. For a full
+# list see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+# -- Path setup --------------------------------------------------------------
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+from datetime import datetime
+from minindn import __version__
+
+# -- Project information -----------------------------------------------------
+
+project = 'Mini-NDN'
+copyright = '2015-{}, Mini-NDN. This research is partially supported by NSF.'.format(datetime.now().year)
+author = 'Mini-NDN'
+
+# The full version, including alpha/beta/rc tags
+release = __version__
+version = __version__
+
+# -- General configuration ---------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'sphinx_rtd_theme'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
\ No newline at end of file
diff --git a/docs/experiment.rst b/docs/experiment.rst
new file mode 100644
index 0000000..58cc303
--- /dev/null
+++ b/docs/experiment.rst
@@ -0,0 +1,235 @@
+Experiment
+==========
+
+Configuration
+-------------
+
+Mini-NDN uses a configuration file describing the topology and its parameters to setup a network.
+
+The [nodes] section:
+
+At the bare minimum, the node section describes the nodes present in the
+topology.
+
+::
+
+ [nodes]
+ a: key1=value1 key2=value2
+ b: key1=value1
+
+Any key and value passed here is accessible in Mini-NDN as:
+
+::
+
+ ndn = Minindn(...)
+ value = ndn.net.hosts[0].params['params'].get('key1', "defaultValue")
+
+One can specify log levels for each node's NFD and NLSR using this key-value system:
+
+::
+
+ [nodes]
+ a: nfd-log-level=DEBUG nlsr-log-level=DEBUG
+ b: nfd-log-level=INFO
+
+To specify a log level for certain modules of NFD, the following line can be added to `nfd.py`:
+
+::
+
+ node.cmd('infoedit -f {} -s log.Forwarder -v {}'.format(self.confFile, 'INFO'))
+
+This will turn on FORWARDER logging to INFO for all nodes.
+
+.. Todo: Add switch section
+
+The [links] section:
+
+The links section describes the links in the topology.
+
+::
+
+ e.g.)
+
+ [links]
+ a:b delay=10ms
+
+This would create a link between a and b. 'b:a' would also result in the
+same. The following parameters can be configured for a node:
+
+- delay : Delay parameter is a required parameter which defines the
+ delay of the link (1-1000ms)
+
+- bw : Bandwidth of a link (<1-1000> Mbps)
+
+- loss : Percentage of packet loss (<1-100>)
+
+Example configuration file
+
+::
+
+ [nodes]
+ a:
+ b:
+ [links]
+ a:b delay=10ms bw=100
+
+See ``ndn_utils/topologies`` for more sample files
+
+Sample
+------
+
+Sample experiment may written as follows:
+
+.. code:: python
+
+ from mininet.log import setLogLevel, info
+
+ from minindn.minindn import Minindn
+ from minindn.util import MiniNDNCLI
+ from minindn.apps.appmanager import AppManager
+ from minindn.apps.nfd import Nfd
+ from minindn.apps.nlsr import Nlsr
+ from minindn.helpers.routing_helper import IPRoutingHelper
+
+ if __name__ == '__main__':
+ setLogLevel('info')
+
+ Minindn.cleanUp()
+ Minindn.verifyDependencies()
+
+ # Can pass a custom parser, custom topology, or any Mininet params here
+ ndn = Minindn()
+
+ ndn.start()
+
+ # IP reachability if needed
+ # IPRoutingHelper.calcAllRoutes(ndn.net)
+ # info("IP routes configured, start ping\n")
+ # ndn.net.pingAll()
+
+ # Start apps with AppManager which registers a clean up function with ndn
+ info('Starting NFD on nodes\n')
+ nfds = AppManager(ndn, ndn.net.hosts, Nfd)
+ info('Starting NLSR on nodes\n')
+ nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr)
+
+ # or can not start NLSRs with some delay in between:
+ # nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr)
+ # for host in ndn.net.hosts:
+ # nlsrs.startOnNode(host)
+ # time.sleep(30)
+
+ MiniNDNCLI(ndn.net)
+
+ # Calls the clean up functions registered via AppManager
+ ndn.stop()
+
+Users may look at how the NFD and NLSR applications are written as a sub class of Application
+in the ``minindn/apps`` folder. Or users may choose to directly run their application on nodes
+such as ndnpingserver is run in ``minindn/helpers/experiment.py``.
+
+Execution
+---------
+
+To run Mini-NDN with the default topology,
+``ndn_utils/topologies/default-topology.conf``, type:
+
+::
+
+ sudo python examples/minindn.py
+
+To run Mini-NDN with a topology file, provide the filename as the first
+argument:
+
+::
+
+ sudo python examples/minindn.py my-topology.conf
+
+After Mini-NDN is installed, users can run examples from anywhere with python directly as follows:
+
+::
+
+ sudo python /path/to/myexample.py
+
+The user no longer needs to create an experiment in the old Mini-NDN way, then install it to the system before executing it via the minindn binary. The new examples can be separate from the Mini-NDN folder if the core is not being modified.
+
+CLI Interface
+_____________
+
+During set up, the list of nodes in the network will be listed as they
+are initialized:
+
+::
+
+ *** Adding hosts:
+ a b c d
+
+After set up, the command-line interface (CLI) will display a prompt.
+
+::
+
+ mini-ndn>
+
+To interact with a node, first type the node's name and then the command
+to be executed:
+
+::
+
+ mini-ndn> a echo "Hello, world!"
+ Hello, world!
+
+To see the status of the forwarder on the node:
+
+::
+
+ mini-ndn> a nfdc status report
+
+To see the status of routing on the node:
+
+::
+
+ mini-ndn> a nlsrc status
+
+To exit Mini-NDN, type ``quit`` in the CLI or use ``ctrl + D``:
+
+::
+
+ mini-ndn> quit
+
+``Ctrl + C`` is used to quit an application run in the foreground of the command line.
+
+For a more in depth explanation of the CLI, please see the `Mininet
+Walkthrough <http://mininet.org/walkthrough/>`__.
+
+To run NDN commands from the outside the command line user can also open a new terminal
+and export the HOME folder of a node ``export HOME=/tmp/minindn/a && cd ~``
+
+Working Directory Structure
+---------------------------
+
+Currently Mini-NDN uses /tmp/minindn as the working directory if not
+specified otherwise by using the option --work-dir.
+
+Each node is given a HOME directory under /tmp/minindn/<node-name> where
+<node-name> is the name of the node specified in the [nodes] section of
+the conf file.
+
+NFD
+___
+
+- NFD conf file is stored at ``/tmp/minindn/<node-name>/nfd.conf``
+
+- NFD log file is stored at ``/tmp/minindn/<node-name>/log/nfd.log``
+
+- ``.ndn`` folder is stored at ``/tmp/minindn/<node-name>/.ndn``
+
+NLSR
+____
+
+- NLSR conf file is stored at ``/tmp/minindn/<node-name>/nlsr.conf``
+- NLSR log file is stored at ``/tmp/minindn/<node-name>/log/nlsr.log``
+
+When security is enabled, NLSR security certificates are stored in:
+``/tmp/minindn/<node-name>/security`` Note that no NLSR publishes the root
+certificate, Mini-NDN installs root.cert in security folder for each
+NLSR.
diff --git a/docs/faq.rst b/docs/faq.rst
new file mode 100644
index 0000000..991dd06
--- /dev/null
+++ b/docs/faq.rst
@@ -0,0 +1,48 @@
+FAQ
+=========
+
+* ``How does Mini-NDN work?``
+
+Mini-NDN's principles of operation most heavily rely on the underlying Mininet code it relies on.
+Mininet uses a combination of limited containerization via network namespaces (which give processes
+isolated interfaces and routing tables) and emulated ethernet connections via veth connections.
+In practical terms, Mini-NDN ensures that processes running on distinct nodes will run seperately
+and without interfering with each other.
+
+* ``How does Mini-NDN apply link loss/delay/etc.?``
+
+Mini-NDN relies on Mininet's code, which in turn uses the Linux tc utility on a stations' virtualized
+interfaces to apply configurations known as qdiscs to these links. Note that these will only be applied
+on egress packets from a station where it's applied.
+For more information on qdiscs and tc, view the information `here <http://wiki.linuxwall.info/doku.php/en%3aressources%3adossiers%3anetworking%3atraffic_control>`_.
+
+* ``Why use Mini-NDN rather than a simulator such as ndnSIM?``
+
+Mini-NDN is easier and faster to use because, rather than serving as a mathematical model of a network,
+it is instead running real NDN code on a real Linux kernel. This also means it's quite useful for testing code changes, as it can more accurately test the interaction of software componenents.
+
++--------------------------------+-----------------------------------------------------------+-----------------------------------------+
+| Criteria | Mini-NDN | ndnSIM |
++--------------------------------+-----------------------------------------------------------+-----------------------------------------+
+| Based On | Mininet | ns-3 |
++--------------------------------+-----------------------------------------------------------+-----------------------------------------+
+| Language | Python | C++ |
++--------------------------------+-----------------------------------------------------------+-----------------------------------------+
+| Library/Forwarder/Applications | Use system binaries (free to use any compatible versions) | Integrated (fixed release version) |
++--------------------------------+-----------------------------------------------------------+-----------------------------------------+
+| Application language | C++ (ndn-cxx), CCL (ndn-cpp, PyNDN, ndn-js, jNDN) | C++ (ndn-cxx) |
++--------------------------------+-----------------------------------------------------------+-----------------------------------------+
+| Simulation size | Medium - Large (cluster edition in development) | Large (can be parallelized using MPI) |
++--------------------------------+-----------------------------------------------------------+-----------------------------------------+
+| Simulation time | Real time | Quick (depending on size/memory) |
++--------------------------------+-----------------------------------------------------------+-----------------------------------------+
+| Porting real applications | Drop in | Changes required |
++--------------------------------+-----------------------------------------------------------+-----------------------------------------+
+| Interactivity | Can interact directly with NFD, NLSR or Apps | Can show stats while running |
++--------------------------------+-----------------------------------------------------------+-----------------------------------------+
+| Logs | May need to manually setup to collect | Available with tracer |
++--------------------------------+-----------------------------------------------------------+-----------------------------------------+
+| Post processing scripts | Not available, users need to write their own | Available to use to process the logs |
++--------------------------------+-----------------------------------------------------------+-----------------------------------------+
+| Other | Not yet supported (Wifi in development) | WiFi, LTE, etc available from ns-3 |
++--------------------------------+-----------------------------------------------------------+-----------------------------------------+
diff --git a/docs/hackathon.rst b/docs/hackathon.rst
new file mode 100644
index 0000000..e51ec74
--- /dev/null
+++ b/docs/hackathon.rst
@@ -0,0 +1,9 @@
+Past NDN Hackathon projects
+===========================
+
+- 1st NDN Hackathon: `NFD integration test <http://ndncomm.github.io/mini-ndn/>`_.
+- 2st NDN Hackathon: `Mini-NDN metrics <https://github.com/2nd-ndn-hackathon/mini-ndn-metrics>`_.
+- 3rd NDN Hackathon: `Mini-NDN cluster <https://github.com/3rd-ndn-hackathon/mini-NDN-cluster>`_.
+- 4th NDN Hackathon: `Mini-NDN wifi <https://github.com/4th-ndn-hackathon/Mini-NDN-Wi-Fi>`_.
+- 7th NDN Hackathon: `Mini-NDN documentation <https://github.com/7th-ndn-hackathon/mini-ndn-documentation>`_.
+
diff --git a/docs/howtos.rst b/docs/howtos.rst
new file mode 100644
index 0000000..b95bde3
--- /dev/null
+++ b/docs/howtos.rst
@@ -0,0 +1,115 @@
+Howtos
+======
+
+Connect Mini-NDN nodes to an outside network
+---------------------------------------------
+
+Mini-NDN nodes can be connected to an outside network indirectly by
+running NFD on the local machine:
+
+::
+
+ (Mini-NDN node) ------ (NFD running on the host machine where Mini-NDN is running) ------- (External Network)
+
+Add a node in root namespace
+____________________________
+
+For this simple example, we can use a single node topology with node 'a'
+
+If we want node 'a' to connect to the host machine, we need to add a
+"root" node which has a link with node "a."
+
+Then the following code can be used:
+
+.. code:: python
+
+ topo = Topo()
+ root = topo.addHost('root', inNamespace=False)
+ a = topo.addHost('a')
+ topo.addLink(root, a, delay='10ms')
+
+ ndn = Minindn(topo=topo)
+
+ ...
+
+Configuration
+_____________
+
+Run Mini-NDN with the above code and issue ifconfig on the local
+machine to confirm the addition of the interface. You should be able to
+locate "root-eth0":
+
+::
+
+ root-eth0 Link encap:Ethernet HWaddr 3e:eb:77:d2:6f:1f
+ inet addr:1.0.0.9 Bcast:1.0.0.11 Mask:255.255.255.252
+ inet6 addr: fe80::3ceb:77ff:fed2:6f1f/64 Scope:Link
+ UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
+ RX packets:34 errors:0 dropped:0 overruns:0 frame:0
+ TX packets:33 errors:0 dropped:0 overruns:0 carrier:0
+ collisions:0 txqueuelen:1000
+ RX bytes:2667 (2.6 KB) TX bytes:2797 (2.7 KB)
+
+To make the IP address associated with this interface persistent, add
+the following line to /etc/network/interfaces and reboot your machine:
+
+::
+
+ iface root-eth0 inet manual
+
+Check connection
+________________
+
+After rebooting, run Mini-NDN and issue the following command:
+
+::
+
+ mini-ndn>net
+ a a-eth0:b-eth0 a-eth1:c-eth0 a-eth2:root-eth0
+
+Node "a" is connected to "root-eth0". Now issue "ifconfig a-eth2" on
+node "a":
+
+::
+
+ mini-ndn>a ifconfig a-eth2
+ a-eth2 Link encap:Ethernet HWaddr fa:76:d4:86:d3:ba
+ inet addr:1.0.0.10 Bcast:1.0.0.11 Mask:255.255.255.252
+
+As learned from the previous step, the IP address of root-eth0 is
+1.0.0.9.
+
+::
+
+ mini-ndn>a ping 1.0.0.9
+ PING 1.0.0.9 (1.0.0.9) 56(84) bytes of data.
+ 64 bytes from 1.0.0.9: icmp_seq=1 ttl=64 time=0.137 ms
+ 64 bytes from 1.0.0.9: icmp_seq=2 ttl=64 time=0.123 ms
+
+The host machine will also be able to ping node "a":
+
+::
+
+ VirtualBox:~$ ping 1.0.0.10
+ PING 1.0.0.10 (1.0.0.10) 56(84) bytes of data.
+ 64 bytes from 1.0.0.10: icmp_seq=1 ttl=64 time=0.086 ms
+
+Run NFD on local machine and register route
+___________________________________________
+
+Start NFD on the local machine by using:
+
+::
+
+ sudo nfd
+
+The "nfd-start" script cannot be used, since the script allows only one
+instance of NFD at a time. The NFD processes running on the Mini-NDN
+nodes will prevent the "nfd-start" script from working.
+
+Now, using "nfdc register", we can register a route from node "a" in
+Mini-NDN to the NFD process on the host machine and from the host
+machine to an external machine.
+
+Also, if the local machine has a public IP, Mini-NDN nodes can be
+reached via external machines.
diff --git a/docs/img/gui/cursor-tool.png b/docs/img/gui/cursor-tool.png
deleted file mode 100644
index 6d53812..0000000
--- a/docs/img/gui/cursor-tool.png
+++ /dev/null
Binary files differ
diff --git a/docs/img/gui/file-dropdown.png b/docs/img/gui/file-dropdown.png
deleted file mode 100644
index 9e0354c..0000000
--- a/docs/img/gui/file-dropdown.png
+++ /dev/null
Binary files differ
diff --git a/docs/img/gui/host-config.png b/docs/img/gui/host-config.png
deleted file mode 100644
index 5cd79a8..0000000
--- a/docs/img/gui/host-config.png
+++ /dev/null
Binary files differ
diff --git a/docs/img/gui/host-tool.png b/docs/img/gui/host-tool.png
deleted file mode 100644
index 4f54d53..0000000
--- a/docs/img/gui/host-tool.png
+++ /dev/null
Binary files differ
diff --git a/docs/img/gui/link-details.png b/docs/img/gui/link-details.png
deleted file mode 100644
index 99e2449..0000000
--- a/docs/img/gui/link-details.png
+++ /dev/null
Binary files differ
diff --git a/docs/img/gui/link-tool.png b/docs/img/gui/link-tool.png
deleted file mode 100644
index 7772ecf..0000000
--- a/docs/img/gui/link-tool.png
+++ /dev/null
Binary files differ
diff --git a/docs/img/gui/minindnedit.png b/docs/img/gui/minindnedit.png
deleted file mode 100644
index 0fe6879..0000000
--- a/docs/img/gui/minindnedit.png
+++ /dev/null
Binary files differ
diff --git a/docs/img/gui/switch-tool.png b/docs/img/gui/switch-tool.png
deleted file mode 100644
index 919b11d..0000000
--- a/docs/img/gui/switch-tool.png
+++ /dev/null
Binary files differ
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..d7d8f01
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,29 @@
+.. Mini-NDN documentation master file, created by
+ sphinx-quickstart on Mon Sep 23 11:15:54 2019.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Mini-NDN: A Mininet-based NDN emulator
+======================================
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents
+
+ introduction
+ install
+ experiment
+ howtos
+ release-notes
+ faq
+ hackathon
+ videos
+
+Helpful Links
+-------------
+
+* `NDN Website <http://named-data.net/>`_
+* `NDN Contributor's Guide <https://github.com/named-data/NFD/blob/master/CONTRIBUTING.md>`_
+* `Mininet Documentation <http://mininet.org/>`_
+* `Mini-NDN redmine <https://redmine.named-data.net/projects/mini-ndn>`_
+* `Mailing list <http://www.lists.cs.ucla.edu/mailman/listinfo/mini-ndn>`_
diff --git a/docs/install.rst b/docs/install.rst
new file mode 100644
index 0000000..391fdfa
--- /dev/null
+++ b/docs/install.rst
@@ -0,0 +1,174 @@
+Install
+=======
+
+Prerequisites
+-------------
+
+For this guide, you will need a laptop/desktop with a recent version of
+a Linux distro that is supported by Mininet. For this guide, the *Ubuntu 18.04 LTS* release was used.
+Some tweaks maybe required to Mini-NDN's install.sh file for other distros.
+Note that you'll need administrative privileges in order to download and install
+extra packages and also to execute **Mini-NDN**.
+
+Using Vagrantfile
+-----------------
+
+With Vagrant installed, simply do ``vagrant up`` which will bring up an Ubuntu 18.04 virtual machine
+and install Mini-NDN and all its dependencies on it. Please make sure to tweak the CPU core count
+(default 4 cores) and RAM (default 4GB) according to your needs before doing vagrant up. Mini-NDN
+can be found in /home/vagrant/mini-ndn which is a symlink to /vagrant if Vagrantfile was used from within mini-ndn cloned on the host. Otherwise it is an actual clone of mini-ndn.
+
+Using install.sh
+----------------
+
+Mini-NDN depends on Mininet and NDN software to be installed in the system.
+If you have all the dependencies (see sections below) **installed in the system** simply
+clone this repository and run:
+
+::
+
+ ./install.sh -i
+
+The ``-i`` option uses ``setup.py develop`` to point the system install
+to the current directory. So any changes made to the cloned ``mini-ndn``
+folder will be used without having to install it again to the system.
+If you do not need to modify the core of Mini-NDN, then setup.py install (or pip install .)
+can be used directly. See :doc:`experiment <experiment>` for more information on running.
+
+If you don't have the dependencies, the following command will
+install them from source along with Mini-NDN. The dependencies include
+Mininet, NDN core (ndn-cxx, NFD, Chronosync, PSync, NLSR), Infoedit,
+and NDN Common Client Libraries (CCL). If you do not wish to install
+the master versions of the NDN core or want to switch to specific versions,
+you can edit the install.sh with release tags/specific versions.
+
+.. _scaling-note:
+.. important::
+ If you wish to scale Mini-NDN experiments and do not have use for security extensions
+ in your emulations, you should apply the ndn-cxx patch given in the ``patches`` folder
+ using ``./install.sh -p`` before running the following commands. The ndn-cxx patch is
+ taken from ndnSIM which provides an in-memory dummy KeyChain to reduce CPU computations.
+ After these patches are applied sleep time after NFD, nfdc, NLSR, etc. is not required
+ making the startup **MUCH** faster and scaling of Mini-NDN **MUCH** better.
+
+::
+
+ ./install.sh -a
+
+This pulls the NDN software from Github to ``ndn-src`` folder under the project.
+
+.. note::
+ If any changes are made to ``ndn-src`` folder, please don't forgot to re-install
+ the sources to the system.
+
+To install without CCL, use:
+
+::
+
+ ./install.sh -mni
+
+See ``install.sh -h`` for detailed options.
+
+Installing Dependencies
+-----------------------
+
+Mininet
+_______
+
+Mini-NDN is based on Mininet. To install Mininet:
+
+::
+
+ git clone --depth 1 https://github.com/mininet/mininet.git
+
+After Mininet source is on your system, run the following command to
+install Mininet core dependencies and Open vSwitch:
+
+::
+
+ ./util/install.sh -nv
+
+To check if Mininet is working correctly, run this test:
+
+::
+
+ sudo mn --test pingall
+
+This will print out a series of statements that show the test setup and
+the results of the test. Look for ``Results:`` two-thirds of the way
+down where it will indicate the percentage of dropped packets. Your
+results should show "0% dropped (2/2 received)".
+
+NOTE: Mini-NDN, while providing a high level of emulation of hosts,
+requires programs to be installed onto your computer. It will not work
+if they are not installed. If you do not want NDN software installed
+onto your computer, you can use a virtual machine, which can be quite
+simply set up with the provided Vagrantfile.
+
+NDN dependencies
+________________
+
+Each node in Mini-NDN will run the official implementation of NDN
+installed on your system. The following dependencies are needed:
+
+Mini-NDN uses NFD, NLSR, and ndn-tools.
+
+- To install NFD: https://named-data.net/doc/NFD/current/INSTALL.html
+- To install NLSR: https://named-data.net/doc/NLSR/current/INSTALL.html
+- To install ndn-tools: https://github.com/named-data/ndn-tools
+
+.. warning::
+ Please do not try to install NDN software from both the source (GitHub) and PPA (apt).
+ It will not work in most cases! If you used ./install.sh -a in the past but now want
+ to use apt, please run ``sudo ./waf uninstall`` in all the NDN projects before proceeding
+ with apt. Similarly, remove from apt if switching to source.
+
+Please see the :ref:`scaling-note <scaling-note>` to learn about disabling
+security for better scalability.
+
+Note that all three of these can be installed from the Named Data PPA.
+Instructions for setting it up can be found in the NFD installation
+instructions. Note that PPA and installs from source **cannot** be
+mixed. You must completely remove PPA installs from the system if switching
+to source and vice-versa.
+
+For PPA installs, if you are using a custom nfd.conf file in an experiment, you should
+place it in /usr/local/etc/ndn/ rather than /etc/ndn/. This is to avoid
+a bug from the default configuration file for the PPA, which is
+incompatible with Mini-NDN.
+
+Infoedit
+________
+
+Infoedit is used to edit configuration files for NFD and NLSR.
+To install infoedit:
+
+::
+
+ git clone --depth 1 https://github.com/NDN-Routing/infoedit
+ cd infoedit
+ make
+ sudo make install
+
+Verification
+------------
+
+You can execute the following example to bring up the Mini-NDN command line
+with NFD and NLSR running on each node:
+
+::
+
+ sudo python examples/mnndn.py
+
+You can use these steps to run the sample pingall experiment:
+
+1. Issue the command: ``sudo python examples/nlsr/pingall.py``
+2. When the ``mini-ndn>`` CLI prompt appears, the experiment has
+ finished. On the Mini-NDN CLI, issue the command ``exit`` to exit the
+ experiment.
+3. Issue the command:
+ ``grep -c content /tmp/minindn/*/ping-data/*.txt``. Each file should
+ report a count of 50.
+4. Issue the command:
+ ``grep -c timeout /tmp/minindn/*/ping-data/*.txt``. Each file should
+ report a count of 0.
diff --git a/docs/introduction.rst b/docs/introduction.rst
new file mode 100644
index 0000000..fe19ad8
--- /dev/null
+++ b/docs/introduction.rst
@@ -0,0 +1,40 @@
+Introduction
+=================
+
+If you are new to the NDN community of software generally, read the
+`Contributor's Guide <https://github.com/named-data/NFD/blob/master/CONTRIBUTING.md>`_.
+
+What is Mini-NDN?
+-----------------
+
+Mini-NDN is a lightweight networking emulation tool that enables testing, experimentation, and
+research on the NDN platform. It was initially based on `Mini-CCNx <https://github.com/chesteve/mn-ccnx>`_ which was a fork of `Mininet <https://github.com/mininet/mininet>`_. Mini-NDN uses the NDN libraries, NFD, NLSR, and tools released by the `NDN project <http://named-data.net/codebase/platform/>`_ to emulate an NDN network on a single system.
+
+The first release of Mini-NDN is developed by members of the NSF-sponsored NDN project team.
+Mini-NDN is open to contribution from the public.
+
+.. image:: minindnnet.svg
+
+License
+_______
+
+Mini-NDN is open and free software licensed under the GPL 3.0 license. Mini-NDN is free to all
+users and developers. For more information about licensing details and limitations,
+please refer to COPYING.md.
+
+Feedback/Mailing List
+_____________________
+
+Bug reports and feedback are highly appreciated and can be made through our
+`Redmine site <http://redmine.named-data.net/projects/mini-ndn>`_ and the
+`mini-ndn mailing list <http://www.lists.cs.ucla.edu/mailman/listinfo/mini-ndn>`_.
+
+Video
+_____
+
+.. raw:: html
+
+ <div id="video-container" class="col-md-6 ">
+ <p>Mini-NDN (content maybe outdated)</p>
+ <iframe width="600" height="345" src="https://www.youtube.com/embed/UxHPqaUwefg" frameborder="0" allowfullscreen=""></iframe>
+ </div>
\ No newline at end of file
diff --git a/docs/minindnnet.svg b/docs/minindnnet.svg
new file mode 100644
index 0000000..0bc985a
--- /dev/null
+++ b/docs/minindnnet.svg
@@ -0,0 +1,126 @@
+<svg width="692" height="380" xmlns="http://www.w3.org/2000/svg">
+
+ <metadata id="metadata7">image/svg+xml</metadata>
+ <g>
+ <title>background</title>
+ <rect fill="none" id="canvas_background" height="382" width="694" y="-1" x="-1"/>
+ </g>
+ <g>
+ <title>Layer 1</title>
+ <g stroke="null" id="g3790">
+ <rect stroke="#000000" fill="#ffffff" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" id="rect2985" width="680.84682" height="350.443392" x="4.962804" y="5.773119" rx="0.324652"/>
+ <path stroke="#000000" fill="none" stroke-miterlimit="4" d="m4,175.828501l681.727736,1.357954" id="path3770"/>
+ </g>
+ <rect stroke="#000000" fill="#e3dedb" stroke-width="0.99538" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-dashoffset="0" rx="2.988095" y="176.111777" x="5.140841" height="180.524655" width="680.312936" id="rect3813"/>
+ <rect stroke="#000000" fill="#ffffff" stroke-width="1.602133" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-dasharray="4.80639973, 4.80639973" stroke-dashoffset="0" ry="8.582684" rx="7.476771" y="44.78072" x="55.492192" height="195.219243" width="148.366914" id="rect3764"/>
+ <rect stroke="#000000" fill="#ffffff" stroke-width="1.638042" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-dasharray="4.9141253, 4.9141253" stroke-dashoffset="0" id="rect3772" width="155.115252" height="195.190135" x="270.220868" y="46.153231" rx="7.816845" ry="8.581405"/>
+ <rect stroke="#000000" fill="#ffffff" stroke-width="1.602133" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-dasharray="4.80639973, 4.80639973" stroke-dashoffset="0" ry="8.582684" rx="7.476771" y="45.459696" x="489.86568" height="195.219243" width="148.366914" id="rect3774"/>
+ <text transform="matrix(1.0192718802397343,0,0,0.9115536073383187,-2.8313337784806336,-12.183034089773187) " font-size="16.005802px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3776" y="392.709737" x="551.171304" xml:space="preserve">
+ <tspan stroke="null" font-weight="normal" y="398.194877" x="552.152396" id="tspan3778">Kernel Space</tspan>
+ </text>
+ <text transform="matrix(1.0524848569125234,0,0,0.8827879284304422,-52.30106698198968,-77.5201889102731) " font-size="14.180006px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="601.466013" y="108.524983" id="text3782">
+ <tspan stroke="null" font-weight="normal" id="tspan3784" x="602.416145" y="114.188857">User Space</tspan>
+ </text>
+ <path stroke="#000000" fill="none" stroke-width="1px" id="path3796" d="m488.56554,176.773764c1.782236,0.480113 1.527628,0.360085 1.527628,0.360085"/>
+ <rect stroke="#000000" fill="#ffffff" stroke-width="0.649807" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-dashoffset="0" rx="0.838801" y="202.851471" x="84.255138" height="26.434283" width="94.537572" id="rect3815"/>
+ <rect stroke="#000000" fill="#ffffff" stroke-width="0.792138" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-dashoffset="0" id="rect3817" width="131.339764" height="28.275376" x="282.077514" y="201.912133" rx="1.165334"/>
+ <path stroke="#000000" fill="none" stroke-width="0.865499px" id="path3823" d="m347.74739,201.086282l0,28.351986"/>
+ <text transform="matrix(0.7776670647796514,0,0,1.19475416519067,-52.30106724263901,-77.52018902784596) " font-size="12.623897px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="434.634023" y="248.956571" id="text3835">
+ <tspan stroke="null" font-size="15.579311px" font-weight="bold" font-family="Monospace" x="435.91992" y="253.141532" id="tspan3837">n2-eth0</tspan>
+ </text>
+ <text transform="matrix(0.9031157255303414,0,0,1.0287949657006918,-2.8313337284492768,-13.069358400177762) " font-size="13.163442px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="110.835751" y="225.210496" id="text3863">
+ <tspan stroke="null" font-size="16.245171px" font-weight="bold" font-family="Monospace" x="111.943029" y="230.070551" id="tspan3865">n1-eth0</tspan>
+ </text>
+ <path stroke="#000000" fill="none" stroke-width="0.992521px" id="path3887" d="m131.263954,229.882774l0,67.221296l176.555867,-0.960307l1.337531,-65.300682"/>
+ <rect stroke="#000000" fill="#ffffff" stroke-width="0.676601" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-dashoffset="0" id="rect3891" width="95.679394" height="28.317195" x="515.346399" y="202.85306" rx="0.848932"/>
+ <path stroke="#000000" fill="none" stroke-width="0.992521px" d="m383.833251,230.842992l0,67.221296l176.555867,-0.960307l1.337531,-65.300682" id="path3897"/>
+ <text transform="matrix(0.9778213687833123,0,0,0.9501950205038839,-52.301066914088324,-76.5370021990862) " font-size="16.459864px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="164.136782" y="409.888383" id="text3907">
+ <tspan stroke="null" id="tspan3915" x="165.159464" y="415.15046">isolated point to point link</tspan>
+ </text>
+ <text transform="matrix(0.9778213687833123,0,0,0.9501950205038839,-52.301066914088324,-76.5370021990862) " font-size="16.459864px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3919" y="409.573373" x="429.378262" xml:space="preserve">
+ <tspan stroke="null" y="414.83545" x="430.400944" id="tspan3921">isolated point to point link</tspan>
+ </text>
+ <text transform="matrix(0.9778213687833123,0,0,0.9501950205038839,-52.301066914088324,-76.5370021990862) " font-size="16.459864px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3923" y="428.078233" x="194.615642" xml:space="preserve">
+ <tspan stroke="null" font-weight="bold" y="433.34031" x="195.638324" id="tspan3925">(eg: 1Mbps, 10ms)</tspan>
+ </text>
+ <text transform="matrix(0.9778213687833123,0,0,0.9501950205038839,-52.301066914088324,-76.5370021990862) " font-size="16.459864px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3927" y="409.888383" x="164.136782" xml:space="preserve">
+ <tspan stroke="null" y="415.15046" x="165.159464" id="tspan3929">Isolated point to point link</tspan>
+ </text>
+ <text transform="matrix(0.9778213687833123,0,0,0.9501950205038839,-52.301066914088324,-76.5370021990862) " font-size="16.459864px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="429.378262" y="409.573373" id="text3931">
+ <tspan stroke="null" id="tspan3933" x="430.400944" y="414.83545">Isolated point to point link</tspan>
+ </text>
+ <text transform="matrix(0.877827228897152,0,0,1.0584326041598764,-53.30106731891522,-78.4233265445007) " font-size="13.706223px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3935" y="282.545218" x="661.482605" xml:space="preserve">
+ <tspan stroke="null" font-size="16.915024px" font-weight="bold" font-family="Monospace" id="tspan3937" y="287.269185" x="662.621781">n3-eth0</tspan>
+ </text>
+ <text transform="matrix(0.7776670647796514,0,0,1.19475416519067,-52.30106724263901,-77.52018902784596) " font-size="12.623897px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3939" y="248.297391" x="520.751053" xml:space="preserve">
+ <tspan stroke="null" font-size="15.579311px" font-weight="bold" font-family="Monospace" id="tspan3941" y="252.482352" x="522.03695">n2-eth1</tspan>
+ </text>
+ <text transform="matrix(0.8745385143393076,0,0,1.0624128521471832,-2.8313338199928846,-14.069358364146652) " font-size="16.205975px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3943" y="80.648481" x="141.655977" xml:space="preserve">
+ <tspan stroke="null" font-size="20px" font-weight="bold" font-family="Monospace" id="tspan3945" y="85.354749" x="142.799437">n1</tspan>
+ </text>
+ <text transform="matrix(0.8745385143393076,0,0,1.0624128521471832,-2.8313338199928846,-14.069358364146652) " font-size="16.205975px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="385.430517" y="78.840861" id="text3955">
+ <tspan stroke="null" font-size="20px" font-weight="bold" font-family="Monospace" x="386.573977" y="83.547129" id="tspan3957">n2</tspan>
+ </text>
+ <text transform="matrix(0.8745385143393076,0,0,1.0624128521471832,-2.8313338199928846,-14.069358364146652) " font-size="16.205975px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3959" y="79.181231" x="632.310457" xml:space="preserve">
+ <tspan stroke="null" font-size="20px" font-weight="bold" font-family="Monospace" id="tspan3961" y="83.887499" x="633.453917">n3</tspan>
+ </text>
+ <text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="125.371536" y="171.060971" id="text3967">
+ <tspan stroke="null" font-weight="normal" id="tspan3969" x="126.421253" y="176.187525">(NDN Container)</tspan>
+ </text>
+ <text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3979" y="170.076461" x="352.011746" xml:space="preserve">
+ <tspan stroke="null" font-weight="normal" y="175.203015" x="353.061463" id="tspan3981">(NDN Container)</tspan>
+ </text>
+ <text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="580.077396" y="169.091931" id="text3983">
+ <tspan stroke="null" font-weight="normal" id="tspan3985" x="581.127113" y="174.218485">(NDN Container)</tspan>
+ </text>
+ <text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3987" y="193.704961" x="123.946116" xml:space="preserve">
+ <tspan stroke="null" font-weight="bold" y="198.831515" x="124.995833" id="tspan3989">NFD</tspan>
+ </text>
+ <text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="140.791686" y="208.664491" id="text3991">
+ <tspan stroke="null" font-weight="normal" id="tspan3993" x="141.841403" y="213.791045">n1.sock</tspan>
+ </text>
+ <text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="123.946116" y="225.286191" id="text3995">
+ <tspan stroke="null" font-weight="bold" id="tspan3997" x="124.995833" y="230.412745">NLSR</tspan>
+ </text>
+ <text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3999" y="240.245731" x="138.385176" xml:space="preserve">
+ <tspan stroke="null" font-weight="normal" y="245.372285" x="139.434893" id="tspan4001">%C1.Router/n1</tspan>
+ </text>
+ <text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="352.011746" y="191.735901" id="text4003">
+ <tspan stroke="null" font-weight="bold" id="tspan4005" x="353.061463" y="196.862455">NFD</tspan>
+ </text>
+ <text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text4007" y="206.695431" x="366.450896" xml:space="preserve">
+ <tspan stroke="null" font-weight="normal" y="211.821985" x="367.500613" id="tspan4009">n2.sock</tspan>
+ </text>
+ <text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text4011" y="223.317141" x="352.011746" xml:space="preserve">
+ <tspan stroke="null" font-weight="bold" y="228.443695" x="353.061463" id="tspan4013">NLSR</tspan>
+ </text>
+ <text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="366.450896" y="238.276671" id="text4015">
+ <tspan stroke="null" font-weight="normal" id="tspan4017" x="367.500613" y="243.403225">%C1.Router/n2</tspan>
+ </text>
+ <text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text4019" y="190.751371" x="582.928226" xml:space="preserve">
+ <tspan stroke="null" font-weight="bold" y="195.877925" x="583.977943" id="tspan4021">NFD</tspan>
+ </text>
+ <text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="599.773686" y="205.710911" id="text4023">
+ <tspan stroke="null" font-weight="normal" id="tspan4025" x="600.823403" y="210.837465">n3.sock</tspan>
+ </text>
+ <text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="582.928226" y="222.332611" id="text4027">
+ <tspan stroke="null" font-weight="bold" id="tspan4029" x="583.977943" y="227.459165">NLSR</tspan>
+ </text>
+ <text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text4031" y="237.292141" x="597.367186" xml:space="preserve">
+ <tspan stroke="null" font-weight="normal" y="242.418695" x="598.416903" id="tspan4033">%C1.Router/n3</tspan>
+ </text>
+ <text transform="matrix(0.9778213687833123,0,0,0.9501950205038839,-52.301066914088324,-76.5370021990862) " font-size="16.459864px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text4035" y="102.475413" x="322.701992" xml:space="preserve">
+ <tspan stroke="null" y="107.73749" x="323.724674" id="tspan4037">Isolated NDN nodes</tspan>
+ </text>
+ <text transform="matrix(0.935021961689298,0,0,0.9936889310882339,-2.9798247609055646,-12.086171479984756) " font-size="11.279781px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="75.549398" y="206.131281" id="text4039">
+ <tspan stroke="null" id="tspan4041" x="76.618892" y="211.163037">Private network space</tspan>
+ </text>
+ <text transform="matrix(0.935021961689298,0,0,0.9936889310882339,-2.9798247609055646,-12.086171479984756) " font-size="11.279781px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text4043" y="206.946991" x="308.474828" xml:space="preserve">
+ <tspan stroke="null" y="211.978747" x="309.544322" id="tspan4045">Private network space</tspan>
+ </text>
+ <text transform="matrix(0.935021961689298,0,0,0.9936889310882339,-2.9798247609055646,-12.086171479984756) " font-size="11.279781px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="540.174348" y="206.131281" id="text4047">
+ <tspan stroke="null" id="tspan4049" x="541.243842" y="211.163037">Private network space</tspan>
+ </text>
+ <text xml:space="preserve" text-anchor="start" font-family="Helvetica,Arial,sans-serif" font-size="15px" id="svg_1" y="377" x="203.5" stroke-width="null" stroke="null" fill="#333">Figure: Relationship between Minindn and Mininet</text>
+ </g>
+</svg>
\ No newline at end of file
diff --git a/docs/release-notes.rst b/docs/release-notes.rst
new file mode 100644
index 0000000..79cbb0f
--- /dev/null
+++ b/docs/release-notes.rst
@@ -0,0 +1,186 @@
+Release Notes
+=============
+
+Mini-NDN version 0.4.0 (changes since version 0.3.0)
+----------------------------------------------------
+
+Release date: January 10, 2018
+
+**New features**:
+
+- Use SIGQUIT to quit Mini-NDN, SIGINT to kill programs
+
+- Use Infoedit to edit NFD and NLSR configuration files
+
+- Use nlsr.conf installed in the system
+
+- Provide a Vagrantfile to setup Mini-NDN and NDN
+
+- Provide option to disable NLSR
+
+- Provide an option to run NLSR in dry-run mode
+
+- Add option to specify whether to use TCP or UDP face in nlsr.conf
+
+- Add option to specify arbitrary arguments to use in experiments
+
+- Include a single option to install Mini-NDN and all the dependencies
+
+**Bug fixes**:
+
+- Fix "key does not exist error" after NLSR starts
+
+- Update install.sh to call ldconfig after installing ChronoSync
+
+- Add hyperbolic coordinates to default topology
+
+**Misc changes**:
+
+- Add an experiment to test nlsrc
+
+- Create faces in NFD for each neighbor in NLSR
+
+- Update to latest ndn-cxx
+
+- Use /tmp/minindn folder as default work dir instead of /tmp
+
+Mini-NDN version 0.3.0 (changes since version 0.2.0)
+----------------------------------------------------
+
+Release date: March 3, 2017
+
+**New features**:
+
+- Mini-NDN cluster edition
+
+- New experiments for making NLSR testing easier
+
+**Bug fixes**:
+
+- Set site name correctly
+
+- Install missing certificates in NLSR security config
+
+- Fix quitting of NLSR due to key not found error
+
+**Misc changes**:
+
+- Removed nlsr.conf file, generate it within the code
+
+- Use argparse instead of deprecated optparse
+
+- Update security config section for NLSR
+
+- Change mininet prompt to mini-ndn
+
+- Set network name at one place
+
+- Update install.sh script to install openssl
+
+- Update install.sh script to install cryptopp from package instead of
+ compiling from source
+
+- Update install.sh to clean build folder every time to get rid of
+ removed files such as old experiments
+
+- Fix old code - use net.hosts instead of storing hosts in a variable
+
+- Use nfdc instead of deprecated nfd-status
+
+Mini-NDN version 0.2.0 (changes since version 0.1.1)
+----------------------------------------------------
+
+Release date: August 18, 2016
+
+**New features**:
+
+- Automatic security configuration for NLSR
+
+- Use /usr/local/etc/ndn/nfd.conf as default config file for NFD
+
+- Class to monitor /proc/$PID/stat file for PID
+
+- Mini-NDN exits gracefully on SIGINT and non-convergence
+
+- Faster Mini-NDN install script - does not do apt-get update everytime
+
+- NLSR is launched with explicit config file for easier process
+ identification
+
+- Add and update more documentation
+
+**Bug fixes**:
+
+- NFD is killed correctly on exit
+
+- Best route strategy is set correctly
+
+Mini-NDN version 0.1.1 (changes since version 0.1.0)
+----------------------------------------------------
+
+Release date: November 4, 2015
+
+**New features**:
+
+- Use nfd.conf.sample from currently installed NFD
+
+- Add working directory option to allow execution environment outside
+ of /tmp
+
+- Add results directory option to store experiment results after
+ completion
+
+- Add support for switches in GUI and configuration file
+
+- Add failNode and recoverNode methods to Experiment class
+
+- Add most connected node (MCN) failure experiment
+
+- Add option to specify percentage of nodes pinged
+
+**Code changes**:
+
+- Refactor program options into container class
+
+- Remove unused "FIB Entries" option from NDN host options
+
+**Bug fixes**:
+
+- Abort start up if experiment name is invalid
+
+- Restart pings after recovery in failure experiment
+
+Mini-NDN version 0.1.0 (initial release)
+----------------------------------------
+
+Release date: July 15, 2015
+
+Mini-NDN is a lightweight networking emulation tool that enables
+testing, experimentation, and research on the NDN platform. Based on
+Mininet, Mini-NDN uses the NDN libraries, NFD, NLSR, and tools released
+by the `NDN project <http://named-data.net/codebase/platform/>`__ to
+emulate an NDN network on a single system.
+
+**Included features**:
+
+- Run a complete NDN network on a single system
+
+- Automatic configuration of NLSR to provide a routable NDN network
+
+- Supports user created NDN applications
+
+- Create a topology using the included Mini-NDN Edit GUI application
+
+- Allows individual configuration of NFD and NLSR parameters for each
+ node
+
+- Provides an experiment management framework for easy creation of
+ custom networking experiments
+
+- Uses a simple topology file format to define hosts, links, and
+ configuration values
+
+- Configure network link parameters including bandwidth, delay, and
+ loss rate
+
+- Includes a pre-configured topology file to replicate the NDN testbed
diff --git a/docs/videos.rst b/docs/videos.rst
new file mode 100644
index 0000000..b6b3a51
--- /dev/null
+++ b/docs/videos.rst
@@ -0,0 +1,18 @@
+Video Tutorials
+===============
+
+Maybe outdated since version 0.5.0.
+
+.. raw:: html
+
+ <div id="video-container" class="col-md-6 ">
+ <p>Mini-NDN Demo at ACM, 2017</p>
+ <iframe width="400" height="230" src="https://www.youtube.com/embed/xYRPHZe18o0" frameborder="0" allowfullscreen=""></iframe>
+ </div>
+
+.. raw:: html
+
+ <div id="video-container" class="col-md-6 "">
+ <p>Mini-NDN Overview </p>
+ <iframe width="400" height="230" src="https://www.youtube.com/embed/Da7t8yBWzv0" frameborder="0" allowfullscreen="">
+ </div>
diff --git a/examples/ip_rounting_experiment.py b/examples/ip_rounting_experiment.py
new file mode 100644
index 0000000..a6a82c0
--- /dev/null
+++ b/examples/ip_rounting_experiment.py
@@ -0,0 +1,53 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+from mininet.log import setLogLevel, info
+
+from minindn.minindn import Minindn
+from minindn.apps.app_manager import AppManager
+from minindn.apps.nfd import Nfd
+from minindn.apps.nlsr import Nlsr
+from minindn.helpers.ip_routing_helper import IPRoutingHelper
+
+if __name__ == '__main__':
+ setLogLevel('info')
+
+ Minindn.cleanUp()
+ Minindn.verifyDependencies()
+
+ ndn = Minindn()
+
+ ndn.start()
+
+ info('Starting NFD on nodes\n')
+ nfds = AppManager(ndn, ndn.net.hosts, Nfd)
+ info('Starting NLSR on nodes\n')
+ nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr)
+
+ # Calculate all routes for IP routing
+ IPRoutingHelper.calcAllRoutes(ndn.net)
+ info("IP routes configured, start ping\n")
+
+ ndn.net.pingAll()
+
+ ndn.net.stop()
diff --git a/ndn/experiments/ip_rounting_experiment.py b/examples/mnndn.py
similarity index 63%
rename from ndn/experiments/ip_rounting_experiment.py
rename to examples/mnndn.py
index 75c87ce..d989633 100644
--- a/ndn/experiments/ip_rounting_experiment.py
+++ b/examples/mnndn.py
@@ -21,27 +21,29 @@
# along with Mini-NDN, e.g., in COPYING.md file.
# If not, see <http://www.gnu.org/licenses/>.
-from ndn.experiments.experiment import Experiment
-from ndn.apps.routing_helper import IPRoutingHelper
+from mininet.log import setLogLevel, info
-from mininet.log import info
+from minindn.minindn import Minindn
+from minindn.util import MiniNDNCLI
+from minindn.apps.app_manager import AppManager
+from minindn.apps.nfd import Nfd
+from minindn.apps.nlsr import Nlsr
+if __name__ == '__main__':
+ setLogLevel('info')
-class IpRoutingExperiment(Experiment):
+ Minindn.cleanUp()
+ Minindn.verifyDependencies()
- def __init__(self, args):
- Experiment.__init__(self, args)
+ ndn = Minindn()
- def setup(self):
- pass
+ ndn.start()
- def run(self):
+ info('Starting NFD on nodes\n')
+ nfds = AppManager(ndn, ndn.net.hosts, Nfd)
+ info('Starting NLSR on nodes\n')
+ nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr)
- # Calculate all routes for IP routing
- IPRoutingHelper.calcAllRoutes(self.net)
- info("IP routes configured, start ping\n")
+ MiniNDNCLI(ndn.net)
- self.net.pingAll()
-
-
-Experiment.register("ip-routing", IpRoutingExperiment)
+ ndn.stop()
diff --git a/examples/nlsr/advertised-delayed-start.py b/examples/nlsr/advertised-delayed-start.py
new file mode 100644
index 0000000..8856fbd
--- /dev/null
+++ b/examples/nlsr/advertised-delayed-start.py
@@ -0,0 +1,79 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+import time
+import sys
+
+from mininet.log import setLogLevel, info
+from mininet.topo import Topo
+
+from minindn.minindn import Minindn
+from minindn.apps.app_manager import AppManager
+from minindn.apps.nfd import Nfd
+from minindn.apps.nlsr import Nlsr
+
+from nlsr_common import getParser
+
+if __name__ == '__main__':
+ setLogLevel('info')
+
+ topo = Topo()
+ h1 = topo.addHost('h1')
+ h2 = topo.addHost('h2')
+ topo.addLink(h1, h2, delay='10ms')
+
+ ndn = Minindn(parser=getParser(), topo=topo)
+ args = ndn.args
+
+ ndn.start()
+
+ nfds = AppManager(ndn, ndn.net.hosts, Nfd)
+ nlsrs = AppManager(ndn, [], Nlsr)
+
+ host1 = ndn.net.hosts[0]
+ nlsrs.startOnNode(host1, security=args.security, faceType=args.faceType,
+ nFaces=args.faces, routingType=args.routingType)
+
+
+ expectedTotalCount = 500
+ for i in range(0, expectedTotalCount):
+ host1.cmd('nlsrc advertise /long/name/to/exceed/max/packet/size/host1/{}'.format(i))
+
+ time.sleep(60)
+
+ host2 = ndn.net.hosts[1]
+ nlsrs.startOnNode(host2, security=args.security, faceType=args.faceType,
+ nFaces=args.faces, routingType=args.routingType)
+
+ time.sleep(60)
+
+ advertiseCount = int(host2.cmd('nfdc fib | grep host1 | wc -l'))
+ info(advertiseCount)
+ if advertiseCount == expectedTotalCount:
+ info('\nSuccessfully advertised {} prefixes\n'.format(expectedTotalCount))
+ else:
+ info('\nAdvertising {} prefixes failed. Exiting...\n'.format(expectedTotalCount))
+ ndn.stop()
+ sys.exit(1)
+
+ ndn.stop()
diff --git a/examples/nlsr/delayed_start.py b/examples/nlsr/delayed_start.py
new file mode 100644
index 0000000..59b2f54
--- /dev/null
+++ b/examples/nlsr/delayed_start.py
@@ -0,0 +1,64 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+import time
+
+from mininet.log import setLogLevel, info
+
+from minindn.minindn import Minindn
+from minindn.apps.app_manager import AppManager
+from minindn.apps.nfd import Nfd
+from minindn.apps.nlsr import Nlsr
+from minindn.helpers.experiment import Experiment
+
+from nlsr_common import getParser
+
+if __name__ == '__main__':
+ setLogLevel('info')
+
+ ndn = Minindn(parser=getParser())
+ args = ndn.args
+
+ ndn.start()
+
+ nfds = AppManager(ndn, ndn.net.hosts, Nfd)
+ nlsrs = AppManager(ndn, [], Nlsr)
+
+ i = 1
+ info('Starting NLSR on nodes\n')
+ for host in ndn.net.hosts:
+ nlsrs.startOnNode(host, security=args.security, sync=args.sync, faceType=args.faceType,
+ nFaces=args.faces, routingType=args.routingType)
+
+ # Wait 1/2 minute between starting NLSRs
+ # Wait 1 hour before starting last NLSR
+ if i == len(ndn.net.hosts) - 1:
+ info('Sleeping 1 hour before starting last NLSR\n')
+ time.sleep(3600)
+ else:
+ time.sleep(30)
+ i += 1
+
+ Experiment.checkConvergence(ndn, ndn.net.hosts, args.ctime, quit=True)
+
+ ndn.stop()
diff --git a/examples/nlsr/mcn_failure.py b/examples/nlsr/mcn_failure.py
new file mode 100644
index 0000000..1bd0449
--- /dev/null
+++ b/examples/nlsr/mcn_failure.py
@@ -0,0 +1,90 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+import time
+
+from mininet.log import setLogLevel, info
+
+from minindn.minindn import Minindn
+from minindn.util import MiniNDNCLI
+from minindn.apps.app_manager import AppManager
+from minindn.apps.nfd import Nfd
+from minindn.apps.nlsr import Nlsr
+from minindn.helpers.experiment import Experiment
+from minindn.helpers.nfdc import Nfdc
+from minindn.helpers.ndnpingclient import NDNPingClient
+
+from nlsr_common import getParser
+
+def mcnFailure(ndn, nfds, nlsrs, args):
+ Experiment.checkConvergence(ndn, ndn.net.hosts, args.ctime, quit=True)
+ if args.nPings != 0:
+ Experiment.setupPing(ndn.net.hosts, Nfdc.STRATEGY_BEST_ROUTE)
+ pingedDict = Experiment.startPctPings(ndn.net, args.nPings, args.pctTraffic)
+
+ PING_COLLECTION_TIME_BEFORE_FAILURE = 60
+ PING_COLLECTION_TIME_AFTER_RECOVERY = 120
+
+ time.sleep(PING_COLLECTION_TIME_BEFORE_FAILURE)
+
+ mcn = max(ndn.net.hosts, key=lambda host: len(host.intfNames()))
+
+ info('Bringing down node {}\n'.format(mcn.name))
+ nlsrs[mcn.name].stop()
+ nfds[mcn.name].stop()
+
+ time.sleep(args.ctime)
+
+ info('Bringing up node {}\n'.format(mcn.name))
+ nfds[mcn.name].start()
+ nlsrs[mcn.name].start()
+
+ # Restart pings
+ if args.nPings != 0:
+ Experiment.setupPing([mcn], Nfdc.STRATEGY_BEST_ROUTE)
+ for nodeToPing in pingedDict[mcn]:
+ NDNPingClient.ping(mcn, nodeToPing, PING_COLLECTION_TIME_AFTER_RECOVERY)
+
+ time.sleep(PING_COLLECTION_TIME_AFTER_RECOVERY)
+
+ Experiment.checkConvergence(ndn, ndn.net.hosts, args.ctime, quit=True)
+
+if __name__ == '__main__':
+ setLogLevel('info')
+
+ ndn = Minindn(parser=getParser())
+ args = ndn.args
+
+ ndn.start()
+
+ nfds = AppManager(ndn, ndn.net.hosts, Nfd)
+ nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr, sync=args.sync,
+ security=args.security, faceType=args.faceType,
+ nFaces=args.faces, routingType=args.routingType)
+
+ mcnFailure(ndn, nfds, nlsrs, args)
+
+ if args.isCliEnabled:
+ MiniNDNCLI(ndn.net)
+
+ ndn.stop()
diff --git a/examples/nlsr/multiple_failure.py b/examples/nlsr/multiple_failure.py
new file mode 100644
index 0000000..48d1afd
--- /dev/null
+++ b/examples/nlsr/multiple_failure.py
@@ -0,0 +1,109 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+import time
+
+from mininet.log import setLogLevel, info
+
+from minindn.minindn import Minindn
+from minindn.util import MiniNDNCLI
+from minindn.apps.app_manager import AppManager
+from minindn.apps.nfd import Nfd
+from minindn.apps.nlsr import Nlsr
+from minindn.helpers.experiment import Experiment
+from minindn.helpers.nfdc import Nfdc
+from minindn.helpers.ndnpingclient import NDNPingClient
+
+from nlsr_common import getParser
+
+def multipleFailure(ndn, nfds, nlsrs, args):
+
+ Experiment.checkConvergence(ndn, ndn.net.hosts, args.ctime, quit=True)
+ Experiment.setupPing(ndn.net.hosts, Nfdc.STRATEGY_BEST_ROUTE)
+
+ PING_COLLECTION_TIME_BEFORE_FAILURE = 60
+ FAILURE_INTERVAL = 60
+ RECOVERY_INTERVAL = 60
+
+ # This is the number of pings required to make it through the full experiment
+ nInitialPings = (PING_COLLECTION_TIME_BEFORE_FAILURE +
+ len(ndn.net.hosts) * (FAILURE_INTERVAL + RECOVERY_INTERVAL))
+ print('Scheduling with {} initial pings'.format(nInitialPings))
+
+ pingedDict = Experiment.startPctPings(ndn.net, nInitialPings, args.pctTraffic)
+ time.sleep(PING_COLLECTION_TIME_BEFORE_FAILURE)
+
+ nNodesRemainingToFail = len(ndn.net.hosts)
+
+ for host in ndn.net.hosts:
+ # Fail the node
+ info('Bringing down node {}\n'.format(host.name))
+ nlsrs[host.name].stop()
+ nfds[host.name].stop()
+
+ # Stay in failure state for FAILURE_INTERVAL seconds
+ time.sleep(FAILURE_INTERVAL)
+
+ # Bring the node back up
+ start_time = time.time()
+ info('Bringing up node {}\n'.format(host.name))
+ nfds[host.name].start()
+ nlsrs[host.name].start()
+ Experiment.setupPing([host], Nfdc.STRATEGY_BEST_ROUTE)
+
+ recovery_time = int(time.time() - start_time)
+
+ # Number of pings required to reach the end of the test
+ nNodesRemainingToFail -= 1
+ nPings = ((RECOVERY_INTERVAL - recovery_time) +
+ nNodesRemainingToFail * (FAILURE_INTERVAL + RECOVERY_INTERVAL))
+
+ info('Scheduling with {} remaining pings\n'.format(nPings))
+
+ # Restart pings
+ for nodeToPing in pingedDict[host]:
+ NDNPingClient.ping(host, nodeToPing, nPings)
+
+ time.sleep(RECOVERY_INTERVAL - recovery_time)
+
+ #Experiment.checkConvergence(ndn, ndn.net.hosts, args.ctime, quit=True)
+
+if __name__ == '__main__':
+ setLogLevel('info')
+
+ ndn = Minindn(parser=getParser())
+ args = ndn.args
+
+ ndn.start()
+
+ nfds = AppManager(ndn, ndn.net.hosts, Nfd)
+ nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr, sync=args.sync,
+ security=args.security, faceType=args.faceType,
+ nFaces=args.faces, routingType=args.routingType)
+
+ multipleFailure(ndn, nfds, nlsrs, args)
+
+ if args.isCliEnabled:
+ MiniNDNCLI(ndn.net)
+
+ ndn.stop()
diff --git a/examples/nlsr/nlsr_common.py b/examples/nlsr/nlsr_common.py
new file mode 100644
index 0000000..5ec7f7c
--- /dev/null
+++ b/examples/nlsr/nlsr_common.py
@@ -0,0 +1,57 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+import argparse
+
+def getParser():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--ctime', type=int, default=60,
+ help='Specify convergence time for the topology (Default: 60 seconds)')
+
+ parser.add_argument('--faces', type=int, default=3,
+ help='Specify number of max faces per prefix for NLSR 0-60')
+
+ parser.add_argument('--routing', dest='routingType', default='link-state',
+ choices=['link-state', 'hr', 'dry'],
+ help='''Choose routing type, dry = link-state is used
+ but hr is calculated for comparision.''')
+
+ parser.add_argument('--sync', dest='sync', default='psync',
+ choices=['chronosync', 'psync'],
+ help='choose the sync protocol to be used by NLSR.')
+
+ parser.add_argument('--security', action='store_true', dest='security',
+ help='Enables NLSR security')
+
+ parser.add_argument('--face-type', dest='faceType', default='udp', choices=['udp', 'tcp'])
+
+ parser.add_argument('--no-cli', action='store_false', dest='isCliEnabled',
+ help='Run experiments and exit without showing the command line interface')
+
+ parser.add_argument('--pct-traffic', dest='pctTraffic', type=float, default=1.0,
+ help='Specify the percentage of nodes each node should ping')
+
+ parser.add_argument('--nPings', type=int, default=300,
+ help='Number of pings to perform between each node in the experiment')
+
+ return parser
diff --git a/examples/nlsr/pingall.py b/examples/nlsr/pingall.py
new file mode 100644
index 0000000..002ace0
--- /dev/null
+++ b/examples/nlsr/pingall.py
@@ -0,0 +1,63 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+import time
+
+from mininet.log import setLogLevel
+
+from minindn.minindn import Minindn
+from minindn.util import MiniNDNCLI
+from minindn.apps.app_manager import AppManager
+from minindn.apps.nfd import Nfd
+from minindn.apps.nlsr import Nlsr
+from minindn.helpers.experiment import Experiment
+from minindn.helpers.nfdc import Nfdc
+
+from nlsr_common import getParser
+
+if __name__ == '__main__':
+ setLogLevel('info')
+
+ ndn = Minindn(parser=getParser())
+ args = ndn.args
+
+ ndn.start()
+
+ nfds = AppManager(ndn, ndn.net.hosts, Nfd)
+ nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr, sync=args.sync,
+ security=args.security, faceType=args.faceType,
+ nFaces=args.faces, routingType=args.routingType,
+ logLevel='ndn.*=TRACE:nlsr.*=TRACE')
+
+ Experiment.checkConvergence(ndn, ndn.net.hosts, args.ctime, quit=False)
+
+ if args.nPings != 0:
+ Experiment.setupPing(ndn.net.hosts, Nfdc.STRATEGY_BEST_ROUTE)
+ Experiment.startPctPings(ndn.net, args.nPings, args.pctTraffic)
+
+ time.sleep(args.nPings + 10)
+
+ if args.isCliEnabled:
+ MiniNDNCLI(ndn.net)
+
+ ndn.stop()
diff --git a/examples/nlsr/prefix_propogation.py b/examples/nlsr/prefix_propogation.py
new file mode 100644
index 0000000..7ea027c
--- /dev/null
+++ b/examples/nlsr/prefix_propogation.py
@@ -0,0 +1,84 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+import time
+
+from mininet.log import setLogLevel, info
+
+from minindn.minindn import Minindn
+from minindn.util import MiniNDNCLI
+from minindn.apps.app_manager import AppManager
+from minindn.apps.nfd import Nfd
+from minindn.apps.nlsr import Nlsr
+from minindn.helpers.experiment import Experiment
+
+from nlsr_common import getParser
+
+if __name__ == '__main__':
+ setLogLevel('info')
+
+ ndn = Minindn(parser=getParser())
+ args = ndn.args
+
+ ndn.start()
+
+ nfds = AppManager(ndn, ndn.net.hosts, Nfd)
+ nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr, sync=args.sync,
+ security=args.security, faceType=args.faceType,
+ nFaces=args.faces, routingType=args.routingType)
+
+ Experiment.checkConvergence(ndn, ndn.net.hosts, args.ctime, quit=True)
+
+ firstNode = ndn.net.hosts[0]
+
+ if args.security:
+ firstNode.cmd('ndnsec-set-default /ndn/{}-site/%C1.Operator/op'.format(firstNode.name))
+
+ info('Testing advertise\n')
+ firstNode.cmd('nlsrc advertise /testPrefix')
+ time.sleep(30)
+
+ for host in ndn.net.hosts:
+ if host.name != firstNode.name:
+ if (int(host.cmd('nfdc fib | grep testPrefix | wc -l')) != 1 or
+ int(host.cmd('nlsrc status | grep testPrefix | wc -l')) != 1):
+ info('Advertise test failed\n')
+ ndn.stop()
+ sys.exit(1)
+
+ info('Testing withdraw\n')
+ firstNode.cmd('nlsrc withdraw /testPrefix')
+ time.sleep(30)
+
+ for host in ndn.net.hosts:
+ if host.name != firstNode.name:
+ if (int(host.cmd('nfdc fib | grep testPrefix | wc -l')) != 0 or
+ int(host.cmd('nlsrc status | grep testPrefix | wc -l')) != 0):
+ info('Withdraw test failed\n')
+ ndn.stop()
+ sys.exit(1)
+
+ if args.isCliEnabled:
+ MiniNDNCLI(ndn.net)
+
+ ndn.stop()
diff --git a/examples/psync/full_sync.py b/examples/psync/full_sync.py
new file mode 100644
index 0000000..1a54a73
--- /dev/null
+++ b/examples/psync/full_sync.py
@@ -0,0 +1,81 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+import time
+import sys
+
+from mininet.log import setLogLevel, info
+
+from minindn.minindn import Minindn
+from minindn.apps.app_manager import AppManager
+from minindn.apps.nfd import Nfd
+from minindn.helpers.nfdc import Nfdc
+
+def registerRouteToAllNeighbors(ndn, host, syncPrefix):
+ for node in ndn.net.hosts:
+ for neighbor in node.connectionsTo(host):
+ ip = node.IP(neighbor[0])
+ Nfdc.createFace(host, ip)
+ Nfdc.registerRoute(host, syncPrefix, ip)
+
+if __name__ == '__main__':
+ setLogLevel('info')
+
+ ndn = Minindn()
+ args = ndn.args
+
+ ndn.start()
+
+ nfds = AppManager(ndn, ndn.net.hosts, Nfd)
+
+ syncPrefix = "/sync"
+ numUserPrefixesPerNode = 2
+ maxUpdatesPerUserPrefixPerNode = 3
+
+ for host in ndn.net.hosts:
+ Nfdc.setStrategy(host, syncPrefix, Nfdc.STRATEGY_MULTICAST)
+ registerRouteToAllNeighbors(ndn, host, syncPrefix)
+
+ info('Starting psync-full-sync on all the nodes\n')
+ for host in ndn.net.hosts:
+ host.cmd('export NDN_LOG=examples.FullSyncApp=INFO')
+ host.cmd('psync-full-sync {} {} {} {} &> psync.logs &'
+ .format(syncPrefix, host.name, numUserPrefixesPerNode,
+ maxUpdatesPerUserPrefixPerNode))
+
+ info('Sleeping 5 minutes for convergence\n')
+ # Estimated time for 4 node default topology
+ time.sleep(300)
+
+ totalUpdates = int(host.cmd('grep -r Update {}/*/psync.logs | wc -l'
+ .format(args.workDir)))
+
+ expectedUpdates = (maxUpdatesPerUserPrefixPerNode *
+ len(ndn.net.hosts) * (len(ndn.net.hosts) - 1) * numUserPrefixesPerNode)
+
+ if totalUpdates == expectedUpdates:
+ info('PSync full sync has successfully converged.\n')
+ else:
+ info('PSync full sync convergence was not successful. Exiting...\n')
+ ndn.stop()
+ sys.exit(1)
diff --git a/examples/psync/partial_sync.py b/examples/psync/partial_sync.py
new file mode 100644
index 0000000..13f2761
--- /dev/null
+++ b/examples/psync/partial_sync.py
@@ -0,0 +1,67 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+import time
+import sys
+
+from mininet.log import setLogLevel, info
+from mininet.topo import Topo
+
+from minindn.minindn import Minindn
+from minindn.apps.app_manager import AppManager
+from minindn.apps.nfd import Nfd
+
+if __name__ == '__main__':
+ setLogLevel('info')
+
+ topo = Topo()
+ topo.addHost('h1')
+
+ ndn = Minindn(topo=topo)
+ args = ndn.args
+
+ ndn.start()
+
+ nfds = AppManager(ndn, ndn.net.hosts, Nfd)
+
+ host1 = ndn.net.hosts[0]
+ host1.cmd('export NDN_LOG=examples.PartialSyncProducerApp=INFO')
+ host1.cmd('psync-producer /sync /{} 10 1 &> producer.log &'.format(host1.name))
+ time.sleep(1)
+
+ host1.cmd('export NDN_LOG=examples.PartialSyncConsumerApp=INFO:$NDN_LOG')
+ host1.cmd('psync-consumer /sync 5 &> consumer.log &')
+
+ info('Sleeping 90 seconds for convergence\n')
+ time.sleep(90)
+
+ consumerSubs = int(host1.cmd('cat consumer.log | grep -c Subscribing'))
+ consumerUpdates = int(host1.cmd('cat consumer.log | grep -c Update'))
+ producerPublish = int(host1.cmd('cat producer.log | grep -c Publish'))
+
+ if consumerSubs == 5 and consumerUpdates == 5 and producerPublish == 10:
+ info('PSync partial sync has successfully converged.\n')
+ else:
+ info('PSync partial sync convergence was not successful. Exiting...\n')
+ ndn.stop()
+ sys.exit(1)
diff --git a/examples/static_routing_experiment.py b/examples/static_routing_experiment.py
new file mode 100644
index 0000000..a5d9b04
--- /dev/null
+++ b/examples/static_routing_experiment.py
@@ -0,0 +1,100 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+import argparse
+import sys
+
+from mininet.log import setLogLevel, info
+from mininet.topo import Topo
+
+from minindn.minindn import Minindn
+from minindn.util import MiniNDNCLI
+from minindn.apps.app_manager import AppManager
+from minindn.apps.nfd import Nfd
+from minindn.helpers.ndn_routing_helper import NdnRoutingHelper
+
+if __name__ == '__main__':
+ setLogLevel('info')
+
+ Minindn.cleanUp()
+ Minindn.verifyDependencies()
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--face-type', dest='faceType', default='udp', choices=['udp', 'tcp'])
+ parser.add_argument('--routing', dest='routingType', default='link-state',
+ choices=['link-state', 'hr', 'dry'],
+ help='''Choose routing type, dry = link-state is used
+ but hr is calculated for comparision.''')
+
+ '''
+ Experiment run with default topology, test cases won't work with other topologies
+ # With calculateNPossibleRoutes,
+ 10 # routing = hr, N = All, from A, 3 routes needs to added to NFD.
+ a +++++++ b # a - b -- cost 10
+ + + # a - c -- cost 10
+ 10 + + 10 # a - d -- cost 20
+ + + # Same goes for B being a source.
+ c d #
+ '''
+ topo = Topo()
+ a = topo.addHost('a')
+ b = topo.addHost('b')
+ c = topo.addHost('c')
+ d = topo.addHost('d')
+ topo.addLink(a, b, delay='10ms')
+ topo.addLink(a, c, delay='10ms')
+ topo.addLink(b, d, delay='10ms')
+
+ ndn = Minindn(parser=parser, topo=topo)
+
+ ndn.start()
+
+ info('Starting NFD on nodes\n')
+ nfds = AppManager(ndn, ndn.net.hosts, Nfd)
+
+ info('Adding static routes to NFD\n')
+ grh = NdnRoutingHelper(ndn.net, ndn.args.faceType, ndn.args.routingType)
+ # For all host, pass ndn.net.hosts or a list, [ndn.net['a'], ..] or [ndn.net.hosts[0],.]
+ grh.addOrigin([ndn.net['a']], ["/abc"])
+ grh.calculateNPossibleRoutes()
+
+ '''
+ prefix "/abc" is advertise from node A, it should be reachable from all other nodes.
+ '''
+ routesFromA = ndn.net['a'].cmd("nfdc route | grep -v '/localhost/nfd'")
+ if '/ndn/b-site/b' not in routesFromA or \
+ '/ndn/c-site/c' not in routesFromA or \
+ '/ndn/d-site/d' not in routesFromA:
+ info("Route addition failed\n")
+
+ routesToPrefix = ndn.net['b'].cmd("nfdc fib | grep '/abc'")
+ if '/abc' not in routesToPrefix:
+ info("Missing route to advertised prefix, Route addition failed\n")
+ ndn.net.stop()
+ sys.exit(1)
+
+ info('Route addition to NFD completed\n')
+
+ MiniNDNCLI(ndn.net)
+
+ ndn.stop()
diff --git a/install.sh b/install.sh
index c5fe190..ab99329 100755
--- a/install.sh
+++ b/install.sh
@@ -1,7 +1,7 @@
#!/bin/bash
# -*- Mode:bash; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
-# Copyright (C) 2015-2018, The University of Memphis,
+# Copyright (C) 2015-2019, The University of Memphis,
# Arizona Board of Regents,
# Regents of the University of California.
#
@@ -85,93 +85,85 @@
fi
fi
-function forwarder {
- if [[ $cxx != true ]]; then
- ndncxx
- cxx="true"
- fi
+NDN_SRC="ndn-src"
- if [[ $DIST == Ubuntu || $DIST == Debian ]]; then
- $install libpcap-dev pkg-config
- fi
+NDN_GITHUB="https://github.com/named-data"
- if [[ $DIST == Fedora ]]; then
- $install libpcap-devel
- fi
+NDN_CXX_VERSION="master"
+NFD_VERSION="master"
+PSYNC_VERSION="master"
+CHRONOSYNC_VERSION="master"
+NLSR_VERSION="master"
+NDN_TOOLS_VERSION="master"
- git clone --depth 1 https://github.com/named-data/NFD
- cd NFD
- ./waf configure --without-websocket
- ./waf
- sudo ./waf install
- cd ../
+if [ $SUDO_USER ]; then
+ REAL_USER=$SUDO_USER
+else
+ REAL_USER=$(whoami)
+fi
+
+function patchDummy {
+ git -C $NDN_SRC/ndn-cxx apply $(pwd)/patches/ndn-cxx-dummy-keychain-from-ndnsim.patch
+ if [[ "$?" -ne 0 ]]; then
+ echo "Patch might already be applied"
+ fi
}
-function routing {
- if [[ $cxx != true ]]; then
- ndncxx
- cxx="true"
+function ndn_install {
+ mkdir -p $NDN_SRC
+ name=$1
+ version=$2
+ wafOptions=$3
+
+ if [[ $version == "master" ]]; then
+ if [[ -d "$NDN_SRC/$name" ]]; then
+ pushd $NDN_SRC/$name
+ git checkout master
+ else
+ git clone --depth 1 $NDN_GITHUB/$name $NDN_SRC/$name
+ pushd $NDN_SRC/$name
+ fi
+ else
+ if [[ -d $NDN_SRC/$name ]]; then
+ pushd $NDN_SRC/$name
+ if [[ $(git rev-parse --is-shallow-repository) == "true" ]]; then
+ git fetch --unshallow
+ git fetch --all
+ fi
+ else
+ git clone $NDN_GITHUB/$name $NDN_SRC/$name
+ pushd $NDN_SRC/$name
+ fi
+ git checkout $version -b version-$version || git checkout version-$version
fi
- git clone --depth 1 https://github.com/named-data/PSync
- cd PSync
- ./waf configure
- ./waf
- sudo ./waf install
- sudo ldconfig
- cd ../
-
- git clone --depth 1 https://github.com/named-data/ChronoSync
- cd ChronoSync
- ./waf configure
- ./waf
- sudo ./waf install
- sudo ldconfig
- cd ../
-
- git clone --depth 1 https://github.com/named-data/NLSR
- cd NLSR
- ./waf configure
- ./waf
- sudo ./waf install
- cd ../
+ # User must use the same python version as root to use ./waf outside of this script
+ sudo -E -u $REAL_USER ./waf configure $wafOptions
+ sudo -E -u $REAL_USER ./waf && sudo ./waf install && sudo ldconfig
+ popd
}
-function ndncxx {
+function ndn {
if [[ updated != true ]]; then
$update
updated="true"
fi
if [[ $DIST == Ubuntu || $DIST == Debian ]]; then
- $install git libsqlite3-dev libboost-all-dev make g++ libssl-dev
+ $install git libsqlite3-dev libboost-all-dev make g++ libssl-dev libpcap-dev pkg-config python-pip
fi
if [[ $DIST == Fedora ]]; then
- $install gcc-c++ sqlite-devel boost-devel openssl-devel
+ $install gcc-c++ sqlite-devel boost-devel openssl-devel libpcap-devel python-pip
fi
- git clone --depth 1 https://github.com/named-data/ndn-cxx
- cd ndn-cxx
- ./waf configure
- ./waf
- sudo ./waf install
- sudo ldconfig
- cd ../
-}
-
-function tools {
- if [[ $cxx != true ]]; then
- ndncxx
- cxx="true"
- fi
-
- git clone --depth 1 https://github.com/named-data/ndn-tools
- cd ndn-tools
- ./waf configure
- ./waf
- sudo ./waf install
- cd ../
+ ndn_install ndn-cxx $NDN_CXX_VERSION
+ ndn_install NFD $NFD_VERSION --without-websocket
+ ndn_install PSync $PSYNC_VERSION --with-examples
+ ndn_install ChronoSync $CHRONOSYNC_VERSION
+ ndn_install NLSR $NLSR_VERSION
+ ndn_install ndn-tools $NDN_TOOLS_VERSION
+ infoedit
}
function mininet {
@@ -185,16 +177,17 @@
fi
git clone --depth 1 https://github.com/mininet/mininet
- cd mininet
- sudo ./util/install.sh -fnv
- cd ../
+ pushd mininet
+ sudo ./util/install.sh -nv
+ popd
}
function infoedit {
- git clone --depth 1 https://github.com/NDN-Routing/infoedit.git
- cd infoedit
+ git clone --depth 1 https://github.com/NDN-Routing/infoedit.git $NDN_SRC/infoedit
+ pushd $NDN_SRC/infoedit
+ rm infoedit
sudo make install
- cd ../
+ popd
}
function minindn {
@@ -220,7 +213,7 @@
sudo cp topologies/minindn.ucla.conf "$install_dir"
sudo cp topologies/minindn.testbed.conf "$install_dir"
sudo cp topologies/current-testbed.conf "$install_dir"
- sudo python setup.py clean --all install
+ sudo python setup.py develop
}
function ndn_cpp {
@@ -238,14 +231,14 @@
return
fi
- git clone --depth 1 https://github.com/named-data/ndn-cpp
- cd ndn-cpp
+ git clone --depth 1 $NDN_GITHUB/ndn-cpp $NDN_SRC/ndn-cpp
+ pushd $NDN_SRC/ndn-cpp
./configure
proc=$(nproc)
make -j$proc
sudo make install
sudo ldconfig
- cd ..
+ popd
}
function pyNDN {
@@ -264,13 +257,13 @@
fi
sudo pip install cryptography trollius protobuf pytest mock
- git clone --depth 1 https://github.com/named-data/PyNDN2
- cd PyNDN2
+ git clone --depth 1 $NDN_GITHUB/PyNDN2 $NDN_SRC/PyNDN2
+ pushd $NDN_SRC/PyNDN2
# Update the user's PYTHONPATH.
echo "export PYTHONPATH=\$PYTHONPATH:`pwd`/python" >> ~/.bashrc
# Also update root's PYTHONPATH in case of running under sudo.
echo "export PYTHONPATH=\$PYTHONPATH:`pwd`/python" | sudo tee -a /root/.bashrc > /dev/null
- cd ..
+ popd
}
function ndn_js {
@@ -291,7 +284,7 @@
sudo ln -fs /usr/bin/nodejs /usr/bin/node
sudo npm install -g mocha
sudo npm install rsa-keygen sqlite3
- git clone --depth 1 https://github.com/named-data/ndn-js
+ git clone --depth 1 $NDN_GITHUB/ndn-js $NDN_SRC/ndn-js
}
function jNDN {
@@ -309,30 +302,10 @@
return
fi
- git clone --depth 1 https://github.com/named-data/jndn
- cd jndn
+ git clone --depth 1 $NDN_GITHUB/jndn $NDN_SRC/jndn
+ pushd $NDN_SRC/jndn
mvn install
- cd ..
-}
-
-function argcomplete {
- if [[ $SHELL == "/bin/bash" ]]; then
- $install bash-completion
- $install python-argcomplete
- if ! grep -q 'eval "$(register-python-argcomplete minindn)"' ~/.bashrc; then
- echo 'eval "$(register-python-argcomplete minindn)"' >> ~/.bashrc
- fi
- source ~/.bashrc
- elif [[ $SHELL == "/bin/zsh" ]] || [[ $SHELL == "/usr/bin/zsh" ]]; then
- $install bash-completion
- $install python-argcomplete
- if ! grep -z -q 'autoload bashcompinit\sbashcompinit\seval "$(register-python-argcomplete minindn)"' ~/.zshrc; then
- echo -e 'autoload bashcompinit\nbashcompinit\neval "$(register-python-argcomplete minindn)"' >> ~/.zshrc
- fi
- source ~/.zshrc
- else
- echo "Skipping argomplete install..."
- fi
+ popd
}
function commonClientLibraries {
@@ -342,47 +315,56 @@
jNDN
}
+function buildDocumentation {
+ sphinxInstalled=$(pip show sphinx | wc -l)
+ sphinxRtdInstalled=$(pip show sphinx_rtd_theme | wc -l)
+ if [[ $sphinxInstalled -eq "0" ]]; then
+ pip install sphinx
+ fi
+
+ if [[ $sphinxRtdInstalled -eq "0" ]]; then
+ pip install sphinx_rtd_theme
+ fi
+ cd docs
+ make clean
+ make html
+}
+
function usage {
printf '\nUsage: %s [-a]\n\n' $(basename $0) >&2
printf 'options:\n' >&2
printf -- ' -a: install all the required dependencies\n' >&2
- printf -- ' -b: install autocomplete for Bash and Zsh users\n' >&2
- printf -- ' -e: install infoedit\n' >&2
- printf -- ' -f: install NFD\n' >&2
+ printf -- ' -c: install Common Client Libraries\n' >&2
+ printf -- ' -d: build documentation\n' >&2
+ printf -- ' -h: print this (H)elp message\n' >&2
printf -- ' -i: install mini-ndn\n' >&2
printf -- ' -m: install mininet and dependencies\n' >&2
- printf -- ' -r: install NLSR\n' >&2
- printf -- ' -t: install tools\n' >&2
- printf -- ' -c: install Common Client Libraries\n' >&2
+ printf -- ' -n: install NDN dependencies of mini-ndn including infoedit\n' >&2
+ printf -- ' -p: patch ndn-cxx with dummy key chain\n' >&2
exit 2
}
if [[ $# -eq 0 ]]; then
usage
else
- while getopts 'abemfrtic' OPTION
+ while getopts 'acdhimnp' OPTION
do
case $OPTION in
a)
- forwarder
- minindn
+ ndn
mininet
- routing
- tools
- infoedit
- argcomplete
+ minindn
commonClientLibraries
break
;;
- b) argcomplete;;
- e) infoedit;;
- f) forwarder;;
+ c) commonClientLibraries;;
+ d) buildDocumentation;;
+ h) usage;;
i) minindn;;
m) mininet;;
- r) routing;;
- t) tools;;
- c) commonClientLibraries;;
+ n) ndn;;
+ p) patchDummy;;
?) usage;;
esac
done
diff --git a/minindn/__init__.py b/minindn/__init__.py
new file mode 100644
index 0000000..2b8877c
--- /dev/null
+++ b/minindn/__init__.py
@@ -0,0 +1 @@
+__version__ = '0.5.0'
diff --git a/ndn/apps/__init__.py b/minindn/apps/__init__.py
similarity index 100%
rename from ndn/apps/__init__.py
rename to minindn/apps/__init__.py
diff --git a/minindn/apps/app_manager.py b/minindn/apps/app_manager.py
new file mode 100644
index 0000000..bfe2ddc
--- /dev/null
+++ b/minindn/apps/app_manager.py
@@ -0,0 +1,56 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+from mininet.node import Node
+
+class AppManager(object):
+ def __init__(self, minindn, hosts, cls, **appParams):
+ self.cls = cls
+ self.apps = []
+ for host in hosts:
+ # Don't run NDN apps on switches
+ if isinstance(host, Node):
+ self.startOnNode(host, **appParams)
+
+ minindn.cleanups.append(self.cleanup)
+
+ def startOnNode(self, host, **appParams):
+ app = self.cls(host, **appParams)
+ app.start()
+ self.apps.append(app)
+
+ def cleanup(self):
+ for app in self.apps:
+ app.stop()
+
+ def __getitem__(self, nodeName):
+ for app in self.apps:
+ if app.node.name == nodeName:
+ return app
+ return None
+
+ def __iter__(self):
+ return self.apps.__iter__()
+
+ def __next__(self):
+ return self.apps.__next__()
diff --git a/minindn/apps/application.py b/minindn/apps/application.py
new file mode 100644
index 0000000..6970cb7
--- /dev/null
+++ b/minindn/apps/application.py
@@ -0,0 +1,48 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+from minindn.util import getPopen
+
+class Application(object):
+ def __init__(self, node):
+ self.node = node
+ self.process = None
+ self.logfile = None
+ self.homeDir = self.node.params['params']['homeDir']
+
+ # Make directory for log file
+ self.logDir = '{}/log'.format(self.homeDir)
+ self.node.cmd('mkdir -p {}'.format(self.logDir))
+
+ def start(self, command, logfile, envDict=None):
+ if self.process is None:
+ self.logfile = open('{}/{}'.format(self.logDir, logfile), 'w')
+ self.process = getPopen(self.node, command.split(), envDict,
+ stdout=self.logfile, stderr=self.logfile)
+
+ def stop(self):
+ if self.process is not None:
+ self.process.kill()
+ self.process = None
+ if self.logfile is not None:
+ self.logfile.close()
diff --git a/minindn/apps/nfd.py b/minindn/apps/nfd.py
new file mode 100644
index 0000000..7130526
--- /dev/null
+++ b/minindn/apps/nfd.py
@@ -0,0 +1,74 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+from minindn.apps.application import Application
+from minindn.util import copyExistentFile
+from minindn.minindn import Minindn
+
+class Nfd(Application):
+
+ def __init__(self, node, logLevel='NONE', csSize=65536,
+ csPolicy='lru', csUnsolicitedPolicy='drop-all'):
+ Application.__init__(self, node)
+
+ self.logLevel = node.params['params'].get('nfd-log-level', logLevel)
+
+ self.confFile = '{}/nfd.conf'.format(self.homeDir)
+ self.logFile = 'nfd.log'
+ self.sockFile = '/var/run/{}.sock'.format(node.name)
+ self.ndnFolder = '{}/.ndn'.format(self.homeDir)
+ self.clientConf = '{}/client.conf'.format(self.ndnFolder)
+
+ # Copy nfd.conf file from /usr/local/etc/ndn or /etc/ndn to the node's home directory
+ # Use nfd.conf as default configuration for NFD, else use the sample
+ possibleConfPaths = ['/usr/local/etc/ndn/nfd.conf.sample', '/usr/local/etc/ndn/nfd.conf',
+ '/etc/ndn/nfd.conf.sample', '/etc/ndn/nfd.conf']
+ copyExistentFile(node, possibleConfPaths, self.confFile)
+
+ # Set log level
+ node.cmd('infoedit -f {} -s log.default_level -v {}'.format(self.confFile, self.logLevel))
+ # Open the conf file and change socket file name
+ node.cmd('infoedit -f {} -s face_system.unix.path -v {}'.format(self.confFile, self.sockFile))
+
+ # Set CS parameters
+ node.cmd('infoedit -f {} -s tables.cs_max_packets -v {}'.format(self.confFile, csSize))
+ node.cmd('infoedit -f {} -s tables.cs_policy -v {}'.format(self.confFile, csPolicy))
+ node.cmd('infoedit -f {} -s tables.cs_unsolicited_policy -v {}'.format(self.confFile, csUnsolicitedPolicy))
+
+ # Make NDN folder
+ node.cmd('mkdir -p {}'.format(self.ndnFolder))
+
+ # Copy client configuration to host
+ possibleClientConfPaths = ['/usr/local/etc/ndn/client.conf.sample', '/etc/ndn/client.conf.sample']
+ copyExistentFile(node, possibleClientConfPaths, self.clientConf)
+
+ # Change the unix socket
+ node.cmd('sudo sed -i "s|nfd.sock|{}.sock|g" {}'.format(node.name, self.clientConf))
+
+ if not Minindn.ndnSecurityDisabled:
+ # Generate key and install cert for /localhost/operator to be used by NFD
+ node.cmd('ndnsec-keygen /localhost/operator | ndnsec-install-cert -')
+
+ def start(self):
+ Application.start(self, 'nfd --config {}'.format(self.confFile), logfile=self.logFile)
+ Minindn.sleep(2)
diff --git a/minindn/apps/nlsr.py b/minindn/apps/nlsr.py
new file mode 100644
index 0000000..36ef971
--- /dev/null
+++ b/minindn/apps/nlsr.py
@@ -0,0 +1,258 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+import shutil
+import os, sys
+
+from mininet.clean import sh
+from mininet.examples.cluster import RemoteMixin
+from mininet.log import warn
+from mininet.node import Switch
+
+from minindn.apps.application import Application
+from minindn.util import scp, copyExistentFile
+from minindn.helpers.nfdc import Nfdc
+from minindn.minindn import Minindn
+
+class Nlsr(Application):
+ ROUTING_LINK_STATE = 'link-state'
+ ROUTING_HYPERBOLIC = 'hr'
+ ROUTING_DRY_RUN = 'dry'
+ SYNC_PSYNC = 'psync'
+ SYNC_CHRONOSYNC = 'chronosync'
+
+ def __init__(self, node, logLevel='NONE', security=False, sync=SYNC_PSYNC,
+ faceType='udp', nFaces=3, routingType=ROUTING_LINK_STATE):
+ Application.__init__(self, node)
+
+ self.network = '/ndn/'
+ self.node = node
+ self.parameters = self.node.params['params']
+
+ if self.parameters.get('nlsr-log-level', None) != None:
+ logLevel = self.parameters.get('nlsr-log-level')
+
+ if logLevel in ['NONE', 'WARN', 'INFO', 'DEBUG', 'TRACE']:
+ self.envDict = {'NDN_LOG': 'nlsr.*={}'.format(logLevel)}
+ else:
+ self.envDict = {'NDN_LOG': logLevel}
+
+ self.logFile = 'nlsr.log'
+ self.routerName = '/{}C1.Router/cs/{}'.format('%', node.name)
+ self.confFile = '{}/nlsr.conf'.format(self.homeDir)
+ self.security = security
+ self.sync = sync
+ self.faceType = faceType
+ self.infocmd = 'infoedit -f nlsr.conf'
+
+ self.parameters = self.node.params['params']
+
+ self.nFaces = nFaces
+ if routingType == Nlsr.ROUTING_HYPERBOLIC:
+ self.hyperbolicState = 'on'
+ elif routingType == Nlsr.ROUTING_DRY_RUN:
+ self.hyperbolicState = 'dry-run'
+ else:
+ self.hyperbolicState = 'off'
+ self.hyperRadius = self.parameters.get('radius', 0.0)
+ self.hyperAngle = self.parameters.get('angle', 0.0)
+
+ if ((self.hyperbolicState == 'on' or self.hyperbolicState == 'dry-run') and
+ (self.hyperRadius == 0.0 or self.hyperAngle == 0.0)):
+ warn('Hyperbolic coordinates in topology file are either missing or misconfigured.')
+ warn('Check that each node has one radius value and one or two angle value(s).')
+ sys.exit(1)
+
+ self.neighborIPs = []
+ possibleConfPaths = ['/usr/local/etc/ndn/nlsr.conf.sample', '/etc/ndn/nlsr.conf.sample']
+ copyExistentFile(node, possibleConfPaths, '{}/nlsr.conf'.format(self.homeDir))
+
+ self.createConfigFile()
+
+ if security and not Minindn.ndnSecurityDisabled:
+ self.createKeysAndCertificates()
+
+ def start(self):
+ self.createFaces()
+ Application.start(self, 'nlsr -f {}'.format(self.confFile), self.logFile, self.envDict)
+ Minindn.sleep(1)
+
+ def createFaces(self):
+ for ip in self.neighborIPs:
+ Nfdc.createFace(self.node, ip, self.faceType, isPermanent=True)
+
+ @staticmethod
+ def createKey(host, name, outputFile):
+ host.cmd('ndnsec-keygen {} > {}'.format(name, outputFile))
+
+ @staticmethod
+ def createCertificate(host, signer, keyFile, outputFile):
+ host.cmd('ndnsec-certgen -s {} -r {} > {}'.format(signer, keyFile, outputFile))
+
+ def createKeysAndCertificates(self):
+ securityDir = '{}/security'.format(self.parameters['workDir'])
+
+ if not os.path.exists(securityDir):
+ os.mkdir(securityDir)
+
+ rootName = self.network
+ rootCertFile = '{}/root.cert'.format(securityDir)
+ if not os.path.isfile(rootCertFile):
+ # Create root certificate
+ sh('ndnsec-keygen {}'.format(rootName)) # Installs a self-signed cert into the system
+ sh('ndnsec-cert-dump -i {} > {}'.format(rootName, rootCertFile))
+
+ # Create necessary certificates for each site
+ nodeSecurityFolder = '{}/security'.format(self.homeDir)
+
+ self.node.cmd('mkdir -p {}'.format(nodeSecurityFolder))
+
+ # Create temp folders for remote nodes on this machine (localhost) to store site.key file
+ # from RemoteNodes
+ if not os.path.exists(nodeSecurityFolder) and \
+ isinstance(self.node, RemoteMixin) and self.node.isRemote:
+ os.makedirs(nodeSecurityFolder)
+
+ shutil.copyfile('{}/root.cert'.format(securityDir),
+ '{}/root.cert'.format(nodeSecurityFolder))
+
+ # Create site certificate
+ siteName = '{}{}-site'.format(self.network, self.node.name)
+ siteKeyFile = '{}/site.keys'.format(nodeSecurityFolder)
+ siteCertFile = '{}/site.cert'.format(nodeSecurityFolder)
+ Nlsr.createKey(self.node, siteName, siteKeyFile)
+
+ # Copy siteKeyFile from remote for ndnsec-certgen
+ if isinstance(self.node, RemoteMixin) and self.node.isRemote:
+ login = 'mininet@{}'.format(self.node.server)
+ src = '{}:{}'.format(login, siteKeyFile)
+ dst = siteKeyFile
+ scp(src, dst)
+
+ # Root key is in root namespace, must sign site key and then install on host
+ sh('ndnsec-certgen -s {} -r {} > {}'.format(rootName, siteKeyFile, siteCertFile))
+
+ # Copy root.cert and site.cert from localhost to remote host
+ if isinstance(self.node, RemoteMixin) and self.node.isRemote:
+ login = 'mininet@{}'.format(self.node.server)
+ src = '{}/site.cert'.format(nodeSecurityFolder)
+ src2 = '{}/root.cert'.format(nodeSecurityFolder)
+ dst = '{}:/tmp/'.format(login)
+ scp(src, src2, dst)
+ self.node.cmd('mv /tmp/*.cert {}'.format(nodeSecurityFolder))
+
+ self.node.cmd('ndnsec-cert-install -f {}'.format(siteCertFile))
+
+ # Create and install operator certificate
+ opName = '{}/%C1.Operator/op'.format(siteName)
+ opKeyFile = '{}/op.keys'.format(nodeSecurityFolder)
+ opCertFile = '{}/op.cert'.format(nodeSecurityFolder)
+ Nlsr.createKey(self.node, opName, opKeyFile)
+ Nlsr.createCertificate(self.node, siteName, opKeyFile, opCertFile)
+ self.node.cmd('ndnsec-cert-install -f {}'.format(opCertFile))
+
+ # Create and install router certificate
+ routerName = '{}/%C1.Router/cs/{}'.format(siteName, self.node.name)
+ routerKeyFile = '{}/router.keys'.format(nodeSecurityFolder)
+ routerCertFile = '{}/router.cert'.format(nodeSecurityFolder)
+ Nlsr.createKey(self.node, routerName, routerKeyFile)
+ Nlsr.createCertificate(self.node, opName, routerKeyFile, routerCertFile)
+ self.node.cmd('ndnsec-cert-install -f {}'.format(routerCertFile))
+
+ def createConfigFile(self):
+
+ self.__editGeneralSection()
+ self.__editNeighborsSection()
+ self.__editHyperbolicSection()
+ self.__editFibSection()
+ self.__editAdvertisingSection()
+ self.__editSecuritySection()
+
+ def __editGeneralSection(self):
+
+ self.node.cmd('{} -s general.network -v {}'.format(self.infocmd, self.network))
+ self.node.cmd('{} -s general.site -v /{}-site'.format(self.infocmd, self.node.name))
+ self.node.cmd('{} -s general.router -v /%C1.Router/cs/{}'.format(self.infocmd, self.node.name))
+ self.node.cmd('{} -s general.state-dir -v {}/log'.format(self.infocmd, self.homeDir))
+ self.node.cmd('{} -s general.sync-protocol -v {}'.format(self.infocmd, self.sync))
+
+ def __editNeighborsSection(self):
+
+ self.node.cmd('{} -d neighbors.neighbor'.format(self.infocmd))
+ for intf in self.node.intfList():
+ link = intf.link
+ if not link:
+ continue
+
+ node1, node2 = link.intf1.node, link.intf2.node
+
+ # Todo: add some switch support
+ if isinstance(node1, Switch) or isinstance(node2, Switch):
+ continue
+
+ if node1 == self.node:
+ other = node2
+ ip = other.IP(str(link.intf2))
+ else:
+ other = node1
+ ip = other.IP(str(link.intf1))
+
+ linkCost = intf.params.get('delay', '10ms').replace('ms', '')
+
+ self.neighborIPs.append(ip)
+
+ self.node.cmd('{} -a neighbors.neighbor \
+ <<<\'name {}{}-site/%C1.Router/cs/{} face-uri {}://{}\n link-cost {}\''
+ .format(self.infocmd, self.network, other.name, other.name,
+ self.faceType, ip, linkCost))
+
+ def __editHyperbolicSection(self):
+
+ self.node.cmd('{} -s hyperbolic.state -v {}'.format(self.infocmd, self.hyperbolicState))
+ self.node.cmd('{} -s hyperbolic.radius -v {}'.format(self.infocmd, self.hyperRadius))
+ self.node.cmd('{} -s hyperbolic.angle -v {}'.format(self.infocmd, self.hyperAngle))
+
+ def __editFibSection(self):
+
+ self.node.cmd('{} -s fib.max-faces-per-prefix -v {}'.format(self.infocmd, self.nFaces))
+
+ def __editAdvertisingSection(self):
+
+ self.node.cmd('{} -d advertising.prefix'.format(self.infocmd))
+ self.node.cmd('{} -s advertising.prefix -v {}{}-site/{}'
+ .format(self.infocmd, self.network, self.node.name, self.node.name))
+
+ def __editSecuritySection(self):
+
+ self.node.cmd('{} -d security.cert-to-publish'.format(self.infocmd))
+ if not self.security:
+ self.node.cmd('{} -s security.validator.trust-anchor.type -v any'.format(self.infocmd))
+ self.node.cmd('{} -d security.validator.trust-anchor.file-name'.format(self.infocmd))
+ self.node.cmd('{} -s security.prefix-update-validator.trust-anchor.type -v any'.format(self.infocmd))
+ self.node.cmd('{} -d security.prefix-update-validator.trust-anchor.file-name'.format(self.infocmd))
+ else:
+ self.node.cmd('{} -s security.validator.trust-anchor.file-name -v security/root.cert'.format(self.infocmd))
+ self.node.cmd('{} -s security.prefix-update-validator.trust-anchor.file-name -v security/site.cert'.format(self.infocmd))
+ self.node.cmd('{} -p security.cert-to-publish -v security/site.cert'.format(self.infocmd))
+ self.node.cmd('{} -p security.cert-to-publish -v security/op.cert'.format(self.infocmd))
+ self.node.cmd('{} -p security.cert-to-publish -v security/router.cert'.format(self.infocmd))
diff --git a/ndn/apps/__init__.py b/minindn/helpers/__init__.py
similarity index 100%
copy from ndn/apps/__init__.py
copy to minindn/helpers/__init__.py
diff --git a/minindn/helpers/experiment.py b/minindn/helpers/experiment.py
new file mode 100644
index 0000000..226684e
--- /dev/null
+++ b/minindn/helpers/experiment.py
@@ -0,0 +1,107 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+import time
+import sys
+from itertools import cycle
+
+from mininet.log import info
+
+from minindn.helpers.nfdc import Nfdc
+from minindn.helpers.ndnpingclient import NDNPingClient
+
+class Experiment(object):
+ @staticmethod
+ def checkConvergence(ndn, hosts, convergenceTime, quit=False):
+ # Wait for convergence time period
+ info('Waiting {} seconds for convergence...\n'.format(convergenceTime))
+ time.sleep(convergenceTime)
+ info('...done\n')
+
+ # To check whether all the nodes of NLSR have converged
+ didNlsrConverge = True
+
+ # Checking for convergence
+ for host in hosts:
+ statusRouter = host.cmd('nfdc fib list | grep site/%C1.Router/cs/')
+ statusPrefix = host.cmd('nfdc fib list | grep ndn | grep site | grep -v Router')
+ didNodeConverge = True
+ for node in hosts:
+ # Node has its own router name in the fib list, but not name prefix
+ if (('/ndn/{}-site/%C1.Router/cs/{}'.format(node.name, node.name)) not in statusRouter or
+ host.name != node.name and ('/ndn/{}-site/{}'.format(node.name, node.name)) not in statusPrefix):
+ didNodeConverge = False
+ didNlsrConverge = False
+
+ host.cmd('echo {} > convergence-result &'.format(didNodeConverge))
+
+ if not didNlsrConverge:
+ info('NLSR has not converged. Exiting...\n')
+ if quit:
+ ndn.stop()
+ sys.exit(1)
+ else:
+ info('NLSR has converged successfully.\n')
+
+ return didNlsrConverge
+
+ @staticmethod
+ def setupPing(hosts, strategy):
+ for host in hosts:
+ host.cmd('mkdir -p ping-data')
+ Nfdc.setStrategy(host, '/ndn/', strategy)
+ host.cmd('ndnpingserver /ndn/{}-site/{} > ping-server &'.format(host.name, host.name))
+
+ @staticmethod
+ def startPctPings(net, nPings, pctTraffic=1.0):
+ nNodesToPing = int(round(len(net.hosts) * pctTraffic))
+ info('Each node will ping {} node(s)\n'.format(nNodesToPing))
+ # Temporarily store all the nodes being pinged by a particular node
+ nodesPingedList = []
+ pingedDict = {}
+
+ for host in net.hosts:
+ # Create a circular list
+ pool = cycle(net.hosts)
+
+ # Move iterator to current node
+ next(x for x in pool if host.name == x.name)
+
+ # Track number of nodes to ping scheduled for this node
+ nNodesScheduled = 0
+
+ while nNodesScheduled < nNodesToPing:
+ other = next(pool)
+
+ # Do not ping self
+ if host.name != other.name:
+ NDNPingClient.ping(host, other, nPings)
+ nodesPingedList.append(other)
+
+ # Always increment because in 100% case a node should not ping itself
+ nNodesScheduled = nNodesScheduled + 1
+
+ pingedDict[host] = nodesPingedList
+ nodesPingedList = []
+
+ return pingedDict
diff --git a/ndn/apps/routing_helper.py b/minindn/helpers/ip_routing_helper.py
similarity index 90%
rename from ndn/apps/routing_helper.py
rename to minindn/helpers/ip_routing_helper.py
index 4c89e48..8c2bddf 100644
--- a/ndn/apps/routing_helper.py
+++ b/minindn/helpers/ip_routing_helper.py
@@ -21,11 +21,10 @@
# along with Mini-NDN, e.g., in COPYING.md file.
# If not, see <http://www.gnu.org/licenses/>.
-from igraph import *
+from igraph import Graph
from mininet.log import info
-
-class LinkInfo:
+class LinkInfo(object):
"""
This class is used to encapsule link information (IP and interface names).
"""
@@ -36,8 +35,7 @@
self.end_intf_name = end_intf_name
self.end_ip = end_ip
-
-class IPRoutingHelper:
+class IPRoutingHelper(object):
"""The routing helper allows to run IP-based evaluations with Mini-NDN. It configures static IP
routes to all nodes, which means that all nodes can reach all other nodes in the network
reachable, even when relaying is required.
@@ -79,9 +77,9 @@
mini_links = net.links
# Enabling IP forwaring on all nodes
- info("Configure IP forwarding on all nodes\n")
+ info('Configure IP forwarding on all nodes\n')
for node in mini_nodes:
- node.cmd("sysctl -w net.ipv4.ip_forward=1")
+ node.cmd('sysctl -w net.ipv4.ip_forward=1')
# Calculate igraph to calculate all shortest paths between nodes
node_names = [node.name for node in mini_nodes]
@@ -107,11 +105,11 @@
shortest_path = paths[0]
shortest_path_with_nodenames = []
for node in shortest_path:
- shortest_path_with_nodenames.append(networkGraph.vs["name"][node])
+ shortest_path_with_nodenames.append(networkGraph.vs['name'][node])
named_paths.append(shortest_path_with_nodenames)
- # Iterate over all paths and configure the routes using the "route add"
- info("Configure routes on all nodes\n")
+ # Iterate over all paths and configure the routes using the 'route add'
+ info('Configure routes on all nodes\n')
for path in named_paths:
start_node = path[0]
end_node = path[-1]
@@ -125,12 +123,12 @@
addr = mini_end.intfs[intf].ip
if len(path) == 2:
# For direct connection, configure exit interface
- info("[{}] route add -host {} dev {}\n".format(start_node, addr, start_intf))
- mini_start.cmd("route add -host {} dev {}".format(addr, start_intf))
+ info('[{}] route add -host {} dev {}\n'.format(start_node, addr, start_intf))
+ mini_start.cmd('route add -host {} dev {}'.format(addr, start_intf))
elif len(path) > 2:
# For longer paths, configure next hop as gateway
gateway_ip = link_info.end_ip
- info("[{}] route add -host {} dev {} gw {}\n"
+ info('[{}] route add -host {} dev {} gw {}\n'
.format(start_node, addr, start_intf, gateway_ip))
- mini_start.cmd("route add -host {} dev {} gw {}"
+ mini_start.cmd('route add -host {} dev {} gw {}'
.format(addr, start_intf, gateway_ip))
diff --git a/ndn/apps/calculate_routing.py b/minindn/helpers/ndn_routing_helper.py
similarity index 68%
rename from ndn/apps/calculate_routing.py
rename to minindn/helpers/ndn_routing_helper.py
index ce1966f..38d841a 100644
--- a/ndn/apps/calculate_routing.py
+++ b/minindn/helpers/ndn_routing_helper.py
@@ -1,5 +1,4 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#!/usr/bin/env python
+ # -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2019, The University of Memphis
#
@@ -20,24 +19,121 @@
# along with Mini-NDN, e.g., in COPYING.md file.
# If not, see <http://www.gnu.org/licenses/>.
+# IMPORTANT! This feature is in highly experimental phase and may go several changes
+# in future
+
'''
This module will compute link state, hyperbolic and geohyperbolic
routes and their costs from the given Mini-NDN topology
'''
import heapq
-import math
-from collections import defaultdict
from math import sin, cos, sinh, cosh, acos, acosh
import json
import operator
+from collections import defaultdict
-from mininet.log import info, debug, error
+from mininet.log import info, debug, error, warn
+from minindn.helpers.nfdc import Nfdc as nfdc
UNKNOWN_DISTANCE = -1
HYPERBOLIC_COST_ADJUSTMENT_FACTOR = 1000
-class CalculateRoutes():
+def dijkstra(graph, start, end, ignoredNode=None):
+ """
+ Compute shortest path and cost from a given source to a destination
+ using Dijkstra algorithm
+
+ :param Graph graph: given network topology/graph
+ :param Start start: source node in a given network graph/topology
+ :end End end: destination node in a given network graph/topology
+ :param Node ignoredNode: node to ignore computing shortest path from
+ """
+ queue = [(0, start, [])]
+ seen = set()
+ while True:
+ (cost, v, path) = heapq.heappop(queue)
+ if v not in seen:
+ path = path + [v]
+ seen.add(v)
+ if v == end:
+ debug("Distance from {} to {} is {}".format(start, end, cost))
+ return cost, path
+ for (_next, c) in graph[v].items():
+ if _next != ignoredNode: # Ignore path going via ignoreNode
+ heapq.heappush(queue, (cost + c, _next, path))
+
+ if not queue: # return if no path exist from source - destination except via ignoreNode
+ debug("Distance from {} to {} is {}".format(start, end, cost))
+ return cost, None
+
+def calculateAngularDistance(angleVectorI, angleVectorJ):
+ """
+ For hyperbolic/geohyperbolic routing algorithm, this function computes angular distance between
+ two nodes. A node can have two or more than two angular coordinates.
+
+ :param AngleVectorI angleVectorI: list of angular coordinate of a give node I
+ :param AngleVectorJ angleVectorJ: list of angular coordinate of a give node J
+
+ ref: https://en.wikipedia.org/wiki/N-sphere#Spherical_coordinates
+
+ """
+ innerProduct = 0.0
+ if len(angleVectorI) != len(angleVectorJ):
+ error("Angle vector sizes do not match")
+ return UNKNOWN_DISTANCE
+
+ # Calculate x0 of the vectors
+ x0i = cos(angleVectorI[0])
+ x0j = cos(angleVectorJ[0])
+
+ # Calculate xn of the vectors
+ xni = sin(angleVectorI[len(angleVectorI) - 1])
+ xnj = sin(angleVectorJ[len(angleVectorJ) - 1])
+
+ # Do the aggregation of the (n-1) coordinates (if there is more than one angle)
+ # i.e contraction of all (n-1)-dimensional angular coordinates to one variable
+ for k in range(0, len(angleVectorI)-1):
+ xni *= sin(angleVectorI[k])
+ xnj *= sin(angleVectorJ[k])
+
+ innerProduct += (x0i * x0j) + (xni * xnj)
+
+ if len(angleVectorI) > 1:
+ for m in range(1, len(angleVectorI)):
+ # Calculate euclidean coordinates given the angles and assuming R_sphere = 1
+ xmi = cos(angleVectorI[m])
+ xmj = cos(angleVectorJ[m])
+ for l in range(0, m):
+ xmi *= sin(angleVectorI[l])
+ xmj *= sin(angleVectorJ[l])
+
+ innerProduct += xmi * xmj
+
+ # ArcCos of the inner product gives the angular distance
+ # between two points on a d-dimensional sphere
+ angularDist = acos(innerProduct)
+ debug("Angular distance from {} to {} is {}".format(angleVectorI, angleVectorJ, angularDist))
+ return angularDist
+
+def getHyperbolicDistance(sourceNode, destNode):
+ """
+ Return hyperbolic or geohyperbolic distance between two nodes. The distance is computed
+ on the basis of following algorithm/mathematics
+ ref: https://en.wikipedia.org/wiki/Hyperbolic_geometry
+ """
+ r1 = [key for key in sourceNode][0]
+ r2 = [key for key in destNode][0]
+
+ zeta = 1.0
+ dtheta = calculateAngularDistance(sourceNode[r1], destNode[r2])
+ hyperbolicDistance = (1./zeta) * acosh(cosh(zeta * r1) * cosh(zeta * r2) -\
+ sinh(zeta * r1) * sinh(zeta * r2) * cos(dtheta))
+
+ debug("Distance from {} to {} is {}".format(sourceNode, destNode, hyperbolicDistance))
+ return hyperbolicDistance
+
+class _CalculateRoutes(object):
"""
Creates a route calculation object, which is used to compute routes from a node to
every other nodes in a given topology topology using hyperbolic or geohyperbolic
@@ -51,14 +147,20 @@
self.nodeDict = defaultdict(dict)
self.routingType = routingType
for host in netObj.hosts:
- radius = float(host.params['params']['radius'])
- angles = [float(x) for x in host.params['params']['angle'].split(',')]
+ if 'radius' in host.params['params']:
+ radius = float(host.params['params']['radius'])
+ else:
+ radius = 0.0
+ if 'angles' in host.params['params']:
+ angles = [float(x) for x in host.params['params']['angle'].split(',')]
+ else:
+ angles = 0.0
self.nodeDict[host.name][radius] = angles
- for link in netObj.topo.links_conf:
- linkDelay = int(link.linkDict['delay'].replace("ms", ""))
- self.adjacenctMatrix[link.h1][link.h2] = linkDelay
- self.adjacenctMatrix[link.h2][link.h1] = linkDelay
+ for link in netObj.topo.links(withInfo=True):
+ linkDelay = int(link[2]['delay'].replace("ms", ""))
+ self.adjacenctMatrix[link[0]][link[1]] = linkDelay
+ self.adjacenctMatrix[link[1]][link[0]] = linkDelay
def getNestedDictionary(self):
return defaultdict(self.getNestedDictionary)
@@ -169,96 +271,100 @@
debug("Shortest Distance Matrix: {}".format(json.dumps(distanceMatrixViaNeighbor)))
return distanceMatrixViaNeighbor
-def dijkstra(graph, start, end, ignoredNode = None):
+class NdnRoutingHelper(object):
"""
- Compute shortest path and cost from a given source to a destination
- using Dijkstra algorithm
+ This module is a helper class which helps to create face and register routes
+ to NFD from a given node to all of its neighbors.
- :param Graph graph: given network topology/graph
- :param Start start: source node in a given network graph/topology
- :end End end: destination node in a given network graph/topology
- :param Node ignoredNode: node to ignore computing shortest path from
- """
- queue = [(0, start, [])]
- seen = set()
- while True:
- (cost, v, path) = heapq.heappop(queue)
- if v not in seen:
- path = path + [v]
- seen.add(v)
- if v == end:
- debug("Distance from {} to {} is {}".format(start, end, cost))
- return cost, path
- for (_next, c) in graph[v].iteritems():
- if _next != ignoredNode: # Ignore path going via ignoreNode
- heapq.heappush(queue, (cost + c, _next, path))
-
- if not queue: # return if no path exist from source - destination except via ignoreNode
- debug("Distance from {} to {} is {}".format(start, end, cost))
- return cost, None
-
-def calculateAngularDistance(angleVectorI, angleVectorJ):
- """
- For hyperbolic/geohyperbolic routing algorithm, this function computes angular distance between
- two nodes. A node can have two or more than two angular coordinates.
-
- :param AngleVectorI angleVectorI: list of angular coordinate of a give node I
- :param AngleVectorJ angleVectorJ: list of angular coordinate of a give node J
-
- ref: https://en.wikipedia.org/wiki/N-sphere#Spherical_coordinates
+ :param NetObject netObject: Mininet net object
+ :param FaceType faceType: UDP, Ethernet etc.
+ :param Routing routingType: (optional) Routing algorithm, link-state or hr etc
"""
- innerProduct = 0.0
- if len(angleVectorI) != len(angleVectorJ):
- error("Angle vector sizes do not match")
- return UNKNOWN_DISTANCE
+ def __init__(self, netObject, faceType=nfdc.PROTOCOL_UDP, routingType="link-state"):
+ self.net = netObject
+ self.faceType = faceType
+ self.routingType = routingType
+ self.routes = []
+ self.namePrefixes = {host_name.name: [] for host_name in self.net.hosts}
+ self.routeObject = _CalculateRoutes(self.net, self.routingType)
- # Calculate x0 of the vectors
- x0i = cos(angleVectorI[0])
- x0j = cos(angleVectorJ[0])
+ def globalRoutingHelperHandler(self):
+ for host in self.net.hosts:
+ neighborIPs = self.getNeighbor(host)
+ self.createFaces(host, neighborIPs)
+ self.routeAdd(host, neighborIPs)
- # Calculate xn of the vectors
- xni = sin(angleVectorI[len(angleVectorI) - 1])
- xnj = sin(angleVectorJ[len(angleVectorJ) - 1])
+ info('Processed all the routes to NFD\n')
- # Do the aggregation of the (n-1) coordinates (if there is more than one angle)
- # i.e contraction of all (n-1)-dimensional angular coordinates to one variable
- for k in range(0, len(angleVectorI)-1):
- xni *= sin(angleVectorI[k])
- xnj *= sin(angleVectorJ[k])
+ def addOrigin(self, nodes, prefix):
+ """
+ Add prefix/s as origin on node/s
- innerProduct += (x0i * x0j) + (xni * xnj)
+ :param Prefix prefix: Prefix that is originated by node/s (as producer) for this prefix
+ :param Nodes nodes: List of nodes from net object
+ """
+ for node in nodes:
+ self.namePrefixes[node.name] = prefix
- if (len(angleVectorI) > 1):
- for m in range(1, len(angleVectorI)):
- # Calculate euclidean coordinates given the angles and assuming R_sphere = 1
- xmi = cos(angleVectorI[m])
- xmj = cos(angleVectorJ[m])
- for l in range (0, m):
- xmi *= sin(angleVectorI[l])
- xmj *= sin(angleVectorJ[l])
+ def calculateNPossibleRoutes(self, nFaces=0):
+ """
+ By default, calculates all possible routes i.e. routes via all the faces of a node.
+ pass nFaces if want to compute routes via n number of faces. e.g. 2. For larger topology
+ the computation might take huge amount of time.
- innerProduct += xmi * xmj
+ :param int nFaces: (optional) number of faces to consider while computing routes. Default
+ i.e. nFaces = 0 will compute all possible routes
- # ArcCos of the inner product gives the angular distance
- # between two points on a d-dimensional sphere
- angularDist = acos(innerProduct)
- debug("Angular distance from {} to {} is {}".format(angleVectorI, angleVectorJ, angularDist))
- return angularDist
+ """
+ self.routes = self.routeObject.getRoutes(nFaces)
+ if self.routes:
+ self.globalRoutingHelperHandler()
+ else:
+ warn("Route computation failed\n")
-def getHyperbolicDistance(sourceNode, destNode):
- """
- Return hyperbolic or geohyperbolic distance between two nodes. The distance is computed
- on the basis of following algorithm/mathematics
- ref: https://en.wikipedia.org/wiki/Hyperbolic_geometry
- """
- r1 = [key for key in sourceNode][0]
- r2 = [key for key in destNode][0]
+ def calculateRoutes(self):
+ # Calculate shortest path for every node
+ self.calculateNPossibleRoutes(nFaces=1)
- zeta = 1.0
- dtheta = calculateAngularDistance(sourceNode[r1], destNode[r2])
- hyperbolicDistance = (1./zeta) * acosh(cosh(zeta * r1) * cosh(zeta * r2) -\
- sinh(zeta * r1) * sinh(zeta * r2) * cos(dtheta))
+ def createFaces(self, node, neighborIPs):
+ for ip in neighborIPs.values():
+ nfdc.createFace(node, ip, self.faceType)
- debug("Distance from {} to {} is {}".format(sourceNode, destNode, hyperbolicDistance))
- return hyperbolicDistance
\ No newline at end of file
+ def routeAdd(self, node, neighborIPs):
+ """
+ Add route from a node to its neighbors for each prefix/s advertised by destination node
+
+ :param Node node: source node (Mininet net.host)
+ :param IP neighborIPs: IP addresses of neighbors
+ """
+ neighbors = self.routes[node.name]
+ for route in neighbors:
+ destination = route[0]
+ cost = int(route[1])
+ nextHop = route[2]
+ defaultPrefix = "/ndn/{}-site/{}".format(destination, destination)
+ prefixes = [defaultPrefix] + self.namePrefixes[destination]
+ for prefix in prefixes:
+ # Register routes to all the available destination name prefix/s
+ nfdc.registerRoute(node, prefix, neighborIPs[nextHop], \
+ nfdc.PROTOCOL_UDP, cost=cost)
+ @staticmethod
+ def getNeighbor(node):
+ # Nodes to IP mapping
+ neighborIPs = defaultdict()
+ for intf in node.intfList():
+ link = intf.link
+ if link:
+ node1, node2 = link.intf1.node, link.intf2.node
+
+ if node1 == node:
+ other = node2
+ ip = other.IP(str(link.intf2))
+ else:
+ other = node1
+ ip = other.IP(str(link.intf1))
+
+ # Used later to create faces
+ neighborIPs[other.name] = ip
+ return neighborIPs
diff --git a/ndn/apps/ndn_ping_client.py b/minindn/helpers/ndnpingclient.py
similarity index 63%
rename from ndn/apps/ndn_ping_client.py
rename to minindn/helpers/ndnpingclient.py
index 7e7ff2a..8220a2d 100644
--- a/ndn/apps/ndn_ping_client.py
+++ b/minindn/helpers/ndnpingclient.py
@@ -1,6 +1,6 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
-# Copyright (C) 2015-2018, The University of Memphis,
+# Copyright (C) 2015-2019, The University of Memphis,
# Arizona Board of Regents,
# Regents of the University of California.
#
@@ -23,21 +23,23 @@
import time
-class NDNPingClient:
+# Todo: convert to app
+
+class NDNPingClient(object):
@staticmethod
def ping(source, dest, nPings=1, interval=None, timeout=None, starting_seq_num=None,
identifier=None, allow_stale_data=False, print_timestamp=True, sleepTime=0.2):
- print("Scheduling ping(s) from {} to {}".format(source.name, dest.name))
- # Use "&" to run in background and perform parallel pings
- source.cmd("ndnping{1}{2}{3}{4}{5}{6}{7} /ndn/{0}-site/{0} >> ping-data/{0}.txt &"
+ print('Scheduling ping(s) from {} to {}'.format(source.name, dest.name))
+ # Use '&' to run in background and perform parallel pings
+ source.cmd('ndnping{1}{2}{3}{4}{5}{6}{7} /ndn/{0}-site/{0} >> ping-data/{0}.txt &'
.format(
dest,
- " -c {}".format(nPings),
- " -i {}".format(interval) if interval else "",
- " -o {}".format(timeout) if timeout else "",
- " -n {}".format(starting_seq_num) if starting_seq_num else "",
- " -p {}".format(identifier) if identifier else "",
- " -a" if allow_stale_data else "",
- " -t" if print_timestamp else ""
+ ' -c {}'.format(nPings),
+ ' -i {}'.format(interval) if interval else '',
+ ' -o {}'.format(timeout) if timeout else '',
+ ' -n {}'.format(starting_seq_num) if starting_seq_num else '',
+ ' -p {}'.format(identifier) if identifier else '',
+ ' -a' if allow_stale_data else '',
+ ' -t' if print_timestamp else ''
))
- time.sleep(sleepTime)
\ No newline at end of file
+ time.sleep(sleepTime)
diff --git a/ndn/apps/nfdc.py b/minindn/helpers/nfdc.py
similarity index 62%
rename from ndn/apps/nfdc.py
rename to minindn/helpers/nfdc.py
index e772a42..4a9ebf2 100644
--- a/ndn/apps/nfdc.py
+++ b/minindn/helpers/nfdc.py
@@ -21,65 +21,65 @@
# along with Mini-NDN, e.g., in COPYING.md file.
# If not, see <http://www.gnu.org/licenses/>.
-import time
from mininet.log import debug
+from minindn.minindn import Minindn
SLEEP_TIME = 0.2
-class Nfdc:
- STRATEGY_ASF = "asf"
- STRATEGY_BEST_ROUTE = "best-route"
- STRATEGY_MULTICAST = "multicast"
- STRATEGY_NCC = "ncc"
- PROTOCOL_UDP = "udp"
- PROTOCOL_TCP = "tcp"
- PROTOCOL_ETHER = "ether"
+class Nfdc(object):
+ STRATEGY_ASF = 'asf'
+ STRATEGY_BEST_ROUTE = 'best-route'
+ STRATEGY_MULTICAST = 'multicast'
+ STRATEGY_NCC = 'ncc'
+ PROTOCOL_UDP = 'udp'
+ PROTOCOL_TCP = 'tcp'
+ PROTOCOL_ETHER = 'ether'
@staticmethod
def registerRoute(node, namePrefix, remoteNodeAddress, protocol=PROTOCOL_UDP, origin=255,
cost=0, inheritFlag=True, captureFlag=False, expirationInMillis=None):
- cmd = ("nfdc route add {} {}://{} origin {} cost {} {}{}").format(
+ cmd = ('nfdc route add {} {}://{} origin {} cost {} {}{}').format(
namePrefix,
protocol,
remoteNodeAddress,
origin,
cost,
- "no-inherit " if not inheritFlag else "",
- "capture " if captureFlag else "",
- "expires {}".format(expirationInMillis) if expirationInMillis else ""
+ 'no-inherit ' if not inheritFlag else '',
+ 'capture ' if captureFlag else '',
+ 'expires {}'.format(expirationInMillis) if expirationInMillis else ''
)
debug(node.cmd(cmd))
- time.sleep(SLEEP_TIME)
+ Minindn.sleep(SLEEP_TIME)
@staticmethod
def unregisterRoute(node, namePrefix, remoteNodeAddress, origin=255):
- cmd = "nfdc route remove {} {} {}".format(namePrefix, remoteNodeAddress, origin)
+ cmd = 'nfdc route remove {} {} {}'.format(namePrefix, remoteNodeAddress, origin)
debug(node.cmd(cmd))
- time.sleep(SLEEP_TIME)
+ Minindn.sleep(SLEEP_TIME)
@staticmethod
- def createFace(node, remoteNodeAddress, protocol="udp", isPermanent=False):
- cmd = ("nfdc face create {}://{} {}".format(
+ def createFace(node, remoteNodeAddress, protocol='udp', isPermanent=False):
+ cmd = ('nfdc face create {}://{} {}'.format(
protocol,
remoteNodeAddress,
- "permanent" if isPermanent else "persistent"
+ 'permanent' if isPermanent else 'persistent'
))
debug(node.cmd(cmd))
- time.sleep(SLEEP_TIME)
+ Minindn.sleep(SLEEP_TIME)
@staticmethod
- def destroyFace(node, remoteNodeAddress, protocol="udp"):
- debug(node.cmd("nfdc face destroy {}://{}".format(protocol, remoteNodeAddress)))
- time.sleep(SLEEP_TIME)
+ def destroyFace(node, remoteNodeAddress, protocol='udp'):
+ debug(node.cmd('nfdc face destroy {}://{}'.format(protocol, remoteNodeAddress)))
+ Minindn.sleep(SLEEP_TIME)
@staticmethod
def setStrategy(node, namePrefix, strategy):
- cmd = "nfdc strategy set {} ndn:/localhost/nfd/strategy/{}".format(namePrefix, strategy)
+ cmd = 'nfdc strategy set {} ndn:/localhost/nfd/strategy/{}'.format(namePrefix, strategy)
debug(node.cmd(cmd))
- time.sleep(SLEEP_TIME)
+ Minindn.sleep(SLEEP_TIME)
@staticmethod
def unsetStrategy(node, namePrefix):
debug(node.cmd("nfdc strategy unset {}".format(namePrefix)))
- time.sleep(SLEEP_TIME)
\ No newline at end of file
+ Minindn.sleep(SLEEP_TIME)
diff --git a/ndn/process_monitor.py b/minindn/helpers/process_monitor.py
similarity index 74%
rename from ndn/process_monitor.py
rename to minindn/helpers/process_monitor.py
index da41b1d..4fa3738 100644
--- a/ndn/process_monitor.py
+++ b/minindn/helpers/process_monitor.py
@@ -1,6 +1,6 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
-# Copyright (C) 2015-2018, The University of Memphis,
+# Copyright (C) 2015-2019, The University of Memphis,
# Arizona Board of Regents,
# Regents of the University of California.
#
@@ -23,27 +23,26 @@
import time
-from subprocess import call
from threading import Timer
-class ProcessMonitor:
+class ProcessMonitor(object):
def __init__(self, processId, processName, outputDir, interval=1):
self._processId = processId.strip()
self._processName = processName
- self._statFile = "/proc/{}/stat".format(self._processId)
- self._logFile = "{}/{}-{}-stat.txt".format(outputDir, self._processName, self._processId)
+ self._statFile = '/proc/{}/stat'.format(self._processId)
+ self._logFile = '{}/{}-{}-stat.txt'.format(outputDir, self._processName, self._processId)
self._interval = interval
def _recordStats(self):
try:
- with open(self._statFile, "r") as stat:
+ with open(self._statFile, 'r') as stat:
currentTime = int(time.time())
- with open(self._logFile, "a") as log:
+ with open(self._logFile, 'a') as log:
for line in stat:
- log.write("{} {}".format(currentTime, line))
+ log.write('{} {}'.format(currentTime, line))
except IOError as e:
- print "I/O error({0}): {1}".format(e.errno, e.strerror)
- print "No process with PID={}".format(self._processId)
+ print('I/O error({0}): {1}'.format(e.errno, e.strerror))
+ print('No process with PID={}'.format(self._processId))
return
self.start() # Reschedule event
diff --git a/minindn/minindn.py b/minindn/minindn.py
new file mode 100644
index 0000000..847e003
--- /dev/null
+++ b/minindn/minindn.py
@@ -0,0 +1,213 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+import argparse
+import sys
+import time
+import os
+import configparser
+from subprocess import call, check_output
+
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.link import TCLink
+from mininet.node import Switch
+from mininet.util import ipStr, ipParse
+from mininet.log import info, error
+
+class Minindn(object):
+ """ This class provides the following features to the user:
+ 1) Wrapper around Mininet object with option to pass topology directly
+ 1.1) Users can pass custom argument parser to extend the default on here
+ 2) Parses the topology file given via command line if user does not pass a topology object
+ 3) Provides way to stop Mini-NDN via stop
+ 3.1) Applications register their clean up function with this class
+ 4) Sets IPs on neighbors for connectivity required in a switch-less topology
+ 5) Some other utility functions
+ """
+ ndnSecurityDisabled = False
+
+ def __init__(self, parser=argparse.ArgumentParser(), topo=None, topoFile=None, **mininetParams):
+ """Create MiniNDN object
+ parser: Parent parser of Mini-NDN parser
+ topo: Mininet topo object (optional)
+ topoFile: Mininet topology file location (optional)
+ mininetParams: Any params to pass to Mininet
+ """
+ self.parser = Minindn.parseArgs(parser)
+ self.args = self.parser.parse_args()
+
+ self.workDir = self.args.workDir
+ self.resultDir = self.args.resultDir
+
+ if not topoFile:
+ # Args has default topology if none specified
+ self.topoFile = self.args.topoFile
+ else:
+ self.topoFile = topoFile
+
+ if topo is None:
+ try:
+ info('Using topology file {}\n'.format(self.topoFile))
+ self.topo = self.processTopo(self.topoFile)
+ except configparser.NoSectionError as e:
+ info('Error reading config file: {}\n'.format(e))
+ sys.exit(1)
+ else:
+ self.topo = topo
+
+ self.net = Mininet(topo=self.topo, link=TCLink, **mininetParams)
+
+ for host in self.net.hosts:
+ if 'params' not in host.params:
+ host.params['params'] = {}
+
+ homeDir = '{}/{}'.format(self.workDir, host.name)
+ host.params['params']['homeDir'] = homeDir
+ host.cmd('mkdir -p {}'.format(homeDir))
+ host.cmd('export HOME={} && cd ~'.format(homeDir))
+
+ self.cleanups = []
+
+ if not self.net.switches:
+ self.ethernetPairConnectivity()
+
+ try:
+ Minindn.ndnSecurityDisabled = '/dummy/KEY/-%9C%28r%B8%AA%3B%60' in \
+ check_output('ndnsec-get-default -k'.split()). \
+ decode('utf-8').split('\n')
+ info('Dummy key chain patch is installed in ndn-cxx. Security will be disabled.\n')
+ except:
+ pass
+
+ @staticmethod
+ def parseArgs(parent):
+ parser = argparse.ArgumentParser(prog='minindn', parents=[parent], add_help=False)
+
+ # nargs='?' required here since optional argument
+ parser.add_argument('topoFile', nargs='?', default='/usr/local/etc/mini-ndn/default-topology.conf',
+ help='If no template_file is given, topologies/default-topology.conf will be used.')
+
+ parser.add_argument('--work-dir', action='store', dest='workDir', default='/tmp/minindn',
+ help='Specify the working directory; default is /tmp/minindn')
+
+ parser.add_argument('--result-dir', action='store', dest='resultDir', default=None,
+ help='Specify the full path destination folder where experiment results will be moved')
+
+ return parser
+
+ def ethernetPairConnectivity(self):
+ ndnNetBase = '10.0.0.0'
+ interfaces = []
+ for host in self.net.hosts:
+ for intf in host.intfList():
+ link = intf.link
+ node1, node2 = link.intf1.node, link.intf2.node
+
+ if isinstance(node1, Switch) or isinstance(node2, Switch):
+ continue
+
+ if link.intf1 not in interfaces and link.intf2 not in interfaces:
+ interfaces.append(link.intf1)
+ interfaces.append(link.intf2)
+ node1.setIP(ipStr(ipParse(ndnNetBase) + 1) + '/30', intf=link.intf1)
+ node2.setIP(ipStr(ipParse(ndnNetBase) + 2) + '/30', intf=link.intf2)
+ ndnNetBase = ipStr(ipParse(ndnNetBase) + 4)
+
+ @staticmethod
+ def processTopo(topoFile):
+ config = configparser.ConfigParser(delimiters=' ')
+ config.read(topoFile)
+ topo = Topo()
+
+ items = config.items('nodes')
+ for item in items:
+ name = item[0].split(':')[0]
+
+ params = {}
+ for param in item[1].split(' '):
+ if param == '_':
+ continue
+ params[param.split('=')[0]] = param.split('=')[1]
+
+ topo.addHost(name, params=params)
+
+ try:
+ items = config.items('switches')
+ for item in items:
+ name = item[0].split(':')[0]
+ topo.addSwitch(name)
+ except configparser.NoSectionError:
+ # Switches are optional
+ pass
+
+ items = config.items('links')
+ for item in items:
+ link = item[0].split(':')
+
+ params = {}
+ for param in item[1].split(' '):
+ key = param.split('=')[0]
+ value = param.split('=')[1]
+ if key in ['bw', 'jitter', 'max_queue_size']:
+ value = int(value)
+ if key == 'loss':
+ value = float(value)
+ params[key] = value
+
+ topo.addLink(link[0], link[1], **params)
+
+ return topo
+
+ def start(self):
+ self.net.start()
+ time.sleep(3)
+
+ def stop(self):
+ for cleanup in self.cleanups:
+ cleanup()
+ self.net.stop()
+
+ @staticmethod
+ def cleanUp():
+ devnull = open(os.devnull, 'w')
+ call('nfd-stop', stdout=devnull, stderr=devnull)
+ call('mn --clean'.split(), stdout=devnull, stderr=devnull)
+
+ @staticmethod
+ def verifyDependencies():
+ """Prevent MiniNDN from running without necessary dependencies"""
+ dependencies = ['nfd', 'nlsr', 'infoedit', 'ndnping', 'ndnpingserver']
+ devnull = open(os.devnull, 'w')
+ # Checks that each program is in the system path
+ for program in dependencies:
+ if call(['which', program], stdout=devnull):
+ error('{} is missing from the system path! Exiting...\n'.format(program))
+ sys.exit(1)
+ devnull.close()
+
+ @staticmethod
+ def sleep(seconds):
+ # sleep is not required if ndn-cxx is using in-memory keychain
+ if not Minindn.ndnSecurityDisabled:
+ time.sleep(seconds)
diff --git a/minindn/util.py b/minindn/util.py
new file mode 100644
index 0000000..dd46557
--- /dev/null
+++ b/minindn/util.py
@@ -0,0 +1,77 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2015-2019, 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/>.
+
+import sys
+from os.path import isfile
+from subprocess import call
+from mininet.cli import CLI
+
+sshbase = ['ssh', '-q', '-t', '-i/home/mininet/.ssh/id_rsa']
+scpbase = ['scp', '-i', '/home/mininet/.ssh/id_rsa']
+devnull = open('/dev/null', 'w')
+
+def ssh(login, cmd):
+ rcmd = sshbase + [login, cmd]
+ call(rcmd, stdout=devnull, stderr=devnull)
+
+def scp(*args):
+ tmp = []
+ for arg in args:
+ tmp.append(arg)
+ rcmd = scpbase + tmp
+ call(rcmd, stdout=devnull, stderr=devnull)
+
+def copyExistentFile(node, fileList, destination):
+ for f in fileList:
+ if isfile(f):
+ node.cmd('cp {} {}'.format(f, destination))
+ break
+ if not isfile(destination):
+ fileName = destination.split('/')[-1]
+ raise IOError('{} not found in expected directory.'.format(fileName))
+
+def popenGetEnv(node, envDict=None):
+ env = {}
+ homeDir = node.params['params']['homeDir']
+ printenv = node.popen('printenv'.split(), cwd=homeDir).communicate()[0].decode('utf-8')
+ for var in printenv.split('\n'):
+ if var == '':
+ break
+ p = var.split('=')
+ env[p[0]] = p[1]
+ env['HOME'] = homeDir
+
+ if envDict is not None:
+ for key, value in envDict.items():
+ env[key] = str(value)
+
+ return env
+
+def getPopen(host, cmd, envDict=None, **params):
+ return host.popen(cmd, cwd=host.params['params']['homeDir'],
+ env=popenGetEnv(host, envDict), **params)
+
+class MiniNDNCLI(CLI):
+ prompt = 'mini-ndn> '
+ def __init__(self, mininet, stdin=sys.stdin, script=None):
+ CLI.__init__(self, mininet, stdin, script)
diff --git a/ndn/__init__.py b/ndn/__init__.py
deleted file mode 100644
index e497565..0000000
--- a/ndn/__init__.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-import experiment_manager as ExperimentManager
diff --git a/ndn/apps/ndn_global_routing_helper.py b/ndn/apps/ndn_global_routing_helper.py
deleted file mode 100644
index b05d697..0000000
--- a/ndn/apps/ndn_global_routing_helper.py
+++ /dev/null
@@ -1,127 +0,0 @@
- # -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2019, The University of Memphis
-#
-# 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/>.
-
-# IMPORTANT! This feature is in highly experimental phase and may go several changes
-# in future
-
-from mininet.log import info
-from ndn.apps.nfdc import Nfdc as nfdc
-from collections import defaultdict
-from ndn.apps.calculate_routing import CalculateRoutes
-from mininet.log import warn
-
-class GlobalRoutingHelper():
- """
- This module is a helper class which helps to create face and register routes
- to NFD from a given node to all of its neighbors.
-
- :param NetObject netObject: Mininet net object
- :param FaceType faceType: UDP, Ethernet etc.
- :param Routing routingType: (optional) Routing algorithm, link-state or hr etc
-
- """
- def __init__(self, netObject, faceType=nfdc.PROTOCOL_UDP, routingType="link-state"):
- self.net = netObject
- self.faceType = faceType
- self.routingType = routingType
- self.routes = []
- self.namePrefixes = {host_name.name: [] for host_name in self.net.hosts}
- self.routeObject = CalculateRoutes(self.net, self.routingType)
-
- def globalRoutingHelperHandler(self):
- for host in self.net.hosts:
- neighborIPs = self.getNeighbor(host)
- self.createFaces(host, neighborIPs)
- self.routeAdd(host, neighborIPs)
-
- info('Processed all the routes to NFD\n')
-
- def addOrigin(self, nodes, prefix):
- """
- Add prefix/s as origin on node/s
-
- :param Prefix prefix: Prefix that is originated by node/s (as producer) for this prefix
- :param Nodes nodes: List of nodes from net object
- """
- for node in nodes:
- self.namePrefixes[node.name] = prefix
-
- def calculateNPossibleRoutes(self, nFaces=0):
- """
- By default, calculates all possible routes i.e. routes via all the faces of a node.
- pass nFaces if want to compute routes via n number of faces. e.g. 2. For larger topology
- the computation might take huge amount of time.
-
- :param int nFaces: (optional) number of faces to consider while computing routes. Default
- i.e. nFaces = 0 will compute all possible routes
-
- """
- self.routes = self.routeObject.getRoutes(nFaces)
- if self.routes:
- self.globalRoutingHelperHandler()
- else:
- warn("Route computation failed\n")
-
- def calculateRoutes(self):
- # Calculate shortest path for every node
- calculateNPossibleRoutes(self, nFaces=1)
-
- def createFaces(self, node, neighborIPs):
- for ip in neighborIPs.values():
- nfdc.createFace(node, ip, self.faceType)
-
- def routeAdd(self, node, neighborIPs):
- """
- Add route from a node to its neighbors for each prefix/s advertised by destination node
-
- :param Node node: source node (Mininet net.host)
- :param IP neighborIPs: IP addresses of neighbors
- """
- neighbors = self.routes[node.name]
- for route in neighbors:
- destination = route[0]
- cost = int(route[1])
- nextHop = route[2]
- defaultPrefix = "/ndn/{}-site/{}".format(destination, destination)
- prefixes = [defaultPrefix] + self.namePrefixes[destination]
- for prefix in prefixes:
- # Register routes to all the available destination name prefix/s
- nfdc.registerRoute(node, prefix, neighborIPs[nextHop], \
- nfdc.PROTOCOL_UDP, cost=cost)
- @staticmethod
- def getNeighbor(node):
- # Nodes to IP mapping
- neighborIPs = defaultdict()
- for intf in node.intfList():
- link = intf.link
- if link:
- node1, node2 = link.intf1.node, link.intf2.node
-
- if node1 == node:
- other = node2
- ip = other.IP(str(link.intf2))
- else:
- other = node1
- ip = other.IP(str(link.intf1))
-
- # Used later to create faces
- neighborIPs[other.name] = ip
- return neighborIPs
\ No newline at end of file
diff --git a/ndn/apps/nlsr.py b/ndn/apps/nlsr.py
deleted file mode 100644
index 79a5fb6..0000000
--- a/ndn/apps/nlsr.py
+++ /dev/null
@@ -1,242 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-from mininet.clean import sh
-from mininet.examples.cluster import RemoteMixin
-from mininet.log import info
-
-from ndn.ndn_application import NdnApplication
-from ndn.util import ssh, scp, copyExistentFile
-from ndn.apps.nfdc import Nfdc
-
-import shutil
-import os
-import textwrap
-from subprocess import call
-import time
-
-NETWORK="/ndn/"
-
-class Nlsr(NdnApplication):
- def __init__(self, node, options):
- NdnApplication.__init__(self, node)
- self.config = NlsrConfigGenerator(node, options)
-
- self.node = node
- self.routerName = "/{}C1.Router/cs/{}".format('%', node.name)
- self.confFile = "{}/nlsr.conf".format(node.homeFolder)
-
- # Make directory for log file
- self.logDir = "{}/log".format(node.homeFolder)
- self.node.cmd("mkdir {}".format(self.logDir))
-
- def start(self, sleepTime = 1):
- self.node.cmd("export NDN_LOG=nlsr.*={}".format(self.node.params["params"].get("nlsr-log-level", "DEBUG")))
- NdnApplication.start(self, "nlsr -f {} > log/nlsr.log 2>&1 &".format(self.confFile))
- time.sleep(sleepTime)
-
- def createFaces(self):
- for ip in self.config.neighborIPs:
- Nfdc.createFace(self.node, ip, self.config.faceType, isPermanent=True)
-
- @staticmethod
- def createKey(host, name, outputFile):
- host.cmd("ndnsec-keygen {} > {}".format(name, outputFile))
-
- @staticmethod
- def createCertificate(host, signer, keyFile, outputFile):
- host.cmd("ndnsec-certgen -s {} -r {} > {}".format(signer, keyFile, outputFile))
-
- @staticmethod
- def createKeysAndCertificates(net, workDir):
- securityDir = "{}/security".format(workDir)
-
- if not os.path.exists(securityDir):
- os.mkdir(securityDir)
-
- # Create root certificate
- rootName = NETWORK
- sh("ndnsec-keygen {}".format(rootName)) # Installs a self-signed cert into the system
- sh("ndnsec-cert-dump -i {} > {}/root.cert".format(rootName, securityDir))
-
- # Create necessary certificates for each site
- for host in net.hosts:
- nodeSecurityFolder = "{}/security".format(host.homeFolder)
-
- host.cmd("mkdir -p %s" % nodeSecurityFolder)
-
- # Create temp folders for remote nodes on this machine (localhost) to store site.key file
- # from RemoteNodes
- if not os.path.exists(nodeSecurityFolder) and isinstance(host, RemoteMixin) and host.isRemote:
- os.makedirs(nodeSecurityFolder)
-
- shutil.copyfile("{}/root.cert".format(securityDir), "{}/root.cert".format(nodeSecurityFolder))
-
- # Create site certificate
- siteName = "{}{}-site".format(NETWORK, host.name)
- siteKeyFile = "{}/site.keys".format(nodeSecurityFolder)
- siteCertFile = "{}/site.cert".format(nodeSecurityFolder)
- Nlsr.createKey(host, siteName, siteKeyFile)
-
- # Copy siteKeyFile from remote for ndnsec-certgen
- if isinstance(host, RemoteMixin) and host.isRemote:
- login = "mininet@{}".format(host.server)
- src = "{}:{}".format(login, siteKeyFile)
- dst = siteKeyFile
- scp(src, dst)
-
- # Root key is in root namespace, must sign site key and then install on host
- sh("ndnsec-certgen -s {} -r {} > {}".format(rootName, siteKeyFile, siteCertFile))
-
- # Copy root.cert and site.cert from localhost to remote host
- if isinstance(host, RemoteMixin) and host.isRemote:
- login = "mininet@{}".format(host.server)
- src = "{}/site.cert".format(nodeSecurityFolder)
- src2 = "{}/root.cert".format(nodeSecurityFolder)
- dst = "{}:/tmp/".format(login)
- scp(src, src2, dst)
- host.cmd("mv /tmp/*.cert {}".format(nodeSecurityFolder))
-
- host.cmd("ndnsec-cert-install -f {}".format(siteCertFile))
-
- # Create and install operator certificate
- opName = "{}/%C1.Operator/op".format(siteName)
- opKeyFile = "{}/op.keys".format(nodeSecurityFolder)
- opCertFile = "{}/op.cert".format(nodeSecurityFolder)
- Nlsr.createKey(host, opName, opKeyFile)
- Nlsr.createCertificate(host, siteName, opKeyFile, opCertFile)
- host.cmd("ndnsec-cert-install -f {}".format(opCertFile))
-
- # Create and install router certificate
- routerName = "{}/%C1.Router/cs/{}".format(siteName, host.name)
- routerKeyFile = "{}/router.keys".format(nodeSecurityFolder)
- routerCertFile = "{}/router.cert".format(nodeSecurityFolder)
- Nlsr.createKey(host, routerName, routerKeyFile)
- Nlsr.createCertificate(host, opName, routerKeyFile, routerCertFile)
- host.cmd("ndnsec-cert-install -f {}".format(routerCertFile))
-
-class NlsrConfigGenerator:
-
- ROUTING_LINK_STATE = "ls"
- ROUTING_HYPERBOLIC = "hr"
-
- def __init__(self, node, options):
- self.node = node
- self.isSecurityEnabled = options.nlsrSecurity
- self.faceType = options.faceType
- self.infocmd = "infoedit -f nlsr.conf"
-
- parameters = node.params["params"]
-
- self.nFaces = options.nFaces
- if options.routingType == "hr":
- self.hyperbolicState = "on"
- elif options.routingType == "dry":
- self.hyperbolicState = "dry-run"
- else:
- self.hyperbolicState = "off"
- self.hyperRadius = parameters.get("radius", 0.0)
- self.hyperAngle = parameters.get("angle", 0.0)
-
- if ((self.hyperbolicState == "on" or self.hyperbolicState == "dry-run") and
- (self.hyperRadius == 0.0 or self.hyperAngle == 0.0)):
- info('Hyperbolic coordinates in topology file are either missing or misconfigured.')
- info('Check that each node has one radius value and one or two angle value(s).')
- sys.exit(1)
-
- self.neighborIPs = []
- possibleConfPaths = ["/usr/local/etc/ndn/nlsr.conf.sample", "/etc/ndn/nlsr.conf.sample"]
- copyExistentFile(node, possibleConfPaths, "{}/nlsr.conf".format(self.node.homeFolder))
-
- self.createConfigFile()
-
- def createConfigFile(self):
-
- self.__editGeneralSection()
- self.__editNeighborsSection()
- self.__editHyperbolicSection()
- self.__editFibSection()
- self.__editAdvertisingSection()
- self.__editSecuritySection()
-
- def __editGeneralSection(self):
-
- self.node.cmd("{} -s general.network -v {}".format(self.infocmd, NETWORK))
- self.node.cmd("{} -s general.site -v /{}-site".format(self.infocmd, self.node.name))
- self.node.cmd("{} -s general.router -v /%C1.Router/cs/{}".format(self.infocmd, self.node.name))
- self.node.cmd("{} -s general.state-dir -v {}/log".format(self.infocmd, self.node.homeFolder))
-
- def __editNeighborsSection(self):
-
- self.node.cmd("{} -d neighbors.neighbor".format(self.infocmd))
- for intf in self.node.intfList():
- link = intf.link
- if link:
- node1, node2 = link.intf1.node, link.intf2.node
-
- if node1 == self.node:
- other = node2
- ip = other.IP(str(link.intf2))
- else:
- other = node1
- ip = other.IP(str(link.intf1))
-
- linkCost = intf.params.get("delay", "10ms").replace("ms", "")
-
- Nfdc.createFace(self.node, ip, self.faceType, isPermanent=True)
- self.neighborIPs.append(ip)
-
- self.node.cmd("{} -a neighbors.neighbor \
- <<<\'name {}{}-site/%C1.Router/cs/{} face-uri {}://{}\n link-cost {}\'"
- .format(self.infocmd, NETWORK, other.name, other.name, self.faceType, ip, linkCost))
-
- def __editHyperbolicSection(self):
-
- self.node.cmd("{} -s hyperbolic.state -v {}".format(self.infocmd, self.hyperbolicState))
- self.node.cmd("{} -s hyperbolic.radius -v {}".format(self.infocmd, self.hyperRadius))
- self.node.cmd("{} -s hyperbolic.angle -v {}".format(self.infocmd, self.hyperAngle))
-
- def __editFibSection(self):
-
- self.node.cmd("{} -s fib.max-faces-per-prefix -v {}".format(self.infocmd, self.nFaces))
-
- def __editAdvertisingSection(self):
-
- self.node.cmd("{} -d advertising.prefix".format(self.infocmd))
- self.node.cmd("{} -s advertising.prefix -v {}{}-site/{}"
- .format(self.infocmd, NETWORK, self.node.name, self.node.name))
-
- def __editSecuritySection(self):
-
- self.node.cmd("{} -d security.cert-to-publish".format(self.infocmd))
- if self.isSecurityEnabled is False:
- self.node.cmd("{} -s security.validator.trust-anchor.type -v any".format(self.infocmd))
- self.node.cmd("{} -d security.validator.trust-anchor.file-name".format(self.infocmd))
- self.node.cmd("{} -s security.prefix-update-validator.trust-anchor.type -v any".format(self.infocmd))
- self.node.cmd("{} -d security.prefix-update-validator.trust-anchor.file-name".format(self.infocmd))
- else:
- self.node.cmd("{} -s security.validator.trust-anchor.file-name -v security/root.cert".format(self.infocmd))
- self.node.cmd("{} -s security.prefix-update-validator.trust-anchor.file-name -v security/site.cert".format(self.infocmd))
- self.node.cmd("{} -p security.cert-to-publish -v security/site.cert".format(self.infocmd))
- self.node.cmd("{} -p security.cert-to-publish -v security/op.cert".format(self.infocmd))
- self.node.cmd("{} -p security.cert-to-publish -v security/router.cert".format(self.infocmd))
diff --git a/ndn/conf_parser.py b/ndn/conf_parser.py
deleted file mode 100644
index b24435a..0000000
--- a/ndn/conf_parser.py
+++ /dev/null
@@ -1,206 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2019, 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 file incorporates work covered by the following copyright and
-# permission notice:
-#
-# Mininet 2.2.1 License
-#
-# Copyright (c) 2013-2015 Open Networking Laboratory
-# Copyright (c) 2009-2012 Bob Lantz and The Board of Trustees of
-# The Leland Stanford Junior University
-#
-# Original authors: Bob Lantz and Brandon Heller
-#
-# We are making Mininet available for public use and benefit with the
-# expectation that others will use, modify and enhance the Software and
-# contribute those enhancements back to the community. However, since we
-# would like to make the Software available for broadest use, with as few
-# restrictions as possible permission is hereby granted, free of charge, to
-# any person obtaining a copy of this Software to deal in the Software
-# under the copyrights without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# The name and trademarks of copyright holder(s) may NOT be used in
-# advertising or publicity pertaining to the Software or any derivatives
-# without specific, written prior permission.
-
-import ConfigParser, re
-import shlex
-import sys
-from mininet.log import error
-
-class confNDNHost():
-
- def __init__(self, name, app='', params='', cpu=None, cores=None, cache=None):
- self.name = name
- self.app = app
- self.params = params
- self.cpu = cpu
- self.cores = cores
- self.cache = cache
-
- def __repr__(self):
- return " Name: {} App: {} Params: {} CPU: {} Cores: {} Cores: {} Cache: {}" \
- .format(self.name, self.app, self.params, self.cpu, self.cores, self.cache)
-
-class confNdnSwitch:
- def __init__(self, name):
- self.name = name
-
-class confNDNLink():
-
- def __init__(self,h1,h2,linkDict=None):
- self.h1 = h1
- self.h2 = h2
- self.linkDict = linkDict
-
- def __repr__(self):
- return "h1: {} h2: {} params: {}".format(self.h1, self.h2, self.linkDict)
-
-def parse_hosts(conf_arq):
- 'Parse hosts section from the conf file.'
- config = ConfigParser.RawConfigParser()
- config.read(conf_arq)
-
- hosts = []
-
- items = config.items('nodes')
-
- # makes a first-pass read to hosts section to find empty host sections
- coordinates = []
- for item in items:
- name = item[0]
- rest = item[1].split()
- # check for the duplicate coordinates
- if "radius" in item[1]:
- if item[1] in coordinates:
- error("FATAL: Duplicate Coordinate, \"{}\" used by multiple nodes\n" \
- .format(item[1]))
- sys.exit(1)
- else:
- coordinates.append(item[1])
- if len(rest) == 0:
- config.set('nodes', name, '_')
- # updates 'items' list
- items = config.items('nodes')
-
- # makes a second-pass read to hosts section to properly add hosts
- for item in items:
-
- name = item[0]
-
- rest = shlex.split(item[1])
-
- uris = rest
- params = {}
- cpu = None
- cores = None
- cache = None
-
- for uri in uris:
- if re.match("cpu",uri):
- cpu = float(uri.split('=')[1])
- elif re.match("cores",uri):
- cores = uri.split('=')[1]
- elif re.match("cache",uri):
- cache = uri.split('=')[1]
- elif re.match("mem",uri):
- mem = uri.split('=')[1]
- elif re.match("app",uri):
- app = uri.split('=')[1]
- elif re.match("_", uri):
- app = ""
- else:
- params[uri.split('=')[0]] = uri.split('=')[1]
-
- hosts.append(confNDNHost(name, app, params, cpu, cores, cache))
-
- return hosts
-
-def parse_switches(conf_arq):
- 'Parse switches section from the conf file.'
- config = ConfigParser.RawConfigParser()
- config.read(conf_arq)
-
- switches = []
-
- try:
- items = config.items('switches')
- except ConfigParser.NoSectionError:
- return switches
-
- for item in items:
- name = item[0]
- switches.append(confNdnSwitch(name))
-
- return switches
-
-def parse_links(conf_arq):
- 'Parse links section from the conf file.'
- arq = open(conf_arq, 'r')
-
- links = []
- linkSectionFlag = False
-
- for line in arq:
- if linkSectionFlag:
- args = line.split()
-
- # checks for non-empty line
- if len(args) == 0:
- continue
-
- h1, h2 = args.pop(0).split(':')
-
- link_dict = {}
-
- for arg in args:
- arg_name, arg_value = arg.split('=')
- key = arg_name
- value = arg_value
- if key in ['bw','jitter','max_queue_size']:
- value = int(value)
- if key in ['loss']:
- value = float(value)
- link_dict[key] = value
-
- links.append(confNDNLink(h1,h2,link_dict))
-
- elif line == "[links]\n":
- linkSectionFlag = True
-
- return links
diff --git a/ndn/experiment_manager.py b/ndn/experiment_manager.py
deleted file mode 100644
index 0be9f92..0000000
--- a/ndn/experiment_manager.py
+++ /dev/null
@@ -1,97 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-import os
-
-class _ExperimentManager:
-
- class Error(Exception):
- def __init__(self, what):
- self.what = what
- def __str__(self):
- return repr(self.what)
-
- instance = None
-
- def __init__(self):
- self.experiments = {}
-
- def loadModules(self):
- currentDir = os.path.dirname(__file__)
- experimentDir = "{}/{}".format(currentDir, "experiments")
- experimentModule = "ndn.experiments"
-
- # Import and register experiments
- for root, dirs, files in os.walk(experimentDir):
- for filename in files:
- if filename.endswith(".py") and filename != "__init__.py":
- module = filename.replace(".py", "")
- subdir = os.path.basename(root)
- if subdir == "experiments":
- __import__("{}.{}".format(experimentModule, module))
- else:
- __import__("{}.{}.{}".format(experimentModule, subdir, module))
-
- def register(self, name, experimentClass):
- if name not in self.experiments:
- self.experiments[name] = experimentClass
- else:
- raise _ExperimentManager.Error("Experiment '{}' has already been registered".format(name))
-
- def create(self, name, args):
- if name in self.experiments:
- return self.experiments[name](args)
- else:
- return None
-
-def __getInstance():
- if _ExperimentManager.instance is None:
- _ExperimentManager.instance = _ExperimentManager()
- _ExperimentManager.instance.loadModules()
-
- return _ExperimentManager.instance
-
-def register(name, experimentClass):
- manager = __getInstance()
- manager.register(name, experimentClass)
-
-def create(name, args):
- manager = __getInstance()
- return manager.create(name, args)
-
-def getExperimentNames():
- manager = __getInstance()
-
- experimentNames = []
-
- for key in manager.experiments:
- experimentNames.append(key)
-
- return experimentNames
-
-def addExperimentArgs(parser):
- # Find all experiment command line arguments and parse them.
- manager = __getInstance()
- for name in manager.experiments:
- if hasattr(manager.experiments[name], "parseArguments"):
- manager.experiments[name].parseArguments(parser)
\ No newline at end of file
diff --git a/ndn/experiments/__init__.py b/ndn/experiments/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/ndn/experiments/__init__.py
+++ /dev/null
diff --git a/ndn/experiments/arguments_experiment.py b/ndn/experiments/arguments_experiment.py
deleted file mode 100644
index 6baacd5..0000000
--- a/ndn/experiments/arguments_experiment.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-from ndn.experiments.experiment import Experiment
-
-class ArgumentsExperiment(Experiment):
- def __init__(self, args):
- Experiment.__init__(self, args)
- self.ds = self.options.arguments.ds
- self.logging = self.options.arguments.logging
-
- def start(self):
- pass
-
- def setup(self):
- pass
-
- def run(self):
- print("Argument ds: {}".format(self.ds))
- print("Argument logging: {}".format(self.logging))
-
- @staticmethod
- def parseArguments(parser):
- parser.add_argument("--ds", dest="ds", default="1000",
- help="[Arguments Experiment] Number of data streams")
- parser.add_argument("--logging", dest="logging", action="store_true",
- help="[Arguments Experiment] Enable logging")
-
-Experiment.register("args-exp", ArgumentsExperiment)
\ No newline at end of file
diff --git a/ndn/experiments/experiment.py b/ndn/experiments/experiment.py
deleted file mode 100644
index 8a2f49c..0000000
--- a/ndn/experiments/experiment.py
+++ /dev/null
@@ -1,172 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-import time
-import sys
-from itertools import cycle
-
-from mininet.log import info
-
-from ndn import ExperimentManager
-from ndn.apps.nfdc import Nfdc
-
-from ndn.apps.nlsr import Nlsr, NlsrConfigGenerator
-from ndn.apps.ndn_ping_client import NDNPingClient
-
-class Experiment:
-
- def __init__(self, args):
- self.net = args["net"]
- self.options = args["options"]
-
- # Used to restart pings on the recovered node if any
- self.pingedDict = {}
-
- def afterNfdStart(self):
- pass
-
- def start(self):
- self.afterNfdStart()
- if self.options.isNlsrEnabled is True:
- self.startNlsr()
- self.setup()
- self.run()
-
- def setup(self):
- for host in self.net.hosts:
- # Set strategy
- Nfdc.setStrategy(host, "/ndn/", self.options.strategy)
-
- # Start ping server
- host.cmd("ndnpingserver /ndn/{}-site/{} > ping-server &".format(host.name, host.name))
-
- # Create folder to store ping data
- host.cmd("mkdir ping-data")
-
- def startNlsr(self, checkConvergence = True):
- # NLSR Security
- if self.options.nlsrSecurity is True:
- Nlsr.createKeysAndCertificates(self.net, self.options.workDir)
-
- # NLSR initialization
- info('Starting NLSR on nodes\n')
- for host in self.net.hosts:
- host.nlsr = Nlsr(host, self.options)
- host.nlsr.start()
-
- for host in self.net.hosts:
- nlsrStatus = host.cmd("ps -g | grep 'nlsr -f {}/[n]lsr.conf'".format(host.homeFolder))
- if not host.nlsr.isRunning or not nlsrStatus:
- print("NLSR on host {} is not running. Printing log file and exiting...".format(host.name))
- print(host.cmd("tail {}/log/nlsr.log".format(host.homeFolder)))
- self.net.stop()
- sys.exit(1)
-
- if checkConvergence:
- self.checkConvergence()
-
- def checkConvergence(self, convergenceTime = None):
- if convergenceTime is None:
- convergenceTime = self.options.ctime
-
- # Wait for convergence time period
- print "Waiting " + str(convergenceTime) + " seconds for convergence..."
- time.sleep(convergenceTime)
- print "...done"
-
- # To check whether all the nodes of NLSR have converged
- didNlsrConverge = True
-
- # Checking for convergence
- for host in self.net.hosts:
- statusRouter = host.cmd("nfdc fib list | grep site/%C1.Router/cs/")
- statusPrefix = host.cmd("nfdc fib list | grep ndn | grep site | grep -v Router")
- didNodeConverge = True
- for node in self.net.hosts:
- # Node has its own router name in the fib list, but not name prefix
- if ( ("/ndn/{}-site/%C1.Router/cs/{}".format(node.name, node.name)) not in statusRouter or
- host.name != node.name and ("/ndn/{}-site/{}".format(node.name, node.name)) not in statusPrefix ):
- didNodeConverge = False
- didNlsrConverge = False
-
- host.cmd("echo " + str(didNodeConverge) + " > convergence-result &")
-
- if didNlsrConverge:
- print("NLSR has successfully converged.")
- else:
- print("NLSR has not converged. Exiting...")
- self.net.stop()
- sys.exit(1)
-
- def startPings(self):
- for host in self.net.hosts:
- for other in self.net.hosts:
- # Do not ping self
- if host.name != other.name:
- NDNPingClient.ping(host, other, self.options.nPings)
-
- def failNode(self, host):
- print("Bringing {} down".format(host.name))
- host.nfd.stop()
-
- def recoverNode(self, host):
- print("Bringing {} up".format(host.name))
- host.nfd.start()
- host.nlsr.createFaces()
- host.nlsr.start()
- Nfdc.setStrategy(host, "/ndn/", self.options.strategy)
- host.cmd("ndnpingserver /ndn/{}-site/{} > ping-server &".format(host.name, host.name))
-
- def startPctPings(self):
- nNodesToPing = int(round(len(self.net.hosts) * self.options.pctTraffic))
- print "Each node will ping {} node(s)".format(nNodesToPing)
- # Temporarily store all the nodes being pinged by a particular node
- nodesPingedList = []
-
- for host in self.net.hosts:
- # Create a circular list
- pool = cycle(self.net.hosts)
-
- # Move iterator to current node
- next(x for x in pool if host.name == x.name)
-
- # Track number of nodes to ping scheduled for this node
- nNodesScheduled = 0
-
- while nNodesScheduled < nNodesToPing:
- other = pool.next()
-
- # Do not ping self
- if host.name != other.name:
- NDNPingClient.ping(host, other, self.options.nPings)
- nodesPingedList.append(other)
-
- # Always increment because in 100% case a node should not ping itself
- nNodesScheduled = nNodesScheduled + 1
-
- self.pingedDict[host] = nodesPingedList
- nodesPingedList = []
-
- @staticmethod
- def register(name, experimentClass):
- ExperimentManager.register(name, experimentClass)
diff --git a/ndn/experiments/nlsr/__init__.py b/ndn/experiments/nlsr/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/ndn/experiments/nlsr/__init__.py
+++ /dev/null
diff --git a/ndn/experiments/nlsr/advertise-delayed-start.py b/ndn/experiments/nlsr/advertise-delayed-start.py
deleted file mode 100644
index cbd8ac8..0000000
--- a/ndn/experiments/nlsr/advertise-delayed-start.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-from ndn.experiments.experiment import Experiment
-from ndn.apps.nlsr import Nlsr, NlsrConfigGenerator
-
-from mininet.log import info
-
-import time, sys
-
-class AdvertiseDelayedStartExperiment(Experiment):
- '''Tests Name LSA data segmentation'''
-
- def __init__(self, args):
- Experiment.__init__(self, args)
-
- def setup(self):
- pass
-
- def run(self):
- pass
-
- def startNlsr(self, checkConvergence = True):
- # NLSR Security
- if self.options.nlsrSecurity is True:
- Nlsr.createKeysAndCertificates(self.net, self.options.workDir)
-
- host1 = self.net.hosts[0]
- host1.nlsr = Nlsr(host1, self.options)
- host1.nlsr.start()
-
- expectedTotalCount = 500
- for i in range(0, expectedTotalCount):
- host1.cmd("nlsrc advertise /long/name/to/exceed/max/packet/size/host1/{}".format(i))
-
- time.sleep(60)
-
- host2 = self.net.hosts[1]
- host2.nlsr = Nlsr(host2, self.options)
- host2.nlsr.start()
-
- time.sleep(60)
-
- advertiseCount = int(host2.cmd("nfdc fib | grep host1 | wc -l"))
- info(advertiseCount)
- if advertiseCount == expectedTotalCount:
- info('\nSuccessfully advertised {} prefixes\n'.format(expectedTotalCount))
- else:
- info('\nAdvertising {} prefixes failed. Exiting...\n'.format(expectedTotalCount))
- self.net.stop()
- sys.exit(1)
-
-Experiment.register("advertise-delayed-start", AdvertiseDelayedStartExperiment)
diff --git a/ndn/experiments/nlsr/delayed-start.py b/ndn/experiments/nlsr/delayed-start.py
deleted file mode 100644
index e995c50..0000000
--- a/ndn/experiments/nlsr/delayed-start.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-from ndn.experiments.experiment import Experiment
-from ndn.apps.nlsr import Nlsr, NlsrConfigGenerator
-
-from mininet.log import info
-
-import time
-
-class NlsrDelayedStartExperiment(Experiment):
-
- def __init__(self, args):
- Experiment.__init__(self, args)
-
- def setup(self):
- pass
-
- def run(self):
- pass
-
- def startNlsr(self, checkConvergence = True):
- # NLSR Security
- if self.options.nlsrSecurity is True:
- Nlsr.createKeysAndCertificates(self.net, self.options.workDir)
-
- i = 1
- # NLSR initialization
- info('Starting NLSR on nodes\n')
- for host in self.net.hosts:
- host.nlsr = Nlsr(host, self.options)
- host.nlsr.start()
-
- # Wait 1/2 minute between starting NLSRs
- # Wait 1 hour before starting last NLSR
- if i == len(self.net.hosts) - 1:
- info('Sleeping 1 hour before starting last NLSR')
- time.sleep(3600)
- else:
- time.sleep(30)
- i += 1
-
- if checkConvergence:
- self.checkConvergence()
-
-Experiment.register("nlsr-delayed-start", NlsrDelayedStartExperiment)
diff --git a/ndn/experiments/nlsr/failure_experiment.py b/ndn/experiments/nlsr/failure_experiment.py
deleted file mode 100644
index 783bac4..0000000
--- a/ndn/experiments/nlsr/failure_experiment.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-from ndn.experiments.experiment import Experiment
-from ndn.apps.ndn_ping_client import NDNPingClient
-
-import time
-
-class FailureExperiment(Experiment):
-
- def __init__(self, args):
- args["options"].nPings = 300
- Experiment.__init__(self, args)
-
- self.PING_COLLECTION_TIME_BEFORE_FAILURE = 60
- self.PING_COLLECTION_TIME_AFTER_RECOVERY = 120
-
- def run(self):
- self.startPctPings()
-
- # After the pings are scheduled, collect pings for 1 minute
- time.sleep(self.PING_COLLECTION_TIME_BEFORE_FAILURE)
-
- # Bring down CSU
- for host in self.net.hosts:
- if host.name == "csu":
- self.failNode(host)
- break
-
- # CSU is down for 2 minutes
- time.sleep(120)
-
- # Bring CSU back up
- for host in self.net.hosts:
- if host.name == "csu":
- self.recoverNode(host)
-
- for other in self.net.hosts:
- if host.name != other.name:
- NDNPingClient.ping(host, other, self.PING_COLLECTION_TIME_AFTER_RECOVERY)
-
- # Collect pings for more seconds after CSU is up
- time.sleep(self.PING_COLLECTION_TIME_AFTER_RECOVERY)
-
-Experiment.register("failure", FailureExperiment)
diff --git a/ndn/experiments/nlsr/mcn_failure_experiment.py b/ndn/experiments/nlsr/mcn_failure_experiment.py
deleted file mode 100644
index cd448cc..0000000
--- a/ndn/experiments/nlsr/mcn_failure_experiment.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-from ndn.experiments.experiment import Experiment
-from ndn.apps.ndn_ping_client import NDNPingClient
-
-import time
-
-class MCNFailureExperiment(Experiment):
-
- def __init__(self, args):
- Experiment.__init__(self, args)
-
- self.PING_COLLECTION_TIME_BEFORE_FAILURE = 60
- self.PING_COLLECTION_TIME_AFTER_RECOVERY = 120
-
- def getMostConnectedNode(self):
- mcn = max(self.net.hosts, key=lambda host: len(host.intfNames()))
- print "The most connected node is: {}".format(mcn.name)
- return mcn
-
- def setup(self):
- if self.options.nPings != 0:
- Experiment.setup(self)
-
- def run(self):
- mostConnectedNode = self.getMostConnectedNode()
-
- if self.options.nPings != 0:
- self.startPctPings()
-
- # After the pings are scheduled, collect pings for 1 minute
- time.sleep(self.PING_COLLECTION_TIME_BEFORE_FAILURE)
-
- # Bring down MCN
- self.failNode(mostConnectedNode)
-
- # MCN is down for 2 minutes
- time.sleep(int(self.options.arguments.waitTime))
-
- # Bring MCN back up
- self.recoverNode(mostConnectedNode)
-
- # Restart pings
- if self.options.nPings != 0:
- for nodeToPing in self.pingedDict[mostConnectedNode]:
- NDNPingClient.ping(mostConnectedNode, nodeToPing, self.PING_COLLECTION_TIME_AFTER_RECOVERY)
-
- # Collect pings for more seconds after MCN is up
- time.sleep(self.PING_COLLECTION_TIME_AFTER_RECOVERY)
- else:
- self.checkConvergence()
-
- @staticmethod
- def parseArguments(parser):
- parser.add_argument("--wait-time", dest="waitTime", default="120",
- help="[Experiment] Generic wait time for experiment use")
-
-Experiment.register("mcn-failure", MCNFailureExperiment)
diff --git a/ndn/experiments/nlsr/multiple_failure_experiment.py b/ndn/experiments/nlsr/multiple_failure_experiment.py
deleted file mode 100644
index efbba60..0000000
--- a/ndn/experiments/nlsr/multiple_failure_experiment.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-from ndn.experiments.experiment import Experiment
-from ndn.apps.ndn_ping_client import NDNPingClient
-
-import time
-
-class MultipleFailureExperiment(Experiment):
-
- def __init__(self, args):
-
- self.PING_COLLECTION_TIME_BEFORE_FAILURE = 60
-
- self.FAILURE_INTERVAL = 60
- self.RECOVERY_INTERVAL = 60
-
- # This is the number of pings required to make it through the full experiment
- nInitialPings = (self.PING_COLLECTION_TIME_BEFORE_FAILURE +
- len(args["net"].hosts) * (self.FAILURE_INTERVAL + self.RECOVERY_INTERVAL))
- print("Scheduling with {} initial pings".format(nInitialPings))
-
- Experiment.__init__(self, args)
- self.options.nPings = nInitialPings
-
- def run(self):
- self.startPctPings()
-
- # After the pings are scheduled, collect pings for 1 minute
- time.sleep(self.PING_COLLECTION_TIME_BEFORE_FAILURE)
-
- nNodesRemainingToFail = len(self.net.hosts)
-
- # Fail and recover each node
- for host in self.net.hosts:
- # Fail the node
- self.failNode(host)
-
- # Stay in failure state for FAILURE_INTERVAL seconds
- time.sleep(self.FAILURE_INTERVAL)
-
- # Bring the node back up
- start_time = time.time()
- self.recoverNode(host)
- recovery_time = int(time.time() - start_time)
-
- # Number of pings required to reach the end of the test
- nNodesRemainingToFail -= 1
- nPings = ((self.RECOVERY_INTERVAL - recovery_time) +
- nNodesRemainingToFail*(self.FAILURE_INTERVAL + self.RECOVERY_INTERVAL))
-
- print("Scheduling with {} remaining pings".format(nPings))
-
- # Restart pings
- for nodeToPing in self.pingedDict[host]:
- NDNPingClient.ping(host, nodeToPing, nPings)
-
- time.sleep(self.RECOVERY_INTERVAL - recovery_time)
-
-Experiment.register("multiple-failure", MultipleFailureExperiment)
diff --git a/ndn/experiments/nlsr/pingall_experiment.py b/ndn/experiments/nlsr/pingall_experiment.py
deleted file mode 100644
index 56a70bd..0000000
--- a/ndn/experiments/nlsr/pingall_experiment.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-from ndn.experiments.experiment import Experiment
-
-import time
-
-class PingallExperiment(Experiment):
-
- def __init__(self, args):
-
- Experiment.__init__(self, args)
- self.COLLECTION_PERIOD_BUFFER = 10
- print "Using {} traffic".format(self.options.pctTraffic)
-
- def setup(self):
- if self.options.nPings != 0:
- Experiment.setup(self)
-
- def run(self):
- if self.options.nPings == 0:
- return
-
- self.startPctPings()
-
- # For pingall experiment sleep for the number of pings + some offset
- time.sleep(self.options.nPings + self.COLLECTION_PERIOD_BUFFER)
-
-Experiment.register("pingall", PingallExperiment)
diff --git a/ndn/experiments/nlsr/prefix_propogation.py b/ndn/experiments/nlsr/prefix_propogation.py
deleted file mode 100644
index ae8301a..0000000
--- a/ndn/experiments/nlsr/prefix_propogation.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-import sys
-import time
-from ndn.experiments.experiment import Experiment
-
-class PrefixPropogationExperiment(Experiment):
-
- def __init__(self, args):
- Experiment.__init__(self, args)
-
- def setup(self):
- self.checkConvergence()
-
- def run(self):
- firstNode = self.net.hosts[0]
-
- if self.options.nlsrSecurity:
- firstNode.cmd("ndnsec-set-default /ndn/{}-site/%C1.Operator/op".format(firstNode.name))
-
- print("Testing advertise")
- firstNode.cmd("nlsrc advertise /testPrefix")
- time.sleep(30)
-
- for host in self.net.hosts:
- if host.name != firstNode.name:
- if (int(host.cmd("nfdc fib | grep testPrefix | wc -l")) != 1 or
- int(host.cmd("nlsrc status | grep testPrefix | wc -l")) != 1):
- print("Advertise test failed")
- self.net.stop()
- sys.exit(1)
-
- print("Testing withdraw")
- firstNode.cmd("nlsrc withdraw /testPrefix")
- time.sleep(30)
-
- for host in self.net.hosts:
- if host.name != firstNode.name:
- if (int(host.cmd("nfdc fib | grep testPrefix | wc -l")) != 0 or
- int(host.cmd("nlsrc status | grep testPrefix | wc -l")) != 0):
- print("Withdraw test failed")
- self.net.stop()
- sys.exit(1)
-
-Experiment.register("prefix-propogation", PrefixPropogationExperiment)
diff --git a/ndn/experiments/psync/__init__.py b/ndn/experiments/psync/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/ndn/experiments/psync/__init__.py
+++ /dev/null
diff --git a/ndn/experiments/psync/psync-full.py b/ndn/experiments/psync/psync-full.py
deleted file mode 100644
index 206993e..0000000
--- a/ndn/experiments/psync/psync-full.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2019, 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/>.
-
-from ndn.experiments.experiment import Experiment
-from ndn.apps.nfdc import Nfdc
-
-import time
-import sys
-
-class PSyncFull(Experiment):
-
- def __init__(self, args):
- Experiment.__init__(self, args)
- self.syncPrefix = "/sync"
- self.numUserPrefixesPerNode = 2
- self.maxUpdatesPerUserPrefixPerNode = 3
-
- def registerRouteToAllNeighbors(self, host):
- for node in self.net.hosts:
- for neighbor in node.connectionsTo(host):
- ip = node.IP(neighbor[0])
- Nfdc.createFace(host, ip)
- Nfdc.registerRoute(host, self.syncPrefix, ip)
-
- def start(self):
- for host in self.net.hosts:
- Nfdc.setStrategy(host, self.syncPrefix, "multicast")
- self.registerRouteToAllNeighbors(host)
-
- print("Starting psync-full-sync on all the nodes")
- for host in self.net.hosts:
- host.cmd("export NDN_LOG=examples.FullSyncApp=INFO")
- host.cmd("psync-full-sync {} {} {} {} &> psync.logs &"
- .format(self.syncPrefix, host.name, self.numUserPrefixesPerNode,
- self.maxUpdatesPerUserPrefixPerNode))
-
- print("Sleeping 5 minutes for convergence")
- # Estimated time for 4 node default topology
- time.sleep(300)
-
- totalUpdates = int(host.cmd("grep -r Update {}/*/psync.logs | wc -l"
- .format(self.options.workDir)))
-
- expectedUpdates = (self.maxUpdatesPerUserPrefixPerNode *
- len(self.net.hosts) * (len(self.net.hosts) - 1) *
- self.numUserPrefixesPerNode)
-
- if totalUpdates == expectedUpdates:
- print("PSync full sync has successfully converged.")
- else:
- print("PSync full sync convergence was not successful. Exiting...")
- self.net.stop()
- sys.exit(1)
-
-Experiment.register("psync-full", PSyncFull)
diff --git a/ndn/experiments/psync/psync-partial.py b/ndn/experiments/psync/psync-partial.py
deleted file mode 100644
index 9b37281..0000000
--- a/ndn/experiments/psync/psync-partial.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2019, 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/>.
-
-from ndn.experiments.experiment import Experiment
-from ndn.apps.nfdc import Nfdc
-
-import time
-import sys
-
-class PSyncPartial(Experiment):
-
- def __init__(self, args):
- Experiment.__init__(self, args)
-
- def start(self):
- host1 = self.net.hosts[0]
-
- host1.cmd("export NDN_LOG=examples.PartialSyncProducerApp=INFO")
- host1.cmd("psync-producer /sync /{} 10 1 &> producer.log &".format(host1.name))
- time.sleep(1)
-
- host1.cmd("export NDN_LOG=examples.PartialSyncConsumerApp=INFO:$NDN_LOG")
- host1.cmd("psync-consumer /sync 5 &> consumer.log &")
-
- print("Sleeping 90 seconds for convergence")
- time.sleep(90)
-
- consumerSubs = int(host1.cmd("cat consumer.log | grep -c Subscribing"))
- consumerUpdates = int(host1.cmd("cat consumer.log | grep -c Update"))
- producerPublish = int(host1.cmd("cat producer.log | grep -c Publish"))
-
- if consumerSubs == 5 and consumerUpdates == 5 and producerPublish == 10:
- print("PSync partial sync has successfully converged.")
- else:
- print("PSync partial sync convergence was not successful. Exiting...")
- self.net.stop()
- sys.exit(1)
-
-Experiment.register("psync-partial", PSyncPartial)
diff --git a/ndn/experiments/static_routing_experiment.py b/ndn/experiments/static_routing_experiment.py
deleted file mode 100644
index e40fbf9..0000000
--- a/ndn/experiments/static_routing_experiment.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2019, 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/>.
-
-from ndn.experiments.experiment import Experiment
-from ndn.apps.ndn_global_routing_helper import GlobalRoutingHelper
-
-from mininet.log import info
-
-class RoutingHelperExp(Experiment):
-
- def __init__(self, args):
- Experiment.__init__(self, args)
-
- def start(self):
- """
- Compute and add routes to NFD
- """
- info('Adding static routes to NFD\n')
- grh = GlobalRoutingHelper(self.net, self.options.faceType, self.options.routingType)
- # For all host, pass self.net.hosts or a list, [self.net['a'], ..] or [self.net.hosts[0],.]
- grh.addOrigin([self.net['a']], ["/abc"])
- grh.calculateNPossibleRoutes()
-
- '''
- Experiment run with default topology, test cases won't work with other topologies
- # With calculateNPossibleRoutes,
- 10 # routing = hr, N = All, from A, 3 routes needs to added to NFD.
- A +++++++ B # A - B -- cost 10
- + + # A - C -- cost 10
- 10 + + 10 # A - D -- cost 20
- + + # Same goes for B being a source.
- C D #
-
- prefix "/abc" is advertise from node A, it should be reachable from all other nodes.
-
- '''
- if self.options.routingType == "link-state":
- # This test only for link-state. Similar test can be done for hyperbolic routing.
- routesFromA = self.net['a'].cmd("nfdc route | grep -v '/localhost/nfd'")
- if '/ndn/b-site/b' not in routesFromA or \
- '/ndn/c-site/c' not in routesFromA or \
- '/ndn/d-site/d' not in routesFromA:
- info("Route addition failed\n")
- exit(-1)
-
- routesToPrefix = self.net['b'].cmd("nfdc fib | grep '/abc'")
- if '/abc' not in routesToPrefix:
- info("Missing route to advertised prefix, Route addition failed\n")
- exit(-1)
-
- info('Route addition to NFD completed\n')
-
-Experiment.register("centralize-routing", RoutingHelperExp)
\ No newline at end of file
diff --git a/ndn/gui.py b/ndn/gui.py
deleted file mode 100644
index 54838c5..0000000
--- a/ndn/gui.py
+++ /dev/null
@@ -1,156 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-from Tkinter import *
-
-LOG_LEVELS = [
- "NONE",
- "ERROR",
- "WARN",
- "INFO",
- "DEBUG",
- "TRACE",
- "ALL"
-]
-
-class GuiFrame(Frame):
- def __init__(self, notebook, prefValues, appId):
- Frame.__init__(self, notebook)
-
- self.prefValues = prefValues
- self.appId = appId
-
- self.row = 0
- self.column = 0
-
- def addEntryBox(self, label, variable, defaultValue=""):
- variable.set(defaultValue)
-
- Label(self, text=label).grid(row=self.row, sticky=E)
- entry = Entry(self, textvariable=variable)
- entry.grid(row=self.row, column=1)
-
- self.row += 1
-
- def addDropDown(self, label, variable, values, defaultValue=""):
- variable.set(defaultValue)
-
- Label(self, text=label).grid(row=self.row, sticky=E)
-
- self.entry = apply(OptionMenu, (self, variable) + tuple(values))
- self.entry.grid(row=self.row, column=1)
-
- self.row += 1
-
- def getPreferredOrDefaultValue(self, key, defaultValue):
- if self.appId in self.prefValues:
- return self.prefValues[self.appId][key]
- else:
- return defaultValue
-
-class NfdFrame(GuiFrame):
- def __init__(self, notebook, prefValues):
- GuiFrame.__init__(self, notebook, prefValues, "nfd")
-
- self.frameLabel = "NFD"
-
- # log-level
- self.logLevel = StringVar(self)
- self.addDropDown("Log level:",
- self.logLevel,
- LOG_LEVELS,
- self.getPreferredOrDefaultValue("log-level", LOG_LEVELS[3]))
-
- def getValues(self):
- return {
- "log-level": self.logLevel.get()
- }
-
-class NlsrFrame(GuiFrame):
-
- HYPERBOLIC_STATES = [
- "off",
- "on",
- "dry-run"
- ]
-
- def __init__(self, notebook, prefValues):
- GuiFrame.__init__(self, notebook, prefValues, "nlsr")
-
- self.frameLabel = "NLSR"
-
- # general: network
- self.network = StringVar(self)
- self.addEntryBox("Network:",
- self.network,
- self.getPreferredOrDefaultValue("network", "/ndn"))
-
- # general: site
- self.site = StringVar(self)
- self.addEntryBox("Site:", self.site, self.getPreferredOrDefaultValue("site", "/edu/site"))
-
- # general: router
- self.router = StringVar(self)
- self.addEntryBox("Router:",
- self.router,
- self.getPreferredOrDefaultValue("router", "/%C1.Router/cs/host"))
-
- # general: log-level
- self.logLevel = StringVar(self)
- self.addDropDown("Log level:",
- self.logLevel,
- LOG_LEVELS,
- self.getPreferredOrDefaultValue("log-level", LOG_LEVELS[3]))
-
- # hyperbolic: state
- self.hyperbolicState = StringVar(self)
- self.addDropDown("Hyperbolic routing:",
- self.hyperbolicState,
- self.HYPERBOLIC_STATES,
- self.getPreferredOrDefaultValue("hyperbolic-state", self.HYPERBOLIC_STATES[0]))
-
- # hyperbolic: angle
- self.angle = StringVar(self)
- self.addEntryBox("Angle:", self.angle, self.getPreferredOrDefaultValue("angle", "0.0"))
-
- # hyperbolic: radius
- self.radius = StringVar(self)
- self.addEntryBox("Radius:", self.radius, self.getPreferredOrDefaultValue("radius", "0.0"))
-
- # fib: max-faces-per-prefix
- self.maxFaces = StringVar(self)
- self.addEntryBox("Max faces per prefix:",
- self.maxFaces,
- self.getPreferredOrDefaultValue("max-faces-per-prefix", "0"))
-
- def getValues(self):
- return {
- "network": self.network.get(),
- "site": self.site.get(),
- "router": self.router.get(),
- "log-level": self.logLevel.get(),
- "hyperbolic-state": self.hyperbolicState.get(),
- "angle": self.angle.get(),
- "radius": self.radius.get(),
- "max-faces-per-prefix": self.maxFaces.get()
- }
diff --git a/ndn/ndn_application.py b/ndn/ndn_application.py
deleted file mode 100644
index 150c7c1..0000000
--- a/ndn/ndn_application.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-import os
-
-class NdnApplication:
- def __init__(self, node):
- self.node = node
- self.isRunning = False
- self.processId = ""
-
- def start(self, command):
- if self.isRunning is True:
- try:
- os.kill(int(self.processId), 0)
- except OSError:
- self.isRunning = False
-
- if self.isRunning is False:
- self.node.cmd(command)
- self.processId = self.node.cmd("echo $!")[:-1]
-
- self.isRunning = True
-
- def stop(self):
- if self.isRunning and self.processId != "":
- self.node.cmd("sudo kill {}".format(self.processId))
-
- self.isRunning = False
diff --git a/ndn/ndn_host.py b/ndn/ndn_host.py
deleted file mode 100644
index 2567794..0000000
--- a/ndn/ndn_host.py
+++ /dev/null
@@ -1,158 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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 file incorporates work covered by the following copyright and
-# permission notice:
-#
-# Mininet 2.3.0d1 License
-#
-# Copyright (c) 2013-2016 Open Networking Laboratory
-# Copyright (c) 2009-2012 Bob Lantz and The Board of Trustees of
-# The Leland Stanford Junior University
-#
-# Original authors: Bob Lantz and Brandon Heller
-#
-# We are making Mininet available for public use and benefit with the
-# expectation that others will use, modify and enhance the Software and
-# contribute those enhancements back to the community. However, since we
-# would like to make the Software available for broadest use, with as few
-# restrictions as possible permission is hereby granted, free of charge, to
-# any person obtaining a copy of this Software to deal in the Software
-# under the copyrights without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# The name and trademarks of copyright holder(s) may NOT be used in
-# advertising or publicity pertaining to the Software or any derivatives
-# without specific, written prior permission.
-
-from mininet.node import CPULimitedHost, Host, Node
-from mininet.examples.cluster import RemoteMixin
-
-from ndn.nfd import Nfd
-
-class NdnHostCommon():
- "Common methods of NdnHost and CpuLimitedNdnHost"
-
- def configNdn(self):
- self.buildPeerIp()
-
- def buildPeerIp(self):
- for iface in self.intfList():
- link = iface.link
- if link:
- node1, node2 = link.intf1.node, link.intf2.node
- if node1 == self:
- self.peerList[node2.name] = link.intf2.node.IP(link.intf2)
- else:
- self.peerList[node1.name] = link.intf1.node.IP(link.intf1)
-
- inited = False
-
- @classmethod
- def init(cls):
- "Initialization for NDNHost class"
- cls.inited = True
-
-class NdnHost(Host, NdnHostCommon):
- "NDNHost is a Host that always runs NFD"
-
- def __init__(self, name, **kwargs):
-
- Host.__init__(self, name, **kwargs)
- if not NdnHost.inited:
- NdnHostCommon.init()
-
- # Create home directory for a node
- self.homeFolder = "%s/%s" % (self.params['workdir'], self.name)
- self.cmd("mkdir -p %s" % self.homeFolder)
- self.cmd("cd %s" % self.homeFolder)
-
- self.nfd = None
-
- self.peerList = {}
-
- def config(self, app=None, cache=None, **params):
-
- r = Node.config(self, **params)
-
- self.setParam(r, 'app', app=app)
- self.setParam(r, 'cache', cache=cache)
-
- return r
-
- def terminate(self):
- "Stop node."
- if self.nfd is not None:
- self.nfd.stop()
- Host.terminate(self)
-
-class CpuLimitedNdnHost(CPULimitedHost, NdnHostCommon):
- '''CPULimitedNDNHost is a Host that always runs NFD and extends CPULimitedHost.
- It should be used when one wants to limit the resources of NDN routers and hosts '''
-
- def __init__(self, name, sched='cfs', **kwargs):
-
- CPULimitedHost.__init__(self, name, sched, **kwargs)
- if not NdnHost.inited:
- NdnHostCommon.init()
-
- # Create home directory for a node
- self.homeFolder = "%s/%s" % (self.params['workdir'], self.name)
- self.cmd("mkdir -p %s" % self.homeFolder)
- self.cmd("cd %s" % self.homeFolder)
-
- self.nfd = None
-
- self.peerList = {}
-
- def config(self, app=None, cpu=None, cores=None, cache=None, **params):
-
- r = CPULimitedHost.config(self,cpu,cores, **params)
-
- self.setParam(r, 'app', app=app)
- self.setParam(r, 'cache', cache=cache)
-
- return r
-
- def terminate(self):
- "Stop node."
- if self.nfd is not None:
- self.nfd.stop()
- CPULimitedHost.terminate(self)
-
-class RemoteNdnHost(RemoteMixin, NdnHost):
- "A node on a remote server"
- pass
diff --git a/ndn/nfd.py b/ndn/nfd.py
deleted file mode 100644
index eb8cb34..0000000
--- a/ndn/nfd.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-import time, sys, os
-from ndn.ndn_application import NdnApplication
-from ndn.util import copyExistentFile
-
-class Nfd(NdnApplication):
-
- def __init__(self, node, csSize):
- NdnApplication.__init__(self, node)
-
- self.logLevel = node.params["params"].get("nfd-log-level", "INFO")
-
- self.confFile = "{}/nfd.conf".format(node.homeFolder)
- self.logFile = "{}/nfd.log".format(node.homeFolder)
- self.sockFile = "/var/run/{}.sock".format(node.name)
- self.ndnFolder = "{}/.ndn".format(node.homeFolder)
- self.clientConf = "{}/client.conf".format(self.ndnFolder)
-
- # Copy nfd.conf file from /usr/local/etc/ndn or /etc/ndn to the node's home directory
- # Use nfd.conf as default configuration for NFD, else use the sample
- possibleConfPaths = ["/usr/local/etc/ndn/nfd.conf.sample", "/usr/local/etc/ndn/nfd.conf",
- "/etc/ndn/nfd.conf.sample", "/etc/ndn/nfd.conf"]
- copyExistentFile(node, possibleConfPaths, self.confFile)
-
- # Set log level
- node.cmd("infoedit -f {} -s log.default_level -v {}".format(self.confFile, self.logLevel))
- # Open the conf file and change socket file name
- node.cmd("infoedit -f {} -s face_system.unix.path -v /var/run/{}.sock".format(self.confFile, node.name))
-
- # Set CS size
- node.cmd("infoedit -f {} -s tables.cs_max_packets -v {}".format(self.confFile, csSize))
-
- # Make NDN folder
- node.cmd("sudo mkdir {}".format(self.ndnFolder))
-
- # Copy client configuration to host
- possibleClientConfPaths = ["/usr/local/etc/ndn/client.conf.sample", "/etc/ndn/client.conf.sample"]
- copyExistentFile(node, possibleClientConfPaths, self.clientConf)
-
- # Change the unix socket
- node.cmd("sudo sed -i 's|nfd.sock|{}.sock|g' {}".format(node.name, self.clientConf))
-
- # Change home folder
- node.cmd("export HOME={}".format(node.homeFolder))
- node.cmd("ndnsec-keygen /localhost/operator | ndnsec-install-cert -")
-
- def start(self):
- NdnApplication.start(self, "setsid nfd --config {} > {} 2>&1 &".format(self.confFile, self.logFile))
- time.sleep(2)
diff --git a/ndn/placer.py b/ndn/placer.py
deleted file mode 100644
index 412dc91..0000000
--- a/ndn/placer.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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 file incorporates work covered by the following copyright and
-# permission notice:
-#
-# Mininet 2.3.0d1 License
-#
-# Copyright (c) 2013-2016 Open Networking Laboratory
-# Copyright (c) 2009-2012 Bob Lantz and The Board of Trustees of
-# The Leland Stanford Junior University
-#
-# Original authors: Bob Lantz and Brandon Heller
-#
-# We are making Mininet available for public use and benefit with the
-# expectation that others will use, modify and enhance the Software and
-# contribute those enhancements back to the community. However, since we
-# would like to make the Software available for broadest use, with as few
-# restrictions as possible permission is hereby granted, free of charge, to
-# any person obtaining a copy of this Software to deal in the Software
-# under the copyrights without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# The name and trademarks of copyright holder(s) may NOT be used in
-# advertising or publicity pertaining to the Software or any derivatives
-# without specific, written prior permission.
-
-from mininet.examples.cluster import Placer
-
-nodePlace = []
-
-class PopulatePlacement():
- def __init__( self, placeList ):
- global nodePlace
- nodePlace = placeList
-
-class GuidedPlacer( Placer ):
- "Guided placement"
- def __init__( self, *args, **kwargs ):
- Placer.__init__( self, *args, **kwargs )
- self.count = 0
-
- def place( self, nodename ):
- assert nodename #please pylint
- while(True):
- global nodePlace
- if nodePlace[self.count] != 0:
- nodePlace[self.count] -= 1
- # args[self.count] is not zero, hence return the server at that position
- # so that if args[0] is 7 and servers[0] is Europa then place 7 nodes on Europa
- return self.servers[self.count]
- else:
- # while makes sure we go back to the if after this
- self.count += 1
diff --git a/ndn/remote_ndn_link.py b/ndn/remote_ndn_link.py
deleted file mode 100644
index 497c098..0000000
--- a/ndn/remote_ndn_link.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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 file incorporates work covered by the following copyright and
-# permission notice:
-#
-# Mininet 2.3.0d1 License
-#
-# Copyright (c) 2013-2016 Open Networking Laboratory
-# Copyright (c) 2009-2012 Bob Lantz and The Board of Trustees of
-# The Leland Stanford Junior University
-#
-# Original authors: Bob Lantz and Brandon Heller
-#
-# We are making Mininet available for public use and benefit with the
-# expectation that others will use, modify and enhance the Software and
-# contribute those enhancements back to the community. However, since we
-# would like to make the Software available for broadest use, with as few
-# restrictions as possible permission is hereby granted, free of charge, to
-# any person obtaining a copy of this Software to deal in the Software
-# under the copyrights without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# The name and trademarks of copyright holder(s) may NOT be used in
-# advertising or publicity pertaining to the Software or any derivatives
-# without specific, written prior permission.
-
-from mininet.link import TCLink
-from mininet.examples.cluster import RemoteLink, RemoteGRELink
-
-class RemoteNdnLink( TCLink, RemoteLink ):
- "A RemoteLink is a link between nodes which may be on different servers"
-
- def __init__( self, node1, node2, **kwargs ):
- """Initialize a RemoteLink
- see Link() for parameters"""
- # Create links on remote node
- self.node1 = node1
- self.node2 = node2
- self.tunnel = None
- kwargs.setdefault( 'params1', {} )
- kwargs.setdefault( 'params2', {} )
- self.cmd = None # satisfy pylint
- TCLink.__init__( self, node1, node2, **kwargs )
-
-class RemoteGRENdnLink( TCLink, RemoteGRELink ):
- def __init__(self, node1, node2, **kwargs):
- """Initialize a RemoteLink
- see Link() for parameters"""
- # Create links on remote node
- self.node1 = node1
- self.node2 = node2
- self.tunnel = None
- kwargs.setdefault( 'params1', {} )
- kwargs.setdefault( 'params2', {} )
- self.cmd = None # satisfy pylint
- TCLink.__init__( self, node1, node2, **kwargs )
diff --git a/ndn/util.py b/ndn/util.py
deleted file mode 100644
index 0398453..0000000
--- a/ndn/util.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-#
-# Copyright (C) 2015-2018, 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/>.
-
-from subprocess import call
-from mininet.cli import CLI
-import sys
-from os.path import isfile
-
-sshbase = [ 'ssh', '-q', '-t', '-i/home/mininet/.ssh/id_rsa' ]
-scpbase = [ 'scp', '-i', '/home/mininet/.ssh/id_rsa' ]
-devnull = open('/dev/null', 'w')
-
-def ssh(login, cmd):
- rcmd = sshbase + [login, cmd]
- call(rcmd, stdout=devnull, stderr=devnull)
-
-def scp(*args):
- tmp = []
- for arg in args:
- tmp.append(arg)
- rcmd = scpbase + tmp
- call(rcmd, stdout=devnull, stderr=devnull)
-
-def copyExistentFile(node, fileList, destination):
- for file in fileList:
- if isfile(file):
- node.cmd("cp {} {}".format(file, destination))
- break
- if not isfile(destination):
- fileName = destination.split("/")[-1]
- raise IOError("{} not found in expected directory.".format(fileName))
-
-
-class MiniNDNCLI(CLI):
- prompt = 'mini-ndn> '
- def __init__(self, mininet, stdin=sys.stdin, script=None):
- CLI.__init__(self, mininet, stdin=sys.stdin, script=None)
-
-class ProgramOptions:
- def __init__(self):
- self.ctime = 60
- self.experimentName = None
- self.nFaces = 3
- self.templateFile = "minindn.conf"
- self.routingType = "link-state"
- self.isNlsrEnabled = True
- self.isCliEnabled = True
- self.nlsrSecurity = False
- self.nPings = 300
- self.testbed = False
- self.workDir = "/tmp/minindn"
- self.resultDir = None
- self.pctTraffic = 1.0
- self.cluster = None
- self.servers = None
- self.guided = None
- self.placer = None
- self.tunnelType = None
- self.faceType = "udp"
- self.arguments = None
- self.csSize = 65536
- self.strategy = "best-route"
\ No newline at end of file
diff --git a/patches/ndn-cxx-dummy-keychain-from-ndnsim.patch b/patches/ndn-cxx-dummy-keychain-from-ndnsim.patch
new file mode 100644
index 0000000..a6e1b30
--- /dev/null
+++ b/patches/ndn-cxx-dummy-keychain-from-ndnsim.patch
@@ -0,0 +1,602 @@
+diff --git a/ndn-cxx/security/v2/key-chain.cpp b/ndn-cxx/security/v2/key-chain.cpp
+index 8043635..b9af6f0 100644
+--- a/ndn-cxx/security/v2/key-chain.cpp
++++ b/ndn-cxx/security/v2/key-chain.cpp
+@@ -25,6 +25,7 @@
+ #include "ndn-cxx/util/config-file.hpp"
+ #include "ndn-cxx/util/logger.hpp"
+ #include "ndn-cxx/util/sha256.hpp"
++#include "ndn-cxx/util/dummy-keychain.hpp"
+
+ #include "ndn-cxx/security/pib/pib-memory.hpp"
+ #include "ndn-cxx/security/pib/pib-sqlite3.hpp"
+@@ -163,7 +164,7 @@ KeyChain::getDefaultKeyParams()
+ //
+
+ KeyChain::KeyChain()
+- : KeyChain(getDefaultPibLocator(), getDefaultTpmLocator(), true)
++ : KeyChain("pib-dummy", "tpm-dummy", true)
+ {
+ }
+
+diff --git a/ndn-cxx/util/dummy-keychain.cpp b/ndn-cxx/util/dummy-keychain.cpp
+new file mode 100644
+index 0000000..aa24465
+--- /dev/null
++++ b/ndn-cxx/util/dummy-keychain.cpp
+@@ -0,0 +1,346 @@
++/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
++/**
++ * Copyright (c) 2011-2015 Regents of the University of California.
++ *
++ * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
++ * contributors.
++ *
++ * ndnSIM 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.
++ *
++ * ndnSIM 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
++ * ndnSIM, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
++ **/
++
++#include "dummy-keychain.hpp"
++
++#include <ndn-cxx/util/io.hpp>
++#include <ndn-cxx/security/transform/public-key.hpp>
++#include <boost/iostreams/device/array.hpp>
++#include <boost/iostreams/stream.hpp>
++
++namespace ndn {
++namespace security {
++
++static const uint8_t DUMMY_CERT[] =
++ "Bv0CqQclCAVkdW1teQgDS0VZCAgtnChyuKo7YAgCTkEICf0AAAFe3zzGfBQJGAEC"
++ "GQQANu6AFf0BJjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOJSa1j6"
++ "JAzobrmtlUdJi38EWQZOigLykf9psImvIu7pa29Q3apBXENcV1E9687FmfY85Ec3"
++ "/onMtN7WG/wiuKiu/9eOr5WslD3VGDgxhesx80ygP0GNsN8FzsMl0lRKduXx3wG4"
++ "MCT8CX7uA4n4JbHY+0QaKUEEMRCiXcRAtF+yKfr+GaVeSemg+i/LR+6CSgpOyH0K"
++ "ogH9nlNhBn1Hxyc8X+B/nEu6P6NNEKkSnhT1jAbWtT1eL3BPGK/HNY19w9k2Ln6/"
++ "OYlhaHfB4m0oR/ePcUguQBwTgYS+40YQYUPivBsSQv3X2/7+gGLhIzA4YppwOooK"
++ "RGhbmL8zF2evmJ8CAwEAARZHGwEBHBgHFggFZHVtbXkIA0tFWQgILZwocriqO2D9"
++ "AP0m/QD+DzIwMTcxMDAyVDIyMzczNv0A/w8yMDE4MTAwMlQyMjM3MzUX/QEAMBUV"
++ "O51BEQwxp646i7IuHkuc1C/LISnOP2+wBFF2Ea1ht9MKjKkyJdmB1/GAOiR3njKd"
++ "UgRjBlownL11EwYDxkPY39RR05TmhF6PkpP81Ro/Vzv7rtSi/dxFIZXCiyuKPRUx"
++ "E0pZelPWVs3zMfqQ+8rWG89Kqs1vM0dglLBzlX9Lbim71TyLmaJaMmmBKv8+eQ22"
++ "CN71sRZOovl1kKcTHpOm61nD3C1n9GRflFtaMAXE/XU4zMJVzBv6XwQl6PCIc9H2"
++ "vjLa28ruVjhMGxqCGhziTC2eR56SUixrnEcbOKT0R+8+0AFnZIjdYglOZPcVwTVB"
++ "G6OxECJOuSoREcd1Ww==;";
++
++static const uint8_t DUMMY_SIGNATURE[] =
++ {0x17, 0xfd, 0x01, 0x00, 0x93, 0x15, 0x09, 0x49, 0x79, 0x9e, 0xb7, 0x9c, 0xd3, 0xc1, 0xbf, 0x61,
++ 0x89, 0xd5, 0xd9, 0xca, 0xf2, 0xb0, 0x14, 0xae, 0x72, 0x7c, 0x1f, 0x8f, 0xf5, 0xb1, 0x70, 0xd6,
++ 0x9b, 0x8f, 0xf8, 0xd7, 0x2d, 0xbc, 0x92, 0x6f, 0x7d, 0x77, 0x96, 0x46, 0xea, 0xd4, 0x7d, 0x90,
++ 0xbc, 0x7a, 0xeb, 0xe2, 0x03, 0x93, 0xb1, 0xd2, 0x62, 0xec, 0x9d, 0xff, 0x9c, 0x9c, 0x2a, 0x14,
++ 0x7d, 0x23, 0xca, 0x29, 0x3d, 0x15, 0x1a, 0x40, 0x42, 0x2c, 0x59, 0x33, 0x8a, 0xf7, 0xc0, 0x6b,
++ 0xc4, 0x9c, 0xf3, 0xc4, 0x99, 0xa4, 0x1a, 0x60, 0xf5, 0x28, 0x7d, 0x4c, 0xef, 0x43, 0x7d, 0xbd,
++ 0x7d, 0x00, 0x51, 0xee, 0x41, 0xf5, 0x25, 0x80, 0xce, 0xe6, 0x64, 0x4f, 0x75, 0x54, 0xf3, 0xb2,
++ 0x99, 0x9a, 0x0f, 0x93, 0x9a, 0x28, 0x1d, 0xfe, 0x12, 0x8a, 0xe0, 0xc1, 0x02, 0xeb, 0xa4, 0x35,
++ 0x52, 0x88, 0xac, 0x44, 0x1a, 0x44, 0x82, 0x97, 0x4f, 0x5f, 0xa8, 0xd8, 0x9f, 0x67, 0x38, 0xa8,
++ 0x64, 0xb6, 0x62, 0x99, 0xbd, 0x96, 0x3c, 0xf5, 0x86, 0x09, 0x5c, 0x97, 0x6b, 0x8f, 0xae, 0xe0,
++ 0x60, 0xe7, 0x23, 0x98, 0x6a, 0xee, 0xc1, 0xb0, 0x14, 0xbe, 0x46, 0x2c, 0xfb, 0xa7, 0x27, 0x73,
++ 0xe4, 0xf3, 0x26, 0x33, 0xba, 0x99, 0xd4, 0x01, 0x38, 0xa8, 0xf2, 0x9e, 0x87, 0xe0, 0x71, 0x0b,
++ 0x25, 0x44, 0x07, 0x35, 0x88, 0xab, 0x67, 0x27, 0x56, 0x0e, 0xb5, 0xb5, 0xe8, 0x27, 0xb4, 0x49,
++ 0xdc, 0xb8, 0x48, 0x31, 0xff, 0x99, 0x48, 0xab, 0x11, 0xb4, 0xa0, 0xdf, 0x8a, 0x6d, 0xff, 0x43,
++ 0x69, 0x32, 0xa7, 0xbc, 0x63, 0x9d, 0x0f, 0xe0, 0x95, 0x34, 0x36, 0x25, 0x4b, 0x3e, 0x36, 0xbd,
++ 0x81, 0x91, 0x0b, 0x91, 0x9f, 0x3a, 0x04, 0xa2, 0x44, 0x28, 0x19, 0xa1, 0x38, 0x21, 0x4f, 0x25,
++ 0x59, 0x8a, 0x48, 0xc2};
++
++const std::string DummyPib::SCHEME = "pib-dummy";
++const std::string DummyTpm::SCHEME = "tpm-dummy";
++
++NDN_CXX_V2_KEYCHAIN_REGISTER_PIB_BACKEND(DummyPib);
++NDN_CXX_V2_KEYCHAIN_REGISTER_TPM_BACKEND(DummyTpm);
++
++DummyPib::DummyPib(const std::string& locator)
++{
++}
++
++void
++DummyPib::setTpmLocator(const std::string& tpmLocator)
++{
++ m_tpmLocator = tpmLocator;
++}
++
++std::string
++DummyPib::getTpmLocator() const
++{
++ return m_tpmLocator;
++}
++
++bool
++DummyPib::hasIdentity(const Name& identityName) const
++{
++ return true;
++}
++
++void
++DummyPib::addIdentity(const Name& identityName)
++{
++}
++
++void
++DummyPib::removeIdentity(const Name& identity)
++{
++}
++
++void
++DummyPib::clearIdentities()
++{
++}
++
++std::set<Name>
++DummyPib::getIdentities() const
++{
++ std::set<Name> identities;
++ identities.insert("/dummy");
++ return identities;
++}
++
++void
++DummyPib::setDefaultIdentity(const Name& identityName)
++{
++}
++
++Name
++DummyPib::getDefaultIdentity() const
++{
++ return "/dummy";
++}
++
++bool
++DummyPib::hasKey(const Name& keyName) const
++{
++ return true;
++}
++
++void
++DummyPib::addKey(const Name& identity, const Name& keyName,
++ const uint8_t* key, size_t keyLen)
++{
++}
++
++void
++DummyPib::removeKey(const Name& keyName)
++{
++}
++
++Buffer
++DummyPib::getKeyBits(const Name& keyName) const
++{
++ typedef boost::iostreams::stream<boost::iostreams::array_source> arrayStream;
++ arrayStream
++ is(reinterpret_cast<const char*>(DUMMY_CERT), sizeof(DUMMY_CERT));
++ auto cert = io::load<v2::Certificate>(is, io::BASE64);
++ return cert->getPublicKey();
++}
++
++std::set<Name>
++DummyPib::getKeysOfIdentity(const Name& identity) const
++{
++ std::set<Name> keys;
++ keys.insert("/dummy/KEY/-%9C%28r%B8%AA%3B%60");
++ return keys;
++}
++
++void
++DummyPib::setDefaultKeyOfIdentity(const Name& identity, const Name& keyName)
++{
++}
++
++Name
++DummyPib::getDefaultKeyOfIdentity(const Name& identity) const
++{
++ return "/dummy/KEY/-%9C%28r%B8%AA%3B%60";
++}
++
++bool
++DummyPib::hasCertificate(const Name& certName) const
++{
++ return true;
++}
++
++void
++DummyPib::addCertificate(const v2::Certificate& certificate)
++{
++}
++
++void
++DummyPib::removeCertificate(const Name& certName)
++{
++}
++
++v2::Certificate
++DummyPib::getCertificate(const Name& certificateName) const
++{
++ static shared_ptr<v2::Certificate> cert = nullptr;
++ if (cert == nullptr) {
++ typedef boost::iostreams::stream<boost::iostreams::array_source> arrayStream;
++ arrayStream
++ is(reinterpret_cast<const char*>(DUMMY_CERT), sizeof(DUMMY_CERT));
++ cert = io::load<v2::Certificate>(is, io::BASE64);
++ }
++
++ return *cert;
++}
++
++std::set<Name>
++DummyPib::getCertificatesOfKey(const Name& keyName) const
++{
++ std::set<Name> certs;
++ certs.insert("/dummy/KEY/-%9C%28r%B8%AA%3B%60/self/%FD%00%00%01%5E%DF%3Bv%01");
++ return certs;
++}
++
++void
++DummyPib::setDefaultCertificateOfKey(const Name& keyName, const Name& certName)
++{
++}
++
++v2::Certificate
++DummyPib::getDefaultCertificateOfKey(const Name& keyName) const
++{
++ static shared_ptr<v2::Certificate> cert = nullptr;
++ if (cert == nullptr) {
++ typedef boost::iostreams::stream<boost::iostreams::array_source> arrayStream;
++ arrayStream
++ is(reinterpret_cast<const char*>(DUMMY_CERT), sizeof(DUMMY_CERT));
++ cert = io::load<v2::Certificate>(is, io::BASE64);
++ }
++
++ return *cert;
++}
++
++std::string
++DummyPib::getScheme()
++{
++ return DummyPib::SCHEME;
++}
++
++//////////////////////////////////////////////////////////////////////////////////////////
++//////////////////////////////////////////////////////////////////////////////////////////
++//////////////////////////////////////////////////////////////////////////////////////////
++//////////////////////////////////////////////////////////////////////////////////////////
++
++namespace tpm {
++
++DummyKeyHandle::DummyKeyHandle(shared_ptr<transform::PrivateKey> key)
++{
++}
++
++ConstBufferPtr
++DummyKeyHandle::doSign(DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t size) const
++{
++ return make_shared<Buffer>(DUMMY_SIGNATURE, sizeof(DUMMY_SIGNATURE));
++}
++
++bool
++DummyKeyHandle::doVerify(DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t bufLen,
++ const uint8_t* sig, size_t sigLen) const
++{
++ return true;
++}
++
++ConstBufferPtr
++DummyKeyHandle::doDecrypt(const uint8_t* cipherText, size_t cipherTextLen) const
++{
++ throw Error("Not supported");
++}
++
++ConstBufferPtr
++DummyKeyHandle::doDerivePublicKey() const
++{
++ throw Error("Not supported");
++}
++
++} // namespace tpm
++
++//////////////////////////////////////////////////////////////////////////////////////////
++//////////////////////////////////////////////////////////////////////////////////////////
++//////////////////////////////////////////////////////////////////////////////////////////
++//////////////////////////////////////////////////////////////////////////////////////////
++
++DummyTpm::DummyTpm(const std::string& locator)
++{
++}
++
++bool
++DummyTpm::isTerminalMode() const
++{
++ return false;
++}
++
++void
++DummyTpm::setTerminalMode(bool isTerminal) const
++{
++}
++
++bool
++DummyTpm::isTpmLocked() const
++{
++ return false;
++}
++
++bool
++DummyTpm::doHasKey(const Name& keyName) const
++{
++ return false;
++}
++
++unique_ptr<tpm::KeyHandle>
++DummyTpm::doGetKeyHandle(const Name& keyName) const
++{
++ unique_ptr<tpm::KeyHandle> m_dummyKeyHandle = make_unique<tpm::DummyKeyHandle>(nullptr);
++ return m_dummyKeyHandle;
++}
++
++unique_ptr<tpm::KeyHandle>
++DummyTpm::doCreateKey(const Name& identity, const KeyParams& params)
++{
++ unique_ptr<tpm::KeyHandle> m_dummyKeyHandle = make_unique<tpm::DummyKeyHandle>(nullptr);
++ return m_dummyKeyHandle;
++}
++
++void
++DummyTpm::doDeleteKey(const Name& keyName)
++{
++ throw Error("Not supported");
++}
++
++ConstBufferPtr
++DummyTpm::doExportKey(const Name& keyName, const char* pw, size_t pwLen)
++{
++ throw Error("Not supported");
++}
++
++void
++DummyTpm::doImportKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len, const char* pw, size_t pwLen)
++{
++ throw Error("Not supported");
++}
++
++std::string
++DummyTpm::getScheme()
++{
++ return DummyTpm::SCHEME;
++}
++
++} // namespace security
++} // namespace ndn
+diff --git a/ndn-cxx/util/dummy-keychain.hpp b/ndn-cxx/util/dummy-keychain.hpp
+new file mode 100644
+index 0000000..d1432a6
+--- /dev/null
++++ b/ndn-cxx/util/dummy-keychain.hpp
+@@ -0,0 +1,223 @@
++/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
++/**
++ * Copyright (c) 2011-2015 Regents of the University of California.
++ *
++ * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
++ * contributors.
++ *
++ * ndnSIM 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.
++ *
++ * ndnSIM 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
++ * ndnSIM, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
++ **/
++
++#ifndef NDNSIM_UTILS_DUMMY_KEYCHAIN_HPP
++#define NDNSIM_UTILS_DUMMY_KEYCHAIN_HPP
++
++#include <ndn-cxx/security/key-chain.hpp>
++#include <ndn-cxx/security/security-common.hpp>
++#include <ndn-cxx/security/pib/pib-impl.hpp>
++#include <ndn-cxx/security/tpm/back-end.hpp>
++#include <ndn-cxx/security/transform/private-key.hpp>
++
++namespace ndn {
++namespace security {
++
++using pib::PibImpl;
++using tpm::BackEnd;
++using tpm::KeyHandle;
++
++class DummyPib : public PibImpl
++{
++public:
++ class Error : public PibImpl::Error
++ {
++ public:
++ explicit
++ Error(const std::string& what)
++ : PibImpl::Error(what)
++ {
++ }
++ };
++
++public:
++ explicit DummyPib(const std::string& locator);
++
++ // TPM management
++ void
++ setTpmLocator(const std::string& tpmLocator) override;
++
++ std::string
++ getTpmLocator() const override;
++
++ // Identity manangement
++ bool
++ hasIdentity(const Name& identityName) const override;
++
++ void
++ addIdentity(const Name& identityName) override;
++
++ void
++ removeIdentity(const Name& identity) override;
++
++ void
++ clearIdentities() override;
++
++ std::set<Name>
++ getIdentities() const override;
++
++ void
++ setDefaultIdentity(const Name& identityName) override;
++
++ Name
++ getDefaultIdentity() const override;
++
++ // Key management
++ bool
++ hasKey(const Name& keyName) const override;
++
++ void
++ addKey(const Name& identity, const Name& keyName, const uint8_t* key,
++ size_t keyLen) override;
++
++ void
++ removeKey(const Name& keyName) override;
++
++ Buffer
++ getKeyBits(const Name& keyName) const override;
++
++ std::set<Name>
++ getKeysOfIdentity(const Name& identity) const override;
++
++ void
++ setDefaultKeyOfIdentity(const Name& identity, const Name& keyName) override;
++
++ Name
++ getDefaultKeyOfIdentity(const Name& identity) const override;
++
++ // certificate management
++ bool
++ hasCertificate(const Name& certName) const override;
++
++ void
++ addCertificate(const v2::Certificate& certificate) override;
++
++ void
++ removeCertificate(const Name& certName) override;
++
++ v2::Certificate
++ getCertificate(const Name& certificateName) const override;
++
++ std::set<Name>
++ getCertificatesOfKey(const Name& keyName) const override;
++
++ void
++ setDefaultCertificateOfKey(const Name& keyName, const Name& certName) override;
++
++ v2::Certificate
++ getDefaultCertificateOfKey(const Name& keyName) const override;
++
++ static std::string
++ getScheme();
++
++ static const std::string SCHEME;
++
++private:
++ std::string m_tpmLocator;
++};
++
++//////////////////////////////////////////////////////////////////////////////////////////
++//////////////////////////////////////////////////////////////////////////////////////////
++
++namespace tpm {
++
++class DummyKeyHandle : public KeyHandle
++{
++public:
++ explicit
++ DummyKeyHandle(shared_ptr<transform::PrivateKey> key);
++
++private:
++ ConstBufferPtr
++ doSign(DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t size) const final;
++
++ bool
++ doVerify(DigestAlgorithm digestAlgorithm, const uint8_t* buf, size_t bufLen,
++ const uint8_t* sig, size_t sigLen) const final;
++
++ ConstBufferPtr
++ doDecrypt(const uint8_t* cipherText, size_t cipherTextLen) const final;
++
++ ConstBufferPtr
++ doDerivePublicKey() const final;
++};
++
++} // namespace tpm
++
++//////////////////////////////////////////////////////////////////////////////////////////
++//////////////////////////////////////////////////////////////////////////////////////////
++
++class DummyTpm : public BackEnd
++{
++public:
++ class Error : public BackEnd::Error
++ {
++ public:
++ explicit
++ Error(const std::string& what)
++ : BackEnd::Error(what)
++ {
++ }
++ };
++
++public:
++ explicit DummyTpm(const std::string& locator);
++
++ bool
++ isTerminalMode() const override;
++
++ void
++ setTerminalMode(bool isTerminal) const override;
++
++ bool
++ isTpmLocked() const override;
++
++ ConstBufferPtr
++ sign(const uint8_t* buf, size_t size, const Name& keyName, DigestAlgorithm digestAlgorithm) const;
++
++ static std::string
++ getScheme();
++
++private:
++ bool
++ doHasKey(const Name& keyName) const final;
++
++ unique_ptr<tpm::KeyHandle>
++ doGetKeyHandle(const Name& keyName) const final;
++
++ unique_ptr<tpm::KeyHandle>
++ doCreateKey(const Name& identity, const KeyParams& params) final;
++
++ void
++ doDeleteKey(const Name& keyName) final;
++
++ ConstBufferPtr
++ doExportKey(const Name& keyName, const char* pw, size_t pwLen) final;
++
++ void
++ doImportKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len, const char* pw, size_t pwLen) final;
++
++public:
++ static const std::string SCHEME;
++};
++
++} // namespace security
++} // namespace ndn
++
++#endif // NDNSIM_UTILS_DUMMY_KEYCHAIN_HPP
diff --git a/requirements.txt b/requirements.txt
index be5de0f..12598fb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1,2 @@
-python-igraph
\ No newline at end of file
+python-igraph
+setuptools
\ No newline at end of file
diff --git a/setup.py b/setup.py
index bac5451..328a68a 100644
--- a/setup.py
+++ b/setup.py
@@ -1,10 +1,13 @@
#!/usr/bin/env python
from setuptools import setup, find_packages
+from minindn import __version__
setup(
name = "Mini-NDN",
- version = '0.4.0',
+ version = __version__,
+ description='Mininet based NDN emulator',
packages = find_packages(),
- scripts = ['bin/minindn', 'bin/minindnedit'],
)
+
+print(find_packages())