ndn: Add NLSR experiments

Change-Id: I0b86b121a5c8bf6a6e6e8df5027fe49561a9283b
diff --git a/ndn/experiments/__init__.py b/ndn/experiments/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ndn/experiments/__init__.py
diff --git a/ndn/experiments/experiment.py b/ndn/experiments/experiment.py
new file mode 100644
index 0000000..9487e22
--- /dev/null
+++ b/ndn/experiments/experiment.py
@@ -0,0 +1,70 @@
+#!/usr/bin/python
+
+import time
+import sys
+
+class Experiment:
+
+    def __init__(self, net, nodes, convergenceTime, nPings, strategy):
+        self.net = net
+        self.nodes = nodes
+        self.convergenceTime = convergenceTime
+        self.nPings = nPings
+        self.strategy = strategy
+
+    def start(self):
+        self.setup()
+        self.run()
+
+    def setup(self):
+        for host in self.net.hosts:
+            # Set strategy
+            host.nfd.setStrategy("/ndn/edu", self.strategy)
+
+            # Start ping server
+            host.cmd("ndnpingserver /ndn/edu/" + str(host) + " > ping-server &")
+
+            # Create folder to store ping data
+            host.cmd("mkdir ping-data")
+
+        # Wait for convergence time period
+        print "Waiting " + str(self.convergenceTime) + " seconds for convergence..."
+        time.sleep(self.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("nfd-status -b | grep /ndn/edu/%C1.Router/cs/")
+            statusPrefix = host.cmd("nfd-status -b | grep /ndn/edu/")
+            didNodeConverge = True
+            for node in self.nodes.split(","):
+                    if ("/ndn/edu/%C1.Router/cs/" + node) not in statusRouter:
+                        didNodeConverge = False
+                        didNlsrConverge = False
+                    if str(host) != node and ("/ndn/edu/" + node) 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...")
+            for host in self.net.hosts:
+                host.nfd.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:
+                    # Use "&" to run in background and perform parallel pings
+                    print "Scheduling ping(s) from %s to %s" % (host.name, other.name)
+                    host.cmd("ndnping -t -c "+ str(self.nPings) + " /ndn/edu/" + other.name + " > ping-data/" + other.name + ".txt &")
+                    time.sleep(0.2)
+
diff --git a/ndn/experiments/failure_experiment.py b/ndn/experiments/failure_experiment.py
new file mode 100644
index 0000000..d4e9380
--- /dev/null
+++ b/ndn/experiments/failure_experiment.py
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+
+from ndn.experiments.experiment import Experiment
+from ndn.nlsr import Nlsr
+
+import time
+
+class FailureExperiment(Experiment):
+
+    def __init__(self, net, nodes, convergenceTime, strategy):
+
+        Experiment.__init__(self, net, nodes, convergenceTime, 300, strategy)
+        self.PING_COLLECTION_TIME_BEFORE_FAILURE = 60
+        self.PING_COLLECTION_TIME_AFTER_RECOVERY = 90
+
+    def run(self):
+        self.startPings()
+
+        # 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":
+                print("Bringing CSU down")
+                host.nfd.stop()
+                break
+
+        # CSU is down for 2 minutes
+        time.sleep(120)
+
+        # Bring CSU back up
+        for host in self.net.hosts:
+            if host.name == "csu":
+                print("Bringing CSU up")
+                host.nfd.start()
+                host.nlsr.start()
+                host.nfd.setStrategy("/ndn/edu", self.strategy)
+                host.cmd("ndnpingserver /ndn/edu/" + str(host) + " > ping-server &")
+
+        # Collect pings for more seconds after CSU is up
+        time.sleep(self.PING_COLLECTION_TIME_AFTER_RECOVERY)
diff --git a/ndn/experiments/pingall_experiment.py b/ndn/experiments/pingall_experiment.py
new file mode 100644
index 0000000..3bbfc1f
--- /dev/null
+++ b/ndn/experiments/pingall_experiment.py
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+
+from ndn.experiments.experiment import Experiment
+
+import time
+
+class PingallExperiment(Experiment):
+
+    def __init__(self, net, nodes, convergenceTime, nPings, strategy):
+
+        Experiment.__init__(self, net, nodes, convergenceTime, nPings, strategy)
+        self.COLLECTION_PERIOD_BUFFER = 10
+
+
+    def run(self):
+        self.startPings()
+
+        # For pingall experiment sleep for the number of pings + some offset
+        time.sleep(self.nPings + self.COLLECTION_PERIOD_BUFFER)
diff --git a/ndn/nfd.py b/ndn/nfd.py
index 614a358..b33fc37 100644
--- a/ndn/nfd.py
+++ b/ndn/nfd.py
@@ -3,6 +3,9 @@
 import time
 
 class Nfd:
+    STRATEGY_BEST_ROUTE_V3 = "best-route/%FD%03"
+    STRATEGY_NCC = "ncc"
+
     def __init__(self, node):
         self.node = node
         self.isRunning = False
@@ -18,8 +21,8 @@
         self.ndnFolder = "%s/.ndn" % self.homeFolder
         self.clientConf = "%s/client.conf" % self.ndnFolder
 
-        # Copy nfd.conf file from mn-ndn/ndn_utils to the node's home
-        node.cmd("sudo cp ~/mn-ndn/ndn_utils/nfd.conf %s" % self.confFile)
+        # Copy nfd.conf file from mini-ndn/ndn_utils to the node's home
+        node.cmd("sudo cp ~/mini-ndn/ndn_utils/nfd.conf %s" % self.confFile)
 
         # Open the conf file and change socket file name
         node.cmd("sudo sed -i 's|nfd.sock|%s.sock|g' %s" % (node.name, self.confFile))
@@ -28,13 +31,19 @@
         node.cmd("sudo mkdir %s" % self.ndnFolder)
 
         # Copy the client.conf file and change the unix socket
-        node.cmd("sudo cp ~/mn-ndn/ndn_utils/client.conf.sample %s" % self.clientConf)
+        node.cmd("sudo cp ~/mini-ndn/ndn_utils/client.conf.sample %s" % self.clientConf)
         node.cmd("sudo sed -i 's|nfd.sock|%s.sock|g' %s" % (node.name, self.clientConf))
 
         # Change home folder
         node.cmd("export HOME=%s" % self.homeFolder)
 
     def start(self):
+        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("sudo nfd --config %s 2>> %s &" % (self.confFile, self.logFile))
             self.processId = self.node.cmd("echo $!")[:-1]
@@ -47,8 +56,8 @@
         if self.isRunning is True:
             self.node.cmd("sudo kill %s" % self.processId)
 
-        self.isRunning = False
+            self.isRunning = False
 
     def setStrategy(self, name, strategy):
-        node.cmd("nfdc set-strategy %s ndn:/localhost/nfd/strategy/%s" % (name, strategy))
+        self.node.cmd("nfdc set-strategy %s ndn:/localhost/nfd/strategy/%s" % (name, strategy))
         time.sleep(0.5)
diff --git a/ndn/nlsr.py b/ndn/nlsr.py
index de9ec86..03719e5 100644
--- a/ndn/nlsr.py
+++ b/ndn/nlsr.py
@@ -1,10 +1,12 @@
 #!/usr/bin/env python
+import os
 
 class Nlsr:
     def __init__(self, node):
         self.node = node
         self.routerName = "/%sC1.Router/cs/%s" % ('%', node.name)
         self.confFile = "/tmp/%s/nlsr.conf" % node.name
+        self.isRunning = False
 
         # Make directory for log file
         self.logDir = "/tmp/%s/log" % node.name
@@ -17,8 +19,23 @@
         node.cmd("sudo sed -i 's|prefix .*netlab|prefix /ndn/edu/%s|g' %s" % (node.name, self.confFile))
 
     def start(self):
-        self.node.cmd("nlsr -d")
+        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("nlsr -d")
+            self.processId = self.node.cmd("echo $!")[:-1]
+
+            self.isRunning = True
+
+    def stop(self):
+        if self.isRunning:
+            self.node.cmd("sudo kill %s" % self.processId)
+
+            self.isRunning = False
 
 class NlsrConfigGenerator:
 
@@ -26,7 +43,7 @@
     ROUTING_HYPERBOLIC = "hr"
 
     def __init__(self, node, home):
-        node.cmd("sudo cp %s/mn-ndn/ndn_utils/nlsr.conf nlsr.conf" % home)
+        node.cmd("sudo cp %s/mini-ndn/ndn_utils/nlsr.conf nlsr.conf" % home)
         self.node = node
 
         parameters = node.nlsrParameters