ndn: Add NFD and NLSR class abstractions

refs: #2528

Change-Id: I3241af0e85f4eec4eb640aca274ff9ca4f812656
diff --git a/bin/minindn b/bin/minindn
new file mode 100755
index 0000000..51a4c52
--- /dev/null
+++ b/bin/minindn
@@ -0,0 +1,186 @@
+#!/usr/bin/env python
+
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.log import setLogLevel, output, info
+from mininet.cli import CLI
+from mininet.link import TCLink
+from mininet.conf_parser import parse_hosts, parse_links
+
+from ndn.experiments import HyperbolicExperiment, FailureExperiment
+from ndn.ndn_host import NdnHost, CpuLimitedNdnHost
+
+import os.path, time
+import optparse
+import datetime
+
+from ndn.nlsr import Nlsr, NlsrConfigGenerator
+
+def parse_args():
+    usage="""Usage: minindn [template_file] [ -t | --testbed ]
+    If no template_file is given, will try to load template
+    from file minindn.conf in the current directory.
+    If --testbed is used, minindn will run the NDN Project Testbed.
+    This assumes you are in the testbed directory in the minindn installation
+    directory.
+    """
+
+    testbed = False
+    pingall = False
+    hr = False
+    failure = False
+
+    parser = optparse.OptionParser(usage)
+
+    parser.add_option("-t", "--testbed", action="store_true", dest="testbed",
+    help="instantiates NDN Testbed")
+
+    parser.add_option("--pingall", action="store", dest="pingall", type="int",
+    help="Sequentiall pings all the other nodes from each node")
+
+    parser.add_option("--ctime", action="store", dest="ctime", type="int",
+    help="Specify convergence time for the topology (Default 60 seconds)")
+
+    parser.add_option("--hr", action="store_true", dest="hr",
+    help="--hr is used to turn on hyperbolic routing")
+
+    parser.add_option("--faces", action="store", dest="faces", type="int",
+    help="Specify number of faces 0-60")
+
+    parser.add_option("--failure", action="store_true", dest="failure",
+    help="Run failure experiment, specify the number of pings using pingall")
+
+    parser.add_option("--no-cli", action="store_false", dest="isCliEnabled",
+        help="Run experiments and exit without showing the command line interface")
+
+    (options, arg) = parser.parse_args()
+
+    testbed = options.testbed
+    pingall = options.pingall
+    ctime = options.ctime
+    hr = options.hr
+    faces = options.faces
+    failure = options.failure
+    isCliEnabled = options.isCliEnabled
+
+    if ctime is None:
+        ctime = 60
+
+    if isCliEnabled is None:
+        isCliEnabled = True
+
+    if len(arg) == 0 or len(arg) > 2:
+        file = ''
+    else:
+        file = arg[0]
+
+    return file, testbed, pingall, ctime, hr, faces, failure, isCliEnabled
+
+class NdnTopo(Topo):
+    def __init__(self, conf_arq, **opts):
+        Topo.__init__(self, **opts)
+
+        global hosts_conf
+        global links_conf
+        hosts_conf = parse_hosts(conf_arq)
+        links_conf = parse_links(conf_arq)
+
+        self.isTCLink = False
+        self.isLimited = False
+
+        for host in hosts_conf:
+            if host.cpu != None and self.isLimited != True:
+                self.isLimited = True
+            self.addHost(host.name, app=host.app, fib=host.uri_tuples,cpu=host.cpu,cores=host.cores,cache=host.cache)
+
+        for link in 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(template_file='minindn.conf', testbed=False, pingall=None, ctime=None, hr=False, faces=3, failure=False, isCliEnabled=True):
+    "Create a network based on template_file"
+
+    home = expanduser("~")
+
+    if template_file == '':
+        template_file='minindn.conf'
+
+    if os.path.exists(template_file) == False:
+        info('No template file given and default template file minindn.conf not found. Exiting...\n')
+        quit()
+
+    topo = NdnTopo(template_file)
+
+    t = datetime.datetime.now()
+
+    if topo.isTCLink == True and topo.isLimited == True:
+        net = Mininet(topo,host=CpuLimitedNdnHost,link=TCLink)
+    elif topo.isTCLink == True and topo.isLimited == False:
+        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)
+
+    t2 = datetime.datetime.now()
+
+    delta = t2 - t
+
+    info('Setup time: ' + str(delta.seconds) + '\n')
+
+    net.start()
+
+    nodes = ""    # Used later to check prefix name in checkFIB
+
+    # NLSR initialization
+    for host in net.hosts:
+        nodes += str(host.name) + ","
+
+        conf = next(x for x in hosts_conf if x.name == host.name)
+        host.nlsrParameters = conf.nlsrParameters
+
+        if faces is not None:
+            host.nlsrParameters["max-faces-per-prefix"] = faces
+
+        if hr is True:
+            host.nlsrParameters["hyperbolic-state"] = "on"
+
+        # Generate NLSR configuration file
+        configGenerator = NlsrConfigGenerator(host, home)
+        configGenerator.createConfigFile()
+
+        # Start NLSR
+        nlsr = Nlsr(host)
+        nlsr.start()
+
+    nodes = nodes[0:-1]
+
+    if failure is True:
+        test = FailureExperiment(net, nodes, ctime)
+        test.run()
+    elif pingall is not None:
+        test = HyperbolicExperiment(net, nodes, ctime, pingall)
+        test.run()
+
+    for host in net.hosts:
+        if 'app' in host.params:
+            if host.params['app'] != '_':
+                host.cmd(host.params['app'])
+
+    if isCliEnabled is True:
+        CLI(net)
+
+    net.stop()
+
+if __name__ == '__main__':
+    hosts_conf = []
+    links_conf = []
+    template, testbed, pingall, ctime, hr, faces, failure, isCliEnabled = parse_args()
+
+    setLogLevel('info')
+    execute(template, testbed, pingall, ctime, hr, faces, failure, isCliEnabled)
diff --git a/mininet/conf_parser.py b/mininet/conf_parser.py
index ae514f3..62cc8fa 100644
--- a/mininet/conf_parser.py
+++ b/mininet/conf_parser.py
@@ -1,19 +1,30 @@
 import ConfigParser, re
 
