Add ndn_utils and modify install script

refs: #2528

Change-Id: I7c26df7c91572f8e48b23ca3cddcec1b8f0216a5
diff --git a/bin/minindn b/bin/minindn
index 51a4c52..7e451aa 100755
--- a/bin/minindn
+++ b/bin/minindn
@@ -13,6 +13,7 @@
 import os.path, time
 import optparse
 import datetime
+from os.path import expanduser
 
 from ndn.nlsr import Nlsr, NlsrConfigGenerator
 
diff --git a/bin/minindnedit b/bin/minindnedit
new file mode 100755
index 0000000..c0ff708
--- /dev/null
+++ b/bin/minindnedit
@@ -0,0 +1,1732 @@
+#!/usr/bin/python
+
+"""
+MiniCCNxEdit: a simple network editor for MiniCCNx
+
+Based on miniedit by:
+Bob Lantz, April 2010
+Gregory Gee, July 2013
+
+Carlos Cabral, Jan 2013
+Caio Elias, Nov 2014
+
+"""
+
+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
+import tkFont
+import csv
+import tkFileDialog
+import tkSimpleDialog
+import re
+import json
+from distutils.version import StrictVersion
+import os
+import sys
+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, customConstructor
+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 'MiniCCNxEdit running...' #+VERSION
+MININET_VERSION = re.sub(r'[^\d\.]', '', VERSION)
+if StrictVersion(MININET_VERSION) > StrictVersion('2.0'):
+    from mininet.node import IVSSwitch
+
+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' ) }
+
+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)
+            self.fibFrame = Frame(n)
+            n.add(self.propFrame, text='Properties')
+            n.add(self.fibFrame, text='FIB Entries')
+            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:").grid(row=5, sticky=E)
+                    self.startEntry = Entry(self.propFrame)
+                    self.startEntry.grid(row=5, column=1, sticky='nswe', columnspan=3)
+                    Label(self.propFrame, text="[full path]").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)
+
+            ### TAB 2
+            # FIB Entries
+            self.fibEntries = 0
+            Label(self.fibFrame, text="FIB Entry:").grid(row=0, column=0, sticky=E)
+            self.fibButton = Button( self.fibFrame, text='Add', command=self.addEntry)
+            self.fibButton.grid(row=0, column=1)
+
+            self.fibFrame = VerticalScrolledTable(self.fibFrame, rows=0, columns=2, title='FIB Entries')
+            self.fibFrame.grid(row=1, column=0, sticky='nswe', columnspan=2)
+            self.fibTableFrame = self.fibFrame.interior
+            self.fibTableFrame.addRow(value=['Prefix','Next Hop'], readonly=True)
+
+            fibList = []
+            if 'fibEntries' in self.prefValues:
+                fibList = self.prefValues['fibEntries']
+            for fibEntr in fibList:
+                if isinstance( fibEntr, tuple ):
+                    self.fibTableFrame.addRow(value=fibEntr)
+                else:
+                    self.fibTableFrame.addRow(value=[fibEntr,''])
+
+        def addEntry( self ):
+            self.fibTableFrame.addRow()
+
+        def apply(self):
+            fibEntries = []
+            for row in range(self.fibTableFrame.rows):
+                if (len(self.fibTableFrame.get(row, 0)) > 0 and row > 0):
+                    if(len(self.fibTableFrame.get(row, 1)) > 0):
+                        fibEntries.append((self.fibTableFrame.get(row, 0), self.fibTableFrame.get(row, 1)))
+                    else:
+                        fibEntries.append(self.fibTableFrame.get(row, 0))
+
+            results = {'cpu': self.cpuEntry.get(),
+                       'cache': self.cacheEntry.get(),
+                       'mem': self.memEntry.get(),
+                       'hostname':self.hostnameEntry.get(),
+                       'startCommand':self.startEntry.get(),
+                       'fibEntries':fibEntries}
+            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 MiniCCNx."
+
+    def __init__( self, parent=None, cheight=600, cwidth=1000, template_file='miniccnx.conf' ):
+
+        self.template_file = template_file
+
+        Frame.__init__( self, parent )
+        self.action = None
+        self.appName = 'MiniccnxEdit'
+        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', 'LegacyRouter', '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'}
+        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.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_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-CCNx', 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-CCNx 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-CCNx - 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 parseFibEntries ( self, fibEntries ):
+        "Parse FIB Entries for write"
+        result=''
+
+        for fibEntry in fibEntries:
+                entry = ','.join(map(str, fibEntry))
+                result += entry + ' '
+
+        return result
+
+    def buildTemplate( self ): #COPIA Mini-CCNx para criar Template
+        "Generate template"
+
+        template = open(self.template_file, 'w')
+
+        # hosts
+        template.write('[hosts]\n')
+        for widget in self.widgetToItem:
+            name = widget[ 'text' ]
+            tags = self.canvas.gettags( self.widgetToItem[ widget ] )
+            #print self.hostOpts[name]
+            if 'Host' in tags:
+                hOpts=self.hostOpts[name]
+                template.write(name + ': ')
+                if 'startCommand' in hOpts:
+                        template.write(hOpts['startCommand'] + ' ')
+                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 'fibEntries' in hOpts:
+                        customFib = self.parseFibEntries(hOpts['fibEntries'])
+                        template.write(customFib)
+                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 'fibEntries' in rOpts:
+                customFib = self.parseFibEntries(rOpts['fibEntries'])
+                template.write(customFib)
+                hasOpt='True'
+            if hasOpt == 'False':
+                template.write('_')
+
+            template.write('\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']))
+
+             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 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 = [
+            ('Miniccnx Topology','*.mnccnx'),
+            ('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 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.links = {}
+        self.hostOpts = {}
+        self.routerOpts = {}
+
+    def saveTopology( self ):
+        "Save command."
+        myFormats = [
+            ('Miniccnx Topology','*.mnccnx'),
+            ('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 = []
+
+            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)
+                else:
+                    raise Exception( "Cannot create mystery node: " + name )
+            savingDictionary['hosts'] = hostsToSave
+            savingDictionary['routers'] = routersToSave
+
+            # 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
+
+        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 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 MiniCCNx - based on Miniedit'
+            warning = 'Development version - not entirely functional!'
+            #version = 'MiniEdit '+MINIEDIT_VERSION
+            author = 'Carlos Cabral, Jan 2013'
+            author2 = 'Caio Elias, Nov 2014'
+            author3 = '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=enhancements, font='Helvetica 9', bg=bg )
+            line7 = Entry( about, font='Helvetica 9', bg=bg, width=len(www), justify=CENTER )
+
+            line7.insert(0, www)
+            line7.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 )
+            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']
+                    if len(hostBox.result['fibEntries']) > 0:
+                        newHostOpts['fibEntries'] = hostBox.result['fibEntries']
+                    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']
+                    if len(hostBox.result['fibEntries']) > 0:
+                        newRouterOpts['fibEntries'] = hostBox.result['fibEntries']
+                    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 Miniccnx network from the\n"
+                 "command line. It can create parametrized topologies,\n"
+                 "invoke the Miniccnx CLI, and run tests." )
+
+        usage = ( '%prog [options] [template_file]\n'
+                  '\nIf no template_file is given, generated template will be written to the file miniccnx.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=
+        """ ),
+
+        '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/ccn_utils/generate_linear.py b/ccn_utils/generate_linear.py
deleted file mode 100644
index fbafe1c..0000000
--- a/ccn_utils/generate_linear.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/python
-
-import optparse
-
-def parse_args():
-    usage="""Usage: generate_linear num_nodes [template_file] [delay]
-    Generates template_file with a linear topology with num_nodes and 
-    delay in the links (10ms, 100ms, etc).If no template_file is given,
-    will write to default file miniccnx.conf in the current directory. 
-    """
-
-    parser = optparse.OptionParser(usage)
-
-    _, arg = parser.parse_args()
-    
-    if len(arg) > 3:
-        print parser.usage
-        quit()
-    elif len(arg) == 0:
-        print parser.usage
-        quit()
-    elif len(arg) == 1:
-        num_nodes = int(parser.parse_args()[1][0])
-        temp_file = ''
-        delay = ''
-    elif len(arg) == 2:
-        num_nodes, delay = int(parser.parse_args()[1][0]), parser.parse_args()[1][1]
-        temp_file = ''
-    else:
-        print parser.parse_args()
-        num_nodes,temp_file, delay = int(parser.parse_args()[1][0]), parser.parse_args()[1][1],parser.parse_args()[1][2]
-    
-    return num_nodes, temp_file, delay
-
-if __name__ == '__main__':
-    
-    n_nodes, t_file, delay = parse_args()
-    
-    if t_file == '':
-        t_file = 'miniccnx.conf'
-        
-    temp_file = open(t_file,'w')
-    
-    temp_file.write('[hosts]\n')
-
-    temp_file.write('[routers]\n')
-    
-    for i in range(n_nodes):
-        if i == (n_nodes - 1):
-            temp_file.write('s' + str(i) + ':\n')
-        else:
-            temp_file.write('s' + str(i) + ': ccnx:/,s' + str(i+1) + '\n')
-        
-    temp_file.write('[links]\n')
-        
-    for i in range(n_nodes-1):
-        peer = i + 1
-        if delay == '':
-            temp_file.write('s' + str(i) + ':s' + str(peer) + '\n')
-        else:
-            temp_file.write('s' + str(i) + ':s' + str(peer) + ' delay=' + delay +'\n')
-            
-    temp_file.close()
diff --git a/ccn_utils/generate_mesh.py b/ccn_utils/generate_mesh.py
deleted file mode 100644
index e150e66..0000000
--- a/ccn_utils/generate_mesh.py
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/usr/bin/python
-
-import optparse
-
-def parse_args():
-    usage="""Usage: generate_mesh num_nodes [template_file]
-    Generates template_file with a full mesh topology with num_nodes
-    If no template_file is given, will write to default 
-    file miniccnx.conf in the current directory.
-    """
-
-    parser = optparse.OptionParser(usage)
-
-    _, arg = parser.parse_args()
-    
-    if len(arg) > 2:
-        print parser.usage
-        quit()
-    elif len(arg) == 0:
-        print parser.usage
-        quit()
-    elif len(arg) == 1:
-        num_nodes = int(parser.parse_args()[1][0])
-        temp_file = ''
-    else:
-        print parser.parse_args()
-        num_nodes,temp_file = int(parser.parse_args()[1][0]), parser.parse_args()[1][1]
-    
-    return num_nodes, temp_file
-
-if __name__ == '__main__':
-    
-    n_nodes, t_file = parse_args()
-    
-    if t_file == '':
-        t_file = 'miniccnx.conf'
-        
-    temp_file = open(t_file,'w')
-    
-    temp_file.write('[hosts]\n')
-
-    temp_file.write('[routers]\n')
-    
-    for i in range(n_nodes):
-        temp_file.write('s' + str(i) + ':\n')
-        
-    temp_file.write('[links]\n')
-        
-    for i in range(n_nodes):
-        peer = i + 1
-        for j in range(peer,n_nodes):
-            temp_file.write('s' + str(i) + ':s' + str(j) + '\n')
-            
-    temp_file.close()
-            
-        
-    
\ No newline at end of file
diff --git a/ccn_utils/miniccnx.conf b/ccn_utils/miniccnx.conf
deleted file mode 100644
index 42f827e..0000000
--- a/ccn_utils/miniccnx.conf
+++ /dev/null
@@ -1,8 +0,0 @@
-[hosts]
-h1: _ ccnx:/,s1
-h2: _ cpu=0.1
-[routers]
-s1: ccnx:/videos,h2
-[links]
-h1:s1 bw=100
-h2:s1 bw=100 loss=1 delay=10ms
diff --git a/ccn_utils/miniccnx.conf_16 b/ccn_utils/miniccnx.conf_16
deleted file mode 100644
index 89a274f..0000000
--- a/ccn_utils/miniccnx.conf_16
+++ /dev/null
@@ -1,68 +0,0 @@
-[hosts]
-c1: _ ccnx:/,s1
-c2: _ ccnx:/,s1
-c3: _ ccnx:/,s1
-c4: _ ccnx:/,s1
-c5: _ ccnx:/,s1
-c6: _ ccnx:/,s1
-c7: _ ccnx:/,s1
-c8: _ ccnx:/,s1
-c9: _ ccnx:/,s1
-c10: _ ccnx:/,s1
-c11: _ ccnx:/,s1
-c12: _ ccnx:/,s1
-c13: _ ccnx:/,s1
-c14: _ ccnx:/,s1
-c15: _ ccnx:/,s1
-c16: _ ccnx:/,s1
-h1: _ 
-h2: _
-h3: _
-h4: _
-h5: _
-h6: _
-h7: _
-h8: _
-h9: _
-h10: _
-h11: _
-h12: _
-h13: _
-h14: _
-h15: _
-h16: _
-[routers]
-s1: ccnx:/s/1,h1 ccnx:/s/2,h2 ccnx:/s/3,h3 ccnx:/s/4,h4 ccnx:/s/5,h5 ccnx:/s/6,h6 ccnx:/s/7,h7 ccnx:/s/8,h8 ccnx:/s/9,h9 ccnx:/s/10,h10 ccnx:/s/11,h11 ccnx:/s/12,h12 ccnx:/s/13,h13 ccnx:/s/14,h14 ccnx:/s/15,h15 ccnx:/s/16,h16
-[links]
-c1:s1
-c2:s1
-c3:s1
-c4:s1
-c5:s1
-c6:s1
-c7:s1
-c8:s1
-c9:s1
-c10:s1
-c11:s1
-c12:s1
-c13:s1
-c14:s1
-c15:s1
-c16:s1
-s1:h1
-s1:h2
-s1:h3
-s1:h4
-s1:h5
-s1:h6
-s1:h7
-s1:h8
-s1:h9
-s1:h10
-s1:h11
-s1:h12
-s1:h13
-s1:h14
-s1:h15
-s1:h16
diff --git a/ccn_utils/miniccnx.conf_2hops b/ccn_utils/miniccnx.conf_2hops
deleted file mode 100644
index acbd30e..0000000
--- a/ccn_utils/miniccnx.conf_2hops
+++ /dev/null
@@ -1,40 +0,0 @@
-[hosts]
-h1: _ ccnx:/,s1
-h2: _ ccnx:/,s1
-h3: _ ccnx:/,s1
-h4: _ ccnx:/,s1
-h5: _ ccnx:/,s1
-h6: _ ccnx:/,s1
-h7: _ ccnx:/,s1
-h8: _ ccnx:/,s1
-r1: _
-r2: _
-r3: _ 
-r4: _
-r5: _
-r6: _
-r7: _
-r8: _
-[routers]
-s1: ccnx:/,s2
-s2: ccnx:/,s3
-s3: ccnx:/s/1,r1 ccnx:/s/2,r2 ccnx:/s/3,r3 ccnx:/s/4,r4 ccnx:/s/5,r5 ccnx:/s/6,r6 ccnx:/s/7,r7 ccnx:/s/8,r8
-[links]
-h1:s1
-h2:s1
-h3:s1
-h4:s1
-h5:s1
-h6:s1
-h7:s1
-h8:s1
-s1:s2
-s2:s3
-r1:s3
-r2:s3
-r3:s3
-r4:s3
-r5:s3
-r6:s3
-r7:s3
-r8:s3
diff --git a/ccn_utils/miniccnx.conf_bkp b/ccn_utils/miniccnx.conf_bkp
deleted file mode 100644
index 4a74752..0000000
--- a/ccn_utils/miniccnx.conf_bkp
+++ /dev/null
@@ -1,20 +0,0 @@
-[hosts]
-h7: ./h7.sh ccnx:/,s5
-h9: _ ccnx:/,s3
-h6: ./h6.sh ccnx:/,s4
-h8: _ ccnx:/,s2
-[routers]
-s2: ccnx:/music,s1
-s3: ccnx:/music,s1
-s5: ccnx:/music/moveis,h7
-s4: ccnx:/music/skank,h6
-s1: ccnx:/music/skank,s4 ccnx:/music/moveis,s5
-[links]
-h6:s4
-s4:s1
-s1:s5
-s5:h7
-s1:s3
-s3:h9
-s1:s2
-s2:h8
diff --git a/ccn_utils/miniccnx.conf_bkp2 b/ccn_utils/miniccnx.conf_bkp2
deleted file mode 100644
index 0b8c19f..0000000
--- a/ccn_utils/miniccnx.conf_bkp2
+++ /dev/null
@@ -1,20 +0,0 @@
-[hosts]
-h7: ./h7.sh ccnx:/,s5
-h9: _ ccnx:/,s3
-h6: ./h6.sh ccnx:/,s4
-h8: _ ccnx:/,s2
-[routers]
-s2: ccnx:/music,s1
-s3: ccnx:/music,s1
-s5: ccnx:/music/moveis,h7
-s4: ccnx:/music/skank,h6
-s1: ccnx:/music/skank,s4 ccnx:/music/moveis,s5
-[links]
-h6:s4 bw=1
-s4:s1 bw=1
-s1:s5 bw=1000
-s5:h7 bw=1000 loss=50
-s1:s3 bw=1
-s3:h9 bw=1
-s1:s2 bw=1
-s2:h8 bw=1
diff --git a/ccn_utils/miniccnx.conf_bkp3 b/ccn_utils/miniccnx.conf_bkp3
deleted file mode 100644
index ee827c9..0000000
--- a/ccn_utils/miniccnx.conf_bkp3
+++ /dev/null
@@ -1,18 +0,0 @@
-[hosts]
-h7: _ ccnx:/,s2
-h4: _ ccnx:/,s3
-h6: _ ccnx:/,s1
-h8: _ ccnx:/,s2
-h5: _ ccnx:/,s1
-[routers]
-s3: ccnx:/music,s1 ccnx:/video,s2
-s1: ccnx:/,s3 ccnx:/music,h5
-s2: ccnx:/,s3 ccnx:/video,h7
-[links]
-h5:s1 bw=1000 
-h6:s1 bw=1000
-s2:h7 bw=1000
-s2:h8 bw=1000
-s1:s3 bw=1000 
-s2:s3 bw=1000 
-h4:s3 bw=1000
diff --git a/ccn_utils/miniccnx.conf_bw_3 b/ccn_utils/miniccnx.conf_bw_3
deleted file mode 100644
index f317008..0000000
--- a/ccn_utils/miniccnx.conf_bw_3
+++ /dev/null
@@ -1,16 +0,0 @@
-[hosts]
-c1: _ ccnx:/,s1
-c2: _ ccnx:/,s1
-c3: _ ccnx:/,s1
-h1: _
-h2: _
-h3: _ 
-[routers]
-s1: ccnx:/1,h1 ccnx:/2,h2 ccnx:/3,h3
-[links]
-c1:s1
-c2:s1
-c3:s1
-s1:h1
-s1:h2
-s1:h3
diff --git a/mininet/cli.py b/mininet/cli.py
index e2c7099..db03787 100644
--- a/mininet/cli.py
+++ b/mininet/cli.py
@@ -35,12 +35,11 @@
 from mininet.log import info, output, error
 from mininet.term import makeTerms
 from mininet.util import quietRun, isShellBuiltin, dumpNodeConnections
-from mininet.node import CCNHost
 
 class CLI( Cmd ):
     "Simple command-line interface to talk to nodes."
 
-    prompt = 'miniccnx> '
+    prompt = 'minindn> '
 
     def __init__( self, mininet, stdin=sys.stdin, script=None ):
         self.mn = mininet
diff --git a/ndn/nfd.py b/ndn/nfd.py
index 8ee9423..614a358 100644
--- a/ndn/nfd.py
+++ b/ndn/nfd.py
@@ -1,7 +1,6 @@
 #!/usr/bin/env python
 
 import time
-from os.path import expanduser
 
 class Nfd:
     def __init__(self, node):
@@ -19,9 +18,6 @@
         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)
 
diff --git a/ndn_utils/client.conf.sample b/ndn_utils/client.conf.sample
new file mode 100644
index 0000000..d911623
--- /dev/null
+++ b/ndn_utils/client.conf.sample
@@ -0,0 +1,33 @@
+; "transport" specifies Face's default transport connection.
+; The value is a unix or tcp4 scheme Face URI.
+;
+; For example:
+;
+;   unix:///var/run/nfd.sock
+;   tcp://192.0.2.1
+;   tcp4://example.com:6363
+
+transport=unix:///var/run/nfd.sock
+
+; "protocol" determines the protocol for prefix registration
+; it has a value of:
+;   nfd-0.1
+;   nrd-0.1
+;   ndnd-tlv-0.7
+;   ndnx-0.7
+protocol=nrd-0.1
+
+; "pib" determines which Public Info Base (PIB) should used by default in applications.
+; If "pib" is not specified, the default PIB will be used.
+; Note that default PIB could be different on different system.
+; If "pib" is specified, it may have a value of:
+;   sqlite3
+; pib=sqlite3
+
+; "tpm" determines which Trusted Platform Module (TPM) should used by default in applications.
+; If "tpm" is not specified, the default TPM will be used.
+; Note that default TPM could be different on different system.
+; If "tpm" is specified, it may have a value of:
+;   file
+;   osx-keychain
+; tpm=file
\ No newline at end of file
diff --git a/ndn_utils/hyperbolic_conf_file/minindn.caida.conf b/ndn_utils/hyperbolic_conf_file/minindn.caida.conf
new file mode 100644
index 0000000..ab243e1
--- /dev/null
+++ b/ndn_utils/hyperbolic_conf_file/minindn.caida.conf
@@ -0,0 +1,36 @@
+[nodes]
+ucla: _ radius=16.586643 angle=2.999108
+pku: _ radius=11.149566 angle=2.870147
+csu: _ radius=14.105693 angle=2.992666
+caida: _ radius=17.603044 angle=2.943027
+arizona: _ radius=16.230539 angle=2.970333
+uiuc: _ radius=29.255355 angle=2.982312
+wustl: _ radius=19.426849 angle=4.310672
+umich: _ radius=17.773804 angle=2.980183
+neu: _ radius=19.900128 angle=2.138942
+memphis: _ radius=15.264774 angle=2.983607
+[links]
+ucla:csu delay=16ms
+ucla:pku delay=79ms
+ucla:memphis delay=39ms
+pku:csu delay=104ms
+pku:umich delay=110ms
+pku:neu delay=115ms
+pku:memphis delay=99ms
+pku:wustl delay=109ms
+pku:arizona delay=82ms
+pku:caida delay=78ms
+csu:uiuc delay=14ms
+csu:umich delay=15ms
+csu:wustl delay=19ms
+csu:memphis delay=21ms
+csu:neu delay=25ms
+csu:caida delay=18ms
+csu:arizona delay=18ms
+wustl:memphis delay=16ms
+uiuc:umich delay=6ms
+uiuc:memphis delay=10ms
+arizona:memphis delay=33ms
+memphis:neu delay=20ms
+memphis:umich delay=12ms
+memphis:caida delay=40ms
diff --git a/ndn_utils/hyperbolic_conf_file/minindn.tesbed.conf b/ndn_utils/hyperbolic_conf_file/minindn.tesbed.conf
new file mode 100644
index 0000000..9fc0bbc
--- /dev/null
+++ b/ndn_utils/hyperbolic_conf_file/minindn.tesbed.conf
@@ -0,0 +1,74 @@
+[nodes]
+unibas: _ radius=13.2717666496574 angle=2.41932700603969 cpu=10
+bupt: _ radius=11.5095245566676 angle=2.87230371009491 cpu=10
+pku: _ radius=11.1495655496376 angle=2.87014667817084 cpu=10
+tongji: _ radius=11.1495655496376 angle=2.8701500000 cpu=10
+orange: _ radius=10.9327229663161 angle=2.7739430543572 cpu=10
+arizona: _ radius=16.2305391313912 angle=2.97033285094067 cpu=10
+byu: _ radius=19.353845431776 angle=3.77334112452928 cpu=10
+csu: _ radius=14.1056931988398 angle=2.99266609145815 cpu=10
+uiuc: _ radius=29.2553552716 angle=2.98231233822261 cpu=10
+memphis: _ radius=15.2647735129845 angle=2.98360655737705 cpu=10
+neu: _ radius=19.9001283692128 angle=2.13894230769231 cpu=10
+uci: _ radius=19.2697694366069 angle=2.94186046511628 cpu=10
+ucla: _ radius=16.5866430024476 angle=2.99910767400357 cpu=10
+remap: _ radius=16.5866430024476 angle=2.9991100000 cpu=10
+umich: _ radius=17.7738038607456 angle=2.98018269081901 cpu=10
+wustl: _ radius=19.426848571939 angle=4.31067173953721 cpu=10
+urjc: _ radius=13.6888312671789 angle=1.17169974115617 cpu=10
+systemx: _ radius=19.1697680538273 angle=2.62274588691716 cpu=10
+lip6: _ radius=29.2553552716 angle=2.62295081967213 cpu=10
+waseda: _ radius=19.3583257471934 angle=2.99935233160622 cpu=10
+anyang: _ radius=14.3378634978013 angle=2.99956859361519 cpu=10
+caida: _ radius=17.6030443241278 angle=2.94302721088435 cpu=10
+[links]
+bupt:pku delay=14ms
+pku:unibas delay=127ms
+pku:tongji delay=14ms
+bupt:anyang delay=33ms
+bupt:tongji delay=18ms
+anyang:tongji delay=54ms
+bupt:waseda delay=48ms
+tongji:waseda delay=98ms
+tongji:caida delay=93ms
+caida:ucla delay=3ms
+anyang:pku delay=38ms
+anyang:waseda delay=22ms
+ucla:pku delay=85ms
+ucla:remap delay=1ms
+caida:uci delay=3ms
+uci:ucla delay=1ms
+uci:remap delay=1ms
+ucla:csu delay=16ms
+remap:csu delay=16ms
+caida:arizona delay=25ms
+waseda:arizona delay=75ms
+remap:arizona delay=25ms
+arizona:wustl delay=33ms
+wustl:uiuc delay=9ms
+csu:uiuc delay=14ms
+uiuc:umich delay=5ms
+csu:byu delay=8ms
+byu:remap delay=9ms
+byu:arizona delay=30ms
+wustl:urjc delay=86ms
+wustl:memphis delay=17ms
+arizona:memphis delay=17ms
+waseda:orange delay=144ms
+orange:systemx delay=2ms
+unibas:systemx delay=10ms
+memphis:neu delay=21ms
+pku:neu delay=112ms
+csu:umich delay=15ms
+urjc:lip6 delay=15ms
+urjc:unibas delay=9ms
+lip6:systemx delay=2ms
+unibas:lip6 delay=18ms
+memphis:umich delay=12ms
+memphis:orange delay=56ms
+urjc:orange delay=15ms
+lip6:orange delay=3ms
+lip6:umich delay=69ms
+unibas:orange delay=18ms
+umich:neu delay=14ms
+csu:arizona delay=18ms
diff --git a/ndn_utils/hyperbolic_conf_file/minindn.ucla.conf b/ndn_utils/hyperbolic_conf_file/minindn.ucla.conf
new file mode 100644
index 0000000..5cdbaf5
--- /dev/null
+++ b/ndn_utils/hyperbolic_conf_file/minindn.ucla.conf
@@ -0,0 +1,35 @@
+[nodes]
+ucla: _ radius=20.700007 angle=2.051234 cpu=5
+pku: _ radius=19.320956 angle=2.011893 cpu=5
+csu: _ radius=18.725071 angle=2.054556 cpu=5
+caida: _ radius=17.334066 angle=1.920136 cpu=5
+arizona: _ radius=21.038109 angle=5.203340 cpu=5
+uiuc: _ radius=21.247178 angle=2.038117 cpu=5
+wustl: _ radius=19.994570 angle=2.035105 cpu=5
+umich: _ radius=19.548038 angle=2.037021 cpu=5
+neu: _ radius=18.335813 angle=2.106513 cpu=5
+memphis: _ radius=17.389593 angle=1.925628 cpu=5
+[links]
+ucla:csu delay=16ms bw=1000
+ucla:umich delay=33ms bw=1000
+ucla:wustl delay=38ms bw=1000
+pku:csu delay=104ms bw=1000
+pku:caida delay=78ms bw=1000
+pku:wustl delay=109ms bw=1000
+pku:memphis delay=99ms bw=1000
+pku:umich delay=110ms bw=1000
+csu:caida delay=18ms bw=1000
+csu:wustl delay=19ms bw=1000
+csu:memphis delay=21ms bw=1000
+csu:uiuc delay=14ms bw=1000
+csu:umich delay=15ms bw=1000
+csu:neu delay=25ms bw=1000
+caida:neu delay=42ms bw=1000
+caida:arizona delay=25ms bw=1000
+caida:memphis delay=40ms bw=1000
+wustl:uiuc delay=9ms bw=1000
+wustl:umich delay=11ms bw=1000
+uiuc:umich delay=6ms bw=1000
+arizona:neu delay=35ms bw=1000
+arizona:memphis delay=33ms bw=1000
+memphis:neu delay=20ms bw=1000
diff --git a/ndn_utils/nfd.conf b/ndn_utils/nfd.conf
new file mode 100644
index 0000000..ffb1f5c
--- /dev/null
+++ b/ndn_utils/nfd.conf
@@ -0,0 +1,269 @@
+; The general section contains settings of nfd process.
+general
+{
+  ; Specify a user and/or group for NFD to drop privileges to
+  ; when not performing privileged tasks. NFD does not drop
+  ; privileges by default.
+
+  ; user ndn-user
+  ; group ndn-user
+}
+
+log
+{
+  ; default_level specifies the logging level for modules
+  ; that are not explicitly named. All debugging levels
+  ; listed above the selected value are enabled.
+  ;
+  ; Valid values:
+  ;
+  ;  NONE ; no messages
+  ;  ERROR ; error messages
+  ;  WARN ; warning messages
+  ;  INFO ; informational messages (default)
+  ;  DEBUG ; debugging messages
+  ;  TRACE ; trace messages (most verbose)
+  ;  ALL ; all messages
+
+  default_level NONE
+
+  ; You may override default_level by assigning a logging level
+  ; to the desired module name. Module names can be found in two ways:
+  ;
+  ; Run:
+  ;   nfd --modules
+  ;   nrd --modules
+  ;
+  ; Or look for NFD_LOG_INIT(<module name>) statements in .cpp files
+  ;
+  ; Example module-level settings:
+  ;
+  ; FibManager DEBUG
+  ; Forwarder INFO
+}
+
+; The tables section configures the CS, PIT, FIB, Strategy Choice, and Measurements
+tables
+{
+
+  ; ContentStore size limit in number of packets
+  ; default is 65536, about 500MB with 8KB packet size
+  cs_max_packets 65536
+
+  ; Set the forwarding strategy for the specified prefixes:
+  ;   <prefix> <strategy>
+  strategy_choice
+  {
+    /               /localhost/nfd/strategy/best-route
+    /localhost      /localhost/nfd/strategy/broadcast
+    /localhost/nfd  /localhost/nfd/strategy/best-route
+    /ndn/broadcast  /localhost/nfd/strategy/broadcast
+  }
+}
+
+; The face_system section defines what faces and channels are created.
+face_system
+{
+  ; The unix section contains settings of Unix stream faces and channels.
+  ; Unix channel is always listening; delete unix section to disable
+  ; Unix stream faces and channels.
+  unix
+  {
+    path /var/run/nfd.sock ; Unix stream listener path
+  }
+
+  ; The tcp section contains settings of TCP faces and channels.
+  tcp
+  {
+    listen yes ; set to 'no' to disable TCP listener, default 'yes'
+    port 6363 ; TCP listener port number
+    enable_v4 yes ; set to 'no' to disable IPv4 channels, default 'yes'
+    enable_v6 yes ; set to 'no' to disable IPv6 channels, default 'yes'
+  }
+
+  ; The udp section contains settings of UDP faces and channels.
+  ; UDP channel is always listening; delete udp section to disable UDP
+  udp
+  {
+    port 6363 ; UDP unicast port number
+    enable_v4 yes ; set to 'no' to disable IPv4 channels, default 'yes'
+    enable_v6 yes ; set to 'no' to disable IPv6 channels, default 'yes'
+    idle_timeout 600 ; idle time (seconds) before closing a UDP unicast face
+    keep_alive_interval 25; interval (seconds) between keep-alive refreshes
+
+    ; UDP multicast settings
+    ; NFD creates one UDP multicast face per NIC
+    ;
+    ; In multi-homed Linux machines these settings will NOT work without
+    ; root or settings the appropriate permissions:
+    ;
+    ;    sudo setcap cap_net_raw=eip /full/path/nfd
+    ;
+    mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
+    mcast_port 56363 ; UDP multicast port number
+    mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
+  }
+}
+
+; The authorizations section grants privileges to authorized keys.
+authorizations
+{
+  ; An authorize section grants privileges to a NDN certificate.
+  authorize
+  {
+    ; If you do not already have NDN certificate, you can generate
+    ; one with the following commands.
+    ;
+    ; 1. Generate and install a self-signed identity certificate:
+    ;
+    ;      ndnsec-keygen /`whoami` | ndnsec-install-cert -
+    ;
+    ; Note that the argument to ndnsec-key will be the identity name of the
+    ; new key (in this case, /your-username). Identities are hierarchical NDN
+    ; names and may have multiple components (e.g. `/ndn/ucla/edu/alice`).
+    ; You may create additional keys and identities as you see fit.
+    ;
+    ; 2. Dump the NDN certificate to a file:
+    ;
+    ;      sudo mkdir -p @SYSCONFDIR@/ndn/keys/
+    ;      ndnsec-cert-dump -i /`whoami` >  default.ndncert
+    ;      sudo mv default.ndncert @SYSCONFDIR@/ndn/keys/default.ndncert
+    ;
+    ; The "certfile" field below specifies the default key directory for
+    ; your machine. You may move your newly created key to the location it
+    ; specifies or path.
+
+    ; certfile keys/default.ndncert ; NDN identity certificate file
+    certfile any ; "any" authorizes command interests signed under any certificate,
+                 ; i.e., no actual validation.
+    privileges ; set of privileges granted to this identity
+    {
+      faces
+      fib
+      strategy-choice
+    }
+  }
+
+  ; You may have multiple authorize sections that specify additional
+  ; certificates and their privileges.
+
+  ; authorize
+  ; {
+  ;   certfile keys/this_cert_does_not_exist.ndncert
+  ;   authorize
+  ;   privileges
+  ;   {
+  ;     faces
+  ;   }
+  ; }
+}
+
+rib
+{
+  ; The following localhost_security allows anyone to register routing entries in local RIB
+  localhost_security
+  {
+    trust-anchor
+    {
+      type any
+    }
+  }
+
+  ; localhop_security should be enabled when NFD runs on a hub.
+  ; "/localhop/nfd/fib" command prefix will be disabled when localhop_security section is missing.
+  ; localhop_security
+  ; {
+  ;   ; This section defines the trust model for NFD RIB Management. It consists of rules and
+  ;   ; trust-anchors, which are briefly defined in this file.  For more information refer to
+  ;   ; manpage of ndn-validator.conf:
+  ;   ;
+  ;   ;     man ndn-validator.conf
+  ;   ;
+  ;   ; A trust-anchor is a pre-trusted certificate.  This can be any certificate that is the
+  ;   ; root of certification chain (e.g., NDN testbed root certificate) or an existing
+  ;   ; default system certificate `default.ndncert`.
+  ;   ;
+  ;   ; A rule defines conditions a valid packet MUST have. A packet must satisfy one of the
+  ;   ; rules defined here. A rule can be broken into two parts: matching & checking. A packet
+  ;   ; will be matched against rules from the first to the last until a matched rule is
+  ;   ; encountered. The matched rule will be used to check the packet. If a packet does not
+  ;   ; match any rule, it will be treated as invalid.  The matching part of a rule consists
+  ;   ; of `for` and `filter` sections. They collectively define which packets can be checked
+  ;   ; with this rule. `for` defines packet type (data or interest) and `filter` defines
+  ;   ; conditions on other properties of a packet. Right now, you can only define conditions
+  ;   ; on packet name, and you can only specify ONLY ONE filter for packet name.  The
+  ;   ; checking part of a rule consists of `checker`, which defines the conditions that a
+  ;   ; VALID packet MUST have. See comments in checker section for more details.
+  ;
+  ;   rule
+  ;   {
+  ;     id "NRD Prefix Registration Command Rule"
+  ;     for interest                         ; rule for Interests (to validate CommandInterests)
+  ;     filter
+  ;     {
+  ;       type name                          ; condition on interest name (w/o signature)
+  ;       regex ^[<localhop><localhost>]<nfd><rib>[<register><unregister>]<>$ ; prefix before
+  ;                                                                           ; timestamp
+  ;     }
+  ;     checker
+  ;     {
+  ;       type customized
+  ;       sig-type rsa-sha256                ; interest must have a rsa-sha256 signature
+  ;       key-locator
+  ;       {
+  ;         type name                        ; key locator must be the certificate name of the
+  ;                                          ; signing key
+  ;         regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT>$
+  ;       }
+  ;     }
+  ;   }
+  ;   rule
+  ;   {
+  ;     id "NDN Testbed Hierarchy Rule"
+  ;     for data                             ; rule for Data (to validate NDN certificates)
+  ;     filter
+  ;     {
+  ;       type name                          ; condition on data name
+  ;       regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT><>$
+  ;     }
+  ;     checker
+  ;     {
+  ;       type hierarchical                  ; the certificate name of the signing key and
+  ;                                          ; the data name must follow the hierarchical model
+  ;       sig-type rsa-sha256                ; data must have a rsa-sha256 signature
+  ;     }
+  ;   }
+  ;   trust-anchor
+  ;   {
+  ;     type file
+  ;     file-name keys/default.ndncert ; the file name, by default this file should be placed in the
+  ;                                    ; same folder as this config file.
+  ;   }
+  ;   ; trust-anchor ; Can be repeated multiple times to specify multiple trust anchors
+  ;   ; {
+  ;   ;   type file
+  ;   ;   file-name keys/ndn-testbed.ndncert
+  ;   ; }
+  ; }
+
+  ; The following localhop_security should be enabled when NFD runs on a hub,
+  ; which accepts all remote registrations and is a short-term solution.
+  ; localhop_security
+  ; {
+  ;   trust-anchor
+  ;   {
+  ;     type any
+  ;   }
+  ; }
+
+  remote_register
+  {
+    cost 15 ; forwarding cost of prefix registered on remote router
+    timeout 10000 ; timeout (in milliseconds) of remote prefix registration command
+    retry 0 ; maximum number of retries for each remote prefix registration command
+
+    refresh_interval 300 ; interval (in seconds) before refreshing the registration
+    ; This setting should be less than face_system.udp.idle_time,
+    ; so that the face is kept alive on the remote router.
+  }
+}
diff --git a/ndn_utils/nlsr.conf b/ndn_utils/nlsr.conf
new file mode 100644
index 0000000..89fad50
--- /dev/null
+++ b/ndn_utils/nlsr.conf
@@ -0,0 +1,147 @@
+; the general section contains all the general settings for router
+
+$GENERAL_SECTION
+
+; the neighbors section contains the configuration for router's neighbors and hello's behavior
+
+$NEIGHBORS_SECTION
+
+; the hyperbolic section contains the configuration settings of enabling a router to calculate
+; routing table using [hyperbolic routing table calculation](http://arxiv.org/abs/0805.1266) method
+
+$HYPERBOLIC_SECTION
+
+
+; the fib section is used to configure fib entry's type to ndn FIB updated by NLSR
+
+$FIB_SECTION
+
+; the advertising section contains the configuration settings of the name prefixes
+; hosted by this router
+
+$ADVERTISING_SECTION
+
+security
+{
+  validator
+  {
+    rule
+    {
+      id "NSLR Hello Rule"
+      for data
+      filter
+      {
+        type name
+        regex ^[^<NLSR><INFO>]*<NLSR><INFO><><>$
+      }
+      checker
+      {
+        type customized
+        sig-type rsa-sha256
+        key-locator
+        {
+          type name
+          hyper-relation
+          {
+            k-regex ^([^<KEY><NLSR>]*)<NLSR><KEY><ksk-.*><ID-CERT>$
+            k-expand \\1
+            h-relation equal
+            p-regex ^([^<NLSR><INFO>]*)<NLSR><INFO><><>$
+            p-expand \\1
+          }
+        }
+      }
+    }
+
+    rule
+    {
+      id "NSLR LSA Rule"
+      for data
+      filter
+      {
+        type name
+        regex ^[^<NLSR><LSA>]*<NLSR><LSA>
+      }
+      checker
+      {
+        type customized
+        sig-type rsa-sha256
+        key-locator
+        {
+          type name
+          hyper-relation
+          {
+            k-regex ^([^<KEY><NLSR>]*)<NLSR><KEY><ksk-.*><ID-CERT>$
+            k-expand \\1
+            h-relation equal
+            p-regex ^([^<NLSR><LSA>]*)<NLSR><LSA>(<>*)<><><>$
+            p-expand \\1\\2
+          }
+        }
+      }
+    }
+
+    rule
+    {
+      id "NSLR Hierarchy Exception Rule"
+      for data
+      filter
+      {
+        type name
+        regex ^[^<KEY><%C1.Router>]*<%C1.Router>[^<KEY><NLSR>]*<KEY><ksk-.*><ID-CERT><>$
+      }
+      checker
+      {
+        type customized
+        sig-type rsa-sha256
+        key-locator
+        {
+          type name
+          hyper-relation
+          {
+	    k-regex ^([^<KEY><%C1.Operator>]*)<%C1.Operator>[^<KEY>]*<KEY><ksk-.*><ID-CERT>$
+            k-expand \\1
+            h-relation equal
+            p-regex ^([^<KEY><%C1.Router>]*)<%C1.Router>[^<KEY>]*<KEY><ksk-.*><ID-CERT><>$
+            p-expand \\1
+          }
+        }
+      }
+    }
+
+    rule
+    {
+      id "NSLR Hierarchical Rule"
+      for data
+      filter
+      {
+        type name
+        regex ^[^<KEY>]*<KEY><ksk-.*><ID-CERT><>$
+      }
+      checker
+      {
+        type hierarchical
+        sig-type rsa-sha256
+      }
+    }
+
+    trust-anchor
+    {
+      type any
+      file-name "root.cert"
+    }
+  }
+  ; cert-to-publish "root.cert"  ; optional, a file containing the root certificate
+                                 ; Only the router that is designated to publish the root cert
+                                 ; needs to specify this
+
+  ; cert-to-publish "site.cert"  ; optional, a file containing the site certificate
+                                 ; Only the router that is designated to publish the site cert
+                                 ; needs to specify this
+
+  ; cert-to-publish "operator.cert" ; optional, a file containing the operator certificate
+                                    ; Only the router that is designated to publish the operator
+                                    ; cert needs to specify this
+
+  ; cert-to-publish "router.cert"  ; required, a file containing the router certificate.
+}
diff --git a/setup.py b/setup.py
index 46fafa9..19bfd83 100644
--- a/setup.py
+++ b/setup.py
@@ -10,14 +10,14 @@
 sys.path.append( '.' )
 from mininet.net import VERSION
 
-scripts = [ join( 'bin', filename ) for filename in [ 'mn', 'miniccnx', 'miniccnxedit' ] ]
+scripts = [ join( 'bin', filename ) for filename in [ 'mn', 'minindn', 'minindnedit' ] ]
 
 modname = distname = 'mininet'
 
 setup(
     name=distname,
     version=VERSION,
-    description='Process-based OpenFlow emulator with CCNx extension',
+    description='Process-based OpenFlow emulator with NDN extension',
     author='Bob Lantz, Carlos Cabral',
     author_email='rlantz@cs.stanford.edu, cabral@dca.fee.unicamp.br',
     packages=find_packages(exclude='test'),
@@ -26,8 +26,8 @@
         virtualization to create virtual networks for rapid
         prototyping of Software-Defined Network (SDN) designs
         using OpenFlow. http://openflow.org/mininet.
-	This also includes an extension for using Content Centric
-	Networks based on the NDN model (project CCNx).
+        This also includes an extension for using Content Centric
+        Networks based on the Named Data Networking (NDN) model.
         """,
     classifiers=[
           "License :: OSI Approved :: BSD License",
@@ -36,7 +36,7 @@
           "Intended Audience :: Developers",
           "Topic :: Internet",
     ],
-    keywords='networking emulator protocol Internet OpenFlow SDN CCNx CCN',
+    keywords='networking emulator protocol Internet OpenFlow SDN NDN NFD NLSR',
     license='BSD',
     install_requires=[
         'setuptools',
diff --git a/util/install.sh b/util/install.sh
index 716132d..c16883d 100755
--- a/util/install.sh
+++ b/util/install.sh
@@ -133,13 +133,13 @@
 
     # Add sysctl parameters as noted in the INSTALL file to increase kernel
     # limits to support larger setups:
-    sudo su -c "cat $HOME/mn-ccnx/util/sysctl_addon >> /etc/sysctl.conf"
+    sudo su -c "cat $HOME/mini-ndn/util/sysctl_addon >> /etc/sysctl.conf"
 
     # Load new sysctl settings:
     sudo sysctl -p
 
     echo "Installing Mininet/Mini-CCNx core"
-    pushd ~/mn-ccnx
+    pushd ~/mini-ndn
     sudo make install
     popd
 }
@@ -158,7 +158,7 @@
     cd ~/openflow
 
     # Patch controller to handle more than 16 switches
-    patch -p1 < ~/mn-ccnx/util/openflow-patches/controller.patch
+    patch -p1 < ~/mini-ndn/util/openflow-patches/controller.patch
 
     # Resume the install:
     ./boot.sh
@@ -208,7 +208,7 @@
 
     # Copy coloring rules: OF is white-on-blue:
     mkdir -p ~/.wireshark
-    cp ~/mn-ccnx/util/colorfilters ~/.wireshark
+    cp ~/mini-ndn/util/colorfilters ~/.wireshark
 }
 
 
@@ -357,9 +357,9 @@
 
     # Apply patches
     git checkout -b tutorial-destiny
-    git am ~/mn-ccnx/util/nox-patches/*tutorial-port-nox-destiny*.patch
+    git am ~/mini-ndn/util/nox-patches/*tutorial-port-nox-destiny*.patch
     if [ "$DIST" = "Ubuntu" ] && [ `expr $RELEASE '>=' 12.04` = 1 ]; then
-        git am ~/mn-ccnx/util/nox-patches/*nox-ubuntu12-hacks.patch
+        git am ~/mini-ndn/util/nox-patches/*nox-ubuntu12-hacks.patch
     fi
 
     # Build