blob: e08188346c0bf2ea74031e62aa0815b101a428f8 [file] [log] [blame]
Vince Lehmanb8b18062015-07-14 13:07:22 -05001# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2#
3# Copyright (C) 2015 The University of Memphis,
4# Arizona Board of Regents,
5# Regents of the University of California.
6#
7# This file is part of Mini-NDN.
8# See AUTHORS.md for a complete list of Mini-NDN authors and contributors.
9#
10# Mini-NDN is free software: you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation, either version 3 of the License, or
13# (at your option) any later version.
14#
15# Mini-NDN is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with Mini-NDN, e.g., in COPYING.md file.
22# If not, see <http://www.gnu.org/licenses/>.
23#
24# This file incorporates work covered by the following copyright and
25# permission notice:
26#
27# Mininet 2.2.1 License
28#
29# Copyright (c) 2013-2015 Open Networking Laboratory
30# Copyright (c) 2009-2012 Bob Lantz and The Board of Trustees of
31# The Leland Stanford Junior University
32#
33# Original authors: Bob Lantz and Brandon Heller
34#
35# We are making Mininet available for public use and benefit with the
36# expectation that others will use, modify and enhance the Software and
37# contribute those enhancements back to the community. However, since we
38# would like to make the Software available for broadest use, with as few
39# restrictions as possible permission is hereby granted, free of charge, to
40# any person obtaining a copy of this Software to deal in the Software
41# under the copyrights without restriction, including without limitation
42# the rights to use, copy, modify, merge, publish, distribute, sublicense,
43# and/or sell copies of the Software, and to permit persons to whom the
44# Software is furnished to do so, subject to the following conditions:
45#
46# The above copyright notice and this permission notice shall be included
47# in all copies or substantial portions of the Software.
48#
49# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
50# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
51# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
52# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
53# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
54# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
55# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
56#
57# The name and trademarks of copyright holder(s) may NOT be used in
58# advertising or publicity pertaining to the Software or any derivatives
59# without specific, written prior permission.
ashuef3490b2015-02-17 11:01:04 -060060
61from mininet.topo import Topo
62from mininet.net import Mininet
63from mininet.log import setLogLevel, output, info
64from mininet.cli import CLI
65from mininet.link import TCLink
ashu2ad32e22015-05-29 13:37:40 -050066from mininet.util import ipStr, ipParse
ashuef3490b2015-02-17 11:01:04 -060067
Vince Lehman3b8bc652015-06-18 15:01:47 -050068
69from ndn import ExperimentManager
ashuef3490b2015-02-17 11:01:04 -060070from ndn.ndn_host import NdnHost, CpuLimitedNdnHost
Vince Lehmanfbd47c92015-10-14 16:00:06 -050071from ndn.conf_parser import parse_hosts, parse_switches, parse_links
ashuef3490b2015-02-17 11:01:04 -060072
73import os.path, time
74import optparse
75import datetime
ashu01b62f72015-03-12 15:16:11 -050076from os.path import expanduser
Vince Lehman3b8bc652015-06-18 15:01:47 -050077import sys
ashuef3490b2015-02-17 11:01:04 -060078
79from ndn.nlsr import Nlsr, NlsrConfigGenerator
ashu34c3ee02015-03-25 14:41:14 -050080from ndn.nfd import Nfd
ashuef3490b2015-02-17 11:01:04 -060081
Vince Lehmane9f116d2015-07-15 10:40:21 -050082VERSION_NUMBER = "0.1.0"
83
Vince Lehman194be242015-10-15 18:01:42 -050084def printExperimentNames(option, opt, value, parser):
Vince Lehman3b8bc652015-06-18 15:01:47 -050085 experimentNames = ExperimentManager.getExperimentNames()
86
87 print "Mini-NDN experiments:"
88 for experiment in experimentNames:
89 print " %s" % experiment
90
Vince Lehman194be242015-10-15 18:01:42 -050091 sys.exit()
92
Vince Lehmane9f116d2015-07-15 10:40:21 -050093def printVersion(option, opt, value, parser):
94 print "Mini-NDN v%s" % VERSION_NUMBER
95 sys.exit()
96
Vince Lehman194be242015-10-15 18:01:42 -050097class ProgramOptions:
98 def __init__(self):
99 self.ctime = 60
100 self.experimentName = None
101 self.nFaces = 3
102 self.templateFile = "minindn.conf"
103 self.hr = False
104 self.isCliEnabled = True
105 self.nPings = 300
106 self.testbed = False
Ashlesh Gawande1b663692015-10-14 16:38:10 -0500107 self.workDir = "/tmp"
Ashlesh Gawanded829bfc2015-10-14 16:38:10 -0500108 self.resultDir = None
Ashlesh Gawanded9c9e522015-10-15 16:40:12 -0500109 self.pctTraffic = 1.0
Ashlesh Gawanded829bfc2015-10-14 16:38:10 -0500110
111def createResultsDir(resultDir, faces, hr):
112 if faces == 0:
113 faces = "all"
114
115 if hr:
116 routingType = "/hr/"
117 else:
118 routingType = "/ls/"
119
120 resultDir = "%s/%s/faces-%s" % (str(resultDir), routingType, str(faces))
121 resultDir = os.path.abspath(resultDir)
122
123 if not os.path.isdir(resultDir):
124 os.makedirs(resultDir)
125 else:
126 print("Results directory (%s) already exists!" % resultDir)
127 sys.exit(1);
128
129 print "Results will be stored at: %s" % resultDir
130 return resultDir
Vince Lehman194be242015-10-15 18:01:42 -0500131
ashuef3490b2015-02-17 11:01:04 -0600132def parse_args():
Vince Lehman194be242015-10-15 18:01:42 -0500133 usage = """Usage: minindn [template_file] [ -t | --testbed ]
Ashlesh Gawande20f70762015-06-17 15:18:19 -0500134 If no template_file is given, ndn_utils/default-topology.conf (given sample file)
135 will be used.
ashuef3490b2015-02-17 11:01:04 -0600136 If --testbed is used, minindn will run the NDN Project Testbed.
ashuef3490b2015-02-17 11:01:04 -0600137 """
138
ashuef3490b2015-02-17 11:01:04 -0600139 parser = optparse.OptionParser(usage)
140
Vince Lehman194be242015-10-15 18:01:42 -0500141 parser.add_option("--ctime", action="store", dest="ctime", type="int", default=60,
142 help="Specify convergence time for the topology (Default: 60 seconds)")
ashuef3490b2015-02-17 11:01:04 -0600143
Vince Lehman3b8bc652015-06-18 15:01:47 -0500144 parser.add_option("--experiment", action="store", dest="experiment",
145 help="Runs the specified experiment")
146
Vince Lehman194be242015-10-15 18:01:42 -0500147 parser.add_option("--faces", action="store", dest="faces", type="int", default=3,
ashuef3490b2015-02-17 11:01:04 -0600148 help="Specify number of faces 0-60")
149
Vince Lehman194be242015-10-15 18:01:42 -0500150 parser.add_option("--hr", action="store_true", dest="hr", default=False,
151 help="--hr is used to turn on hyperbolic routing")
152
153 parser.add_option("--list-experiments", action="callback", callback=printExperimentNames,
154 help="Lists the names of all available experiments")
155
156 parser.add_option("--no-cli", action="store_false", dest="isCliEnabled", default=True,
157 help="Run experiments and exit without showing the command line interface")
158
159 parser.add_option("--nPings", action="store", dest="nPings", type="int", default=300,
160 help="Number of pings to perform between each node in the experiment")
161
162 parser.add_option("-t", "--testbed", action="store_true", dest="testbed", default=False,
163 help="instantiates NDN Testbed")
ashuef3490b2015-02-17 11:01:04 -0600164
Ashlesh Gawande1b663692015-10-14 16:38:10 -0500165 parser.add_option("--work-dir", action="store", dest="workDir", default="/tmp",
166 help="Specify the working directory; default is /tmp")
167
Ashlesh Gawanded829bfc2015-10-14 16:38:10 -0500168 parser.add_option("--result-dir", action="store", dest="resultDir", default=None,
169 help="Specify the full path destination folder where experiment results will be moved")
170
Ashlesh Gawanded9c9e522015-10-15 16:40:12 -0500171 parser.add_option("--pct-traffic", action="store", dest="pctTraffic", type="float", default=1.0,
172 help="Specify the percentage of nodes each node should ping")
173
Vince Lehmane9f116d2015-07-15 10:40:21 -0500174 parser.add_option('--version', '-V', action='callback', callback=printVersion,
175 help='Displays version information')
176
Vince Lehman194be242015-10-15 18:01:42 -0500177 (args, arg) = parser.parse_args()
ashuef3490b2015-02-17 11:01:04 -0600178
Vince Lehman194be242015-10-15 18:01:42 -0500179 options = ProgramOptions()
180 options.ctime = args.ctime
181 options.experimentName = args.experiment
182 options.nFaces = args.faces
183 options.hr = args.hr
184 options.isCliEnabled = args.isCliEnabled
185 options.nPings = args.nPings
186 options.testbed = args.testbed
Ashlesh Gawande1b663692015-10-14 16:38:10 -0500187 options.workDir = args.workDir
Ashlesh Gawanded829bfc2015-10-14 16:38:10 -0500188 options.resultDir = args.resultDir
Ashlesh Gawanded9c9e522015-10-15 16:40:12 -0500189 options.pctTraffic = args.pctTraffic
ashuef3490b2015-02-17 11:01:04 -0600190
Vince Lehman194be242015-10-15 18:01:42 -0500191 if options.experimentName is not None and options.experimentName not in ExperimentManager.getExperimentNames():
192 print("No experiment named %s" % options.experimentName)
Vince Lehman3b8bc652015-06-18 15:01:47 -0500193 sys.exit()
194
Ashlesh Gawanded829bfc2015-10-14 16:38:10 -0500195 if options.experimentName is not None and options.resultDir is None:
196 print "No results folder specified; experiment results will remain in the working directory"
197
ashuef3490b2015-02-17 11:01:04 -0600198 if len(arg) == 0 or len(arg) > 2:
Vince Lehman194be242015-10-15 18:01:42 -0500199 options.templateFile = ''
ashuef3490b2015-02-17 11:01:04 -0600200 else:
Vince Lehman194be242015-10-15 18:01:42 -0500201 options.templateFile = arg[0]
ashuef3490b2015-02-17 11:01:04 -0600202
Vince Lehman194be242015-10-15 18:01:42 -0500203 return options
ashuef3490b2015-02-17 11:01:04 -0600204
205class NdnTopo(Topo):
Ashlesh Gawande1b663692015-10-14 16:38:10 -0500206 def __init__(self, conf_arq, workDir, **opts):
ashuef3490b2015-02-17 11:01:04 -0600207 Topo.__init__(self, **opts)
208
209 global hosts_conf
210 global links_conf
211 hosts_conf = parse_hosts(conf_arq)
Vince Lehmanfbd47c92015-10-14 16:00:06 -0500212 switches_conf = parse_switches(conf_arq)
ashuef3490b2015-02-17 11:01:04 -0600213 links_conf = parse_links(conf_arq)
214
215 self.isTCLink = False
216 self.isLimited = False
217
218 for host in hosts_conf:
219 if host.cpu != None and self.isLimited != True:
220 self.isLimited = True
Ashlesh Gawande1b663692015-10-14 16:38:10 -0500221 self.addHost(host.name, app=host.app, params=host.uri_tuples, cpu=host.cpu,cores=host.cores,cache=host.cache, workdir=workDir)
ashuef3490b2015-02-17 11:01:04 -0600222
Vince Lehmanfbd47c92015-10-14 16:00:06 -0500223 for switch in switches_conf:
224 self.addSwitch(switch.name)
225
ashuef3490b2015-02-17 11:01:04 -0600226 for link in links_conf:
227 if len(link.linkDict) == 0:
228 self.addLink(link.h1, link.h2)
229 else:
230 self.addLink(link.h1, link.h2, **link.linkDict)
231 self.isTCLink = True
232
233 info('Parse of ' + conf_arq + ' done.\n')
234
Vince Lehman194be242015-10-15 18:01:42 -0500235def execute(options):
ashuef3490b2015-02-17 11:01:04 -0600236 "Create a network based on template_file"
237
Vince Lehman194be242015-10-15 18:01:42 -0500238 template_file = options.templateFile
Ashlesh Gawande20f70762015-06-17 15:18:19 -0500239 install_dir='/usr/local/etc/mini-ndn/'
240
ashuef3490b2015-02-17 11:01:04 -0600241 if template_file == '':
Ashlesh Gawande20f70762015-06-17 15:18:19 -0500242 template_file = install_dir + 'default-topology.conf'
243
Vince Lehman194be242015-10-15 18:01:42 -0500244 if options.testbed:
Ashlesh Gawande20f70762015-06-17 15:18:19 -0500245 template_file = install_dir + 'minindn.testbed.conf'
ashuef3490b2015-02-17 11:01:04 -0600246
247 if os.path.exists(template_file) == False:
Ashlesh Gawande20f70762015-06-17 15:18:19 -0500248 info('No template file given and default template file cannot be found. Exiting...\n')
ashuef3490b2015-02-17 11:01:04 -0600249 quit()
Ashlesh Gawande20f70762015-06-17 15:18:19 -0500250
Vince Lehman498625b2015-10-21 14:25:24 -0500251 # Update nfd.conf file used by Mini-NDN to match the currently installed version of NFD
252 nfdConfFile = "%s/nfd.conf" % install_dir
253 os.system("sudo cp /usr/local/etc/ndn/nfd.conf.sample %s" % nfdConfFile)
254 os.system("sudo sed -i \'s|default_level [A-Z]*$|default_level $LOG_LEVEL|g\' %s" % nfdConfFile)
255
Ashlesh Gawanded829bfc2015-10-14 16:38:10 -0500256 if options.resultDir is not None:
257 options.resultDir = createResultsDir(options.resultDir, options.nFaces, options.hr)
258
Ashlesh Gawande1b663692015-10-14 16:38:10 -0500259 topo = NdnTopo(template_file, options.workDir)
ashuef3490b2015-02-17 11:01:04 -0600260
261 t = datetime.datetime.now()
262
263 if topo.isTCLink == True and topo.isLimited == True:
264 net = Mininet(topo,host=CpuLimitedNdnHost,link=TCLink)
265 elif topo.isTCLink == True and topo.isLimited == False:
266 net = Mininet(topo,host=NdnHost,link=TCLink)
267 elif topo.isTCLink == False and topo.isLimited == True:
268 net = Mininet(topo,host=CpuLimitedNdnHost)
269 else:
270 net = Mininet(topo,host=NdnHost)
271
272 t2 = datetime.datetime.now()
273
274 delta = t2 - t
275
276 info('Setup time: ' + str(delta.seconds) + '\n')
277
278 net.start()
279
ashu2ad32e22015-05-29 13:37:40 -0500280 # Giving proper IPs to intf so neighbor nodes can communicate
281 # This is one way of giving connectivity, another way could be
282 # to insert a switch between each pair of neighbors
283 ndnNetBase = "1.0.0.0"
284 interfaces = []
285 for host in net.hosts:
286 for intf in host.intfList():
287 link = intf.link
288 node1, node2 = link.intf1.node, link.intf2.node
Vince Lehmanfbd47c92015-10-14 16:00:06 -0500289
290 if node1 in net.switches or node2 in net.switches:
Vince Lehmanfbd47c92015-10-14 16:00:06 -0500291 continue
292
ashu2ad32e22015-05-29 13:37:40 -0500293 if link.intf1 not in interfaces and link.intf2 not in interfaces:
294 interfaces.append(link.intf1)
295 interfaces.append(link.intf2)
296 node1.setIP(ipStr(ipParse(ndnNetBase) + 1) + '/30', intf=link.intf1)
297 node2.setIP(ipStr(ipParse(ndnNetBase) + 2) + '/30', intf=link.intf2)
298 ndnNetBase = ipStr(ipParse(ndnNetBase) + 4)
299
ashuef3490b2015-02-17 11:01:04 -0600300 nodes = "" # Used later to check prefix name in checkFIB
301
302 # NLSR initialization
303 for host in net.hosts:
304 nodes += str(host.name) + ","
305
306 conf = next(x for x in hosts_conf if x.name == host.name)
307 host.nlsrParameters = conf.nlsrParameters
308
Vince Lehman194be242015-10-15 18:01:42 -0500309 if options.nFaces is not None:
310 host.nlsrParameters["max-faces-per-prefix"] = options.nFaces
ashuef3490b2015-02-17 11:01:04 -0600311
Vince Lehman194be242015-10-15 18:01:42 -0500312 if options.hr is True:
ashuef3490b2015-02-17 11:01:04 -0600313 host.nlsrParameters["hyperbolic-state"] = "on"
314
315 # Generate NLSR configuration file
ashu2ad32e22015-05-29 13:37:40 -0500316 configGenerator = NlsrConfigGenerator(host)
ashuef3490b2015-02-17 11:01:04 -0600317 configGenerator.createConfigFile()
318
319 # Start NLSR
ashu34c3ee02015-03-25 14:41:14 -0500320 host.nlsr = Nlsr(host)
321 host.nlsr.start()
ashuef3490b2015-02-17 11:01:04 -0600322
323 nodes = nodes[0:-1]
324
ashuef3490b2015-02-17 11:01:04 -0600325 for host in net.hosts:
326 if 'app' in host.params:
Ashlesh Gawande557cb842015-07-01 15:39:44 -0500327 if host.params['app'] != '':
328 app = host.params['app']
329 print "Starting " + app + " on node " + host.name
330 print(host.cmd(app))
ashuef3490b2015-02-17 11:01:04 -0600331
Vince Lehman3b8bc652015-06-18 15:01:47 -0500332 # Load experiment
Vince Lehman194be242015-10-15 18:01:42 -0500333 experimentName = options.experimentName
334
Vince Lehman3b8bc652015-06-18 15:01:47 -0500335 if experimentName is not None:
336 print "Loading experiment: %s" % experimentName
337
338 experimentArgs = {
339 "net": net,
340 "nodes": nodes,
Vince Lehman194be242015-10-15 18:01:42 -0500341 "ctime": options.ctime,
342 "nPings": options.nPings,
Ashlesh Gawanded9c9e522015-10-15 16:40:12 -0500343 "strategy": Nfd.STRATEGY_BEST_ROUTE_V3,
344 "pctTraffic": options.pctTraffic
Vince Lehman3b8bc652015-06-18 15:01:47 -0500345 }
346
347 experiment = ExperimentManager.create(experimentName, experimentArgs)
348
349 if experiment is not None:
350 experiment.start()
351 else:
352 print "ERROR: Experiment '%s' does not exist" % experimentName
353 return
354
Vince Lehman194be242015-10-15 18:01:42 -0500355 if options.isCliEnabled is True:
ashuef3490b2015-02-17 11:01:04 -0600356 CLI(net)
357
358 net.stop()
359
Ashlesh Gawanded829bfc2015-10-14 16:38:10 -0500360 if options.resultDir is not None:
361 print("Moving results to %s" % options.resultDir)
362 os.system("sudo mv /%s/* %s" % (options.workDir, options.resultDir))
363
ashuef3490b2015-02-17 11:01:04 -0600364if __name__ == '__main__':
Vince Lehman3b8bc652015-06-18 15:01:47 -0500365
ashuef3490b2015-02-17 11:01:04 -0600366 hosts_conf = []
367 links_conf = []
Vince Lehman194be242015-10-15 18:01:42 -0500368
369 options = parse_args()
ashuef3490b2015-02-17 11:01:04 -0600370
371 setLogLevel('info')
Vince Lehman194be242015-10-15 18:01:42 -0500372 execute(options)