-class confCCNHost():
+class confNDNHost():
 
-    def __init__(self, name, app='', uri_tuples='', cpu=None, cores=None, cache=None):
+    def __init__(self, name, app='', params='', cpu=None, cores=None, cache=None):
         self.name = name
         self.app = app
-        self.uri_tuples = uri_tuples
+        self.uri_tuples = params
         self.cpu = cpu
         self.cores = cores
-	self.cache = cache
+        self.cache = cache
+
+        # For now assume leftovers are NLSR configuration parameters
+        self.nlsrParameters = params
 
     def __repr__(self):
-        return 'Name: ' + self.name + ' App: ' + self.app + ' URIS: ' + str(self.uri_tuples) + ' CPU:' + str(self.cpu) + ' Cores:' +str(self.cores) + ' Cache: ' + str(self.cache)
+        return 'Name: '    + self.name + \
+               ' App: '    + self.app + \
+               ' URIS: '   + str(self.uri_tuples) + \
+               ' CPU: '    + str(self.cpu) + \
+               ' Cores: '  + str(self.cores) + \
+               ' Cache: '  + str(self.cache) + \
+               ' Radius: ' + str(self.radius) + \
+               ' Angle: '  + str(self.angle) + \
+               ' NLSR Parameters: ' + self.nlsrParameters
 
-class confCCNLink():
+class confNDNLink():
 
     def __init__(self,h1,h2,linkDict=None):
         self.h1 = h1
@@ -30,18 +41,18 @@
 
     hosts = []
 
-    items = config.items('hosts')
-	
-	#makes a first-pass read to hosts section to find empty host sections
-    for item in items:
-	name = item[0]
-	rest = item[1].split()
-	if len(rest) == 0:
-		config.set('hosts', name, '_')
-	#updates 'items' list
-    items = config.items('hosts')
+    items = config.items('nodes')
 
