blob: 0b8af7922bc0f3337f4746b4151744953c96cf28 [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
ashu2ad32e22015-05-29 13:37:40 -050071from ndn.conf_parser import parse_hosts, 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 Lehman3b8bc652015-06-18 15:01:47 -050084def printExperimentNames():
85 experimentNames = ExperimentManager.getExperimentNames()
86
87 print "Mini-NDN experiments:"
88 for experiment in experimentNames:
89 print " %s" % experiment
90
Vince Lehmane9f116d2015-07-15 10:40:21 -050091def printVersion(option, opt, value, parser):
92 print "Mini-NDN v%s" % VERSION_NUMBER
93 sys.exit()
94
ashuef3490b2015-02-17 11:01:04 -060095def parse_args():
96 usage="""Usage: minindn [template_file] [ -t | --testbed ]
Ashlesh Gawande20f70762015-06-17 15:18:19 -050097 If no template_file is given, ndn_utils/default-topology.conf (given sample file)
98 will be used.
ashuef3490b2015-02-17 11:01:04 -060099 If --testbed is used, minindn will run the NDN Project Testbed.
ashuef3490b2015-02-17 11:01:04 -0600100 """
101
102 testbed = False
ashuef3490b2015-02-17 11:01:04 -0600103 hr = False
ashuef3490b2015-02-17 11:01:04 -0600104
105 parser = optparse.OptionParser(usage)
106
107 parser.add_option("-t", "--testbed", action="store_true", dest="testbed",
108 help="instantiates NDN Testbed")
109
Vince Lehman3b8bc652015-06-18 15:01:47 -0500110 parser.add_option("--experiment", action="store", dest="experiment",
111 help="Runs the specified experiment")
112
113 parser.add_option("--list-experiments", action="store_true", dest="shouldListExperiments",
114 help="Lists the names of all available experiments")
115
116 parser.add_option("--nPings", action="store", dest="nPings", type="int",
117 help="Number of pings to perform between each node in the experiment")
ashuef3490b2015-02-17 11:01:04 -0600118
119 parser.add_option("--ctime", action="store", dest="ctime", type="int",
120 help="Specify convergence time for the topology (Default 60 seconds)")
121
122 parser.add_option("--hr", action="store_true", dest="hr",
123 help="--hr is used to turn on hyperbolic routing")
124
125 parser.add_option("--faces", action="store", dest="faces", type="int",
126 help="Specify number of faces 0-60")
127
ashuef3490b2015-02-17 11:01:04 -0600128 parser.add_option("--no-cli", action="store_false", dest="isCliEnabled",
129 help="Run experiments and exit without showing the command line interface")
130
Vince Lehmane9f116d2015-07-15 10:40:21 -0500131 parser.add_option('--version', '-V', action='callback', callback=printVersion,
132 help='Displays version information')
133
ashuef3490b2015-02-17 11:01:04 -0600134 (options, arg) = parser.parse_args()
135
136 testbed = options.testbed
Vince Lehman3b8bc652015-06-18 15:01:47 -0500137 experimentName = options.experiment
138 shouldListExperiments = options.shouldListExperiments
139 nPings = options.nPings
ashuef3490b2015-02-17 11:01:04 -0600140 ctime = options.ctime
141 hr = options.hr
142 faces = options.faces
ashuef3490b2015-02-17 11:01:04 -0600143 isCliEnabled = options.isCliEnabled
144
Vince Lehman3b8bc652015-06-18 15:01:47 -0500145 if shouldListExperiments is not None:
146 printExperimentNames()
147 sys.exit()
148
ashuef3490b2015-02-17 11:01:04 -0600149 if ctime is None:
150 ctime = 60
151
Vince Lehman3b8bc652015-06-18 15:01:47 -0500152 if nPings is None:
153 nPings = 300
154
ashuef3490b2015-02-17 11:01:04 -0600155 if isCliEnabled is None:
156 isCliEnabled = True
157
158 if len(arg) == 0 or len(arg) > 2:
159 file = ''
160 else:
161 file = arg[0]
162
Vince Lehman3b8bc652015-06-18 15:01:47 -0500163 return file, testbed, experimentName, nPings, ctime, hr, faces, isCliEnabled
ashuef3490b2015-02-17 11:01:04 -0600164
165class NdnTopo(Topo):
166 def __init__(self, conf_arq, **opts):
167 Topo.__init__(self, **opts)
168
169 global hosts_conf
170 global links_conf
171 hosts_conf = parse_hosts(conf_arq)
172 links_conf = parse_links(conf_arq)
173
174 self.isTCLink = False
175 self.isLimited = False
176
177 for host in hosts_conf:
178 if host.cpu != None and self.isLimited != True:
179 self.isLimited = True
Ashlesh Gawande3a4afb12015-07-09 09:23:30 -0500180 self.addHost(host.name, app=host.app, params=host.uri_tuples, cpu=host.cpu,cores=host.cores,cache=host.cache)
ashuef3490b2015-02-17 11:01:04 -0600181
182 for link in links_conf:
183 if len(link.linkDict) == 0:
184 self.addLink(link.h1, link.h2)
185 else:
186 self.addLink(link.h1, link.h2, **link.linkDict)
187 self.isTCLink = True
188
189 info('Parse of ' + conf_arq + ' done.\n')
190
Vince Lehman3b8bc652015-06-18 15:01:47 -0500191def execute(template_file='minindn.conf', testbed=False, experimentName=None, nPings=None, ctime=None, hr=False, faces=3, isCliEnabled=True):
ashuef3490b2015-02-17 11:01:04 -0600192 "Create a network based on template_file"
193
Ashlesh Gawande20f70762015-06-17 15:18:19 -0500194 install_dir='/usr/local/etc/mini-ndn/'
195
ashuef3490b2015-02-17 11:01:04 -0600196 if template_file == '':
Ashlesh Gawande20f70762015-06-17 15:18:19 -0500197 template_file = install_dir + 'default-topology.conf'
198
199 if testbed:
200 template_file = install_dir + 'minindn.testbed.conf'
ashuef3490b2015-02-17 11:01:04 -0600201
202 if os.path.exists(template_file) == False:
Ashlesh Gawande20f70762015-06-17 15:18:19 -0500203 info('No template file given and default template file cannot be found. Exiting...\n')
ashuef3490b2015-02-17 11:01:04 -0600204 quit()
Ashlesh Gawande20f70762015-06-17 15:18:19 -0500205
ashuef3490b2015-02-17 11:01:04 -0600206 topo = NdnTopo(template_file)
207
208 t = datetime.datetime.now()
209
210 if topo.isTCLink == True and topo.isLimited == True:
211 net = Mininet(topo,host=CpuLimitedNdnHost,link=TCLink)
212 elif topo.isTCLink == True and topo.isLimited == False:
213 net = Mininet(topo,host=NdnHost,link=TCLink)
214 elif topo.isTCLink == False and topo.isLimited == True:
215 net = Mininet(topo,host=CpuLimitedNdnHost)
216 else:
217 net = Mininet(topo,host=NdnHost)
218
219 t2 = datetime.datetime.now()
220
221 delta = t2 - t
222
223 info('Setup time: ' + str(delta.seconds) + '\n')
224
225 net.start()
226
ashu2ad32e22015-05-29 13:37:40 -0500227 # Giving proper IPs to intf so neighbor nodes can communicate
228 # This is one way of giving connectivity, another way could be
229 # to insert a switch between each pair of neighbors
230 ndnNetBase = "1.0.0.0"
231 interfaces = []
232 for host in net.hosts:
233 for intf in host.intfList():
234 link = intf.link
235 node1, node2 = link.intf1.node, link.intf2.node
236 if link.intf1 not in interfaces and link.intf2 not in interfaces:
237 interfaces.append(link.intf1)
238 interfaces.append(link.intf2)
239 node1.setIP(ipStr(ipParse(ndnNetBase) + 1) + '/30', intf=link.intf1)
240 node2.setIP(ipStr(ipParse(ndnNetBase) + 2) + '/30', intf=link.intf2)
241 ndnNetBase = ipStr(ipParse(ndnNetBase) + 4)
242
ashuef3490b2015-02-17 11:01:04 -0600243 nodes = "" # Used later to check prefix name in checkFIB
244
245 # NLSR initialization
246 for host in net.hosts:
247 nodes += str(host.name) + ","
248
249 conf = next(x for x in hosts_conf if x.name == host.name)
250 host.nlsrParameters = conf.nlsrParameters
251
252 if faces is not None:
253 host.nlsrParameters["max-faces-per-prefix"] = faces
254
255 if hr is True:
256 host.nlsrParameters["hyperbolic-state"] = "on"
257
258 # Generate NLSR configuration file
ashu2ad32e22015-05-29 13:37:40 -0500259 configGenerator = NlsrConfigGenerator(host)
ashuef3490b2015-02-17 11:01:04 -0600260 configGenerator.createConfigFile()
261
262 # Start NLSR
ashu34c3ee02015-03-25 14:41:14 -0500263 host.nlsr = Nlsr(host)
264 host.nlsr.start()
ashuef3490b2015-02-17 11:01:04 -0600265
266 nodes = nodes[0:-1]
267
ashuef3490b2015-02-17 11:01:04 -0600268 for host in net.hosts:
269 if 'app' in host.params:
Ashlesh Gawande557cb842015-07-01 15:39:44 -0500270 if host.params['app'] != '':
271 app = host.params['app']
272 print "Starting " + app + " on node " + host.name
273 print(host.cmd(app))
ashuef3490b2015-02-17 11:01:04 -0600274
Vince Lehman3b8bc652015-06-18 15:01:47 -0500275 # Load experiment
276 if experimentName is not None:
277 print "Loading experiment: %s" % experimentName
278
279 experimentArgs = {
280 "net": net,
281 "nodes": nodes,
282 "ctime": ctime,
283 "nPings": nPings,
284 "strategy": Nfd.STRATEGY_BEST_ROUTE_V3
285 }
286
287 experiment = ExperimentManager.create(experimentName, experimentArgs)
288
289 if experiment is not None:
290 experiment.start()
291 else:
292 print "ERROR: Experiment '%s' does not exist" % experimentName
293 return
294
ashuef3490b2015-02-17 11:01:04 -0600295 if isCliEnabled is True:
296 CLI(net)
297
298 net.stop()
299
300if __name__ == '__main__':
Vince Lehman3b8bc652015-06-18 15:01:47 -0500301
ashuef3490b2015-02-17 11:01:04 -0600302 hosts_conf = []
303 links_conf = []
Vince Lehman3b8bc652015-06-18 15:01:47 -0500304 template, testbed, experimentName, nPings, ctime, hr, faces, isCliEnabled = parse_args()
ashuef3490b2015-02-17 11:01:04 -0600305
306 setLogLevel('info')
Vince Lehman3b8bc652015-06-18 15:01:47 -0500307 execute(template, testbed, experimentName, nPings, ctime, hr, faces, isCliEnabled)