blob: 15bde0d9ba5f29edf605b34f6f430b13784b70c7 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
Jon Hall7eb38402015-01-08 17:19:54 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004Copyright 2012 Open Networking Foundation (ONF)
adminbae64d82013-08-01 10:50:15 -07005
Jeremy Songsterae01bba2016-07-11 15:39:17 -07006Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
7the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
8or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
adminbae64d82013-08-01 10:50:15 -07009
Jon Hall7eb38402015-01-08 17:19:54 -080010TestON is free software: you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation, either version 2 of the License, or
13( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070014
Jon Hall7eb38402015-01-08 17:19:54 -080015TestON is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070019
Jon Hall7eb38402015-01-08 17:19:54 -080020You should have received a copy of the GNU General Public License
21along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070022
Jon Hallbe6dfc42015-01-12 17:37:25 -080023MininetCliDriver is the basic driver which will handle the Mininet functions
24
25Some functions rely on a modified version of Mininet. These functions
26should all be noted in the comments. To get this MN version run these commands
27from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080028 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080029 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080030 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080031 git pull
32
Jon Hall272a4db2015-01-12 17:43:48 -080033
34 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080035changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070036import pexpect
adminbae64d82013-08-01 10:50:15 -070037import re
38import sys
kelvin-onlabfa6ada82015-06-11 13:06:24 -070039import types
kelvin-onlaba4074292015-07-09 15:19:49 -070040import os
Devin Lima7cfdbd2017-09-29 15:02:22 -070041import time
Jon Hall1ccf82c2014-10-15 14:55:16 -040042from math import pow
adminbae64d82013-08-01 10:50:15 -070043from drivers.common.cli.emulatordriver import Emulator
You Wangdb8cd0a2016-05-26 15:19:45 -070044from core.graph import Graph
adminbae64d82013-08-01 10:50:15 -070045
Jon Hall7eb38402015-01-08 17:19:54 -080046
kelvin-onlab50907142015-04-01 13:37:45 -070047class MininetCliDriver( Emulator ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -070048
Jon Hall7eb38402015-01-08 17:19:54 -080049 """
50 MininetCliDriver is the basic driver which will handle
51 the Mininet functions"""
52 def __init__( self ):
Devin Limdc78e202017-06-09 18:30:07 -070053 super( MininetCliDriver, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070054 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080055 self.name = None
kelvin-onlabd9e23de2015-08-06 10:34:44 -070056 self.home = None
Jon Hall7eb38402015-01-08 17:19:54 -080057 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070058 self.flag = 0
Jon Hall892818c2015-10-20 17:58:34 -070059 # TODO: Refactor driver to use these everywhere
60 self.mnPrompt = "mininet>"
61 self.hostPrompt = "~#"
62 self.bashPrompt = "\$"
63 self.scapyPrompt = ">>>"
You Wangdb8cd0a2016-05-26 15:19:45 -070064 self.graph = Graph()
adminbae64d82013-08-01 10:50:15 -070065
Jon Hall7eb38402015-01-08 17:19:54 -080066 def connect( self, **connectargs ):
67 """
68 Here the main is the TestON instance after creating
69 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080070 try:
71 for key in connectargs:
72 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070073 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080074 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070075 for key in self.options:
76 if key == "home":
77 self.home = self.options[ 'home' ]
78 break
79 if self.home is None or self.home == "":
80 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070081
82 try:
Jon Hall892818c2015-10-20 17:58:34 -070083 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070084 self.ip_address = os.getenv( str( self.ip_address ) )
85 else:
86 main.log.info( self.name +
87 ": Trying to connect to " +
88 self.ip_address )
89
90 except KeyError:
91 main.log.info( "Invalid host name," +
92 " connecting to local host instead" )
93 self.ip_address = 'localhost'
94 except Exception as inst:
95 main.log.error( "Uncaught exception: " + str( inst ) )
96
kelvin-onlaba1484582015-02-02 15:46:20 -080097 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070098 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080099 self ).connect(
100 user_name=self.user_name,
101 ip_address=self.ip_address,
102 port=None,
103 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -0800104
kelvin-onlaba1484582015-02-02 15:46:20 -0800105 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -0800106 main.log.info( "Connection successful to the host " +
107 self.user_name +
108 "@" +
109 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800110 return main.TRUE
111 else:
112 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800113 self.user_name +
114 "@" +
115 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800116 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800117 return main.FALSE
118 except pexpect.EOF:
119 main.log.error( self.name + ": EOF exception found" )
120 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700121 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800122 except Exception:
123 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700124 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -0800125
kelvin-onlab10e8d392015-06-03 13:53:45 -0700126 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800127 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700128 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000129 Starts Mininet accepts a topology(.py) file and/or an optional
kelvin-onlabf512e942015-06-08 19:42:59 -0700130 argument, to start the mininet, as a parameter.
131 Can also send regular mininet command to load up desired topology.
alison12f34c32016-06-10 14:39:21 -0700132 Eg. Pass in a string 'mn --topo=tree,3,3' to mnCmd
kelvin-onlabf512e942015-06-08 19:42:59 -0700133 Options:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000134 topoFile = file path for topology file (.py)
kelvin-onlabf512e942015-06-08 19:42:59 -0700135 args = extra option added when starting the topology from the file
136 mnCmd = Mininet command use to start topology
137 Returns:
138 main.TRUE if the mininet starts successfully, main.FALSE
139 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800140 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700141 try:
142 if self.handle:
143 # make sure old networks are cleaned up
144 main.log.info( self.name +
145 ": Clearing any residual state or processes" )
146 self.handle.sendline( "sudo mn -c" )
147 i = self.handle.expect( [ 'password\sfor\s',
148 'Cleanup\scomplete',
Jon Hallefbd9792015-03-05 16:11:36 -0800149 pexpect.EOF,
150 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700151 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800152 if i == 0:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700153 # Sudo asking for password
154 main.log.info( self.name + ": Sending sudo password" )
155 self.handle.sendline( self.pwd )
Jon Hall173f2a02018-01-11 13:56:37 -0800156 i = self.handle.expect( [ '%s:' % self.user_name,
Devin Limdc78e202017-06-09 18:30:07 -0700157 self.prompt,
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700158 pexpect.EOF,
159 pexpect.TIMEOUT ],
160 timeout )
161 if i == 1:
162 main.log.info( self.name + ": Clean" )
Jon Hall689d8e42015-04-03 13:59:24 -0700163 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700164 main.log.error( self.name + ": Connection terminated" )
165 elif i == 3: # timeout
166 main.log.error( self.name + ": Something while cleaning " +
167 "Mininet took too long... " )
168 # Craft the string to start mininet
169 cmdString = "sudo "
170 if not mnCmd:
171 if topoFile is None or topoFile == '': # If no file is given
172 main.log.info( self.name + ": building fresh Mininet" )
173 cmdString += "mn "
174 if args is None or args == '':
175 # If no args given, use args from .topo file
176 args = self.options[ 'arg1' ] +\
177 " " + self.options[ 'arg2' ] +\
178 " --mac --controller " +\
179 self.options[ 'controller' ] + " " +\
180 self.options[ 'arg3' ]
181 else: # else only use given args
182 pass
183 # TODO: allow use of topo args and method args?
184 else: # Use given topology file
185 main.log.info(
186 "Starting Mininet from topo file " +
187 topoFile )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700188 cmdString += "-E python " + topoFile + " "
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700189 if args is None:
190 args = ''
191 # TODO: allow use of args from .topo file?
192 cmdString += args
193 else:
194 main.log.info( "Starting Mininet topology using '" + mnCmd +
195 "' command" )
196 cmdString += mnCmd
197 # Send the command and check if network started
198 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -0700199 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700200 main.log.info( "Sending '" + cmdString + "' to " + self.name )
201 self.handle.sendline( cmdString )
Devin Lima7cfdbd2017-09-29 15:02:22 -0700202 startTime = time.time()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700203 while True:
204 i = self.handle.expect( [ 'mininet>',
Jon Hallbc743112018-04-18 11:09:01 -0700205 'Exception|Error',
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700206 '\*\*\*',
207 pexpect.EOF,
Jon Hallab611372018-02-21 15:26:05 -0800208 pexpect.TIMEOUT,
209 "No such file or directory"],
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700210 timeout )
211 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -0700212 main.log.info( self.name + ": Mininet built\nTime Took : " + str( time.time() - startTime ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700213 return main.TRUE
214 elif i == 1:
215 response = str( self.handle.before +
216 self.handle.after )
Devin Limdc78e202017-06-09 18:30:07 -0700217 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700218 response += str( self.handle.before +
219 self.handle.after )
220 main.log.error(
221 self.name +
222 ": Launching Mininet failed: " + response )
223 return main.FALSE
224 elif i == 2:
225 self.handle.expect( [ "\n",
226 pexpect.EOF,
227 pexpect.TIMEOUT ],
228 timeout )
229 main.log.info( self.handle.before )
230 elif i == 3:
231 main.log.error( self.name + ": Connection timeout" )
232 return main.FALSE
233 elif i == 4: # timeout
234 main.log.error(
235 self.name +
236 ": Something took too long... " )
Jon Hallbc743112018-04-18 11:09:01 -0700237 main.log.debug( self.handle.before + self.handle.after )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700238 return main.FALSE
Jon Hallab611372018-02-21 15:26:05 -0800239 elif i == 5:
240 main.log.error( self.name + ": " + self.handle.before + self.handle.after )
241 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700242 # Why did we hit this part?
243 main.log.error( "startNet did not return correctly" )
244 return main.FASLE
245 else: # if no handle
246 main.log.error( self.name + ": Connection failed to the host " +
247 self.user_name + "@" + self.ip_address )
248 main.log.error( self.name + ": Failed to connect to the Mininet" )
249 return main.FALSE
250 except pexpect.TIMEOUT:
251 main.log.exception( self.name + ": TIMEOUT exception found while starting Mininet" )
252 main.log.error( self.name + ": " + self.handle.before )
adminbae64d82013-08-01 10:50:15 -0700253 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700254 except pexpect.EOF:
255 main.log.error( self.name + ": EOF exception found" )
256 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700257 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700258 except Exception:
259 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700260 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800261
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800262 def numSwitchesNlinks( self, topoType, depth, fanout ):
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700263 try:
264 if topoType == 'tree':
265 # In tree topology, if fanout arg is not given, by default it is 2
266 if fanout is None:
267 fanout = 2
268 k = 0
269 count = 0
270 while( k <= depth - 1 ):
271 count = count + pow( fanout, k )
272 k = k + 1
273 numSwitches = count
274 while( k <= depth - 2 ):
275 # depth-2 gives you only core links and not considering
276 # edge links as seen by ONOS. If all the links including
277 # edge links are required, do depth-1
278 count = count + pow( fanout, k )
279 k = k + 1
280 numLinks = count * fanout
281 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
282 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800283
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700284 elif topoType == 'linear':
285 # In linear topology, if fanout or numHostsPerSw is not given,
286 # by default it is 1
287 if fanout is None:
288 fanout = 1
289 numSwitches = depth
290 numHostsPerSw = fanout
291 totalNumHosts = numSwitches * numHostsPerSw
292 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hallab611372018-02-21 15:26:05 -0800293 main.log.debug( "num_switches for %s(%d,%d) = %d and links=%d" %
294 ( topoType, depth, fanout, numSwitches, numLinks ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700295 topoDict = { "num_switches": int( numSwitches ),
296 "num_corelinks": int( numLinks ) }
297 return topoDict
298 except Exception:
299 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700300 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400301
kelvin-onlabd3b64892015-01-20 13:26:24 -0800302 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700303 """
304 Calculate the number of switches and links in a topo."""
305 # TODO: combine this function and numSwitchesNlinks
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700306 try:
307 argList = self.options[ 'arg1' ].split( "," )
308 topoArgList = argList[ 0 ].split( " " )
309 argList = map( int, argList[ 1: ] )
310 topoArgList = topoArgList[ 1: ] + argList
Jon Hall689d8e42015-04-03 13:59:24 -0700311
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700312 topoDict = self.numSwitchesNlinks( *topoArgList )
313 return topoDict
314 except Exception:
315 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700316 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400317
GlennRCf07c44a2015-09-18 13:33:46 -0700318 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800319 """
320 Verifies the reachability of the hosts using pingall command.
321 Optional parameter timeout allows you to specify how long to
322 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700323 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700324 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700325 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700326 ping
327 acceptableFailed - Set the number of acceptable failed pings for the
328 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800329 Returns:
330 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700331 otherwise main.FALSE
332 """
333 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700334 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700335 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700336 if self.handle:
337 main.log.info(
338 self.name +
339 ": Checking reachabilty to the hosts using pingall" )
340 response = ""
341 failedPings = 0
342 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700343 cmd = "pingall"
344 if protocol == "IPv6":
345 cmd = "py net.pingAll6()"
346 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700347 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700348 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700349 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700350 pexpect.EOF,
351 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700352 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700353 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700354 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700355 response += self.handle.before
356 break
357 elif i == 1:
358 response += self.handle.before + self.handle.after
359 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700360 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700361 returnValue = main.FALSE
362 if shortCircuit:
363 main.log.error( self.name +
364 ": Aborting pingall - "
365 + str( failedPings ) +
366 " pings failed" )
367 break
Jon Hall390696c2015-05-05 17:13:41 -0700368 if ( time.time() - startTime ) > timeout:
369 returnValue = main.FALSE
370 main.log.error( self.name +
371 ": Aborting pingall - " +
372 "Function took too long " )
373 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700374 elif i == 2:
375 main.log.error( self.name +
376 ": EOF exception found" )
377 main.log.error( self.name + ": " +
378 self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700379 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700380 elif i == 3:
381 response += self.handle.before
382 main.log.error( self.name +
383 ": TIMEOUT exception found" )
384 main.log.error( self.name +
385 ": " +
386 str( response ) )
387 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800388 self.handle.send( "\x03" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700389 self.handle.expect( "Interrupt" )
390 self.handle.expect( "mininet>" )
391 break
392 pattern = "Results\:"
393 main.log.info( "Pingall output: " + str( response ) )
394 if re.search( pattern, response ):
395 main.log.info( self.name + ": Pingall finished with "
396 + str( failedPings ) + " failed pings" )
397 return returnValue
398 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700399 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800400 self.handle.send( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700401 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700402 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700403 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700404 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700405 main.log.error( self.name + ": Connection failed to the host" )
Devin Lim44075962017-08-11 10:56:37 -0700406 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700407 except pexpect.TIMEOUT:
408 if response:
409 main.log.info( "Pingall output: " + str( response ) )
410 main.log.error( self.name + ": pexpect.TIMEOUT found" )
411 return main.FALSE
412 except pexpect.EOF:
413 main.log.error( self.name + ": EOF exception found" )
414 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700415 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -0700416
Jon Hall7eb38402015-01-08 17:19:54 -0800417 def fpingHost( self, **pingParams ):
418 """
419 Uses the fping package for faster pinging...
420 *requires fping to be installed on machine running mininet"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700421 try:
422 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
423 command = args[ "SRC" ] + \
424 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
425 self.handle.sendline( command )
426 self.handle.expect(
427 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
428 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
429 response = self.handle.before
430 if re.search( ":\s-", response ):
431 main.log.info( self.name + ": Ping fail" )
432 return main.FALSE
433 elif re.search( ":\s\d{1,2}\.\d\d", response ):
434 main.log.info( self.name + ": Ping good!" )
435 return main.TRUE
436 main.log.info( self.name + ": Install fping on mininet machine... " )
437 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700438 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700439 except Exception:
440 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700441 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700442
Jon Hall3b489db2015-10-05 14:38:37 -0700443 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400444 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700445 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700446
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400447 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700448 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700449
450 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400451 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700452
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400453 Returns main.FALSE if one or more of hosts specified
454 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700455 wait = int( wait )
456 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400457
458 try:
459 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700460
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400461 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700462 pingResponse = "IPv4 ping across specified hosts\n"
463 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400464 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700465 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400466 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700467 pingList = hostList[ :listIndex ] + \
468 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700469
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700470 pingResponse += str( str( host ) + " -> " )
GlennRCd10d3cc2015-09-24 12:47:16 -0700471
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400472 for temp in pingList:
473 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700474 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700475 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700476 self.handle.expect( "mininet>", timeout=wait + 5 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400477 response = self.handle.before
478 if re.search( ',\s0\%\spacket\sloss', response ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700479 pingResponse += str( " h" + str( temp[ 1: ] ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400480 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700481 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400482 # One of the host to host pair is unreachable
483 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700484 failedPings += 1
You Wang11f9ead2018-03-21 14:34:59 -0700485 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
GlennRCd10d3cc2015-09-24 12:47:16 -0700486 pingResponse += "\n"
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700487 main.log.info( pingResponse + "Failed pings: " + str( failedPings ) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700488 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700489 except pexpect.TIMEOUT:
490 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800491 response = self.handle.before
492 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700493 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800494 self.handle.expect( "Interrupt" )
495 response += self.handle.before + self.handle.after
496 self.handle.expect( "mininet>" )
497 response += self.handle.before + self.handle.after
498 main.log.debug( response )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700499 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400500 except pexpect.EOF:
501 main.log.error( self.name + ": EOF exception found" )
502 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700503 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700504 except Exception:
505 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700506 main.cleanAndExit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400507
You Wangf19d9f42018-02-23 16:34:19 -0800508 def pingIpv6Hosts( self, hostList, wait=1, acceptableFailed=0 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700509 """
You Wangf19d9f42018-02-23 16:34:19 -0800510 IPv6 ping all hosts in hostList.
511
512 acceptableFailed: max number of acceptable failed pings
Hari Krishna9592fc82015-07-31 15:11:15 -0700513
Jon Hall3b489db2015-10-05 14:38:37 -0700514 Returns main.TRUE if all hosts specified can reach each other
Jon Hall3b489db2015-10-05 14:38:37 -0700515 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700516 """
517 try:
518 main.log.info( "Testing reachability between specified IPv6 hosts" )
519 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700520 wait = int( wait )
521 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700522 pingResponse = "IPv6 Pingall output:\n"
You Wangf19d9f42018-02-23 16:34:19 -0800523 failedPingsTotal = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700524 for host in hostList:
525 listIndex = hostList.index( host )
526 # List of hosts to ping other than itself
527 pingList = hostList[ :listIndex ] + \
528 hostList[ ( listIndex + 1 ): ]
529
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700530 pingResponse += str( str( host ) + " -> " )
GlennRC2cf7d952015-09-11 16:32:13 -0700531
Hari Krishna9592fc82015-07-31 15:11:15 -0700532 for temp in pingList:
533 # Current host pings all other hosts specified
You Wangf19d9f42018-02-23 16:34:19 -0800534 failedPings = 0
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700535 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
You Wangf19d9f42018-02-23 16:34:19 -0800536 while failedPings <= acceptableFailed:
537 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
538 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700539 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangf19d9f42018-02-23 16:34:19 -0800540 response = self.handle.before
541 if re.search( ',\s0\%\spacket\sloss', response ):
You Wangba231e72018-03-01 13:18:21 -0800542 pingResponse += " " + str( temp )
543 break
544 else:
545 failedPings += 1
546 time.sleep(1)
547 if failedPings > acceptableFailed:
548 # One of the host to host pair is unreachable
549 pingResponse += " X"
550 isReachable = main.FALSE
551 failedPingsTotal += 1
You Wang11f9ead2018-03-21 14:34:59 -0700552 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
You Wangba231e72018-03-01 13:18:21 -0800553 pingResponse += "\n"
554 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
555 return isReachable
556
557 except pexpect.TIMEOUT:
558 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800559 response = self.handle.before
560 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700561 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800562 self.handle.expect( "Interrupt" )
563 response += self.handle.before + self.handle.after
564 self.handle.expect( "mininet>" )
565 response += self.handle.before + self.handle.after
566 main.log.debug( response )
You Wangba231e72018-03-01 13:18:21 -0800567 return main.FALSE
568 except pexpect.EOF:
569 main.log.error( self.name + ": EOF exception found" )
570 main.log.error( self.name + ": " + self.handle.before )
571 main.cleanAndExit()
572 except Exception:
573 main.log.exception( self.name + ": Uncaught exception!" )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700574
575 main.cleanAndExit()
576
You Wang48381752018-05-07 13:50:57 -0700577 def discoverHosts( self, hostList=[], wait=1, dstIp="6.6.6.6", dstIp6="1020::3fe" ):
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700578 '''
You Wang48381752018-05-07 13:50:57 -0700579 Hosts in hostList will do a single ping to a non-existent address for ONOS to
580 discover them. A host will use ping/ping6 to send echo requests depending on if
581 it has IPv4/IPv6 addresses configured.
582 Optional:
583 hostList: a list of names of the hosts that need to be discovered. If not
584 specified mininet will send ping from all the hosts
585 wait: timeout for IPv4/IPv6 echo requests
586 dstIp: destination address used by IPv4 hosts
587 dstIp6: destination address used by IPv6 hosts
588 Returns:
589 main.TRUE if all ping packets were successfully sent. Otherwise main.FALSE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700590 '''
591 try:
You Wang48381752018-05-07 13:50:57 -0700592 if not hostList:
593 hosts = self.getHosts( getInterfaces=False )
594 hostList = hosts.keys()
595 discoveryResult = main.TRUE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700596 for host in hostList:
You Wang0b82aa52018-06-06 14:33:58 -0700597 flushCmd = ""
You Wang48381752018-05-07 13:50:57 -0700598 cmd = ""
599 if self.getIPAddress( host ):
You Wang0b82aa52018-06-06 14:33:58 -0700600 flushCmd = "{} ip neigh flush all".format( host )
You Wang48381752018-05-07 13:50:57 -0700601 cmd = "{} ping -c 1 -i 1 -W {} {}".format( host, wait, dstIp )
602 main.log.debug( "Sending IPv4 probe ping from host {}".format( host ) )
603 elif self.getIPAddress( host, proto='IPV6' ):
You Wang0b82aa52018-06-06 14:33:58 -0700604 flushCmd = "{} ip -6 neigh flush all".format( host )
You Wang48381752018-05-07 13:50:57 -0700605 cmd = "{} ping6 -c 1 -i 1 -W {} {}".format( host, wait, dstIp6 )
606 main.log.debug( "Sending IPv6 probe ping from host {}".format( host ) )
607 else:
608 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
609 discoveryResult = main.FALSE
610 if cmd:
You Wang0b82aa52018-06-06 14:33:58 -0700611 self.handle.sendline( flushCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700612 self.handle.expect( "mininet>" )
You Wang48381752018-05-07 13:50:57 -0700613 self.handle.sendline( cmd )
Jon Halla604fd42018-05-04 14:27:27 -0700614 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700615 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700616 except pexpect.TIMEOUT:
617 main.log.exception( self.name + ": TIMEOUT exception" )
618 response = self.handle.before
619 # NOTE: Send ctrl-c to make sure command is stopped
620 self.handle.send( "\x03" )
621 self.handle.expect( "Interrupt" )
622 response += self.handle.before + self.handle.after
623 self.handle.expect( "mininet>" )
624 response += self.handle.before + self.handle.after
625 main.log.debug( response )
626 return main.FALSE
627 except pexpect.EOF:
628 main.log.error( self.name + ": EOF exception found" )
629 main.log.error( self.name + ": " + self.handle.before )
630 main.cleanAndExit()
631 except Exception:
632 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800633 main.cleanAndExit()
634
635 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
636 """
637 Verify ping from each host in srcList to each host in dstList
638
639 acceptableFailed: max number of acceptable failed pings
640
641 Returns main.TRUE if all src hosts can reach all dst hosts
642 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
643 """
644 try:
645 main.log.info( "Verifying ping from each src host to each dst host" )
646 isReachable = main.TRUE
647 wait = int( wait )
648 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
649 pingResponse = "Ping output:\n"
650 failedPingsTotal = 0
651 for host in srcList:
652 pingResponse += str( str( host ) + " -> " )
653 for temp in dstList:
654 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700655 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
656 assert dstIP, "Not able to get IP address of host {}".format( temp )
657 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800658 while failedPings <= acceptableFailed:
659 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
660 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700661 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800662 response = self.handle.before
663 if re.search( ',\s0\%\spacket\sloss', response ):
664 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800665 break
666 else:
667 failedPings += 1
668 time.sleep(1)
669 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700670 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800671 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700672 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800673 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700674 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800675 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700676 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700677 except AssertionError:
678 main.log.exception( "" )
679 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700680 except pexpect.TIMEOUT:
681 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800682 response = self.handle.before
683 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700684 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800685 self.handle.expect( "Interrupt" )
686 response += self.handle.before + self.handle.after
687 self.handle.expect( "mininet>" )
688 response += self.handle.before + self.handle.after
689 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700690 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700691 except pexpect.EOF:
692 main.log.error( self.name + ": EOF exception found" )
693 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700694 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700695 except Exception:
696 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700697 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700698
Jon Hall7eb38402015-01-08 17:19:54 -0800699 def pingHost( self, **pingParams ):
700 """
Jon Hall3b489db2015-10-05 14:38:37 -0700701 Ping from one mininet host to another
702 Currently the only supported Params: SRC, TARGET, and WAIT
703 """
704 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700705 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700706 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800707 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700708 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700709 try:
Jon Hall61282e32015-03-19 11:34:11 -0700710 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800711 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700712 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700713 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700714 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800715 main.log.error(
716 self.name +
717 ": timeout when waiting for response from mininet" )
718 main.log.error( "response: " + str( self.handle.before ) )
719 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700720 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800721 main.log.error(
722 self.name +
723 ": timeout when waiting for response from mininet" )
724 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700725 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700726 if re.search( ',\s0\%\spacket\sloss', response ):
727 main.log.info( self.name + ": no packets lost, host is reachable" )
728 return main.TRUE
729 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800730 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700731 self.name +
732 ": PACKET LOST, HOST IS NOT REACHABLE" )
733 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800734 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800735 main.log.error( self.name + ": EOF exception found" )
736 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700737 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700738 except Exception:
739 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700740 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700741
742 def ping6pair( self, **pingParams ):
743 """
GlennRC2cf7d952015-09-11 16:32:13 -0700744 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700745 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000746 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700747 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
748 """
Jon Hall3b489db2015-10-05 14:38:37 -0700749 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700750 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700751 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530752 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700753 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700754 try:
755 main.log.info( "Sending: " + command )
756 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700757 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700758 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700759 if i == 1:
760 main.log.error(
761 self.name +
762 ": timeout when waiting for response from mininet" )
763 main.log.error( "response: " + str( self.handle.before ) )
764 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
765 if i == 1:
766 main.log.error(
767 self.name +
768 ": timeout when waiting for response from mininet" )
769 main.log.error( "response: " + str( self.handle.before ) )
770 response = self.handle.before
771 main.log.info( self.name + ": Ping Response: " + response )
772 if re.search( ',\s0\%\spacket\sloss', response ):
773 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700774 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700775 else:
alisone4121a92016-11-22 16:31:36 -0800776 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700777 self.name +
778 ": PACKET LOST, HOST IS NOT REACHABLE" )
779 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700780 except pexpect.EOF:
781 main.log.error( self.name + ": EOF exception found" )
782 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700783 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700784 except Exception:
785 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700786 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800787
You Wangdb927a52016-02-26 11:03:28 -0800788 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
789 """
790 Description:
791 Ping a set of destination host from host CLI.
792 Logging into a Mininet host CLI is required before calling this funtion.
793 Params:
794 dstIPList is a list of destination ip addresses
795 Returns:
796 main.TRUE if the destination host is reachable
797 main.FALSE otherwise
798 """
799 isReachable = main.TRUE
800 wait = int( wait )
801 cmd = "ping"
802 if IPv6:
803 cmd = cmd + "6"
804 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
805 try:
806 for dstIP in dstIPList:
807 pingCmd = cmd + " " + dstIP
808 self.handle.sendline( pingCmd )
809 i = self.handle.expect( [ self.hostPrompt,
810 '\*\*\* Unknown command: ' + pingCmd,
811 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700812 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700813 # For some reason we need to send something
814 # Otherwise ping results won't be read by handle
815 self.handle.sendline( "" )
816 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800817 if i == 0:
818 response = self.handle.before
819 if not re.search( ',\s0\%\spacket\sloss', response ):
820 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
821 isReachable = main.FALSE
822 elif i == 1:
823 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700824 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800825 elif i == 2:
826 main.log.error( self.name + ": timeout when waiting for response" )
827 isReachable = main.FALSE
828 else:
829 main.log.error( self.name + ": unknown response: " + self.handle.before )
830 isReachable = main.FALSE
831 except pexpect.TIMEOUT:
832 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800833 response = self.handle.before
834 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700835 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800836 self.handle.expect( "Interrupt" )
837 response += self.handle.before + self.handle.after
838 self.handle.expect( "mininet>" )
839 response += self.handle.before + self.handle.after
840 main.log.debug( response )
You Wangdb927a52016-02-26 11:03:28 -0800841 isReachable = main.FALSE
842 except pexpect.EOF:
843 main.log.error( self.name + ": EOF exception found" )
844 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700845 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800846 except Exception:
847 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700848 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800849 return isReachable
850
Jon Hall7eb38402015-01-08 17:19:54 -0800851 def checkIP( self, host ):
852 """
853 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700854 try:
855 if self.handle:
856 try:
857 response = self.execute(
858 cmd=host +
859 " ifconfig",
860 prompt="mininet>",
861 timeout=10 )
862 except pexpect.EOF:
863 main.log.error( self.name + ": EOF exception found" )
864 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700865 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700866
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700867 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
868 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
869 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
870 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
871 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
872 "[0-9]|25[0-5]|[0-9]{1,2})"
873 # pattern = "inet addr:10.0.0.6"
874 if re.search( pattern, response ):
875 main.log.info( self.name + ": Host Ip configured properly" )
876 return main.TRUE
877 else:
878 main.log.error( self.name + ": Host IP not found" )
879 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700880 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700881 main.log.error( self.name + ": Connection failed to the host" )
882 except Exception:
883 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700884 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800885
Jon Hall7eb38402015-01-08 17:19:54 -0800886 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800887 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700888 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800889 response = self.execute(
890 cmd="h1 /usr/sbin/sshd -D&",
891 prompt="mininet>",
892 timeout=10 )
893 response = self.execute(
894 cmd="h4 /usr/sbin/sshd -D&",
895 prompt="mininet>",
896 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700897 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800898 vars( self )[ key ] = connectargs[ key ]
899 response = self.execute(
900 cmd="xterm h1 h4 ",
901 prompt="mininet>",
902 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800903 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800904 main.log.error( self.name + ": EOF exception found" )
905 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700906 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700907 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800908 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700909 if self.flag == 0:
910 self.flag = 1
911 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800912 else:
adminbae64d82013-08-01 10:50:15 -0700913 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800914
Jonghwan Hyun785471d2018-05-14 14:48:19 -0700915 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=None ):
Jon Hall53c5e662016-04-13 16:06:56 -0700916 """
917 Moves a host from one switch to another on the fly
Jonghwan Hyun785471d2018-05-14 14:48:19 -0700918 If macAddr is specified, change MAC address of the host interface
919 to specified MAC address.
Jon Hall53c5e662016-04-13 16:06:56 -0700920 Note: The intf between host and oldSw when detached
921 using detach(), will still show up in the 'net'
922 cmd, because switch.detach() doesn't affect switch.intfs[]
923 ( which is correct behavior since the interfaces
924 haven't moved ).
925 """
926 if self.handle:
927 try:
928 # Bring link between oldSw-host down
929 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
930 "'," + "'down')"
931 print "cmd1= ", cmd
932 response = self.execute( cmd=cmd,
933 prompt="mininet>",
934 timeout=10 )
935
936 # Determine hostintf and Oldswitchintf
937 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
938 ")[0]"
939 print "cmd2= ", cmd
940 self.handle.sendline( cmd )
941 self.handle.expect( "mininet>" )
942
943 # Determine ip and mac address of the host-oldSw interface
944 cmd = "px ipaddr = hintf.IP()"
945 print "cmd3= ", cmd
946 self.handle.sendline( cmd )
947 self.handle.expect( "mininet>" )
948
Jonghwan Hyun785471d2018-05-14 14:48:19 -0700949 if macAddr is None:
950 cmd = "px macaddr = hintf.MAC()"
951 else:
952 cmd = 'px macaddr = "%s"' % macAddr
Jon Hall53c5e662016-04-13 16:06:56 -0700953 print "cmd3= ", cmd
954 self.handle.sendline( cmd )
955 self.handle.expect( "mininet>" )
956
957 # Detach interface between oldSw-host
958 cmd = "px " + oldSw + ".detach( sintf )"
959 print "cmd4= ", cmd
960 self.handle.sendline( cmd )
961 self.handle.expect( "mininet>" )
962
963 # Add link between host-newSw
964 cmd = "py net.addLink(" + host + "," + newSw + ")"
965 print "cmd5= ", cmd
966 self.handle.sendline( cmd )
967 self.handle.expect( "mininet>" )
968
969 # Determine hostintf and Newswitchintf
970 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jonghwan Hyun785471d2018-05-14 14:48:19 -0700971 ")[-1]"
Jon Hall53c5e662016-04-13 16:06:56 -0700972 print "cmd6= ", cmd
973 self.handle.sendline( cmd )
974 self.handle.expect( "mininet>" )
975
976 # Attach interface between newSw-host
977 cmd = "px " + newSw + ".attach( sintf )"
978 print "cmd3= ", cmd
979 self.handle.sendline( cmd )
980 self.handle.expect( "mininet>" )
981
982 # Set ipaddress of the host-newSw interface
Jonghwan Hyun785471d2018-05-14 14:48:19 -0700983 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf, " \
984 "prefixLen = %s )" % str( prefixLen )
Jon Hall53c5e662016-04-13 16:06:56 -0700985 print "cmd7 = ", cmd
986 self.handle.sendline( cmd )
987 self.handle.expect( "mininet>" )
988
989 # Set macaddress of the host-newSw interface
990 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
991 print "cmd8 = ", cmd
992 self.handle.sendline( cmd )
993 self.handle.expect( "mininet>" )
994
995 cmd = "net"
996 print "cmd9 = ", cmd
997 self.handle.sendline( cmd )
998 self.handle.expect( "mininet>" )
999 print "output = ", self.handle.before
1000
1001 # Determine ipaddress of the host-newSw interface
1002 cmd = host + " ifconfig"
1003 print "cmd10= ", cmd
1004 self.handle.sendline( cmd )
1005 self.handle.expect( "mininet>" )
1006 print "ifconfig o/p = ", self.handle.before
1007
1008 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001009
1010 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001011 main.log.error( self.name + ": TIMEOUT exception found" )
1012 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001013 main.cleanAndExit()
Jon Hall53c5e662016-04-13 16:06:56 -07001014 except pexpect.EOF:
1015 main.log.error( self.name + ": EOF exception found" )
1016 main.log.error( self.name + ": " + self.handle.before )
1017 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001018 except Exception:
1019 main.log.exception( self.name + ": Uncaught exception!" )
1020 return main.FALSE
Jon Hall53c5e662016-04-13 16:06:56 -07001021
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001022 def moveHostv6( self, host, oldSw, newSw, macAddr=None ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001023 """
1024 Moves a host from one switch to another on the fly
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001025 If macAddr is specified, change MAC address of the host interface
1026 to specified MAC address.
kelvin-onlaba1484582015-02-02 15:46:20 -08001027 Note: The intf between host and oldSw when detached
1028 using detach(), will still show up in the 'net'
1029 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -07001030 ( which is correct behavior since the interfaces
1031 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -08001032 """
1033 if self.handle:
1034 try:
Jon Hall439c8912016-04-15 02:22:03 -07001035 IP = str( self.getIPAddress( host, proto='IPV6' ) ) + "/64"
kelvin-onlaba1484582015-02-02 15:46:20 -08001036 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -07001037 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -08001038 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -08001039 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -08001040 response = self.execute( cmd=cmd,
1041 prompt="mininet>",
1042 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -07001043
kelvin-onlaba1484582015-02-02 15:46:20 -08001044 # Determine hostintf and Oldswitchintf
1045 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -08001046 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -08001047 print "cmd2= ", cmd
1048 self.handle.sendline( cmd )
1049 self.handle.expect( "mininet>" )
1050
shahshreya73537862015-02-11 15:15:24 -08001051 # Determine ip and mac address of the host-oldSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001052 cmd = "px ipaddr = " + str( IP )
kelvin-onlaba1484582015-02-02 15:46:20 -08001053 print "cmd3= ", cmd
1054 self.handle.sendline( cmd )
1055 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -08001056
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001057 if macAddr is None:
1058 cmd = "px macaddr = hintf.MAC()"
1059 else:
1060 cmd = 'px macaddr = "%s"' % macAddr
shahshreya73537862015-02-11 15:15:24 -08001061 print "cmd3= ", cmd
1062 self.handle.sendline( cmd )
1063 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001064
kelvin-onlaba1484582015-02-02 15:46:20 -08001065 # Detach interface between oldSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001066 cmd = "px " + oldSw + ".detach(sintf)"
kelvin-onlaba1484582015-02-02 15:46:20 -08001067 print "cmd4= ", cmd
1068 self.handle.sendline( cmd )
1069 self.handle.expect( "mininet>" )
1070
1071 # Add link between host-newSw
1072 cmd = "py net.addLink(" + host + "," + newSw + ")"
1073 print "cmd5= ", cmd
1074 self.handle.sendline( cmd )
1075 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001076
kelvin-onlaba1484582015-02-02 15:46:20 -08001077 # Determine hostintf and Newswitchintf
1078 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001079 ")[-1]"
kelvin-onlaba1484582015-02-02 15:46:20 -08001080 print "cmd6= ", cmd
1081 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -07001082 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001083
1084 # Attach interface between newSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001085 cmd = "px " + newSw + ".attach(sintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001086 print "cmd6= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001087 self.handle.sendline( cmd )
1088 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -08001089
1090 # Set macaddress of the host-newSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001091 cmd = "px " + host + ".setMAC(mac = macaddr, intf = hintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001092 print "cmd7 = ", cmd
1093 self.handle.sendline( cmd )
1094 self.handle.expect( "mininet>" )
1095
1096 # Set ipaddress of the host-newSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001097 cmd = "px " + host + ".setIP(ip = ipaddr, intf = hintf)"
shahshreya73537862015-02-11 15:15:24 -08001098 print "cmd8 = ", cmd
1099 self.handle.sendline( cmd )
1100 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001101
Jon Hall439c8912016-04-15 02:22:03 -07001102 cmd = host + " ifconfig"
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001103 print "cmd9 =", cmd
1104 response = self.execute( cmd = cmd, prompt="mininet>", timeout=10 )
Jon Hall439c8912016-04-15 02:22:03 -07001105 print response
1106 pattern = "h\d-eth([\w])"
Jeremyd9e4eb12016-04-13 12:09:06 -07001107 ipAddressSearch = re.search( pattern, response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001108 print ipAddressSearch.group( 1 )
1109 intf = host + "-eth" + str( ipAddressSearch.group( 1 ) )
Jon Hall439c8912016-04-15 02:22:03 -07001110 cmd = host + " ip -6 addr add %s dev %s" % ( IP, intf )
1111 print "cmd10 = ", cmd
1112 self.handle.sendline( cmd )
1113 self.handle.expect( "mininet>" )
1114
kelvin-onlaba1484582015-02-02 15:46:20 -08001115 cmd = "net"
Jon Hall439c8912016-04-15 02:22:03 -07001116 print "cmd11 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001117 self.handle.sendline( cmd )
1118 self.handle.expect( "mininet>" )
1119 print "output = ", self.handle.before
1120
1121 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -08001122 cmd = host + " ifconfig"
Jon Hall439c8912016-04-15 02:22:03 -07001123 print "cmd12= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001124 self.handle.sendline( cmd )
1125 self.handle.expect( "mininet>" )
1126 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -07001127
kelvin-onlaba1484582015-02-02 15:46:20 -08001128 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001129 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001130 main.log.error( self.name + ": TIMEOUT exception found" )
1131 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001132 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08001133 except pexpect.EOF:
1134 main.log.error( self.name + ": EOF exception found" )
1135 main.log.error( self.name + ": " + self.handle.before )
1136 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001137 except Exception:
1138 main.log.exception( self.name + ": Uncaught exception!" )
1139 return main.FALSE
kelvin-onlaba1484582015-02-02 15:46:20 -08001140
Jon Hall7eb38402015-01-08 17:19:54 -08001141 def changeIP( self, host, intf, newIP, newNetmask ):
1142 """
1143 Changes the ip address of a host on the fly
1144 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001145 if self.handle:
1146 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001147 cmd = host + " ifconfig " + intf + " " + \
1148 newIP + " " + 'netmask' + " " + newNetmask
1149 self.handle.sendline( cmd )
1150 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001151 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001152 main.log.info( "response = " + response )
1153 main.log.info(
1154 "Ip of host " +
1155 host +
1156 " changed to new IP " +
1157 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -08001158 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001159 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001160 main.log.error( self.name + ": TIMEOUT exception found" )
1161 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001162 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001163 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001164 main.log.error( self.name + ": EOF exception found" )
1165 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001166 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001167 except Exception:
1168 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001169 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001170
Jon Hall7eb38402015-01-08 17:19:54 -08001171 def changeDefaultGateway( self, host, newGW ):
1172 """
1173 Changes the default gateway of a host
1174 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001175 if self.handle:
1176 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001177 cmd = host + " route add default gw " + newGW
1178 self.handle.sendline( cmd )
1179 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001180 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001181 main.log.info( "response = " + response )
1182 main.log.info(
1183 "Default gateway of host " +
1184 host +
1185 " changed to " +
1186 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -08001187 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001188 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001189 main.log.error( self.name + ": TIMEOUT exception found" )
1190 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001191 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001192 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001193 main.log.error( self.name + ": EOF exception found" )
1194 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001195 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001196 except Exception:
1197 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001198 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001199
You Wange24d6272018-03-27 21:18:50 -07001200 def addRoute( self, host, dstIP, interface, ipv6=False ):
1201 """
1202 Add a route to host
1203 Ex: h1 route add -host 224.2.0.1 h1-eth0
1204 """
1205 if self.handle:
1206 try:
1207 cmd = str( host )
1208 if ipv6:
1209 cmd += " route -A inet6 add "
1210 else:
1211 cmd += " route add -host "
1212 cmd += str( dstIP ) + " " + str( interface )
1213 self.handle.sendline( cmd )
1214 self.handle.expect( "mininet>" )
1215 response = self.handle.before
1216 main.log.debug( "response = " + response )
1217 return main.TRUE
1218 except pexpect.TIMEOUT:
1219 main.log.error( self.name + ": TIMEOUT exception found" )
1220 main.log.error( self.name + ": " + self.handle.before )
1221 main.cleanAndExit()
1222 except pexpect.EOF:
1223 main.log.error( self.name + ": EOF exception found" )
1224 main.log.error( self.name + ": " + self.handle.before )
1225 return main.FALSE
1226 except Exception:
1227 main.log.exception( self.name + ": Uncaught exception!" )
1228 main.cleanAndExit()
1229
Jon Hall7eb38402015-01-08 17:19:54 -08001230 def addStaticMACAddress( self, host, GW, macaddr ):
1231 """
Jon Hallefbd9792015-03-05 16:11:36 -08001232 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001233 if self.handle:
1234 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001235 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1236 cmd = host + " arp -s " + GW + " " + macaddr
1237 self.handle.sendline( cmd )
1238 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001239 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001240 main.log.info( "response = " + response )
1241 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001242 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001243 GW +
1244 " changed to " +
1245 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001246 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001247 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001248 main.log.error( self.name + ": TIMEOUT exception found" )
1249 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001250 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001251 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001252 main.log.error( self.name + ": EOF exception found" )
1253 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001254 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001255 except Exception:
1256 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001257 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001258
Jon Hall7eb38402015-01-08 17:19:54 -08001259 def verifyStaticGWandMAC( self, host ):
1260 """
1261 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001262 if self.handle:
1263 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001264 # h1 arp -an
1265 cmd = host + " arp -an "
1266 self.handle.sendline( cmd )
1267 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001268 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001269 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001270 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001271 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001272 main.log.error( self.name + ": TIMEOUT exception found" )
1273 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001274 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001275 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001276 main.log.error( self.name + ": EOF exception found" )
1277 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001278 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001279 except Exception:
1280 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001281 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001282
Jon Hall7eb38402015-01-08 17:19:54 -08001283 def getMacAddress( self, host ):
1284 """
1285 Verifies the host's ip configured or not."""
1286 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001287 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001288 response = self.execute(
1289 cmd=host +
1290 " ifconfig",
1291 prompt="mininet>",
1292 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001293 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001294 main.log.error( self.name + ": EOF exception found" )
1295 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001296 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001297 except Exception:
1298 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001299 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001300
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001301 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001302 macAddressSearch = re.search( pattern, response, re.I )
1303 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001304 main.log.info(
1305 self.name +
1306 ": Mac-Address of Host " +
1307 host +
1308 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001309 macAddress )
1310 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001311 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001312 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001313
Jon Hall7eb38402015-01-08 17:19:54 -08001314 def getInterfaceMACAddress( self, host, interface ):
1315 """
1316 Return the IP address of the interface on the given host"""
1317 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001318 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001319 response = self.execute( cmd=host + " ifconfig " + interface,
1320 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001321 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001322 main.log.error( self.name + ": EOF exception found" )
1323 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001324 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001325 except Exception:
1326 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001327 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001328
1329 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001330 macAddressSearch = re.search( pattern, response, re.I )
1331 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001332 main.log.info( "No mac address found in %s" % response )
1333 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001334 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001335 main.log.info(
1336 "Mac-Address of " +
1337 host +
1338 ":" +
1339 interface +
1340 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001341 macAddress )
1342 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001343 else:
1344 main.log.error( "Connection failed to the host" )
1345
You Wang5da39c82018-04-26 22:55:08 -07001346 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001347 """
1348 Verifies the host's ip configured or not."""
1349 if self.handle:
1350 try:
1351 response = self.execute(
1352 cmd=host +
1353 " ifconfig",
1354 prompt="mininet>",
1355 timeout=10 )
1356 except pexpect.EOF:
1357 main.log.error( self.name + ": EOF exception found" )
1358 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001359 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001360 except Exception:
1361 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001362 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001363
sathishmad953462015-12-03 17:42:07 +05301364 pattern = ''
1365 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001366 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301367 else:
Jon Hall439c8912016-04-15 02:22:03 -07001368 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001369 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001370 if not ipAddressSearch:
1371 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001372 main.log.info(
1373 self.name +
1374 ": IP-Address of Host " +
1375 host +
1376 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001377 ipAddressSearch.group( 1 ) )
1378 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001379 else:
1380 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001381
Jon Hall7eb38402015-01-08 17:19:54 -08001382 def getSwitchDPID( self, switch ):
1383 """
1384 return the datapath ID of the switch"""
1385 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001386 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001387 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001388 response = self.execute(
1389 cmd=cmd,
1390 prompt="mininet>",
1391 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001392 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001393 main.log.error( self.name + ": EOF exception found" )
1394 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001395 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001396 except Exception:
1397 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001398 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001399 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001400 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001401 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001402 main.log.info(
1403 "Couldn't find DPID for switch %s, found: %s" %
1404 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001405 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001406 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001407 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001408 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001409
Jon Hall7eb38402015-01-08 17:19:54 -08001410 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001411 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001412 self.handle.sendline( "" )
1413 self.expect( "mininet>" )
1414 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001415 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001416 response = self.execute(
1417 cmd=cmd,
1418 prompt="mininet>",
1419 timeout=10 )
1420 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001421 response = self.handle.before
1422 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001423 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001424 main.log.error( self.name + ": TIMEOUT exception found" )
1425 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001426 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001427 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001428 main.log.error( self.name + ": EOF exception found" )
1429 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001430 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001431 except Exception:
1432 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001433 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001434
Jon Hall7eb38402015-01-08 17:19:54 -08001435 def getInterfaces( self, node ):
1436 """
1437 return information dict about interfaces connected to the node"""
1438 if self.handle:
1439 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001440 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001441 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001442 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001443 response = self.execute(
1444 cmd=cmd,
1445 prompt="mininet>",
1446 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001447 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001448 main.log.error( self.name + ": EOF exception found" )
1449 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001450 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001451 except Exception:
1452 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001453 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001454 return response
1455 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001456 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001457
Jon Hall7eb38402015-01-08 17:19:54 -08001458 def dump( self ):
1459 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001460 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001461 response = self.execute(
1462 cmd='dump',
1463 prompt='mininet>',
1464 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001465 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001466 main.log.error( self.name + ": EOF exception found" )
1467 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001468 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001469 except Exception:
1470 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001471 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001472 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001473
Jon Hall7eb38402015-01-08 17:19:54 -08001474 def intfs( self ):
1475 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001476 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001477 response = self.execute(
1478 cmd='intfs',
1479 prompt='mininet>',
1480 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001481 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001482 main.log.error( self.name + ": EOF exception found" )
1483 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001484 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001485 except Exception:
1486 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001487 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001488 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001489
Jon Hall7eb38402015-01-08 17:19:54 -08001490 def net( self ):
1491 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001492 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001493 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001494 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001495 main.log.error( self.name + ": EOF exception found" )
1496 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001497 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001498 except Exception:
1499 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001500 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001501 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001502
Devin Lima7cfdbd2017-09-29 15:02:22 -07001503 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001504 main.log.info( self.name + ": List network links" )
1505 try:
1506 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001507 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001508 except pexpect.EOF:
1509 main.log.error( self.name + ": EOF exception found" )
1510 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001511 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001512 except Exception:
1513 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001514 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001515 return response
1516
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001517 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001518 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001519 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001520
kelvin-onlab7cce9382015-07-17 10:21:03 -07001521 @parm:
1522 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1523 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001524 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001525 try:
1526 for host1 in hosts:
1527 for host2 in hosts:
1528 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001529 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1530 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001531 except Exception:
1532 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001533 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001534
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001535 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001536 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001537 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1538 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001539
kelvin-onlab7cce9382015-07-17 10:21:03 -07001540 @parm:
1541 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1542 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001543 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001544 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1545 try:
1546 # Setup the mininet command
1547 cmd1 = 'iperf ' + host1 + " " + host2
1548 self.handle.sendline( cmd1 )
1549 outcome = self.handle.expect( "mininet>", timeout )
1550 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001551
kelvin-onlab7cce9382015-07-17 10:21:03 -07001552 # checks if there are results in the mininet response
1553 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001554 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001555 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001556 response = response.split( "\r\n" )
1557 response = response[ len( response )-2 ]
1558 response = response.split( ": " )
1559 response = response[ len( response )-1 ]
1560 response = response.replace( "[", "" )
1561 response = response.replace( "]", "" )
1562 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001563
kelvin-onlab7cce9382015-07-17 10:21:03 -07001564 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001565 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001566
kelvin-onlab7cce9382015-07-17 10:21:03 -07001567 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001568 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001569 if len( bandwidth ) == 2:
1570 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001571 return main.TRUE
1572 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001573 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001574 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001575 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001576 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001577 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001578 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001579 main.log.error( self.name + ": TIMEOUT exception found" )
1580 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001581 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001582 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001583 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001584 self.handle.expect( "Interrupt" )
1585 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001586 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001587 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001588 main.log.error( self.name + ": EOF exception found" )
1589 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001590 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001591 except Exception:
1592 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001593 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001594
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001595 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001596 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1597 try:
1598 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001599 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001600 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001601 outcome1 = self.handle.expect( "mininet>" )
1602 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001603 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001604 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001605 response1 = self.handle.before
1606 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001607 print response1, response2
1608 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001609 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001610 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001611 return main.TRUE
1612 else:
1613 main.log.error( self.name + ": iperf test failed" )
1614 return main.FALSE
1615 except pexpect.TIMEOUT:
1616 main.log.error( self.name + ": TIMEOUT exception found" )
1617 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001618 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001619 self.handle.expect( "Interrupt" )
1620 self.handle.expect( "mininet>" )
1621 return main.FALSE
1622 except pexpect.EOF:
1623 main.log.error( self.name + ": EOF exception found" )
1624 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001625 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001626 except Exception:
1627 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001628 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001629
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001630 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001631 '''
GlennRC61321f22015-07-16 13:36:54 -07001632 Runs the iperfudp function with a given set of hosts and specified
1633 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001634
GlennRC61321f22015-07-16 13:36:54 -07001635 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001636 bandwidth: the targeted bandwidth, in megabits ('M')
1637 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001638 try:
1639 for host1 in hosts:
1640 for host2 in hosts:
1641 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001642 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1643 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001644 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001645 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001646 return main.FALSE
1647 except Exception:
1648 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001649 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001650
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001651 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001652 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001653 Creates an iperf UDP test with a specific bandwidth.
1654 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001655
kelvin-onlab7cce9382015-07-17 10:21:03 -07001656 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001657 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1658 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001659 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001660 try:
1661 # setup the mininet command
1662 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001663 self.handle.sendline( cmd )
1664 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001665 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001666
kelvin-onlab7cce9382015-07-17 10:21:03 -07001667 # check if there are in results in the mininet response
1668 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001669 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001670 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001671 response = response.split( "\r\n" )
1672 response = response[ len( response )-2 ]
1673 response = response.split( ": " )
1674 response = response[ len( response )-1 ]
1675 response = response.replace( "[", "" )
1676 response = response.replace( "]", "" )
1677 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001678
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001679 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001680
kelvin-onlab7cce9382015-07-17 10:21:03 -07001681 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001682 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001683 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001684 # if one entry is blank then something is wrong
1685 for item in mnBandwidth:
1686 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001687 main.log.error( self.name + ": Could not parse iperf output" )
1688 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001689 return main.FALSE
1690 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001691 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001692 return main.TRUE
1693 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001694 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001695 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001696
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001697 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001698 main.log.error( self.name + ": TIMEOUT exception found" )
1699 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001700 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001701 except pexpect.EOF:
1702 main.log.error( self.name + ": EOF exception found" )
1703 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001704 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001705 except Exception:
1706 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001707 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001708
Jon Hall7eb38402015-01-08 17:19:54 -08001709 def nodes( self ):
1710 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001711 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001712 response = self.execute(
1713 cmd='nodes',
1714 prompt='mininet>',
1715 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001716 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001717 main.log.error( self.name + ": EOF exception found" )
1718 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001719 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001720 except Exception:
1721 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001722 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001723 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001724
Jon Hall7eb38402015-01-08 17:19:54 -08001725 def pingpair( self ):
1726 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001727 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001728 response = self.execute(
1729 cmd='pingpair',
1730 prompt='mininet>',
1731 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001732 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001733 main.log.error( self.name + ": EOF exception found" )
1734 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001735 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001736 except Exception:
1737 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001738 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001739
Jon Hall7eb38402015-01-08 17:19:54 -08001740 if re.search( ',\s0\%\spacket\sloss', response ):
1741 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001742 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001743 else:
alisone4121a92016-11-22 16:31:36 -08001744 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001745 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001746
Jon Hall7eb38402015-01-08 17:19:54 -08001747 def link( self, **linkargs ):
1748 """
GlennRCed771242016-01-13 17:02:47 -08001749 Bring link( s ) between two nodes up or down
1750 """
Jon Hall6094a362014-04-11 14:46:56 -07001751 try:
GlennRCed771242016-01-13 17:02:47 -08001752 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1753 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1754 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1755 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1756
1757 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1758 cmd = "link {} {} {}".format( end1, end2, option )
1759 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001760 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001761 response = self.handle.before
1762 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001763 if "not in network" in response:
1764 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1765 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001766 return main.TRUE
1767 except pexpect.TIMEOUT:
1768 main.log.exception( self.name + ": Command timed out" )
1769 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001770 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001771 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001772 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001773 except Exception:
1774 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001775 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001776
pingping-lin8244a3b2015-09-16 13:36:56 -07001777 def switch( self, **switchargs ):
1778 """
1779 start/stop a switch
1780 """
1781 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1782 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1783 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1784 command = "switch " + str( sw ) + " " + str( option )
1785 main.log.info( command )
1786 try:
1787 self.handle.sendline( command )
1788 self.handle.expect( "mininet>" )
1789 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001790 main.log.error( self.name + ": TIMEOUT exception found" )
1791 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001792 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001793 except pexpect.EOF:
1794 main.log.error( self.name + ": EOF exception found" )
1795 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001796 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001797 return main.TRUE
1798
pingping-lin5bb663b2015-09-24 11:47:50 -07001799 def node( self, nodeName, commandStr ):
1800 """
1801 Carry out a command line on a given node
1802 @parm:
1803 nodeName: the node name in Mininet testbed
1804 commandStr: the command line will be carried out on the node
1805 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1806 """
1807 command = str( nodeName ) + " " + str( commandStr )
1808 main.log.info( command )
1809
1810 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001811 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001812 if re.search( "Unknown command", response ):
1813 main.log.warn( response )
1814 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001815 if re.search( "Permission denied", response ):
1816 main.log.warn( response )
1817 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001818 except pexpect.EOF:
1819 main.log.error( self.name + ": EOF exception found" )
1820 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001821 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001822 main.log.info( " response is :" )
1823 main.log.info( response )
1824 return response
1825
Jon Hall7eb38402015-01-08 17:19:54 -08001826 def yank( self, **yankargs ):
1827 """
1828 yank a mininet switch interface to a host"""
1829 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001830 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001831 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1832 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001833 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001834 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001835 response = self.execute(
1836 cmd=command,
1837 prompt="mininet>",
1838 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001839 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001840 main.log.error( self.name + ": EOF exception found" )
1841 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001842 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001843 except Exception:
1844 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001845 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001846 return main.TRUE
1847
Jon Hall7eb38402015-01-08 17:19:54 -08001848 def plug( self, **plugargs ):
1849 """
1850 plug the yanked mininet switch interface to a switch"""
1851 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001852 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001853 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1854 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001855 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001856 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001857 response = self.execute(
1858 cmd=command,
1859 prompt="mininet>",
1860 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001861 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001862 main.log.error( self.name + ": EOF exception found" )
1863 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001864 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001865 except Exception:
1866 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001867 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001868 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001869
Jon Hall7eb38402015-01-08 17:19:54 -08001870 def dpctl( self, **dpctlargs ):
1871 """
1872 Run dpctl command on all switches."""
1873 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001874 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001875 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1876 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1877 command = "dpctl " + cmd + " " + str( cmdargs )
1878 try:
1879 response = self.execute(
1880 cmd=command,
1881 prompt="mininet>",
1882 timeout=10 )
1883 except pexpect.EOF:
1884 main.log.error( self.name + ": EOF exception found" )
1885 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001886 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001887 except Exception:
1888 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001889 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001890 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001891
kelvin-onlabd3b64892015-01-20 13:26:24 -08001892 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001893 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001894 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001895 try:
1896 fileInput = path + '/lib/Mininet/INSTALL'
1897 version = super( Mininet, self ).getVersion()
1898 pattern = 'Mininet\s\w\.\w\.\w\w*'
1899 for line in open( fileInput, 'r' ).readlines():
1900 result = re.match( pattern, line )
1901 if result:
1902 version = result.group( 0 )
1903 return version
1904 except Exception:
1905 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001906 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001907
kelvin-onlabd3b64892015-01-20 13:26:24 -08001908 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001909 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001910 Parameters:
1911 sw: The name of an OVS switch. Example "s1"
1912 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001913 The output of the command from the mininet cli
1914 or main.FALSE on timeout"""
1915 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001916 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001917 response = self.execute(
1918 cmd=command,
1919 prompt="mininet>",
1920 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001921 if response:
Jon Hallab611372018-02-21 15:26:05 -08001922 if "no bridge named" in response:
1923 main.log.error( self.name + ": Error in getSwController: " +
1924 self.handle.before )
1925 return main.FALSE
1926 else:
1927 return response
admin2a9548d2014-06-17 14:08:07 -07001928 else:
1929 return main.FALSE
1930 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001931 main.log.error( self.name + ": EOF exception found" )
1932 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001933 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001934 except Exception:
1935 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001936 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001937
Charles Chan029be652015-08-24 01:46:10 +08001938 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001939 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001940 Description:
1941 Assign switches to the controllers ( for ovs use only )
1942 Required:
1943 sw - Name of the switch. This can be a list or a string.
1944 ip - Ip addresses of controllers. This can be a list or a string.
1945 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001946 port - ONOS use port 6653, if no list of ports is passed, then
1947 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001948 ptcp - ptcp number, This can be a string or a list that has
1949 the same length as switch. This is optional and not required
1950 when using ovs switches.
1951 NOTE: If switches and ptcp are given in a list type they should have the
1952 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1953 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001954
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001955 Return:
1956 Returns main.TRUE if mininet correctly assigned switches to
1957 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001958 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001959 """
1960 assignResult = main.TRUE
1961 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001962 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001963 command = "sh ovs-vsctl set-controller "
1964 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001965 try:
1966 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001967 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001968 if isinstance( port, types.StringType ) or \
1969 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001970 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001971 elif isinstance( port, types.ListType ):
1972 main.log.error( self.name + ": Only one controller " +
1973 "assigned and a list of ports has" +
1974 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001975 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001976 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001977 main.log.error( self.name + ": Invalid controller port " +
1978 "number. Please specify correct " +
1979 "controller port" )
1980 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001981
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001982 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001983 if isinstance( port, types.StringType ) or \
1984 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001985 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001986 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1987 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001988 elif isinstance( port, types.ListType ):
1989 if ( len( ip ) != len( port ) ):
1990 main.log.error( self.name + ": Port list = " +
1991 str( len( port ) ) +
1992 "should be the same as controller" +
1993 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001994 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001995 else:
1996 onosIp = ""
1997 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001998 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1999 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002000 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002001 main.log.error( self.name + ": Invalid controller port " +
2002 "number. Please specify correct " +
2003 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002004 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07002005 else:
2006 main.log.error( self.name + ": Invalid ip address" )
2007 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002008
2009 if isinstance( sw, types.StringType ):
2010 command += sw + " "
2011 if ptcp:
2012 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07002013 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002014 elif isinstance( ptcp, types.ListType ):
2015 main.log.error( self.name + ": Only one switch is " +
2016 "being set and multiple PTCP is " +
2017 "being passed " )
2018 else:
2019 main.log.error( self.name + ": Invalid PTCP" )
2020 ptcp = ""
2021 command += onosIp
2022 commandList.append( command )
2023
2024 elif isinstance( sw, types.ListType ):
2025 if ptcp:
2026 if isinstance( ptcp, types.ListType ):
2027 if len( ptcp ) != len( sw ):
2028 main.log.error( self.name + ": PTCP length = " +
2029 str( len( ptcp ) ) +
2030 " is not the same as switch" +
2031 " length = " +
2032 str( len( sw ) ) )
2033 return main.FALSE
2034 else:
2035 for switch, ptcpNum in zip( sw, ptcp ):
2036 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07002037 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07002038 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002039 tempCmd += onosIp
2040 commandList.append( tempCmd )
2041 else:
2042 main.log.error( self.name + ": Invalid PTCP" )
2043 return main.FALSE
2044 else:
2045 for switch in sw:
2046 tempCmd = "sh ovs-vsctl set-controller "
2047 tempCmd += switch + " " + onosIp
2048 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002049 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002050 main.log.error( self.name + ": Invalid switch type " )
2051 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002052
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002053 for cmd in commandList:
2054 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002055 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08002056 if "no bridge named" in self.handle.before:
2057 main.log.error( self.name + ": Error in assignSwController: " +
2058 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002059 except pexpect.TIMEOUT:
2060 main.log.error( self.name + ": pexpect.TIMEOUT found" )
2061 return main.FALSE
2062 except pexpect.EOF:
2063 main.log.error( self.name + ": EOF exception found" )
2064 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002065 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002066 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002067 except pexpect.EOF:
2068 main.log.error( self.name + ": EOF exception found" )
2069 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002070 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002071 except Exception:
2072 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002073 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07002074
kelvin-onlabd3b64892015-01-20 13:26:24 -08002075 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08002076 """
2077 Removes the controller target from sw"""
2078 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07002079 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002080 response = self.execute(
2081 cmd=command,
2082 prompt="mininet>",
2083 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08002084 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002085 main.log.error( self.name + ": EOF exception found" )
2086 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002087 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002088 except Exception:
2089 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002090 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002091 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002092 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07002093
kelvin-onlabd3b64892015-01-20 13:26:24 -08002094 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002095 """
Jon Hallb1290e82014-11-18 16:17:48 -05002096 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002097 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002098 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002099 NOTE: cannot currently specify what type of switch
2100 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08002101 sw = name of the new switch as a string
2102 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05002103 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08002104 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002105 """
2106 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002107 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05002108 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002109 response = self.execute(
2110 cmd=command,
2111 prompt="mininet>",
2112 timeout=10 )
2113 if re.search( "already exists!", response ):
2114 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002115 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002116 elif re.search( "Error", response ):
2117 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002118 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002119 elif re.search( "usage:", response ):
2120 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002121 return main.FALSE
2122 else:
2123 return main.TRUE
2124 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002125 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07002126 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002127 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002128 except Exception:
2129 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002130 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002131
kelvin-onlabd3b64892015-01-20 13:26:24 -08002132 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08002133 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08002134 delete a switch from the mininet topology
2135 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002136 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08002137 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08002138 sw = name of the switch as a string
2139 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002140 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05002141 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002142 response = self.execute(
2143 cmd=command,
2144 prompt="mininet>",
2145 timeout=10 )
2146 if re.search( "no switch named", response ):
2147 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002148 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002149 elif re.search( "Error", response ):
2150 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002151 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002152 elif re.search( "usage:", response ):
2153 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002154 return main.FALSE
2155 else:
2156 return main.TRUE
2157 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002158 main.log.error( self.name + ": EOF exception found" )
2159 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002160 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002161 except Exception:
2162 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002163 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002164
You Wangdb8cd0a2016-05-26 15:19:45 -07002165 def getSwitchRandom( self, timeout=60, nonCut=True ):
2166 """
2167 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002168 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002169 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002170 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002171 it just randomly returns one switch from all current switches in
2172 Mininet.
2173 Returns the name of the chosen switch.
2174 """
2175 import random
2176 candidateSwitches = []
2177 try:
2178 if not nonCut:
2179 switches = self.getSwitches( timeout=timeout )
2180 assert len( switches ) != 0
2181 for switchName in switches.keys():
2182 candidateSwitches.append( switchName )
2183 else:
2184 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002185 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002186 return None
2187 self.graph.update( graphDict )
2188 candidateSwitches = self.graph.getNonCutVertices()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002189 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002190 return None
2191 elif len( candidateSwitches ) == 0:
2192 main.log.info( self.name + ": No candidate switch for deletion" )
2193 return None
2194 else:
2195 switch = random.sample( candidateSwitches, 1 )
2196 return switch[ 0 ]
2197 except KeyError:
2198 main.log.exception( self.name + ": KeyError exception found" )
2199 return None
2200 except AssertionError:
2201 main.log.exception( self.name + ": AssertionError exception found" )
2202 return None
2203 except Exception:
2204 main.log.exception( self.name + ": Uncaught exception" )
2205 return None
2206
2207 def delSwitchRandom( self, timeout=60, nonCut=True ):
2208 """
2209 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002210 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002211 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002212 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002213 otherwise it just randomly delete one switch from all current
2214 switches in Mininet.
2215 Returns the name of the deleted switch
2216 """
2217 try:
2218 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002219 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002220 return None
2221 else:
2222 deletionResult = self.delSwitch( switch )
2223 if deletionResult:
2224 return switch
2225 else:
2226 return None
2227 except Exception:
2228 main.log.exception( self.name + ": Uncaught exception" )
2229 return None
2230
kelvin-onlabd3b64892015-01-20 13:26:24 -08002231 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002232 """
2233 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002234 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002235 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002236 NOTE: cannot currently specify what type of link
2237 required params:
2238 node1 = the string node name of the first endpoint of the link
2239 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002240 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002241 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002242 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002243 response = self.execute(
2244 cmd=command,
2245 prompt="mininet>",
2246 timeout=10 )
2247 if re.search( "doesnt exist!", response ):
2248 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002249 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002250 elif re.search( "Error", response ):
2251 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002252 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002253 elif re.search( "usage:", response ):
2254 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002255 return main.FALSE
2256 else:
2257 return main.TRUE
2258 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002259 main.log.error( self.name + ": EOF exception found" )
2260 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002261 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002262 except Exception:
2263 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002264 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002265
kelvin-onlabd3b64892015-01-20 13:26:24 -08002266 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002267 """
2268 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002269 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002270 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002271 required params:
2272 node1 = the string node name of the first endpoint of the link
2273 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002274 returns: main.FALSE on an error, else main.TRUE
2275 """
Jon Hallffb386d2014-11-21 13:43:38 -08002276 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002277 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002278 response = self.execute(
2279 cmd=command,
2280 prompt="mininet>",
2281 timeout=10 )
2282 if re.search( "no node named", response ):
2283 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002284 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002285 elif re.search( "Error", response ):
2286 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002287 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002288 elif re.search( "usage:", response ):
2289 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002290 return main.FALSE
2291 else:
2292 return main.TRUE
2293 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002294 main.log.error( self.name + ": EOF exception found" )
2295 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002296 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002297 except Exception:
2298 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002299 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002300
You Wangdb8cd0a2016-05-26 15:19:45 -07002301 def getLinkRandom( self, timeout=60, nonCut=True ):
2302 """
2303 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002304 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002305 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002306 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002307 it just randomly returns one link from all current links in
2308 Mininet.
2309 Returns the link as a list, e.g. [ 's1', 's2' ]
2310 """
2311 import random
2312 candidateLinks = []
2313 try:
2314 if not nonCut:
2315 links = self.getLinks( timeout=timeout )
2316 assert len( links ) != 0
2317 for link in links:
2318 # Exclude host-switch link
2319 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2320 continue
2321 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2322 else:
2323 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002324 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002325 return None
2326 self.graph.update( graphDict )
2327 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002328 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002329 return None
2330 elif len( candidateLinks ) == 0:
2331 main.log.info( self.name + ": No candidate link for deletion" )
2332 return None
2333 else:
2334 link = random.sample( candidateLinks, 1 )
2335 return link[ 0 ]
2336 except KeyError:
2337 main.log.exception( self.name + ": KeyError exception found" )
2338 return None
2339 except AssertionError:
2340 main.log.exception( self.name + ": AssertionError exception found" )
2341 return None
2342 except Exception:
2343 main.log.exception( self.name + ": Uncaught exception" )
2344 return None
2345
2346 def delLinkRandom( self, timeout=60, nonCut=True ):
2347 """
2348 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002349 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002350 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002351 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002352 otherwise it just randomly delete one link from all current links
2353 in Mininet.
2354 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2355 """
2356 try:
2357 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002358 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002359 return None
2360 else:
2361 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2362 if deletionResult:
2363 return link
2364 else:
2365 return None
2366 except Exception:
2367 main.log.exception( self.name + ": Uncaught exception" )
2368 return None
2369
kelvin-onlabd3b64892015-01-20 13:26:24 -08002370 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002371 """
Jon Hallb1290e82014-11-18 16:17:48 -05002372 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002373 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002374 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002375 NOTE: cannot currently specify what type of host
2376 required params:
2377 hostname = the string hostname
2378 optional key-value params
2379 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002380 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002381 """
2382 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002383 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002384 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002385 response = self.execute(
2386 cmd=command,
2387 prompt="mininet>",
2388 timeout=10 )
2389 if re.search( "already exists!", response ):
2390 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002391 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002392 elif re.search( "doesnt exists!", response ):
2393 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002394 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002395 elif re.search( "Error", response ):
2396 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002397 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002398 elif re.search( "usage:", response ):
2399 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002400 return main.FALSE
2401 else:
2402 return main.TRUE
2403 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002404 main.log.error( self.name + ": EOF exception found" )
2405 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002406 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002407 except Exception:
2408 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002409 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002410
kelvin-onlabd3b64892015-01-20 13:26:24 -08002411 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002412 """
2413 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002414 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002415 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002416 NOTE: this uses a custom mn function
2417 required params:
2418 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002419 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002420 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002421 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002422 response = self.execute(
2423 cmd=command,
2424 prompt="mininet>",
2425 timeout=10 )
2426 if re.search( "no host named", response ):
2427 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002428 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002429 elif re.search( "Error", response ):
2430 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002431 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002432 elif re.search( "usage:", response ):
2433 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002434 return main.FALSE
2435 else:
2436 return main.TRUE
2437 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002438 main.log.error( self.name + ": EOF exception found" )
2439 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002440 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002441 except Exception:
2442 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002443 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002444
Jon Hall7eb38402015-01-08 17:19:54 -08002445 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002446 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002447 Called at the end of the test to stop the mininet and
2448 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002449 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002450 try:
2451 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002452 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002453 timeout=2 )
2454 response = main.TRUE
2455 if i == 0:
2456 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002457 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002458 return main.TRUE
2459 # print "Disconnecting Mininet"
2460 if self.handle:
2461 self.handle.sendline( "exit" )
2462 self.handle.expect( "exit" )
2463 self.handle.expect( "(.*)" )
2464 else:
2465 main.log.error( "Connection failed to the host" )
2466 return response
2467 except pexpect.EOF:
2468 main.log.error( self.name + ": EOF exception found" )
2469 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002470 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002471 except Exception:
2472 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002473 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002474
Devin Lima7cfdbd2017-09-29 15:02:22 -07002475 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002476 """
Jon Hall21270ac2015-02-16 17:59:55 -08002477 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002478 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002479 main.FALSE if the pexpect handle does not exist.
2480
Jon Halld61331b2015-02-17 16:35:47 -08002481 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002482 """
Jon Halld61331b2015-02-17 16:35:47 -08002483 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002484 response = ''
2485 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002486 try:
Jon Halld80cc142015-07-06 13:36:05 -07002487 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002488 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002489 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002490 pexpect.EOF,
2491 pexpect.TIMEOUT ],
2492 timeout )
2493 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002494 main.log.info( "Exiting mininet.." )
2495 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002496 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002497 prompt=self.prompt,
2498 timeout=exitTimeout )
2499 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002500 self.handle.sendline( "sudo mn -c" )
2501 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002502
Jeremyd9e4eb12016-04-13 12:09:06 -07002503 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002504 main.log.info( " Mininet trying to exit while not " +
2505 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002506 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002507 elif i == 2:
2508 main.log.error( "Something went wrong exiting mininet" )
2509 elif i == 3: # timeout
2510 main.log.error( "Something went wrong exiting mininet " +
2511 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002512
You Wang18db8592018-04-02 13:52:03 -07002513 self.handle.sendline( "" )
2514 self.handle.expect( self.prompt )
2515 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2516
Hari Krishnab35c6d02015-03-18 11:13:51 -07002517 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002518 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002519 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002520 self.handle.sendline(
2521 "sudo kill -9 \`ps -ef | grep \"" +
2522 fileName +
2523 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002524 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002525 main.log.error( self.name + ": TIMEOUT exception found" )
2526 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002527 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002528 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002529 main.log.error( self.name + ": EOF exception found" )
2530 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002531 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002532 except Exception:
2533 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002534 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002535 else:
2536 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002537 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002538 return response
2539
YPZhang26a139e2016-04-25 14:01:55 -07002540 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002541 """
2542 Description:
2543 Sends arp message from mininet host for hosts discovery
2544 Required:
2545 host - hosts name
2546 Optional:
2547 ip - ip address that does not exist in the network so there would
2548 be no reply.
2549 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002550 if ethDevice:
2551 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002552 cmd = srcHost + " arping -c1 "
2553 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002554 cmd += "-w10 " # If we don't want the actural arping result, set -w10, arping will exit after 10 ms.
YPZhang26a139e2016-04-25 14:01:55 -07002555 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002556 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002557 if output:
2558 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002559 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002560 i = self.handle.expect( [ "mininet>", "arping: " ] )
2561 if i == 0:
2562 return main.TRUE
2563 elif i == 1:
2564 response = self.handle.before + self.handle.after
2565 self.handle.expect( "mininet>" )
2566 response += self.handle.before + self.handle.after
2567 main.log.warn( "Error sending arping, output was: " +
2568 response )
2569 return main.FALSE
2570 except pexpect.TIMEOUT:
2571 main.log.error( self.name + ": TIMEOUT exception found" )
2572 main.log.warn( self.handle.before )
2573 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002574 except pexpect.EOF:
2575 main.log.error( self.name + ": EOF exception found" )
2576 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002577 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002578 except Exception:
2579 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002580 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002581
Jon Hall7eb38402015-01-08 17:19:54 -08002582 def decToHex( self, num ):
2583 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002584
Jon Hall7eb38402015-01-08 17:19:54 -08002585 def getSwitchFlowCount( self, switch ):
2586 """
2587 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002588 if self.handle:
2589 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2590 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002591 response = self.execute(
2592 cmd=cmd,
2593 prompt="mininet>",
2594 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002595 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002596 main.log.error( self.name + ": EOF exception found" )
2597 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002598 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002599 except Exception:
2600 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002601 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002602 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002603 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002604 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002605 main.log.info(
2606 "Couldn't find flows on switch %s, found: %s" %
2607 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002608 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002609 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002610 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002611 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002612
Jon Hall9ed8f372016-02-24 17:34:07 -08002613 def checkFlows( self, sw, dumpFormat=None ):
2614 if dumpFormat:
2615 command = "sh ovs-ofctl -F " + \
2616 dumpFormat + " dump-flows " + str( sw )
2617 else:
2618 command = "sh ovs-ofctl dump-flows " + str( sw )
2619 try:
2620 response = self.execute(
2621 cmd=command,
2622 prompt="mininet>",
2623 timeout=10 )
2624 return response
2625 except pexpect.EOF:
2626 main.log.error( self.name + ": EOF exception found" )
2627 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002628 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002629 except Exception:
2630 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002631 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002632
GlennRC68467eb2015-11-16 18:01:01 -08002633 def flowTableComp( self, flowTable1, flowTable2 ):
2634 # This function compares the selctors and treatments of each flow
2635 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002636 assert flowTable1, "flowTable1 is empty or None"
2637 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002638 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002639 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002640 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002641 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002642 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2643 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002644 for field in dFields:
2645 try:
2646 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002647 except KeyError:
2648 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002649 try:
2650 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002651 except KeyError:
2652 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002653 for i in range( len( flowTable1 ) ):
2654 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002655 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002656 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002657 returnValue = main.FALSE
2658 break
2659 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002660 except AssertionError:
2661 main.log.exception( "Nothing to compare" )
2662 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002663 except Exception:
2664 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002665 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002666
GlennRC528ad292015-11-12 10:38:18 -08002667 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002668 '''
GlennRC956ea742015-11-05 16:14:15 -08002669 Discription: Parses flows into json format.
2670 NOTE: this can parse any string thats separated with commas
2671 Arguments:
2672 Required:
2673 flows: a list of strings that represnt flows
2674 Optional:
2675 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2676 debug: prints out the final result
2677 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002678 '''
GlennRC528ad292015-11-12 10:38:18 -08002679 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002680 try:
2681 for flow in flowTable:
2682 jsonFlow = {}
2683 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002684 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002685 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002686 for i in range( len( parsedFlow ) ):
2687 item = parsedFlow[ i ]
2688 if item[ 0 ] == " ":
2689 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002690 # grab the selector and treatment from the parsed flow
2691 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002692 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002693 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002694 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002695 index = 0
2696 # parse the flags
2697 # NOTE: This only parses one flag
2698 flag = {}
2699 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002700 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002701 index += 1
2702 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002703 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002704 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002705 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002706 # the priority is stuck in the selecter so put it back
2707 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002708 if 'priority' in sel[0]:
2709 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002710 # parse selector
2711 criteria = []
2712 for item in sel:
2713 # this is the type of the packet e.g. "arp"
2714 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002715 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002716 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002717 field = item.split( "=" )
2718 criteria.append( { field[ 0 ]: field[ 1 ] } )
2719 selector = { "selector": { "criteria": sorted( criteria ) } }
2720 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002721 # get rid of the action part e.g. "action=output:2"
2722 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002723 treat = treat.split( "=" )
2724 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002725 # parse treatment
2726 action = []
2727 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002728 if ":" in item:
2729 field = item.split( ":" )
2730 action.append( { field[ 0 ]: field[ 1 ] } )
2731 else:
2732 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2733 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002734 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002735 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002736 # parse the rest of the flow
2737 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002738 field = item.split( "=" )
2739 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002740 # add the treatment and the selector to the json flow
2741 jsonFlow.update( selector )
2742 jsonFlow.update( treatment )
2743 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002744
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002745 if debug:
2746 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002747
You Wang91c37cf2016-05-23 09:39:42 -07002748 # add the json flow to the json flow table
2749 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002750
You Wang91c37cf2016-05-23 09:39:42 -07002751 return jsonFlowTable
2752
2753 except IndexError:
2754 main.log.exception( self.name + ": IndexError found" )
2755 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002756 except pexpect.EOF:
2757 main.log.error( self.name + ": EOF exception found" )
2758 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002759 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002760 except Exception:
2761 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002762 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002763
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002764 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002765 '''
2766 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002767 Each element is a flow.
2768 Arguments:
2769 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002770 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002771 a list of switches.
2772 Optional:
2773 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2774 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002775 '''
GlennRC956ea742015-11-05 16:14:15 -08002776 try:
2777 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002778 if isinstance( sw, list ):
2779 switches.extend( sw )
2780 else:
2781 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002782
2783 flows = []
2784 for s in switches:
2785 cmd = "sh ovs-ofctl dump-flows " + s
2786
GlennRC528ad292015-11-12 10:38:18 -08002787 if "1.0" == version:
2788 cmd += " -F OpenFlow10-table_id"
2789 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002790 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002791
2792 main.log.info( "Sending: " + cmd )
2793 self.handle.sendline( cmd )
2794 self.handle.expect( "mininet>" )
2795 response = self.handle.before
2796 response = response.split( "\r\n" )
2797 # dump the first two elements and the last
2798 # the first element is the command that was sent
2799 # the second is the table header
2800 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002801 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002802 flows.extend( response )
2803
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002804 if debug:
2805 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002806
GlennRC528ad292015-11-12 10:38:18 -08002807 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002808
GlennRC956ea742015-11-05 16:14:15 -08002809 except pexpect.EOF:
2810 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002811 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002812 except Exception:
2813 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002814 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002815
2816 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002817 '''
GlennRC956ea742015-11-05 16:14:15 -08002818 Discription: Checks whether the ID provided matches a flow ID in Mininet
2819 Arguments:
2820 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002821 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002822 a list of switches.
2823 flowId: the flow ID in hex format. Can also be a list of IDs
2824 Optional:
2825 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2826 debug: prints out the final result
2827 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2828 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002829 '''
GlennRC956ea742015-11-05 16:14:15 -08002830 try:
2831 main.log.info( "Getting flows from Mininet" )
2832 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002833 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002834 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002835
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002836 if debug:
2837 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002838
2839 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002840 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002841 result = False
2842 for f in flows:
2843 if flowId in f.get( 'cookie' ):
2844 result = True
2845 break
2846 # flowId is a list
2847 else:
2848 result = True
2849 # Get flow IDs from Mininet
2850 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2851 # Save the IDs that are not in Mininet
2852 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2853
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002854 if debug:
2855 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002856
2857 # Print out the IDs that are not in Mininet
2858 if absentIds:
2859 main.log.warn( "Absent ids: {}".format( absentIds ) )
2860 result = False
2861
2862 return main.TRUE if result else main.FALSE
2863
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002864 except pexpect.EOF:
2865 main.log.error( self.name + ": EOF exception found" )
2866 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002867 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002868 except Exception:
2869 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002870 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002871
Charles Chan029be652015-08-24 01:46:10 +08002872 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002873 """
Jon Hallefbd9792015-03-05 16:11:36 -08002874 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002875 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002876 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002877 self.handle.sendline( "" )
2878 self.handle.expect( "mininet>" )
2879 self.handle.sendline(
2880 "sh sudo tcpdump -n -i " +
2881 intf +
2882 " " +
2883 port +
2884 " -w " +
2885 filename.strip() +
2886 " &" )
2887 self.handle.sendline( "" )
2888 i = self.handle.expect( [ 'No\ssuch\device',
2889 'listening\son',
2890 pexpect.TIMEOUT,
2891 "mininet>" ],
2892 timeout=10 )
2893 main.log.warn( self.handle.before + self.handle.after )
2894 self.handle.sendline( "" )
2895 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002896 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002897 main.log.error(
2898 self.name +
2899 ": tcpdump - No such device exists. " +
2900 "tcpdump attempted on: " +
2901 intf )
admin2a9548d2014-06-17 14:08:07 -07002902 return main.FALSE
2903 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002904 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002905 return main.TRUE
2906 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002907 main.log.error(
2908 self.name +
2909 ": tcpdump command timed out! Check interface name," +
2910 " given interface was: " +
2911 intf )
admin2a9548d2014-06-17 14:08:07 -07002912 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002913 elif i == 3:
2914 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002915 return main.TRUE
2916 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002917 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002918 return main.FALSE
2919 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002920 main.log.error( self.name + ": EOF exception found" )
2921 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002922 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002923 except Exception:
2924 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002925 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002926
kelvin-onlabd3b64892015-01-20 13:26:24 -08002927 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002928 """
2929 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002930 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002931 self.handle.sendline( "sh sudo pkill tcpdump" )
2932 self.handle.expect( "mininet>" )
2933 self.handle.sendline( "" )
2934 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002935 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002936 main.log.error( self.name + ": TIMEOUT exception found" )
2937 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002938 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002939 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002940 main.log.error( self.name + ": EOF exception found" )
2941 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002942 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002943 except Exception:
2944 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002945 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002946
Jon Halld80cc142015-07-06 13:36:05 -07002947 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002948 """
2949 Read ports from a Mininet switch.
2950
2951 Returns a json structure containing information about the
2952 ports of the given switch.
2953 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002954 try:
2955 response = self.getInterfaces( nodeName )
2956 # TODO: Sanity check on response. log if no such switch exists
2957 ports = []
2958 for line in response.split( "\n" ):
2959 if not line.startswith( "name=" ):
2960 continue
2961 portVars = {}
2962 for var in line.split( "," ):
2963 key, value = var.split( "=" )
2964 portVars[ key ] = value
2965 isUp = portVars.pop( 'enabled', "True" )
2966 isUp = "True" in isUp
2967 if verbose:
2968 main.log.info( "Reading switch port %s(%s)" %
2969 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2970 mac = portVars[ 'mac' ]
2971 if mac == 'None':
2972 mac = None
2973 ips = []
2974 ip = portVars[ 'ip' ]
2975 if ip == 'None':
2976 ip = None
2977 ips.append( ip )
2978 name = portVars[ 'name' ]
2979 if name == 'None':
2980 name = None
2981 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2982 if name == 'lo':
2983 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2984 else:
2985 portNo = re.search( portRe, name ).group( 'port' )
2986 ports.append( { 'of_port': portNo,
2987 'mac': str( mac ).replace( '\'', '' ),
2988 'name': name,
2989 'ips': ips,
2990 'enabled': isUp } )
2991 return ports
2992 except pexpect.EOF:
2993 main.log.error( self.name + ": EOF exception found" )
2994 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002995 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002996 except Exception:
2997 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002998 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002999
You Wangdb8cd0a2016-05-26 15:19:45 -07003000 def getOVSPorts( self, nodeName ):
3001 """
3002 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
3003
3004 Returns a list of dictionaries containing information about each
3005 port of the given switch.
3006 """
3007 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
3008 try:
3009 response = self.execute(
3010 cmd=command,
3011 prompt="mininet>",
3012 timeout=10 )
3013 ports = []
3014 if response:
3015 for line in response.split( "\n" ):
3016 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
3017 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003018 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07003019 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
3020 result = re.search( pattern, line )
3021 if result:
3022 index = result.group( 'index' )
3023 name = result.group( 'name' )
3024 # This port number is extracted from port name
3025 port = result.group( 'port' )
3026 mac = result.group( 'mac' )
3027 ports.append( { 'index': index,
3028 'name': name,
3029 'port': port,
3030 'mac': mac } )
3031 return ports
3032 except pexpect.EOF:
3033 main.log.error( self.name + ": EOF exception found" )
3034 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003035 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003036 except Exception:
3037 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003038 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003039
Devin Lima7cfdbd2017-09-29 15:02:22 -07003040 def getSwitches( self, verbose=False, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07003041 """
3042 Read switches from Mininet.
3043
3044 Returns a dictionary whose keys are the switch names and the value is
3045 a dictionary containing information about the switch.
3046 """
Jon Halla22481b2015-07-28 17:46:01 -07003047 # NOTE: To support new Mininet switch classes, just append the new
3048 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07003049
Jon Halla22481b2015-07-28 17:46:01 -07003050 # Regex patterns to parse 'dump' output
3051 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07003052 # <OVSSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=5238>
Jon Halld80cc142015-07-06 13:36:05 -07003053 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07003054 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
3055 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
3056 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003057 try:
3058 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
3059 swRE = r"<(?P<class>" + switchClasses + r")" +\
3060 r"(?P<options>\{.*\})?\s" +\
3061 r"(?P<name>[^:]+)\:\s" +\
3062 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
3063 r"\spid=(?P<pid>(\d)+)"
3064 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07003065 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003066 output = {}
3067 dump = self.dump().split( "\n" )
3068 for line in dump:
3069 result = re.search( swRE, line, re.I )
3070 if result:
3071 name = result.group( 'name' )
3072 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
3073 pid = result.group( 'pid' )
3074 swClass = result.group( 'class' )
3075 options = result.group( 'options' )
3076 if verbose:
3077 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
3078 ports = self.getPorts( name )
3079 output[ name ] = { "dpid": dpid,
3080 "ports": ports,
3081 "swClass": swClass,
3082 "pid": pid,
3083 "options": options }
3084 return output
3085 except pexpect.EOF:
3086 main.log.error( self.name + ": EOF exception found" )
3087 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003088 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003089 except Exception:
3090 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003091 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003092
You Wangd66de192018-04-30 17:30:12 -07003093 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08003094 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
3095 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07003096 """
3097 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08003098 Optional:
3099 hostClass: it is used to match the class of the mininet host. It
3100 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07003101 Returns a dictionary whose keys are the host names and the value is
3102 a dictionary containing information about the host.
3103 """
3104 # Regex patterns to parse dump output
3105 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07003106 # <Host h1: pid=12725>
3107 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
3108 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
3109 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07003110 # NOTE: Does not correctly match hosts with multi-links
3111 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
3112 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003113 try:
You Wang53dba1e2018-02-02 17:45:44 -08003114 if not isinstance( hostClass, types.ListType ):
3115 hostClass = [ str( hostClass ) ]
3116 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08003117 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
3118 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
3119 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07003120 if update:
3121 # update mn port info
3122 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003123 # Get mininet dump
3124 dump = self.dump().split( "\n" )
3125 hosts = {}
3126 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08003127 result = re.search( hostRE, line )
3128 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003129 name = result.group( 'name' )
3130 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07003131 if getInterfaces:
3132 response = self.getInterfaces( name )
3133 # Populate interface info
3134 for line in response.split( "\n" ):
3135 if line.startswith( "name=" ):
3136 portVars = {}
3137 for var in line.split( "," ):
3138 key, value = var.split( "=" )
3139 portVars[ key ] = value
3140 isUp = portVars.pop( 'enabled', "True" )
3141 isUp = "True" in isUp
3142 if verbose:
3143 main.log.info( "Reading host port %s(%s)" %
3144 ( portVars[ 'name' ],
3145 portVars[ 'mac' ] ) )
3146 mac = portVars[ 'mac' ]
3147 if mac == 'None':
3148 mac = None
3149 ips = []
3150 ip = portVars[ 'ip' ]
3151 if ip == 'None':
3152 ip = None
3153 ips.append( ip )
3154 intfName = portVars[ 'name' ]
3155 if name == 'None':
3156 name = None
3157 interfaces.append( {
3158 "name": intfName,
3159 "ips": ips,
3160 "mac": str( mac ),
3161 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003162 hosts[ name ] = { "interfaces": interfaces }
3163 return hosts
3164 except pexpect.EOF:
3165 main.log.error( self.name + ": EOF exception found" )
3166 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003167 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003168 except Exception:
3169 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003170 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003171
Devin Lima7cfdbd2017-09-29 15:02:22 -07003172 def getLinks( self, timeout=20, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07003173 """
3174 Gathers information about current Mininet links. These links may not
3175 be up if one of the ports is down.
3176
3177 Returns a list of dictionaries with link endpoints.
3178
3179 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07003180 { 'node1': str( node1 name )
3181 'node2': str( node2 name )
3182 'port1': str( port1 of_port )
3183 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07003184 Note: The port number returned is the eth#, not necessarily the of_port
3185 number. In Mininet, for OVS switch, these should be the same. For
3186 hosts, this is just the eth#.
3187 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003188 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003189 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003190 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07003191
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003192 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003193 # s1-eth3<->s2-eth1 (OK OK)
3194 # s13-eth3<->h27-eth0 (OK OK)
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003195 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
3196 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
3197 links = []
3198 for line in response:
3199 match = re.search( linkRE, line )
3200 if match:
3201 node1 = match.group( 'node1' )
3202 node2 = match.group( 'node2' )
3203 port1 = match.group( 'port1' )
3204 port2 = match.group( 'port2' )
3205 links.append( { 'node1': node1,
3206 'node2': node2,
3207 'port1': port1,
3208 'port2': port2 } )
3209 return links
3210
3211 except pexpect.EOF:
3212 main.log.error( self.name + ": EOF exception found" )
3213 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003214 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003215 except Exception:
3216 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003217 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003218
3219 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003220 """
3221 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003222 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003223
Jon Hallafa8a472015-06-12 14:02:42 -07003224 Dependencies:
3225 1. numpy - "sudo pip install numpy"
3226 """
3227 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003228 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003229 try:
3230 mnDPIDs = []
3231 for swName, switch in switches.iteritems():
3232 mnDPIDs.append( switch[ 'dpid' ].lower() )
3233 mnDPIDs.sort()
3234 if switchesJson == "": # if rest call fails
3235 main.log.error(
3236 self.name +
3237 ".compareSwitches(): Empty JSON object given from ONOS" )
3238 return main.FALSE
3239 onos = switchesJson
3240 onosDPIDs = []
3241 for switch in onos:
3242 if switch[ 'available' ]:
3243 onosDPIDs.append(
3244 switch[ 'id' ].replace(
3245 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003246 '' ).replace(
3247 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003248 '' ).lower() )
3249 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003250
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003251 if mnDPIDs != onosDPIDs:
3252 switchResults = main.FALSE
3253 main.log.error( "Switches in MN but not in ONOS:" )
3254 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3255 main.log.error( str( list1 ) )
3256 main.log.error( "Switches in ONOS but not in MN:" )
3257 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3258 main.log.error( str( list2 ) )
3259 else: # list of dpid's match in onos and mn
3260 switchResults = main.TRUE
3261 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003262
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003263 # FIXME: this does not look for extra ports in ONOS, only checks that
3264 # ONOS has what is in MN
3265 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003266
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003267 # PORTS
3268 for name, mnSwitch in switches.iteritems():
3269 mnPorts = []
3270 onosPorts = []
3271 switchResult = main.TRUE
3272 for port in mnSwitch[ 'ports' ]:
3273 if port[ 'enabled' ]:
3274 mnPorts.append( int( port[ 'of_port' ] ) )
3275 for onosSwitch in portsJson:
3276 if onosSwitch[ 'device' ][ 'available' ]:
3277 if onosSwitch[ 'device' ][ 'id' ].replace(
3278 ':',
3279 '' ).replace(
3280 "of",
3281 '' ) == mnSwitch[ 'dpid' ]:
3282 for port in onosSwitch[ 'ports' ]:
3283 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003284 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003285 # onosPorts.append( 'local' )
3286 onosPorts.append( long( uint64( -2 ) ) )
3287 else:
3288 onosPorts.append( int( port[ 'port' ] ) )
3289 break
3290 mnPorts.sort( key=float )
3291 onosPorts.sort( key=float )
3292
3293 mnPortsLog = mnPorts
3294 onosPortsLog = onosPorts
3295 mnPorts = [ x for x in mnPorts ]
3296 onosPorts = [ x for x in onosPorts ]
3297
3298 # TODO: handle other reserved port numbers besides LOCAL
3299 # NOTE: Reserved ports
3300 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3301 # long( uint64( -2 ) )
3302 for mnPort in mnPortsLog:
3303 if mnPort in onosPorts:
3304 # don't set results to true here as this is just one of
3305 # many checks and it might override a failure
3306 mnPorts.remove( mnPort )
3307 onosPorts.remove( mnPort )
3308
3309 # NOTE: OVS reports this as down since there is no link
3310 # So ignoring these for now
3311 # TODO: Come up with a better way of handling these
3312 if 65534 in mnPorts:
3313 mnPorts.remove( 65534 )
3314 if long( uint64( -2 ) ) in onosPorts:
3315 onosPorts.remove( long( uint64( -2 ) ) )
3316 if len( mnPorts ): # the ports of this switch don't match
3317 switchResult = main.FALSE
3318 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3319 if len( onosPorts ): # the ports of this switch don't match
3320 switchResult = main.FALSE
3321 main.log.warn(
3322 "Ports in ONOS but not MN: " +
3323 str( onosPorts ) )
3324 if switchResult == main.FALSE:
3325 main.log.error(
3326 "The list of ports for switch %s(%s) does not match:" %
3327 ( name, mnSwitch[ 'dpid' ] ) )
3328 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3329 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3330 portsResults = portsResults and switchResult
3331 finalResults = finalResults and portsResults
3332 return finalResults
3333 except pexpect.EOF:
3334 main.log.error( self.name + ": EOF exception found" )
3335 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003336 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003337 except Exception:
3338 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003339 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003340
Jon Hallafa8a472015-06-12 14:02:42 -07003341 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003342 """
3343 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003344 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003345
Jon Hallafa8a472015-06-12 14:02:42 -07003346 """
Jon Hall7eb38402015-01-08 17:19:54 -08003347 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003348 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003349 try:
3350 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003351
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003352 mnLinks = []
3353 for l in links:
3354 try:
3355 node1 = switches[ l[ 'node1' ] ]
3356 node2 = switches[ l[ 'node2' ] ]
3357 enabled = True
3358 for port in node1[ 'ports' ]:
3359 if port[ 'of_port' ] == l[ 'port1' ]:
3360 enabled = enabled and port[ 'enabled' ]
3361 for port in node2[ 'ports' ]:
3362 if port[ 'of_port' ] == l[ 'port2' ]:
3363 enabled = enabled and port[ 'enabled' ]
3364 if enabled:
3365 mnLinks.append( l )
3366 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003367 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003368 if 2 * len( mnLinks ) == len( onos ):
3369 linkResults = main.TRUE
3370 else:
3371 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003372 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003373 "Mininet has " + str( len( mnLinks ) ) +
3374 " bidirectional links and ONOS has " +
3375 str( len( onos ) ) + " unidirectional links" )
3376
3377 # iterate through MN links and check if an ONOS link exists in
3378 # both directions
3379 for link in mnLinks:
3380 # TODO: Find a more efficient search method
3381 node1 = None
3382 port1 = None
3383 node2 = None
3384 port2 = None
3385 firstDir = main.FALSE
3386 secondDir = main.FALSE
3387 for swName, switch in switches.iteritems():
3388 if swName == link[ 'node1' ]:
3389 node1 = switch[ 'dpid' ]
3390 for port in switch[ 'ports' ]:
3391 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3392 port1 = port[ 'of_port' ]
3393 if node1 is not None and node2 is not None:
3394 break
3395 if swName == link[ 'node2' ]:
3396 node2 = switch[ 'dpid' ]
3397 for port in switch[ 'ports' ]:
3398 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3399 port2 = port[ 'of_port' ]
3400 if node1 is not None and node2 is not None:
3401 break
3402
3403 for onosLink in onos:
3404 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3405 ":", '' ).replace( "of", '' )
3406 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3407 ":", '' ).replace( "of", '' )
3408 onosPort1 = onosLink[ 'src' ][ 'port' ]
3409 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3410
3411 # check onos link from node1 to node2
3412 if str( onosNode1 ) == str( node1 ) and str(
3413 onosNode2 ) == str( node2 ):
3414 if int( onosPort1 ) == int( port1 ) and int(
3415 onosPort2 ) == int( port2 ):
3416 firstDir = main.TRUE
3417 else:
Jon Hallab611372018-02-21 15:26:05 -08003418 # The right switches, but wrong ports, could be
3419 # another link between these devices, or onos
3420 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003421 main.log.warn(
3422 'The port numbers do not match for ' +
3423 str( link ) +
3424 ' between ONOS and MN. When checking ONOS for ' +
3425 'link %s/%s -> %s/%s' %
3426 ( node1, port1, node2, port2 ) +
3427 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003428 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3429 '. This could be another link between these devices' +
3430 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003431
3432 # check onos link from node2 to node1
3433 elif ( str( onosNode1 ) == str( node2 ) and
3434 str( onosNode2 ) == str( node1 ) ):
3435 if ( int( onosPort1 ) == int( port2 )
3436 and int( onosPort2 ) == int( port1 ) ):
3437 secondDir = main.TRUE
3438 else:
Jon Hallab611372018-02-21 15:26:05 -08003439 # The right switches, but wrong ports, could be
3440 # another link between these devices, or onos
3441 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003442 main.log.warn(
3443 'The port numbers do not match for ' +
3444 str( link ) +
3445 ' between ONOS and MN. When checking ONOS for ' +
3446 'link %s/%s -> %s/%s' %
3447 ( node1, port1, node2, port2 ) +
3448 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003449 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3450 '. This could be another link between these devices' +
3451 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003452 else: # this is not the link you're looking for
3453 pass
3454 if not firstDir:
3455 main.log.error(
3456 'ONOS does not have the link %s/%s -> %s/%s' %
3457 ( node1, port1, node2, port2 ) )
3458 if not secondDir:
3459 main.log.error(
3460 'ONOS does not have the link %s/%s -> %s/%s' %
3461 ( node2, port2, node1, port1 ) )
3462 linkResults = linkResults and firstDir and secondDir
3463 return linkResults
3464 except pexpect.EOF:
3465 main.log.error( self.name + ": EOF exception found" )
3466 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003467 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003468 except Exception:
3469 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003470 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003471
Jon Hallafa8a472015-06-12 14:02:42 -07003472 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003473 """
Jon Hallafa8a472015-06-12 14:02:42 -07003474 Compare mn and onos Hosts.
3475 Since Mininet hosts are quiet, ONOS will only know of them when they
3476 speak. For this reason, we will only check that the hosts in ONOS
3477 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003478
Jon Hallafa8a472015-06-12 14:02:42 -07003479 Arguments:
3480 hostsJson: parsed json object from the onos hosts api
3481 Returns:
3482 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003483 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003484 try:
3485 hostResults = main.TRUE
3486 for onosHost in hostsJson:
3487 onosMAC = onosHost[ 'mac' ].lower()
3488 match = False
3489 for mnHost, info in hosts.iteritems():
3490 for mnIntf in info[ 'interfaces' ]:
3491 if onosMAC == mnIntf[ 'mac' ].lower():
3492 match = True
3493 for ip in mnIntf[ 'ips' ]:
3494 if ip in onosHost[ 'ipAddresses' ]:
3495 pass # all is well
3496 else:
3497 # misssing ip
3498 main.log.error( "ONOS host " +
3499 onosHost[ 'id' ] +
3500 " has a different IP(" +
3501 str( onosHost[ 'ipAddresses' ] ) +
3502 ") than the Mininet host(" +
3503 str( ip ) +
3504 ")." )
3505 output = json.dumps(
3506 onosHost,
3507 sort_keys=True,
3508 indent=4,
3509 separators=( ',', ': ' ) )
3510 main.log.info( output )
3511 hostResults = main.FALSE
3512 if not match:
3513 hostResults = main.FALSE
3514 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3515 "corresponding Mininet host." )
3516 output = json.dumps( onosHost,
3517 sort_keys=True,
3518 indent=4,
3519 separators=( ',', ': ' ) )
3520 main.log.info( output )
3521 return hostResults
3522 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003523 main.log.error( self.name + ": EOF exception found" )
3524 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003525 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003526 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003527 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003528 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003529
You Wangd66de192018-04-30 17:30:12 -07003530 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003531 """
3532 Description:
3533 Verify that all hosts have IP address assigned to them
3534 Optional:
3535 hostList: If specified, verifications only happen to the hosts
3536 in hostList
3537 prefix: at least one of the ip address assigned to the host
3538 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003539 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003540 Returns:
3541 main.TRUE if all hosts have specific IP address assigned;
3542 main.FALSE otherwise
3543 """
3544 try:
You Wangd66de192018-04-30 17:30:12 -07003545 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003546 if not hostList:
3547 hostList = hosts.keys()
3548 for hostName in hosts.keys():
3549 if hostName not in hostList:
3550 continue
3551 ipList = []
3552 self.handle.sendline( str( hostName ) + " ip a" )
3553 self.handle.expect( "mininet>" )
3554 ipa = self.handle.before
3555 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3556 ipList += re.findall( ipv4Pattern, ipa )
3557 # It's tricky to make regex for IPv6 addresses and this one is simplified
3558 ipv6Pattern = r'inet6 ((?:[0-9a-fA-F]{1,4})?(?:[:0-9a-fA-F]{1,4}){1,7}(?:::)?(?:[:0-9a-fA-F]{1,4}){1,7})/'
3559 ipList += re.findall( ipv6Pattern, ipa )
3560 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3561 if not ipList:
3562 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3563 else:
3564 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3565 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3566 else:
3567 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3568 hostList.remove( hostName )
3569 return main.FALSE if hostList else main.TRUE
3570 except KeyError:
3571 main.log.exception( self.name + ": host data not as expected: " + hosts )
3572 return None
3573 except pexpect.EOF:
3574 main.log.error( self.name + ": EOF exception found" )
3575 main.log.error( self.name + ": " + self.handle.before )
3576 main.cleanAndExit()
3577 except Exception:
3578 main.log.exception( self.name + ": Uncaught exception" )
3579 return None
3580
Jon Hallafa8a472015-06-12 14:02:42 -07003581 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003582 """
3583 Returns a list of all hosts
3584 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003585 try:
3586 self.handle.sendline( "" )
3587 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003588
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003589 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3590 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003591
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003592 handlePy = self.handle.before
3593 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3594 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003595
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003596 self.handle.sendline( "" )
3597 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003598
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003599 hostStr = handlePy.replace( "]", "" )
3600 hostStr = hostStr.replace( "'", "" )
3601 hostStr = hostStr.replace( "[", "" )
3602 hostStr = hostStr.replace( " ", "" )
3603 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003604
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003605 return hostList
3606 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003607 main.log.error( self.name + ": TIMEOUT exception found" )
3608 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003609 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003610 except pexpect.EOF:
3611 main.log.error( self.name + ": EOF exception found" )
3612 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003613 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003614 except Exception:
3615 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003616 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003617
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003618 def getSwitch( self ):
3619 """
3620 Returns a list of all switches
3621 Again, don't ask question just use it...
3622 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003623 try:
3624 # get host list...
3625 hostList = self.getHosts()
3626 # Make host set
3627 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003628
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003629 # Getting all the nodes in mininet
3630 self.handle.sendline( "" )
3631 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003632
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003633 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3634 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003635
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003636 handlePy = self.handle.before
3637 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3638 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003639
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003640 self.handle.sendline( "" )
3641 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003642
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003643 nodesStr = handlePy.replace( "]", "" )
3644 nodesStr = nodesStr.replace( "'", "" )
3645 nodesStr = nodesStr.replace( "[", "" )
3646 nodesStr = nodesStr.replace( " ", "" )
3647 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003648
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003649 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003650 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003651 nodesSet.discard( 'c0' )
3652 nodesSet.discard( 'c1' )
3653 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003654
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003655 switchSet = nodesSet - hostSet
3656 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003657
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003658 return switchList
3659 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003660 main.log.error( self.name + ": TIMEOUT exception found" )
3661 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003662 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003663 except pexpect.EOF:
3664 main.log.error( self.name + ": EOF exception found" )
3665 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003666 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003667 except Exception:
3668 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003669 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003670
You Wangdb8cd0a2016-05-26 15:19:45 -07003671 def getGraphDict( self, timeout=60, useId=True, includeHost=False ):
3672 """
3673 Return a dictionary which describes the latest Mininet topology data as a
3674 graph.
3675 An example of the dictionary:
3676 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3677 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3678 Each vertex should at least have an 'edges' attribute which describes the
3679 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003680 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003681 list of attributes.
3682 An example of the edges dictionary:
3683 'edges': { vertex2: { 'port': ..., 'weight': ... },
3684 vertex3: { 'port': ..., 'weight': ... } }
3685 If useId == True, dpid/mac will be used instead of names to identify
3686 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3687 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003688 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003689 in topology data.
3690 Note that link or switch that are brought down by 'link x x down' or 'switch
3691 x down' commands still show in the output of Mininet CLI commands such as
3692 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3693 recommended to use delLink() or delSwitch functions to simulate link/switch
3694 down, and addLink() or addSwitch to add them back.
3695 """
3696 graphDict = {}
3697 try:
3698 links = self.getLinks( timeout=timeout )
3699 portDict = {}
3700 if useId:
3701 switches = self.getSwitches()
3702 if includeHost:
3703 hosts = self.getHosts()
3704 for link in links:
3705 # FIXME: support 'includeHost' argument
3706 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3707 continue
3708 nodeName1 = link[ 'node1' ]
3709 nodeName2 = link[ 'node2' ]
3710 port1 = link[ 'port1' ]
3711 port2 = link[ 'port2' ]
3712 # Loop for two nodes
3713 for i in range( 2 ):
3714 # Get port index from OVS
3715 # The index extracted from port name may be inconsistent with ONOS
3716 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003717 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003718 portList = self.getOVSPorts( nodeName1 )
3719 if len( portList ) == 0:
3720 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3721 return None
3722 portDict[ nodeName1 ] = portList
3723 for port in portDict[ nodeName1 ]:
3724 if port[ 'port' ] == port1:
3725 portIndex = port[ 'index' ]
3726 break
3727 if portIndex == -1:
3728 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3729 return None
3730 if useId:
3731 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3732 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3733 else:
3734 node1 = nodeName1
3735 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003736 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003737 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003738 graphDict[ node1 ] = { 'edges': {},
3739 'dpid': switches[ nodeName1 ][ 'dpid' ],
3740 'name': nodeName1,
3741 'ports': switches[ nodeName1 ][ 'ports' ],
3742 'swClass': switches[ nodeName1 ][ 'swClass' ],
3743 'pid': switches[ nodeName1 ][ 'pid' ],
3744 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003745 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003746 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003747 else:
3748 # Assert node2 is not connected to any current links of node1
3749 assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003750 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
You Wangdb8cd0a2016-05-26 15:19:45 -07003751 # Swap two nodes/ports
3752 nodeName1, nodeName2 = nodeName2, nodeName1
3753 port1, port2 = port2, port1
3754 return graphDict
3755 except KeyError:
3756 main.log.exception( self.name + ": KeyError exception found" )
3757 return None
3758 except AssertionError:
3759 main.log.exception( self.name + ": AssertionError exception found" )
3760 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003761 except pexpect.EOF:
3762 main.log.error( self.name + ": EOF exception found" )
3763 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003764 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003765 except Exception:
3766 main.log.exception( self.name + ": Uncaught exception" )
3767 return None
3768
Devin Lima7cfdbd2017-09-29 15:02:22 -07003769 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003770 """
3771 updates the port address and status information for
3772 each port in mn"""
3773 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003774 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003775 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003776 self.handle.sendline( "" )
3777 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003778
Jon Hall7eb38402015-01-08 17:19:54 -08003779 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003780 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003781
Jon Hall7eb38402015-01-08 17:19:54 -08003782 self.handle.sendline( "" )
3783 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003784
Jon Hallb1290e82014-11-18 16:17:48 -05003785 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003786 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003787 main.log.error( self.name + ": TIMEOUT exception found" )
3788 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003789 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003790 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003791 main.log.error( self.name + ": EOF exception found" )
3792 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003793 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003794 except Exception:
3795 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003796 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003797
Jon Halld80cc142015-07-06 13:36:05 -07003798 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003799 """
3800 Add vlan tag to a host.
3801 Dependencies:
3802 This class depends on the "vlan" package
3803 $ sudo apt-get install vlan
3804 Configuration:
3805 Load the 8021q module into the kernel
3806 $sudo modprobe 8021q
3807
3808 To make this setup permanent:
3809 $ sudo su -c 'echo "8021q" >> /etc/modules'
3810 """
3811 if self.handle:
3812 try:
Jon Halld80cc142015-07-06 13:36:05 -07003813 # get the ip address of the host
3814 main.log.info( "Get the ip address of the host" )
3815 ipaddr = self.getIPAddress( host )
3816 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003817
Jon Halld80cc142015-07-06 13:36:05 -07003818 # remove IP from interface intf
3819 # Ex: h1 ifconfig h1-eth0 inet 0
3820 main.log.info( "Remove IP from interface " )
3821 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3822 self.handle.sendline( cmd2 )
3823 self.handle.expect( "mininet>" )
3824 response = self.handle.before
3825 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003826
Jon Halld80cc142015-07-06 13:36:05 -07003827 # create VLAN interface
3828 # Ex: h1 vconfig add h1-eth0 100
3829 main.log.info( "Create Vlan" )
3830 cmd3 = host + " vconfig add " + intf + " " + vlan
3831 self.handle.sendline( cmd3 )
3832 self.handle.expect( "mininet>" )
3833 response = self.handle.before
3834 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003835
Jon Halld80cc142015-07-06 13:36:05 -07003836 # assign the host's IP to the VLAN interface
3837 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3838 main.log.info( "Assign the host IP to the vlan interface" )
3839 vintf = intf + "." + vlan
3840 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3841 self.handle.sendline( cmd4 )
3842 self.handle.expect( "mininet>" )
3843 response = self.handle.before
3844 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003845
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003846 # update Mininet node variables
3847 main.log.info( "Update Mininet node variables" )
3848 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3849 self.handle.sendline( cmd5 )
3850 self.handle.expect( "mininet>" )
3851 response = self.handle.before
3852 main.log.info( "====> %s ", response )
3853
3854 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3855 self.handle.sendline( cmd6 )
3856 self.handle.expect( "mininet>" )
3857 response = self.handle.before
3858 main.log.info( "====> %s ", response )
3859
3860 return main.TRUE
3861 except pexpect.TIMEOUT:
3862 main.log.error( self.name + ": TIMEOUT exception found" )
3863 main.log.error( self.name + ": " + self.handle.before )
3864 main.cleanAndExit()
3865 except pexpect.EOF:
3866 main.log.error( self.name + ": EOF exception found" )
3867 main.log.error( self.name + ": " + self.handle.before )
3868 return main.FALSE
3869 except Exception:
3870 main.log.exception( self.name + ": Uncaught exception!" )
3871 return main.FALSE
3872
3873 def removeVLAN( self, host, intf ):
3874 """
3875 Remove vlan tag from a host.
3876 Dependencies:
3877 This class depends on the "vlan" package
3878 $ sudo apt-get install vlan
3879 Configuration:
3880 Load the 8021q module into the kernel
3881 $sudo modprobe 8021q
3882
3883 To make this setup permanent:
3884 $ sudo su -c 'echo "8021q" >> /etc/modules'
3885 """
3886 if self.handle:
3887 try:
3888 # get the ip address of the host
3889 main.log.info( "Get the ip address of the host" )
3890 ipaddr = self.getIPAddress( host )
3891
3892 # remove VLAN interface
3893 # Ex: h1 vconfig rem h1-eth0.100
3894 main.log.info( "Remove Vlan interface" )
3895 cmd2 = host + " vconfig rem " + intf
3896 self.handle.sendline( cmd2 )
3897 self.handle.expect( "mininet>" )
3898 response = self.handle.before
3899 main.log.info( "====> %s ", response )
3900
3901 # assign the host's IP to the original interface
3902 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3903 main.log.info( "Assign the host IP to the original interface" )
3904 original_intf = intf.split(".")[0]
3905 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3906 self.handle.sendline( cmd3 )
3907 self.handle.expect( "mininet>" )
3908 response = self.handle.before
3909 main.log.info( "====> %s ", response )
3910
3911 # update Mininet node variables
3912 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3913 self.handle.sendline( cmd4 )
3914 self.handle.expect( "mininet>" )
3915 response = self.handle.before
3916 main.log.info( "====> %s ", response )
3917
3918 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3919 self.handle.sendline( cmd5 )
3920 self.handle.expect( "mininet>" )
3921 response = self.handle.before
3922 main.log.info( "====> %s ", response )
3923
kaouthera3f13ca22015-05-05 15:01:41 -07003924 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003925 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003926 main.log.error( self.name + ": TIMEOUT exception found" )
3927 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003928 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003929 except pexpect.EOF:
3930 main.log.error( self.name + ": EOF exception found" )
3931 main.log.error( self.name + ": " + self.handle.before )
3932 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003933 except Exception:
3934 main.log.exception( self.name + ": Uncaught exception!" )
3935 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003936
Jon Hall892818c2015-10-20 17:58:34 -07003937 def createHostComponent( self, name ):
3938 """
3939 Creates a new mininet cli component with the same parameters as self.
3940 This new component is intended to be used to login to the hosts created
3941 by mininet.
3942
3943 Arguments:
3944 name - The string of the name of this component. The new component
3945 will be assigned to main.<name> .
3946 In addition, main.<name>.name = str( name )
3947 """
3948 try:
3949 # look to see if this component already exists
3950 getattr( main, name )
3951 except AttributeError:
3952 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003953 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3954 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003955 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003956 except pexpect.EOF:
3957 main.log.error( self.name + ": EOF exception found" )
3958 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003959 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003960 except Exception:
3961 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003962 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003963 else:
3964 # namespace is not clear!
3965 main.log.error( name + " component already exists!" )
3966 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003967 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003968
3969 def removeHostComponent( self, name ):
3970 """
3971 Remove host component
3972 Arguments:
3973 name - The string of the name of the component to delete.
3974 """
3975 try:
3976 # Get host component
3977 component = getattr( main, name )
3978 except AttributeError:
3979 main.log.error( "Component " + name + " does not exist." )
3980 return
3981 try:
3982 # Disconnect from component
3983 component.disconnect()
3984 # Delete component
3985 delattr( main, name )
3986 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003987 del( main.componentDictionary[ name ] )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003988 except pexpect.EOF:
3989 main.log.error( self.name + ": EOF exception found" )
3990 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003991 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003992 except Exception:
3993 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003994 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003995
3996 def startHostCli( self, host=None ):
3997 """
3998 Use the mininet m utility to connect to the host's cli
3999 """
4000 # These are fields that can be used by scapy packets. Initialized to None
4001 self.hostIp = None
4002 self.hostMac = None
4003 try:
4004 if not host:
4005 host = self.name
4006 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07004007 self.handle.sendline( "cd" )
4008 self.handle.expect( self.hostPrompt )
4009 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07004010 self.handle.expect( self.hostPrompt )
4011 return main.TRUE
4012 except pexpect.TIMEOUT:
4013 main.log.exception( self.name + ": Command timed out" )
4014 return main.FALSE
4015 except pexpect.EOF:
4016 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07004017 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07004018 except Exception:
4019 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004020 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07004021
YPZhang801d46d2016-08-08 13:26:28 -07004022 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004023 '''
4024
YPZhang801d46d2016-08-08 13:26:28 -07004025 Args:
4026 devicename: switch name
4027 intf: port name on switch
4028 status: up or down
4029
4030 Returns: boolean to show success change status
4031
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004032 '''
YPZhang801d46d2016-08-08 13:26:28 -07004033 if status == "down" or status == "up":
4034 try:
4035 cmd = devicename + " ifconfig " + intf + " " + status
4036 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004037 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07004038 return main.TRUE
4039 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004040 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07004041 return main.FALSE
4042 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004043 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07004044 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07004045 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004046 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07004047 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07004048 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004049 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004050 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07004051 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004052 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07004053 return main.FALSE
4054
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004055 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
4056 macAddr=None, prefixLen=None, bondedName='bond1' ):
4057 """
4058 Moves a dual-homed host from one switch-pair to another pair on the fly
4059 If macAddr is specified, change MAC address of the bonded host interface
4060 to specified MAC address.
4061 Assumes that the host has two interfaces (eth0 and eth1) originally.
4062 """
4063
4064 bond1 = "%s-%s" % ( host, bondedName )
4065 newIntf = host + '-eth2'
4066 newIntfPair = host + '-eth3'
4067 commands = [
4068 # Bring link between oldSw-host down
4069 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
4070 # Bring link between oldPairSw-host down
4071 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
4072 # Determine hostintf and Oldswitchintf
4073 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
4074 # Determine ip and mac address of the host-oldSw interface
4075 "px ipaddr = hintf.IP()",
4076 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
4077 # Detach interface between oldSw-host
4078 "px " + oldSw + ".detach( sintf )",
4079 # Determine hostintf and Oldpairswitchintf
4080 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
4081 # Detach interface between oldPairSw-host
4082 "px " + oldPairSw + ".detach( sintfpair )",
4083 # Add link between host-newSw
4084 "py net.addLink(" + host + "," + newSw + ", 2)",
4085 # Add link between host-newPairSw
4086 "py net.addLink(" + host + "," + newPairSw + ")",
4087 # Determine hostintf and Newswitchintf
4088 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
4089 # Determine hostintf and NewPairswitchintf
4090 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
4091 # Attach interface between newSw-host
4092 "px " + newSw + ".attach( sintf )",
4093 # Attach interface between newPairSw-host
4094 "px " + newPairSw + ".attach( sintfpair )",
4095 # Bond two interfaces
4096 host + ' ip link add %s type bond' % bond1,
4097 host + ' ip link set %s down' % newIntf,
4098 host + ' ip link set %s down' % newIntfPair,
4099 host + ' ip link set %s master %s' % ( newIntf, bond1 ),
4100 host + ' ip link set %s master %s' % ( newIntfPair, bond1 ),
4101 host + ' ip addr flush dev %s' % newIntf,
4102 host + ' ip addr flush dev %s' % newIntfPair,
4103 host + ' ip link set %s up' % bond1,
4104 "px lowestIntf = min( [ hintf, hintfpair ] )",
4105 "px highestIntf = max( [ hintf, hintfpair ] )",
4106 "px lowestIntf.name = '" + bond1 + "'",
4107 "px " + host + ".nameToIntf['" + bond1 + "'] = lowestIntf",
4108 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
4109 "px del " + host + ".ports[ highestIntf ]",
4110 # Set ipaddress of the host-newSw interface
4111 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
4112 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
4113 # Set macaddress of the host-newSw interface
4114 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
4115 "net",
4116 # Determine ipaddress of the bonded host interface
4117 host + " ifconfig",
4118 ]
4119
4120 if self.handle:
4121 try:
4122 for cmd in commands:
4123 print "cmd= ", cmd
4124 self.handle.sendline( cmd )
4125 self.handle.expect( "mininet>" )
4126 main.log.info( "====> %s ", self.handle.before )
4127 return main.TRUE
4128
4129 except pexpect.TIMEOUT:
4130 main.log.error( self.name + ": TIMEOUT exception found" )
4131 main.log.error( self.name + ": " + self.handle.before )
4132 main.cleanAndExit()
4133 except pexpect.EOF:
4134 main.log.error( self.name + ": EOF exception found" )
4135 main.log.error( self.name + ": " + self.handle.before )
4136 return main.FALSE
4137 except Exception:
4138 main.log.exception( self.name + ": Uncaught exception!" )
4139 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07004140
adminbae64d82013-08-01 10:50:15 -07004141if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004142 sys.modules[ __name__ ] = MininetCliDriver()