-	#makes a second-pass read to hosts section to properly add hosts
+        #makes a first-pass read to hosts section to find empty host sections
+    for item in items:
+        name = item[0]
+        rest = item[1].split()
+        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]
@@ -51,66 +62,27 @@
         app = rest.pop(0)
 
         uris = rest
-        uri_list=[]
+        params = {}
         cpu = None
         cores = None
-	cache = 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("cache",uri):
+                cache = uri.split('=')[1]
+            elif re.match("mem",uri):
+                mem = uri.split('=')[1]
             else:
-                uri_list.append((uri.split(',')[0],uri.split(',')[1]))
+                params[uri.split('=')[0]] = uri.split('=')[1]
 
-        hosts.append(confCCNHost(name , app, uri_list,cpu,cores,cache))
+        hosts.append(confNDNHost(name, app, params, cpu, cores, cache))
 
     return hosts
 
-def parse_routers(conf_arq):
-    'Parse routers section from the conf file.'
-    config = ConfigParser.RawConfigParser()
-    config.read(conf_arq)
-
-    routers = []
-
-    items = config.items('routers')
-
-    for item in items:
-        name = item[0]
-
-        rest = item[1].split()
-
-        uris = rest
-        uri_list=[]
-        cpu = None
-        cores = None
-	cache = None
-
-	if '_' in uris:
-		pass
-	else:
-		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]
-		    else:
-			uri_list.append((uri.split(',')[0],uri.split(',')[1]))
-
-        routers.append(confCCNHost(name=name , uri_tuples=uri_list, cpu=cpu, cores=cores))
-
-    return routers
-
 def parse_links(conf_arq):
     'Parse links section from the conf file.'
     arq = open(conf_arq,'r')
@@ -128,10 +100,10 @@
             break
 
         args = line.split()
-	
-	#checks for non-empty line
-	if len(args) == 0:
-		continue
+
+        #checks for non-empty line
+        if len(args) == 0:
+            continue
 
         h1, h2 = args.pop(0).split(':')
 
@@ -147,7 +119,7 @@
                 value = float(value)
             link_dict[key] = value
 
-        links.append(confCCNLink(h1,h2,link_dict))
+        links.append(confNDNLink(h1,h2,link_dict))
 
 
     return links
diff --git a/mininet/net.py b/mininet/net.py
index 2d6bca6..847850b 100644
--- a/mininet/net.py
+++ b/mininet/net.py
@@ -164,7 +164,7 @@
         if topo and build:
             self.build()
 
-    def isCCNhost(self, node):
+    def isNdnhost(self, node):
         if 'fib' in node.params:
             return True
         else:
@@ -260,8 +260,8 @@
         for host in self.hosts:
             info( host.name + ' ' )
             intf = host.defaultIntf()
-            if self.isCCNhost(host):
-                host.configCCN()    
+            if self.isNdnhost(host):
+                host.configNdn()
                 host.configDefault(ip=None,mac=None)         
             elif intf:
                 host.configDefault( defaultRoute=intf )
@@ -315,7 +315,7 @@
             params = topo.linkInfo( srcName, dstName )
             srcPort, dstPort = topo.port( srcName, dstName )
             self.addLink( src, dst, srcPort, dstPort, **params )
-            if self.isCCNhost(src):
+            if self.isNdnhost(src):
                 src.setIP(ipStr(ipParse(self.ccnNetBase) + 1) + '/30', intf=src.name + '-eth' + str(srcPort))
                 dst.setIP(ipStr(ipParse(self.ccnNetBase) + 2) + '/30', intf=dst.name + '-eth' + str(dstPort))
                 self.ccnNetBase=nextCCNnet(self.ccnNetBase)
diff --git a/mininet/node.py b/mininet/node.py
index 8749987..84e0bc6 100644
--- a/mininet/node.py
+++ b/mininet/node.py
@@ -717,153 +717,6 @@
         mountCgroups()
         cls.inited = True
 
-class CCNHost( Host ):
-    "CCNHost is a Host that always runs the ccnd daemon"
-
-    def __init__( self, name, **kwargs ):
-
-
-        Host.__init__( self, name, **kwargs )
-        if not CCNHost.inited:
-            CCNHost.init()
-
-        self.cmd("export CCND_DEBUG=6")
-        self.cmd("export CCND_LOG=./log.{0}".format(self.name))
-	#pdb.set_trace()
-#	print self.params['cache']
-	if self.params['cache'] != None:
-		self.cmd("export CCND_CAP={0}".format(self.params['cache']))
-
-        self.cmd("export CCN_LOCAL_SOCKNAME=/tmp/.sock.ccnx.{0}".format(self.name))
-        self.cmd("ccndstart")
-        self.peerList = {}
-
-    def config( self, fib=None, app=None, cache=None, **params ):
-
-        r = Node.config( self, **params )
-
-        self.setParam( r, 'app', fib=fib )
-        self.setParam( r, 'fib', app=app)
-	self.setParam( r, 'cache', cache=cache )
-
-        return r
-
-    def configCCN(self):
-
-        self.buildPeerIP()
-        self.setFIB()
-
-    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)
-
-
-    def setFIB(self):
-
-        for name in self.params['fib']:
-            if not name:
-                pass
-            else:
-                self.insert_fib(name[0],self.peerList[name[1]])
-
-
-    def insert_fib(self, uri, host):
-        self.cmd('ccndc add {0} tcp {1}'.format(uri,host))
- #	 self.cmd('ccndc add {0} udp {1}'.format(uri,host))
-
-    def terminate( self ):
-        "Stop node."
-        self.cmd('ccndstop')
-        self.cmd('killall -r zebra ospf')
-        Host.terminate(self)
-
-    inited = False
-
-
-    @classmethod
-    def init( cls ):
-        "Initialization for CCNHost class"
-        cls.inited = True
-
-class CPULimitedCCNHost( CPULimitedHost ):
-    '''CPULimitedCCNHost is a Host that always runs the ccnd daemon and extends CPULimitedHost.
-       It should be used when one wants to limit the resources of CCN routers and hosts '''
-
-
-    def __init__( self, name, sched='cfs', **kwargs ):
-
-        CPULimitedHost.__init__( self, name, sched, **kwargs )
-        if not CCNHost.inited:
-            CCNHost.init()
-
-        self.cmd("export CCND_DEBUG=6")
-        self.cmd("export CCND_LOG=./log.{0}".format(self.name))
-        if self.params['cache'] != None:
-                self.cmd("export CCND_CAP={0}".format(self.params['cache']))
-
-	self.cmd("export CCN_LOCAL_SOCKNAME=/tmp/.sock.ccnx.{0}".format(self.name))
-        self.cmd("ccndstart")
-        self.peerList = {}
-
-    def config( self, fib=None, app=None, cpu=None, cores=None, cache=None, **params):
-
-        r = CPULimitedHost.config(self,cpu,cores, **params)
-
-        self.setParam( r, 'app', fib=fib )
-        self.setParam( r, 'fib', app=app)
-	self.setParam( r, 'cache', cache=cache)
-
-        return r
-
-    def configCCN(self):
-
-        self.buildPeerIP()
-        self.setFIB()
-
-    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)
-
-
-    def setFIB(self):
-
-        for name in self.params['fib']:
-            if not name:
-                pass
-            else:
-                self.insert_fib(name[0],self.peerList[name[1]])
-
-
-    def insert_fib(self, uri, host):
-        self.cmd('ccndc add {0} tcp {1}'.format(uri,host))
-#	self.cmd('ccndc add {0} udp {1}'.format(uri,host))
-
-    def terminate( self ):
-        "Stop node."
-        self.cmd('ccndstop')
-        self.cmd('killall -r zebra ospf')
-        Host.terminate(self)
-
-    inited = False
-
-
-    @classmethod
-    def init( cls ):
-        "Initialization for CCNHost class"
-        cls.inited = True
-
 # Some important things to note:
 #
 # The "IP" address which setIP() assigns to the switch is not
diff --git a/ndn/__init__.py b/ndn/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ndn/__init__.py
diff --git a/ndn/ndn_host.py b/ndn/ndn_host.py
new file mode 100644
index 0000000..427aced
--- /dev/null
+++ b/ndn/ndn_host.py
@@ -0,0 +1,84 @@
+from mininet.node import CPULimitedHost, Host, Node
+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()
+
+        self.nfd = Nfd(self)
+        self.nfd.start()
+
+        self.peerList = {}
+
+    def config(self, fib=None, app=None, cache=None, **params):
+
+        r = Node.config(self, **params)
+
+        self.setParam(r, 'app', fib=fib)   # why is this not app=app, to be investigated
+        self.setParam(r, 'fib', app=app)   # and this fib=fib
+        self.setParam(r, 'cache', cache=cache)
+
+        return r
+
+    def terminate(self):
+        "Stop node."
+        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()
+
+        self.nfd = Nfd(self)
+        self.nfd.start()
+
+        self.peerList = {}
+
+    def config(self, fib=None, app=None, cpu=None, cores=None, cache=None, **params):
+
+        r = CPULimitedHost.config(self,cpu,cores, **params)
+
+        self.setParam(r, 'app', fib=fib)   #????? shoud it be app=app
+        self.setParam(r, 'fib', app=app)
+        self.setParam(r, 'cache', cache=cache)
+
+        return r
+
+    def terminate(self):
+        "Stop node."
+        self.nfd.stop()
+        Host.terminate(self)
diff --git a/ndn/nfd.py b/ndn/nfd.py
new file mode 100644
index 0000000..8ee9423
--- /dev/null
+++ b/ndn/nfd.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+
+import time
+from os.path import expanduser
+
+class Nfd:
+    def __init__(self, node):
+        self.node = node
+        self.isRunning = False
+
+        # Create home directory for a node
+        node.cmd("cd /tmp && mkdir %s" % node.name)
+        node.cmd("cd %s" % node.name)
+
+        self.homeFolder = "/tmp/%s" % node.name
+        self.confFile = "%s/%s.conf" % (self.homeFolder, node.name)
+        self.logFile = "%s/%s.log" % (self.homeFolder, node.name)
+        self.sockFile = "/var/run/%s.sock" % node.name
+        self.ndnFolder = "%s/.ndn" % self.homeFolder
+        self.clientConf = "%s/client.conf" % self.ndnFolder
+
+        # Copy file that checks FIB
+        node.cmd("sudo cp ~/mn-ndn/ndn_utils/checkFIB %s/checkFIB" % self.homeFolder)
+
+        # 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)
+
+        # 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))
+
+        # Make NDN folder
+        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 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 False:
+            self.node.cmd("sudo nfd --config %s 2>> %s &" % (self.confFile, self.logFile))
+            self.processId = self.node.cmd("echo $!")[:-1]
+
+            time.sleep(2)
+
+            self.isRunning = True
+
+    def stop(self):
+        if self.isRunning is True:
+            self.node.cmd("sudo kill %s" % self.processId)
+
+        self.isRunning = False
+
+    def setStrategy(self, name, strategy):
+        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
new file mode 100644
index 0000000..de9ec86
--- /dev/null
+++ b/ndn/nlsr.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python
+
+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
+
+        # Make directory for log file
+        self.logDir = "/tmp/%s/log" % node.name
+        node.cmd("mkdir %s" % self.logDir)
+
+        # Configure basic router information in nlsr.conf based on host name
+        node.cmd("sudo sed -i 's|router .*|router %s|g' %s" % (self.routerName, self.confFile))
+        node.cmd("sudo sed -i 's|log-dir .*|log-dir %s|g' %s" % (self.logDir, self.confFile))
+        node.cmd("sudo sed -i 's|seq-dir .*|seq-dir %s|g' %s" % (self.logDir, self.confFile))
+        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")
+
+
+class NlsrConfigGenerator:
+
+    ROUTING_LINK_STATE = "ls"
+    ROUTING_HYPERBOLIC = "hr"
+
+    def __init__(self, node, home):
+        node.cmd("sudo cp %s/mn-ndn/ndn_utils/nlsr.conf nlsr.conf" % home)
+        self.node = node
+
+        parameters = node.nlsrParameters
+
+        self.nFaces = parameters.get("max-faces-per-prefix", 3)
+        self.hyperbolicState = parameters.get("hyperbolic-state", "off")
+        self.hyperRadius = parameters.get("radius", 0.0)
+        self.hyperAngle = parameters.get("angle", 0.0)
+
+    def createConfigFile(self):
+
+        filePath = "/tmp/%s/nlsr.conf" % self.node.name
+
+        configFile = open(filePath, 'r')
+        oldContent = configFile.read()
+        configFile.close()
+
+        newContent = oldContent.replace("$GENERAL_SECTION", self.__getGeneralSection())
+        newContent = newContent.replace("$NEIGHBORS_SECTION", self.__getNeighborsSection())
+        newContent = newContent.replace("$HYPERBOLIC_SECTION", self.__getHyperbolicSection())
+        newContent = newContent.replace("$FIB_SECTION", self.__getFibSection())
+        newContent = newContent.replace("$ADVERTISING_SECTION", self.__getAdvertisingSection())
+
+        configFile = open(filePath, 'w')
+        configFile.write(newContent)
+        configFile.close()
+
+    def __getConfig(self):
+
+        config =  self.__getGeneralSection()
+        config += self.__getNeighborsSection()
+        config += self.__getHyperbolicSection()
+        config += self.__getFibSection()
+        config += self.__getAdvertisingSection()
+        config += self.__getSecuritySection()
+
+        return config
+
+    def __getGeneralSection(self):
+
+        general =  "general\n"
+        general += "{\n"
+        general += "  network /ndn/\n"
+        general += "  site /edu\n"
+        general += "  router /%C1.Router/cs/" + self.node.name + "\n"
+        general += "  log-level DEBUG\n"
+        general += "  log-dir /tmp/" + self.node.name + "/log\n"
+        general += "  seq-dir /tmp/" + self.node.name + "/log\n"
+        general += "}\n"
+
+        return general
+
+    def __getNeighborsSection(self):
+
+        neighbors =  "neighbors\n"
+        neighbors += "{\n"
+
+        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", "0ms").replace("ms", "")
+
+                neighbors += "neighbor\n"
+                neighbors += "{\n"
+                neighbors += "  name /ndn/edu/%C1.Router/cs/" + other.name + "\n"
+                neighbors += "  face-uri udp://" + str(ip) + "\n"
+                neighbors += "  link-cost " + linkCost + "\n"
+                neighbors += "}\n"
+
+        neighbors += "}\n"
+
+        return neighbors
+
+    def __getHyperbolicSection(self):
+
+        hyper =  "hyperbolic\n"
+        hyper += "{\n"
+        hyper += "state %s\n" % self.hyperbolicState
+        hyper += "radius " + str(self.hyperRadius) + "\n"
+        hyper += "angle " + str(self.hyperAngle) + "\n"
+        hyper += "}\n"
+
+        return hyper
+
+    def __getFibSection(self):
+
+        fib =  "fib\n"
+        fib += "{\n"
+        fib += "  max-faces-per-prefix " + str(self.nFaces) + "\n"
+        fib += "}\n"
+
+        return fib
+
+    def __getAdvertisingSection(self):
+
+        advertising =  "advertising\n"
+        advertising += "{\n"
+        advertising += "  prefix /ndn/edu/" + self.node.name + "\n"
+        advertising += "}\n"
+
+        return advertising
+
+    def __getSecuritySection(self):
+
+        security =  "security\n"
+        security += "{\n"
+        security += "  validator\n"
+        security += "  {\n"
+        security += "    trust-anchor\n"
+        security += "    {\n"
+        security += "      type any\n"
+        security += "    }\n"
+        security += "  }\n"
+        security += "}\n"
+
+        return security