blob: cb06f60d8fca9edc48113186c7a598fdbd2d880e [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 Wang32833172018-10-23 15:19:31 -0700577 def discoverHosts( self, hostList=[], wait=1000, dstIp="6.6.6.6", dstIp6="1020::3fe" ):
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700578 '''
You Wang32833172018-10-23 15:19:31 -0700579 Hosts in hostList will do a single ARP/ND to a non-existent address for ONOS to
580 discover them. A host will use arping/ndisc6 to send ARP/ND depending on if it
581 has IPv4/IPv6 addresses configured.
You Wang48381752018-05-07 13:50:57 -0700582 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
You Wang32833172018-10-23 15:19:31 -0700585 wait: timeout for ARP/ND in milliseconds
You Wang48381752018-05-07 13:50:57 -0700586 dstIp: destination address used by IPv4 hosts
587 dstIp6: destination address used by IPv6 hosts
588 Returns:
You Wang32833172018-10-23 15:19:31 -0700589 main.TRUE if all packets were successfully sent. Otherwise main.FALSE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700590 '''
591 try:
You Wang32833172018-10-23 15:19:31 -0700592 hosts = self.getHosts()
You Wang48381752018-05-07 13:50:57 -0700593 if not hostList:
You Wang48381752018-05-07 13:50:57 -0700594 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 Wang32833172018-10-23 15:19:31 -0700601 cmd = "{} arping -c 1 -w {} {}".format( host, wait, dstIp )
602 main.log.debug( "Sending IPv4 arping from host {}".format( host ) )
You Wang48381752018-05-07 13:50:57 -0700603 elif self.getIPAddress( host, proto='IPV6' ):
You Wang0b82aa52018-06-06 14:33:58 -0700604 flushCmd = "{} ip -6 neigh flush all".format( host )
You Wangad347c92019-02-20 16:13:47 -0800605 for intf in hosts[ host ][ 'interfaces' ]:
606 intfName = intf[ 'name' ]
607 cmd = "{} ndisc6 -r 1 -w {} {} {}".format( host, wait, dstIp6, intfName )
608 main.log.debug( "Sending IPv6 ND from interface {} on host {}".format( intfName, host ) )
You Wang48381752018-05-07 13:50:57 -0700609 else:
610 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
611 discoveryResult = main.FALSE
612 if cmd:
You Wang0b82aa52018-06-06 14:33:58 -0700613 self.handle.sendline( flushCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700614 self.handle.expect( "mininet>" )
You Wang48381752018-05-07 13:50:57 -0700615 self.handle.sendline( cmd )
Jon Halla604fd42018-05-04 14:27:27 -0700616 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700617 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700618 except pexpect.TIMEOUT:
619 main.log.exception( self.name + ": TIMEOUT exception" )
620 response = self.handle.before
621 # NOTE: Send ctrl-c to make sure command is stopped
622 self.handle.send( "\x03" )
623 self.handle.expect( "Interrupt" )
624 response += self.handle.before + self.handle.after
625 self.handle.expect( "mininet>" )
626 response += self.handle.before + self.handle.after
627 main.log.debug( response )
628 return main.FALSE
629 except pexpect.EOF:
630 main.log.error( self.name + ": EOF exception found" )
631 main.log.error( self.name + ": " + self.handle.before )
632 main.cleanAndExit()
633 except Exception:
634 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800635 main.cleanAndExit()
636
637 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
638 """
639 Verify ping from each host in srcList to each host in dstList
640
641 acceptableFailed: max number of acceptable failed pings
642
643 Returns main.TRUE if all src hosts can reach all dst hosts
644 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
645 """
646 try:
647 main.log.info( "Verifying ping from each src host to each dst host" )
648 isReachable = main.TRUE
649 wait = int( wait )
650 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
651 pingResponse = "Ping output:\n"
652 failedPingsTotal = 0
653 for host in srcList:
654 pingResponse += str( str( host ) + " -> " )
655 for temp in dstList:
656 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700657 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
658 assert dstIP, "Not able to get IP address of host {}".format( temp )
659 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800660 while failedPings <= acceptableFailed:
661 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
662 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700663 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800664 response = self.handle.before
665 if re.search( ',\s0\%\spacket\sloss', response ):
666 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800667 break
668 else:
669 failedPings += 1
670 time.sleep(1)
671 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700672 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800673 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700674 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800675 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700676 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800677 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700678 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700679 except AssertionError:
680 main.log.exception( "" )
681 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700682 except pexpect.TIMEOUT:
683 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800684 response = self.handle.before
685 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700686 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800687 self.handle.expect( "Interrupt" )
688 response += self.handle.before + self.handle.after
689 self.handle.expect( "mininet>" )
690 response += self.handle.before + self.handle.after
691 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700692 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700693 except pexpect.EOF:
694 main.log.error( self.name + ": EOF exception found" )
695 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700696 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700697 except Exception:
698 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700699 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700700
Jon Hall7eb38402015-01-08 17:19:54 -0800701 def pingHost( self, **pingParams ):
702 """
Jon Hall3b489db2015-10-05 14:38:37 -0700703 Ping from one mininet host to another
704 Currently the only supported Params: SRC, TARGET, and WAIT
705 """
706 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700707 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700708 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800709 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700710 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700711 try:
Jon Hall61282e32015-03-19 11:34:11 -0700712 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800713 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700714 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700715 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700716 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800717 main.log.error(
718 self.name +
719 ": timeout when waiting for response from mininet" )
720 main.log.error( "response: " + str( self.handle.before ) )
721 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700722 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800723 main.log.error(
724 self.name +
725 ": timeout when waiting for response from mininet" )
726 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700727 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700728 if re.search( ',\s0\%\spacket\sloss', response ):
729 main.log.info( self.name + ": no packets lost, host is reachable" )
730 return main.TRUE
731 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800732 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700733 self.name +
734 ": PACKET LOST, HOST IS NOT REACHABLE" )
735 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800736 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800737 main.log.error( self.name + ": EOF exception found" )
738 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700739 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700740 except Exception:
741 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700742 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700743
744 def ping6pair( self, **pingParams ):
745 """
GlennRC2cf7d952015-09-11 16:32:13 -0700746 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700747 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000748 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700749 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
750 """
Jon Hall3b489db2015-10-05 14:38:37 -0700751 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700752 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700753 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530754 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700755 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700756 try:
757 main.log.info( "Sending: " + command )
758 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700759 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700760 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700761 if i == 1:
762 main.log.error(
763 self.name +
764 ": timeout when waiting for response from mininet" )
765 main.log.error( "response: " + str( self.handle.before ) )
766 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
767 if i == 1:
768 main.log.error(
769 self.name +
770 ": timeout when waiting for response from mininet" )
771 main.log.error( "response: " + str( self.handle.before ) )
772 response = self.handle.before
773 main.log.info( self.name + ": Ping Response: " + response )
774 if re.search( ',\s0\%\spacket\sloss', response ):
775 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700776 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700777 else:
alisone4121a92016-11-22 16:31:36 -0800778 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700779 self.name +
780 ": PACKET LOST, HOST IS NOT REACHABLE" )
781 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700782 except pexpect.EOF:
783 main.log.error( self.name + ": EOF exception found" )
784 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700785 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700786 except Exception:
787 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700788 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800789
You Wangdb927a52016-02-26 11:03:28 -0800790 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
791 """
792 Description:
793 Ping a set of destination host from host CLI.
794 Logging into a Mininet host CLI is required before calling this funtion.
795 Params:
796 dstIPList is a list of destination ip addresses
797 Returns:
798 main.TRUE if the destination host is reachable
799 main.FALSE otherwise
800 """
801 isReachable = main.TRUE
802 wait = int( wait )
803 cmd = "ping"
804 if IPv6:
805 cmd = cmd + "6"
806 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
807 try:
808 for dstIP in dstIPList:
809 pingCmd = cmd + " " + dstIP
810 self.handle.sendline( pingCmd )
811 i = self.handle.expect( [ self.hostPrompt,
812 '\*\*\* Unknown command: ' + pingCmd,
813 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700814 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700815 # For some reason we need to send something
816 # Otherwise ping results won't be read by handle
817 self.handle.sendline( "" )
818 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800819 if i == 0:
820 response = self.handle.before
821 if not re.search( ',\s0\%\spacket\sloss', response ):
822 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
823 isReachable = main.FALSE
824 elif i == 1:
825 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700826 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800827 elif i == 2:
828 main.log.error( self.name + ": timeout when waiting for response" )
829 isReachable = main.FALSE
830 else:
831 main.log.error( self.name + ": unknown response: " + self.handle.before )
832 isReachable = main.FALSE
833 except pexpect.TIMEOUT:
834 main.log.exception( self.name + ": TIMEOUT exception" )
You Wangd4fae5c2018-08-22 13:56:49 -0700835 self.exitFromCmd( [ self.hostPrompt, self.bashPrompt ] )
You Wangdb927a52016-02-26 11:03:28 -0800836 isReachable = main.FALSE
837 except pexpect.EOF:
838 main.log.error( self.name + ": EOF exception found" )
839 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700840 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800841 except Exception:
842 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700843 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800844 return isReachable
845
Jon Hall7eb38402015-01-08 17:19:54 -0800846 def checkIP( self, host ):
847 """
848 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700849 try:
850 if self.handle:
851 try:
852 response = self.execute(
853 cmd=host +
854 " ifconfig",
855 prompt="mininet>",
856 timeout=10 )
857 except pexpect.EOF:
858 main.log.error( self.name + ": EOF exception found" )
859 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700860 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700861
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700862 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
863 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
864 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
865 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
866 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
867 "[0-9]|25[0-5]|[0-9]{1,2})"
868 # pattern = "inet addr:10.0.0.6"
869 if re.search( pattern, response ):
870 main.log.info( self.name + ": Host Ip configured properly" )
871 return main.TRUE
872 else:
873 main.log.error( self.name + ": Host IP not found" )
874 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700875 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700876 main.log.error( self.name + ": Connection failed to the host" )
877 except Exception:
878 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700879 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800880
Jon Hall7eb38402015-01-08 17:19:54 -0800881 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800882 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700883 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800884 response = self.execute(
885 cmd="h1 /usr/sbin/sshd -D&",
886 prompt="mininet>",
887 timeout=10 )
888 response = self.execute(
889 cmd="h4 /usr/sbin/sshd -D&",
890 prompt="mininet>",
891 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700892 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800893 vars( self )[ key ] = connectargs[ key ]
894 response = self.execute(
895 cmd="xterm h1 h4 ",
896 prompt="mininet>",
897 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800898 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800899 main.log.error( self.name + ": EOF exception found" )
900 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700901 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700902 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800903 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700904 if self.flag == 0:
905 self.flag = 1
906 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800907 else:
adminbae64d82013-08-01 10:50:15 -0700908 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800909
Jon Hall7eb38402015-01-08 17:19:54 -0800910 def changeIP( self, host, intf, newIP, newNetmask ):
911 """
912 Changes the ip address of a host on the fly
913 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800914 if self.handle:
915 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800916 cmd = host + " ifconfig " + intf + " " + \
917 newIP + " " + 'netmask' + " " + newNetmask
918 self.handle.sendline( cmd )
919 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800920 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800921 main.log.info( "response = " + response )
922 main.log.info(
923 "Ip of host " +
924 host +
925 " changed to new IP " +
926 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800927 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700928 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700929 main.log.error( self.name + ": TIMEOUT exception found" )
930 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700931 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800932 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800933 main.log.error( self.name + ": EOF exception found" )
934 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800935 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700936 except Exception:
937 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700938 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800939
Jon Hall7eb38402015-01-08 17:19:54 -0800940 def changeDefaultGateway( self, host, newGW ):
941 """
942 Changes the default gateway of a host
943 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800944 if self.handle:
945 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800946 cmd = host + " route add default gw " + newGW
947 self.handle.sendline( cmd )
948 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800949 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800950 main.log.info( "response = " + response )
951 main.log.info(
952 "Default gateway of host " +
953 host +
954 " changed to " +
955 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800956 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700957 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700958 main.log.error( self.name + ": TIMEOUT exception found" )
959 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700960 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800961 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800962 main.log.error( self.name + ": EOF exception found" )
963 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800964 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700965 except Exception:
966 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700967 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800968
You Wange24d6272018-03-27 21:18:50 -0700969 def addRoute( self, host, dstIP, interface, ipv6=False ):
970 """
971 Add a route to host
972 Ex: h1 route add -host 224.2.0.1 h1-eth0
973 """
974 if self.handle:
975 try:
976 cmd = str( host )
977 if ipv6:
978 cmd += " route -A inet6 add "
979 else:
980 cmd += " route add -host "
981 cmd += str( dstIP ) + " " + str( interface )
982 self.handle.sendline( cmd )
983 self.handle.expect( "mininet>" )
984 response = self.handle.before
985 main.log.debug( "response = " + response )
986 return main.TRUE
987 except pexpect.TIMEOUT:
988 main.log.error( self.name + ": TIMEOUT exception found" )
989 main.log.error( self.name + ": " + self.handle.before )
990 main.cleanAndExit()
991 except pexpect.EOF:
992 main.log.error( self.name + ": EOF exception found" )
993 main.log.error( self.name + ": " + self.handle.before )
994 return main.FALSE
995 except Exception:
996 main.log.exception( self.name + ": Uncaught exception!" )
997 main.cleanAndExit()
998
Jon Hall7eb38402015-01-08 17:19:54 -0800999 def addStaticMACAddress( self, host, GW, macaddr ):
1000 """
Jon Hallefbd9792015-03-05 16:11:36 -08001001 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001002 if self.handle:
1003 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001004 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1005 cmd = host + " arp -s " + GW + " " + macaddr
1006 self.handle.sendline( cmd )
1007 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001008 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001009 main.log.info( "response = " + response )
1010 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001011 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001012 GW +
1013 " changed to " +
1014 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001015 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001016 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001017 main.log.error( self.name + ": TIMEOUT exception found" )
1018 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001019 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001020 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001021 main.log.error( self.name + ": EOF exception found" )
1022 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001023 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001024 except Exception:
1025 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001026 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001027
Jon Hall7eb38402015-01-08 17:19:54 -08001028 def verifyStaticGWandMAC( self, host ):
1029 """
1030 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001031 if self.handle:
1032 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001033 # h1 arp -an
1034 cmd = host + " arp -an "
1035 self.handle.sendline( cmd )
1036 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001037 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001038 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001039 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001040 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001041 main.log.error( self.name + ": TIMEOUT exception found" )
1042 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001043 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001044 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001045 main.log.error( self.name + ": EOF exception found" )
1046 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001047 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001048 except Exception:
1049 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001050 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001051
Jon Hall7eb38402015-01-08 17:19:54 -08001052 def getMacAddress( self, host ):
1053 """
1054 Verifies the host's ip configured or not."""
1055 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001056 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001057 response = self.execute(
1058 cmd=host +
1059 " ifconfig",
1060 prompt="mininet>",
1061 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001062 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001063 main.log.error( self.name + ": EOF exception found" )
1064 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001065 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001066 except Exception:
1067 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001068 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001069
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001070 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001071 macAddressSearch = re.search( pattern, response, re.I )
1072 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001073 main.log.info(
1074 self.name +
1075 ": Mac-Address of Host " +
1076 host +
1077 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001078 macAddress )
1079 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001080 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001081 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001082
Jon Hall7eb38402015-01-08 17:19:54 -08001083 def getInterfaceMACAddress( self, host, interface ):
1084 """
1085 Return the IP address of the interface on the given host"""
1086 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001087 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001088 response = self.execute( cmd=host + " ifconfig " + interface,
1089 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001090 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001091 main.log.error( self.name + ": EOF exception found" )
1092 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001093 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001094 except Exception:
1095 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001096 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001097
1098 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001099 macAddressSearch = re.search( pattern, response, re.I )
1100 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001101 main.log.info( "No mac address found in %s" % response )
1102 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001103 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001104 main.log.info(
1105 "Mac-Address of " +
1106 host +
1107 ":" +
1108 interface +
1109 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001110 macAddress )
1111 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001112 else:
1113 main.log.error( "Connection failed to the host" )
1114
You Wang5da39c82018-04-26 22:55:08 -07001115 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001116 """
1117 Verifies the host's ip configured or not."""
1118 if self.handle:
1119 try:
1120 response = self.execute(
1121 cmd=host +
1122 " ifconfig",
1123 prompt="mininet>",
1124 timeout=10 )
1125 except pexpect.EOF:
1126 main.log.error( self.name + ": EOF exception found" )
1127 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001128 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001129 except Exception:
1130 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001131 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001132
sathishmad953462015-12-03 17:42:07 +05301133 pattern = ''
1134 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001135 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301136 else:
Jon Hall439c8912016-04-15 02:22:03 -07001137 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001138 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001139 if not ipAddressSearch:
1140 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001141 main.log.info(
1142 self.name +
1143 ": IP-Address of Host " +
1144 host +
1145 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001146 ipAddressSearch.group( 1 ) )
1147 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001148 else:
1149 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001150
Jon Hall7eb38402015-01-08 17:19:54 -08001151 def getSwitchDPID( self, switch ):
1152 """
1153 return the datapath ID of the switch"""
1154 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001155 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001156 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001157 response = self.execute(
1158 cmd=cmd,
1159 prompt="mininet>",
1160 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001161 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001162 main.log.error( self.name + ": EOF exception found" )
1163 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001164 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001165 except Exception:
1166 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001167 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001168 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001169 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001170 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001171 main.log.info(
1172 "Couldn't find DPID for switch %s, found: %s" %
1173 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001174 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001175 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001176 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001177 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001178
Jon Hall7eb38402015-01-08 17:19:54 -08001179 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001180 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001181 self.handle.sendline( "" )
1182 self.expect( "mininet>" )
1183 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001184 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001185 response = self.execute(
1186 cmd=cmd,
1187 prompt="mininet>",
1188 timeout=10 )
1189 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001190 response = self.handle.before
1191 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001192 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001193 main.log.error( self.name + ": TIMEOUT exception found" )
1194 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001195 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001196 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001197 main.log.error( self.name + ": EOF exception found" )
1198 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001199 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001200 except Exception:
1201 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001202 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001203
Jon Hall7eb38402015-01-08 17:19:54 -08001204 def getInterfaces( self, node ):
1205 """
1206 return information dict about interfaces connected to the node"""
1207 if self.handle:
1208 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001209 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001210 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001211 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001212 response = self.execute(
1213 cmd=cmd,
1214 prompt="mininet>",
You Wang7d14d642019-01-23 15:10:08 -08001215 timeout=10,
1216 logCmd=False )
Jon Hallfbc828e2015-01-06 17:30:19 -08001217 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001218 main.log.error( self.name + ": EOF exception found" )
1219 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001220 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001221 except Exception:
1222 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001223 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001224 return response
1225 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001226 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001227
Jon Hall7eb38402015-01-08 17:19:54 -08001228 def dump( self ):
1229 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001230 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001231 response = self.execute(
1232 cmd='dump',
1233 prompt='mininet>',
1234 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001235 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001236 main.log.error( self.name + ": EOF exception found" )
1237 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001238 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001239 except Exception:
1240 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001241 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001242 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001243
Jon Hall7eb38402015-01-08 17:19:54 -08001244 def intfs( self ):
1245 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001246 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001247 response = self.execute(
1248 cmd='intfs',
1249 prompt='mininet>',
1250 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -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 )
Devin Lim44075962017-08-11 10:56:37 -07001254 main.cleanAndExit()
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()
Jon Hall668ed802014-04-08 17:17:59 -07001258 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001259
Jon Hall7eb38402015-01-08 17:19:54 -08001260 def net( self ):
1261 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001262 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001263 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001264 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001265 main.log.error( self.name + ": EOF exception found" )
1266 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001267 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001268 except Exception:
1269 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001270 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001271 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001272
Devin Lima7cfdbd2017-09-29 15:02:22 -07001273 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001274 main.log.info( self.name + ": List network links" )
1275 try:
1276 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001277 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001278 except pexpect.EOF:
1279 main.log.error( self.name + ": EOF exception found" )
1280 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001281 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001282 except Exception:
1283 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001284 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001285 return response
1286
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001287 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001288 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001289 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001290
kelvin-onlab7cce9382015-07-17 10:21:03 -07001291 @parm:
1292 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1293 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001294 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001295 try:
1296 for host1 in hosts:
1297 for host2 in hosts:
1298 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001299 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1300 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001301 except Exception:
1302 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001303 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001304
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001305 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001306 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001307 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1308 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001309
kelvin-onlab7cce9382015-07-17 10:21:03 -07001310 @parm:
1311 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1312 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001313 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001314 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1315 try:
1316 # Setup the mininet command
1317 cmd1 = 'iperf ' + host1 + " " + host2
1318 self.handle.sendline( cmd1 )
1319 outcome = self.handle.expect( "mininet>", timeout )
1320 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001321
kelvin-onlab7cce9382015-07-17 10:21:03 -07001322 # checks if there are results in the mininet response
1323 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001324 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001325 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001326 response = response.split( "\r\n" )
1327 response = response[ len( response )-2 ]
1328 response = response.split( ": " )
1329 response = response[ len( response )-1 ]
1330 response = response.replace( "[", "" )
1331 response = response.replace( "]", "" )
1332 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001333
kelvin-onlab7cce9382015-07-17 10:21:03 -07001334 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001335 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001336
kelvin-onlab7cce9382015-07-17 10:21:03 -07001337 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001338 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001339 if len( bandwidth ) == 2:
1340 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001341 return main.TRUE
1342 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001343 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001344 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001345 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001346 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001347 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001348 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001349 main.log.error( self.name + ": TIMEOUT exception found" )
1350 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001351 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001352 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001353 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001354 self.handle.expect( "Interrupt" )
1355 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001356 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001357 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001358 main.log.error( self.name + ": EOF exception found" )
1359 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001360 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001361 except Exception:
1362 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001363 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001364
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001365 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001366 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1367 try:
1368 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001369 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001370 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001371 outcome1 = self.handle.expect( "mininet>" )
1372 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001373 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001374 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001375 response1 = self.handle.before
1376 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001377 print response1, response2
1378 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001379 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001380 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001381 return main.TRUE
1382 else:
1383 main.log.error( self.name + ": iperf test failed" )
1384 return main.FALSE
1385 except pexpect.TIMEOUT:
1386 main.log.error( self.name + ": TIMEOUT exception found" )
1387 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001388 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001389 self.handle.expect( "Interrupt" )
1390 self.handle.expect( "mininet>" )
1391 return main.FALSE
1392 except pexpect.EOF:
1393 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 Hall439c8912016-04-15 02:22:03 -07001399
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001400 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001401 '''
GlennRC61321f22015-07-16 13:36:54 -07001402 Runs the iperfudp function with a given set of hosts and specified
1403 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001404
GlennRC61321f22015-07-16 13:36:54 -07001405 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001406 bandwidth: the targeted bandwidth, in megabits ('M')
1407 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001408 try:
1409 for host1 in hosts:
1410 for host2 in hosts:
1411 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001412 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1413 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001414 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001415 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001416 return main.FALSE
1417 except Exception:
1418 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001419 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001420
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001421 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001422 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001423 Creates an iperf UDP test with a specific bandwidth.
1424 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001425
kelvin-onlab7cce9382015-07-17 10:21:03 -07001426 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001427 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1428 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001429 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001430 try:
1431 # setup the mininet command
1432 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001433 self.handle.sendline( cmd )
1434 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001435 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001436
kelvin-onlab7cce9382015-07-17 10:21:03 -07001437 # check if there are in results in the mininet response
1438 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001439 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001440 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001441 response = response.split( "\r\n" )
1442 response = response[ len( response )-2 ]
1443 response = response.split( ": " )
1444 response = response[ len( response )-1 ]
1445 response = response.replace( "[", "" )
1446 response = response.replace( "]", "" )
1447 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001448
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001449 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001450
kelvin-onlab7cce9382015-07-17 10:21:03 -07001451 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001452 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001453 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001454 # if one entry is blank then something is wrong
1455 for item in mnBandwidth:
1456 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001457 main.log.error( self.name + ": Could not parse iperf output" )
1458 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001459 return main.FALSE
1460 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001461 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001462 return main.TRUE
1463 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001464 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001465 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001466
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001467 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001468 main.log.error( self.name + ": TIMEOUT exception found" )
1469 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001470 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001471 except pexpect.EOF:
1472 main.log.error( self.name + ": EOF exception found" )
1473 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001474 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001475 except Exception:
1476 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001477 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001478
Jon Hall7eb38402015-01-08 17:19:54 -08001479 def nodes( self ):
1480 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001481 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001482 response = self.execute(
1483 cmd='nodes',
1484 prompt='mininet>',
1485 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001486 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001487 main.log.error( self.name + ": EOF exception found" )
1488 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001489 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001490 except Exception:
1491 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001492 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001493 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001494
Jon Hall7eb38402015-01-08 17:19:54 -08001495 def pingpair( self ):
1496 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001497 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001498 response = self.execute(
1499 cmd='pingpair',
1500 prompt='mininet>',
1501 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001502 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001503 main.log.error( self.name + ": EOF exception found" )
1504 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001505 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001506 except Exception:
1507 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001508 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001509
Jon Hall7eb38402015-01-08 17:19:54 -08001510 if re.search( ',\s0\%\spacket\sloss', response ):
1511 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001512 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001513 else:
alisone4121a92016-11-22 16:31:36 -08001514 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001515 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001516
Jon Hall7eb38402015-01-08 17:19:54 -08001517 def link( self, **linkargs ):
1518 """
GlennRCed771242016-01-13 17:02:47 -08001519 Bring link( s ) between two nodes up or down
1520 """
Jon Hall6094a362014-04-11 14:46:56 -07001521 try:
GlennRCed771242016-01-13 17:02:47 -08001522 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1523 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1524 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1525 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1526
1527 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1528 cmd = "link {} {} {}".format( end1, end2, option )
1529 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001530 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001531 response = self.handle.before
1532 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001533 if "not in network" in response:
1534 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1535 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001536 return main.TRUE
1537 except pexpect.TIMEOUT:
1538 main.log.exception( self.name + ": Command timed out" )
1539 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001540 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001541 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001542 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001543 except Exception:
1544 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001545 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001546
pingping-lin8244a3b2015-09-16 13:36:56 -07001547 def switch( self, **switchargs ):
1548 """
1549 start/stop a switch
1550 """
1551 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1552 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1553 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1554 command = "switch " + str( sw ) + " " + str( option )
1555 main.log.info( command )
1556 try:
1557 self.handle.sendline( command )
1558 self.handle.expect( "mininet>" )
1559 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001560 main.log.error( self.name + ": TIMEOUT exception found" )
1561 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001562 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001563 except pexpect.EOF:
1564 main.log.error( self.name + ": EOF exception found" )
1565 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001566 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001567 return main.TRUE
1568
pingping-lin5bb663b2015-09-24 11:47:50 -07001569 def node( self, nodeName, commandStr ):
1570 """
1571 Carry out a command line on a given node
1572 @parm:
1573 nodeName: the node name in Mininet testbed
1574 commandStr: the command line will be carried out on the node
1575 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1576 """
1577 command = str( nodeName ) + " " + str( commandStr )
1578 main.log.info( command )
1579
1580 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001581 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001582 if re.search( "Unknown command", response ):
1583 main.log.warn( response )
1584 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001585 if re.search( "Permission denied", response ):
1586 main.log.warn( response )
1587 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001588 except pexpect.EOF:
1589 main.log.error( self.name + ": EOF exception found" )
1590 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001591 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001592 main.log.info( " response is :" )
1593 main.log.info( response )
1594 return response
1595
Jon Hall7eb38402015-01-08 17:19:54 -08001596 def yank( self, **yankargs ):
1597 """
1598 yank a mininet switch interface to a host"""
1599 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001600 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001601 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1602 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001603 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001604 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001605 response = self.execute(
1606 cmd=command,
1607 prompt="mininet>",
1608 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001609 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001610 main.log.error( self.name + ": EOF exception found" )
1611 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001612 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001613 except Exception:
1614 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001615 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001616 return main.TRUE
1617
Jon Hall7eb38402015-01-08 17:19:54 -08001618 def plug( self, **plugargs ):
1619 """
1620 plug the yanked mininet switch interface to a switch"""
1621 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001622 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001623 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1624 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001625 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001626 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001627 response = self.execute(
1628 cmd=command,
1629 prompt="mininet>",
1630 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001631 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001632 main.log.error( self.name + ": EOF exception found" )
1633 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001634 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001635 except Exception:
1636 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001637 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001638 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001639
Jon Hall7eb38402015-01-08 17:19:54 -08001640 def dpctl( self, **dpctlargs ):
1641 """
1642 Run dpctl command on all switches."""
1643 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001644 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001645 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1646 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1647 command = "dpctl " + cmd + " " + str( cmdargs )
1648 try:
1649 response = self.execute(
1650 cmd=command,
1651 prompt="mininet>",
1652 timeout=10 )
1653 except pexpect.EOF:
1654 main.log.error( self.name + ": EOF exception found" )
1655 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001656 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001657 except Exception:
1658 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001659 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001660 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001661
kelvin-onlabd3b64892015-01-20 13:26:24 -08001662 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001663 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001664 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001665 try:
1666 fileInput = path + '/lib/Mininet/INSTALL'
1667 version = super( Mininet, self ).getVersion()
1668 pattern = 'Mininet\s\w\.\w\.\w\w*'
1669 for line in open( fileInput, 'r' ).readlines():
1670 result = re.match( pattern, line )
1671 if result:
1672 version = result.group( 0 )
1673 return version
1674 except Exception:
1675 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001676 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001677
kelvin-onlabd3b64892015-01-20 13:26:24 -08001678 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001679 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001680 Parameters:
1681 sw: The name of an OVS switch. Example "s1"
1682 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001683 The output of the command from the mininet cli
1684 or main.FALSE on timeout"""
1685 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001686 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001687 response = self.execute(
1688 cmd=command,
1689 prompt="mininet>",
1690 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001691 if response:
Jon Hallab611372018-02-21 15:26:05 -08001692 if "no bridge named" in response:
1693 main.log.error( self.name + ": Error in getSwController: " +
1694 self.handle.before )
1695 return main.FALSE
1696 else:
1697 return response
admin2a9548d2014-06-17 14:08:07 -07001698 else:
1699 return main.FALSE
1700 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001701 main.log.error( self.name + ": EOF exception found" )
1702 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001703 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001704 except Exception:
1705 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001706 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001707
Charles Chan029be652015-08-24 01:46:10 +08001708 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001709 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001710 Description:
1711 Assign switches to the controllers ( for ovs use only )
1712 Required:
1713 sw - Name of the switch. This can be a list or a string.
1714 ip - Ip addresses of controllers. This can be a list or a string.
1715 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001716 port - ONOS use port 6653, if no list of ports is passed, then
1717 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001718 ptcp - ptcp number, This can be a string or a list that has
1719 the same length as switch. This is optional and not required
1720 when using ovs switches.
1721 NOTE: If switches and ptcp are given in a list type they should have the
1722 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1723 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001724
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001725 Return:
1726 Returns main.TRUE if mininet correctly assigned switches to
1727 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001728 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001729 """
1730 assignResult = main.TRUE
1731 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001732 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001733 command = "sh ovs-vsctl set-controller "
1734 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001735 try:
1736 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001737 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001738 if isinstance( port, types.StringType ) or \
1739 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001740 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001741 elif isinstance( port, types.ListType ):
1742 main.log.error( self.name + ": Only one controller " +
1743 "assigned and a list of ports has" +
1744 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001745 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001746 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001747 main.log.error( self.name + ": Invalid controller port " +
1748 "number. Please specify correct " +
1749 "controller port" )
1750 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001751
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001752 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001753 if isinstance( port, types.StringType ) or \
1754 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001755 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001756 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1757 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001758 elif isinstance( port, types.ListType ):
1759 if ( len( ip ) != len( port ) ):
1760 main.log.error( self.name + ": Port list = " +
1761 str( len( port ) ) +
1762 "should be the same as controller" +
1763 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001764 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001765 else:
1766 onosIp = ""
1767 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001768 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1769 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001770 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001771 main.log.error( self.name + ": Invalid controller port " +
1772 "number. Please specify correct " +
1773 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001774 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001775 else:
1776 main.log.error( self.name + ": Invalid ip address" )
1777 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001778
1779 if isinstance( sw, types.StringType ):
1780 command += sw + " "
1781 if ptcp:
1782 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001783 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001784 elif isinstance( ptcp, types.ListType ):
1785 main.log.error( self.name + ": Only one switch is " +
1786 "being set and multiple PTCP is " +
1787 "being passed " )
1788 else:
1789 main.log.error( self.name + ": Invalid PTCP" )
1790 ptcp = ""
1791 command += onosIp
1792 commandList.append( command )
1793
1794 elif isinstance( sw, types.ListType ):
1795 if ptcp:
1796 if isinstance( ptcp, types.ListType ):
1797 if len( ptcp ) != len( sw ):
1798 main.log.error( self.name + ": PTCP length = " +
1799 str( len( ptcp ) ) +
1800 " is not the same as switch" +
1801 " length = " +
1802 str( len( sw ) ) )
1803 return main.FALSE
1804 else:
1805 for switch, ptcpNum in zip( sw, ptcp ):
1806 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001807 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001808 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001809 tempCmd += onosIp
1810 commandList.append( tempCmd )
1811 else:
1812 main.log.error( self.name + ": Invalid PTCP" )
1813 return main.FALSE
1814 else:
1815 for switch in sw:
1816 tempCmd = "sh ovs-vsctl set-controller "
1817 tempCmd += switch + " " + onosIp
1818 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001819 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001820 main.log.error( self.name + ": Invalid switch type " )
1821 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001822
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001823 for cmd in commandList:
1824 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001825 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08001826 if "no bridge named" in self.handle.before:
1827 main.log.error( self.name + ": Error in assignSwController: " +
1828 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001829 except pexpect.TIMEOUT:
1830 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1831 return main.FALSE
1832 except pexpect.EOF:
1833 main.log.error( self.name + ": EOF exception found" )
1834 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001835 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001836 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001837 except pexpect.EOF:
1838 main.log.error( self.name + ": EOF exception found" )
1839 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001840 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001841 except Exception:
1842 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001843 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001844
kelvin-onlabd3b64892015-01-20 13:26:24 -08001845 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001846 """
1847 Removes the controller target from sw"""
1848 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001849 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001850 response = self.execute(
1851 cmd=command,
1852 prompt="mininet>",
1853 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001854 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001855 main.log.error( self.name + ": EOF exception found" )
1856 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001857 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001858 except Exception:
1859 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001860 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001861 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001862 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001863
kelvin-onlabd3b64892015-01-20 13:26:24 -08001864 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001865 """
Jon Hallb1290e82014-11-18 16:17:48 -05001866 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001867 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001868 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001869 NOTE: cannot currently specify what type of switch
1870 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001871 sw = name of the new switch as a string
1872 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001873 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001874 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001875 """
1876 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001877 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001878 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001879 response = self.execute(
1880 cmd=command,
1881 prompt="mininet>",
1882 timeout=10 )
1883 if re.search( "already exists!", response ):
1884 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001885 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001886 elif re.search( "Error", response ):
1887 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001888 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001889 elif re.search( "usage:", response ):
1890 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001891 return main.FALSE
1892 else:
1893 return main.TRUE
1894 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001895 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001896 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001897 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001898 except Exception:
1899 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001900 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001901
kelvin-onlabd3b64892015-01-20 13:26:24 -08001902 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001903 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001904 delete a switch from the mininet topology
1905 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001906 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001907 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001908 sw = name of the switch as a string
1909 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001910 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001911 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001912 response = self.execute(
1913 cmd=command,
1914 prompt="mininet>",
1915 timeout=10 )
1916 if re.search( "no switch named", response ):
1917 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001918 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001919 elif re.search( "Error", response ):
1920 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001921 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001922 elif re.search( "usage:", response ):
1923 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001924 return main.FALSE
1925 else:
1926 return main.TRUE
1927 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001928 main.log.error( self.name + ": EOF exception found" )
1929 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001930 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001931 except Exception:
1932 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001933 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001934
You Wanga9a5e002019-01-31 12:33:26 -08001935 def getSwitchRandom( self, timeout=60, nonCut=True, switchClasses=None, excludeNodes=[], excludeSwitches=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07001936 """
1937 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001938 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001939 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001940 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07001941 it just randomly returns one switch from all current switches in
1942 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08001943 excludeNodes will be pased to getGraphDict method
You Wanga9a5e002019-01-31 12:33:26 -08001944 Switches specified in excludeSwitches will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07001945 Returns the name of the chosen switch.
1946 """
1947 import random
1948 candidateSwitches = []
1949 try:
1950 if not nonCut:
You Wang7d14d642019-01-23 15:10:08 -08001951 switches = self.getSwitches( timeout=timeout, switchClasses=switchClasses )
You Wangdb8cd0a2016-05-26 15:19:45 -07001952 assert len( switches ) != 0
1953 for switchName in switches.keys():
1954 candidateSwitches.append( switchName )
1955 else:
You Wang7d14d642019-01-23 15:10:08 -08001956 graphDict = self.getGraphDict( timeout=timeout, useId=False,
1957 switchClasses=switchClasses,
1958 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001959 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001960 return None
1961 self.graph.update( graphDict )
1962 candidateSwitches = self.graph.getNonCutVertices()
You Wanga9a5e002019-01-31 12:33:26 -08001963 candidateSwitches = [ switch for switch in candidateSwitches if switch not in excludeSwitches ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001964 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001965 return None
1966 elif len( candidateSwitches ) == 0:
1967 main.log.info( self.name + ": No candidate switch for deletion" )
1968 return None
1969 else:
1970 switch = random.sample( candidateSwitches, 1 )
1971 return switch[ 0 ]
1972 except KeyError:
1973 main.log.exception( self.name + ": KeyError exception found" )
1974 return None
1975 except AssertionError:
1976 main.log.exception( self.name + ": AssertionError exception found" )
1977 return None
1978 except Exception:
1979 main.log.exception( self.name + ": Uncaught exception" )
1980 return None
1981
1982 def delSwitchRandom( self, timeout=60, nonCut=True ):
1983 """
1984 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001985 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001986 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001987 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07001988 otherwise it just randomly delete one switch from all current
1989 switches in Mininet.
1990 Returns the name of the deleted switch
1991 """
1992 try:
1993 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001994 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001995 return None
1996 else:
1997 deletionResult = self.delSwitch( switch )
1998 if deletionResult:
1999 return switch
2000 else:
2001 return None
2002 except Exception:
2003 main.log.exception( self.name + ": Uncaught exception" )
2004 return None
2005
kelvin-onlabd3b64892015-01-20 13:26:24 -08002006 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002007 """
2008 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002009 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002010 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002011 NOTE: cannot currently specify what type of link
2012 required params:
2013 node1 = the string node name of the first endpoint of the link
2014 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002015 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002016 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002017 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002018 response = self.execute(
2019 cmd=command,
2020 prompt="mininet>",
2021 timeout=10 )
2022 if re.search( "doesnt exist!", response ):
2023 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002024 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002025 elif re.search( "Error", response ):
2026 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002027 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002028 elif re.search( "usage:", response ):
2029 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002030 return main.FALSE
2031 else:
2032 return main.TRUE
2033 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002034 main.log.error( self.name + ": EOF exception found" )
2035 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002036 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002037 except Exception:
2038 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002039 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002040
kelvin-onlabd3b64892015-01-20 13:26:24 -08002041 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002042 """
2043 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002044 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002045 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002046 required params:
2047 node1 = the string node name of the first endpoint of the link
2048 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002049 returns: main.FALSE on an error, else main.TRUE
2050 """
Jon Hallffb386d2014-11-21 13:43:38 -08002051 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002052 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002053 response = self.execute(
2054 cmd=command,
2055 prompt="mininet>",
2056 timeout=10 )
2057 if re.search( "no node named", response ):
2058 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002059 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002060 elif re.search( "Error", response ):
2061 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002062 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002063 elif re.search( "usage:", response ):
2064 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002065 return main.FALSE
2066 else:
2067 return main.TRUE
2068 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002069 main.log.error( self.name + ": EOF exception found" )
2070 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002071 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002072 except Exception:
2073 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002074 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002075
You Wang7d14d642019-01-23 15:10:08 -08002076 def getLinkRandom( self, timeout=60, nonCut=True, switchClasses=None, excludeNodes=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07002077 """
2078 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002079 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002080 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002081 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002082 it just randomly returns one link from all current links in
2083 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08002084 excludeNodes will be passed to getLinks method to exclude unexpected links.
You Wangdb8cd0a2016-05-26 15:19:45 -07002085 Returns the link as a list, e.g. [ 's1', 's2' ]
2086 """
2087 import random
2088 candidateLinks = []
2089 try:
2090 if not nonCut:
You Wang7d14d642019-01-23 15:10:08 -08002091 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07002092 assert len( links ) != 0
2093 for link in links:
2094 # Exclude host-switch link
2095 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2096 continue
2097 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2098 else:
You Wang7d14d642019-01-23 15:10:08 -08002099 graphDict = self.getGraphDict( timeout=timeout, useId=False,
2100 switchClasses=switchClasses,
2101 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002102 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002103 return None
2104 self.graph.update( graphDict )
2105 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002106 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002107 return None
2108 elif len( candidateLinks ) == 0:
2109 main.log.info( self.name + ": No candidate link for deletion" )
2110 return None
2111 else:
2112 link = random.sample( candidateLinks, 1 )
2113 return link[ 0 ]
2114 except KeyError:
2115 main.log.exception( self.name + ": KeyError exception found" )
2116 return None
2117 except AssertionError:
2118 main.log.exception( self.name + ": AssertionError exception found" )
2119 return None
2120 except Exception:
2121 main.log.exception( self.name + ": Uncaught exception" )
2122 return None
2123
2124 def delLinkRandom( self, timeout=60, nonCut=True ):
2125 """
2126 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002127 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002128 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002129 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002130 otherwise it just randomly delete one link from all current links
2131 in Mininet.
2132 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2133 """
2134 try:
2135 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002136 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002137 return None
2138 else:
2139 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2140 if deletionResult:
2141 return link
2142 else:
2143 return None
2144 except Exception:
2145 main.log.exception( self.name + ": Uncaught exception" )
2146 return None
2147
kelvin-onlabd3b64892015-01-20 13:26:24 -08002148 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002149 """
Jon Hallb1290e82014-11-18 16:17:48 -05002150 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002151 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002152 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002153 NOTE: cannot currently specify what type of host
2154 required params:
2155 hostname = the string hostname
2156 optional key-value params
2157 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002158 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002159 """
2160 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002161 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002162 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002163 response = self.execute(
2164 cmd=command,
2165 prompt="mininet>",
2166 timeout=10 )
2167 if re.search( "already exists!", response ):
2168 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002169 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002170 elif re.search( "doesnt exists!", response ):
2171 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002172 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002173 elif re.search( "Error", response ):
2174 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002175 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002176 elif re.search( "usage:", response ):
2177 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002178 return main.FALSE
2179 else:
2180 return main.TRUE
2181 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002182 main.log.error( self.name + ": EOF exception found" )
2183 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002184 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002185 except Exception:
2186 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002187 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002188
kelvin-onlabd3b64892015-01-20 13:26:24 -08002189 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002190 """
2191 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002192 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002193 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002194 NOTE: this uses a custom mn function
2195 required params:
2196 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002197 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002198 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002199 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002200 response = self.execute(
2201 cmd=command,
2202 prompt="mininet>",
2203 timeout=10 )
2204 if re.search( "no host named", response ):
2205 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002206 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002207 elif re.search( "Error", response ):
2208 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002209 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002210 elif re.search( "usage:", response ):
2211 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002212 return main.FALSE
2213 else:
2214 return main.TRUE
2215 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002216 main.log.error( self.name + ": EOF exception found" )
2217 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002218 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002219 except Exception:
2220 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002221 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002222
Jon Hall7eb38402015-01-08 17:19:54 -08002223 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002224 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002225 Called at the end of the test to stop the mininet and
2226 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002227 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002228 try:
2229 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002230 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002231 timeout=2 )
2232 response = main.TRUE
2233 if i == 0:
2234 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002235 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002236 return main.TRUE
2237 # print "Disconnecting Mininet"
2238 if self.handle:
2239 self.handle.sendline( "exit" )
2240 self.handle.expect( "exit" )
2241 self.handle.expect( "(.*)" )
2242 else:
2243 main.log.error( "Connection failed to the host" )
2244 return response
2245 except pexpect.EOF:
2246 main.log.error( self.name + ": EOF exception found" )
2247 main.log.error( self.name + ": " + self.handle.before )
You Wangd4fae5c2018-08-22 13:56:49 -07002248 # Do not exit the entire test when pexpect.EOF is caught
2249 # FIXME: We might need to do something else here
2250 return main.ERROR
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002251 except Exception:
2252 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002253 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002254
Devin Lima7cfdbd2017-09-29 15:02:22 -07002255 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002256 """
Jon Hall21270ac2015-02-16 17:59:55 -08002257 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002258 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002259 main.FALSE if the pexpect handle does not exist.
2260
Jon Halld61331b2015-02-17 16:35:47 -08002261 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002262 """
Jon Halld61331b2015-02-17 16:35:47 -08002263 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002264 response = ''
2265 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002266 try:
Jon Halld80cc142015-07-06 13:36:05 -07002267 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002268 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002269 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002270 pexpect.EOF,
2271 pexpect.TIMEOUT ],
2272 timeout )
2273 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002274 main.log.info( "Exiting mininet.." )
2275 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002276 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002277 prompt=self.prompt,
2278 timeout=exitTimeout )
2279 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002280 self.handle.sendline( "sudo mn -c" )
2281 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002282
Jeremyd9e4eb12016-04-13 12:09:06 -07002283 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002284 main.log.info( " Mininet trying to exit while not " +
2285 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002286 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002287 elif i == 2:
2288 main.log.error( "Something went wrong exiting mininet" )
2289 elif i == 3: # timeout
2290 main.log.error( "Something went wrong exiting mininet " +
2291 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002292
You Wang18db8592018-04-02 13:52:03 -07002293 self.handle.sendline( "" )
2294 self.handle.expect( self.prompt )
2295 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2296
Hari Krishnab35c6d02015-03-18 11:13:51 -07002297 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002298 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002299 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002300 self.handle.sendline(
2301 "sudo kill -9 \`ps -ef | grep \"" +
2302 fileName +
2303 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002304 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002305 main.log.error( self.name + ": TIMEOUT exception found" )
2306 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002307 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002308 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002309 main.log.error( self.name + ": EOF exception found" )
2310 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002311 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002312 except Exception:
2313 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002314 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002315 else:
2316 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002317 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002318 return response
2319
YPZhang26a139e2016-04-25 14:01:55 -07002320 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002321 """
2322 Description:
2323 Sends arp message from mininet host for hosts discovery
2324 Required:
2325 host - hosts name
2326 Optional:
2327 ip - ip address that does not exist in the network so there would
2328 be no reply.
2329 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002330 if ethDevice:
2331 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002332 cmd = srcHost + " arping -c1 "
2333 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002334 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 -07002335 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002336 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002337 if output:
2338 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002339 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002340 i = self.handle.expect( [ "mininet>", "arping: " ] )
2341 if i == 0:
2342 return main.TRUE
2343 elif i == 1:
2344 response = self.handle.before + self.handle.after
2345 self.handle.expect( "mininet>" )
2346 response += self.handle.before + self.handle.after
2347 main.log.warn( "Error sending arping, output was: " +
2348 response )
2349 return main.FALSE
2350 except pexpect.TIMEOUT:
2351 main.log.error( self.name + ": TIMEOUT exception found" )
2352 main.log.warn( self.handle.before )
2353 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002354 except pexpect.EOF:
2355 main.log.error( self.name + ": EOF exception found" )
2356 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002357 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002358 except Exception:
2359 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002360 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002361
Jon Hall7eb38402015-01-08 17:19:54 -08002362 def decToHex( self, num ):
2363 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002364
Jon Hall7eb38402015-01-08 17:19:54 -08002365 def getSwitchFlowCount( self, switch ):
2366 """
2367 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002368 if self.handle:
2369 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2370 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002371 response = self.execute(
2372 cmd=cmd,
2373 prompt="mininet>",
2374 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002375 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002376 main.log.error( self.name + ": EOF exception found" )
2377 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002378 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002379 except Exception:
2380 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002381 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002382 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002383 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002384 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002385 main.log.info(
2386 "Couldn't find flows on switch %s, found: %s" %
2387 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002388 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002389 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002390 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002391 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002392
Jon Hall9ed8f372016-02-24 17:34:07 -08002393 def checkFlows( self, sw, dumpFormat=None ):
2394 if dumpFormat:
2395 command = "sh ovs-ofctl -F " + \
2396 dumpFormat + " dump-flows " + str( sw )
2397 else:
2398 command = "sh ovs-ofctl dump-flows " + str( sw )
2399 try:
2400 response = self.execute(
2401 cmd=command,
2402 prompt="mininet>",
2403 timeout=10 )
2404 return response
2405 except pexpect.EOF:
2406 main.log.error( self.name + ": EOF exception found" )
2407 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002408 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002409 except Exception:
2410 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002411 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002412
GlennRC68467eb2015-11-16 18:01:01 -08002413 def flowTableComp( self, flowTable1, flowTable2 ):
2414 # This function compares the selctors and treatments of each flow
2415 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002416 assert flowTable1, "flowTable1 is empty or None"
2417 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002418 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002419 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002420 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002421 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002422 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2423 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002424 for field in dFields:
2425 try:
2426 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002427 except KeyError:
2428 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002429 try:
2430 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002431 except KeyError:
2432 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002433 for i in range( len( flowTable1 ) ):
2434 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002435 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002436 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002437 returnValue = main.FALSE
2438 break
2439 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002440 except AssertionError:
2441 main.log.exception( "Nothing to compare" )
2442 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002443 except Exception:
2444 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002445 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002446
GlennRC528ad292015-11-12 10:38:18 -08002447 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002448 '''
GlennRC956ea742015-11-05 16:14:15 -08002449 Discription: Parses flows into json format.
2450 NOTE: this can parse any string thats separated with commas
2451 Arguments:
2452 Required:
2453 flows: a list of strings that represnt flows
2454 Optional:
2455 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2456 debug: prints out the final result
2457 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002458 '''
GlennRC528ad292015-11-12 10:38:18 -08002459 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002460 try:
2461 for flow in flowTable:
2462 jsonFlow = {}
2463 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002464 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002465 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002466 for i in range( len( parsedFlow ) ):
2467 item = parsedFlow[ i ]
2468 if item[ 0 ] == " ":
2469 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002470 # grab the selector and treatment from the parsed flow
2471 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002472 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002473 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002474 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002475 index = 0
2476 # parse the flags
2477 # NOTE: This only parses one flag
2478 flag = {}
2479 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002480 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002481 index += 1
2482 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002483 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002484 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002485 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002486 # the priority is stuck in the selecter so put it back
2487 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002488 if 'priority' in sel[0]:
2489 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002490 # parse selector
2491 criteria = []
2492 for item in sel:
2493 # this is the type of the packet e.g. "arp"
2494 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002495 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002496 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002497 field = item.split( "=" )
2498 criteria.append( { field[ 0 ]: field[ 1 ] } )
2499 selector = { "selector": { "criteria": sorted( criteria ) } }
2500 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002501 # get rid of the action part e.g. "action=output:2"
2502 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002503 treat = treat.split( "=" )
2504 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002505 # parse treatment
2506 action = []
2507 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002508 if ":" in item:
2509 field = item.split( ":" )
2510 action.append( { field[ 0 ]: field[ 1 ] } )
2511 else:
2512 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2513 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002514 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002515 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002516 # parse the rest of the flow
2517 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002518 field = item.split( "=" )
2519 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002520 # add the treatment and the selector to the json flow
2521 jsonFlow.update( selector )
2522 jsonFlow.update( treatment )
2523 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002524
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002525 if debug:
2526 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002527
You Wang91c37cf2016-05-23 09:39:42 -07002528 # add the json flow to the json flow table
2529 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002530
You Wang91c37cf2016-05-23 09:39:42 -07002531 return jsonFlowTable
2532
2533 except IndexError:
2534 main.log.exception( self.name + ": IndexError found" )
2535 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002536 except pexpect.EOF:
2537 main.log.error( self.name + ": EOF exception found" )
2538 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002539 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002540 except Exception:
2541 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002542 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002543
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002544 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002545 '''
2546 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002547 Each element is a flow.
2548 Arguments:
2549 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002550 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002551 a list of switches.
2552 Optional:
2553 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2554 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002555 '''
GlennRC956ea742015-11-05 16:14:15 -08002556 try:
2557 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002558 if isinstance( sw, list ):
2559 switches.extend( sw )
2560 else:
2561 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002562
2563 flows = []
2564 for s in switches:
2565 cmd = "sh ovs-ofctl dump-flows " + s
2566
GlennRC528ad292015-11-12 10:38:18 -08002567 if "1.0" == version:
2568 cmd += " -F OpenFlow10-table_id"
2569 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002570 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002571
2572 main.log.info( "Sending: " + cmd )
2573 self.handle.sendline( cmd )
2574 self.handle.expect( "mininet>" )
2575 response = self.handle.before
2576 response = response.split( "\r\n" )
2577 # dump the first two elements and the last
2578 # the first element is the command that was sent
2579 # the second is the table header
2580 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002581 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002582 flows.extend( response )
2583
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002584 if debug:
2585 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002586
GlennRC528ad292015-11-12 10:38:18 -08002587 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002588
GlennRC956ea742015-11-05 16:14:15 -08002589 except pexpect.EOF:
2590 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002591 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002592 except Exception:
2593 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002594 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002595
2596 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002597 '''
GlennRC956ea742015-11-05 16:14:15 -08002598 Discription: Checks whether the ID provided matches a flow ID in Mininet
2599 Arguments:
2600 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002601 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002602 a list of switches.
2603 flowId: the flow ID in hex format. Can also be a list of IDs
2604 Optional:
2605 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2606 debug: prints out the final result
2607 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2608 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002609 '''
GlennRC956ea742015-11-05 16:14:15 -08002610 try:
2611 main.log.info( "Getting flows from Mininet" )
2612 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002613 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002614 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002615
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002616 if debug:
2617 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002618
2619 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002620 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002621 result = False
2622 for f in flows:
2623 if flowId in f.get( 'cookie' ):
2624 result = True
2625 break
2626 # flowId is a list
2627 else:
2628 result = True
2629 # Get flow IDs from Mininet
2630 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2631 # Save the IDs that are not in Mininet
2632 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2633
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002634 if debug:
2635 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002636
2637 # Print out the IDs that are not in Mininet
2638 if absentIds:
2639 main.log.warn( "Absent ids: {}".format( absentIds ) )
2640 result = False
2641
2642 return main.TRUE if result else main.FALSE
2643
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002644 except pexpect.EOF:
2645 main.log.error( self.name + ": EOF exception found" )
2646 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002647 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002648 except Exception:
2649 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002650 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002651
Charles Chan029be652015-08-24 01:46:10 +08002652 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002653 """
Jon Hallefbd9792015-03-05 16:11:36 -08002654 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002655 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002656 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002657 self.handle.sendline( "" )
2658 self.handle.expect( "mininet>" )
2659 self.handle.sendline(
2660 "sh sudo tcpdump -n -i " +
2661 intf +
2662 " " +
2663 port +
2664 " -w " +
2665 filename.strip() +
2666 " &" )
2667 self.handle.sendline( "" )
2668 i = self.handle.expect( [ 'No\ssuch\device',
2669 'listening\son',
2670 pexpect.TIMEOUT,
2671 "mininet>" ],
2672 timeout=10 )
2673 main.log.warn( self.handle.before + self.handle.after )
2674 self.handle.sendline( "" )
2675 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002676 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002677 main.log.error(
2678 self.name +
2679 ": tcpdump - No such device exists. " +
2680 "tcpdump attempted on: " +
2681 intf )
admin2a9548d2014-06-17 14:08:07 -07002682 return main.FALSE
2683 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002684 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002685 return main.TRUE
2686 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002687 main.log.error(
2688 self.name +
2689 ": tcpdump command timed out! Check interface name," +
2690 " given interface was: " +
2691 intf )
admin2a9548d2014-06-17 14:08:07 -07002692 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002693 elif i == 3:
2694 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002695 return main.TRUE
2696 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002697 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002698 return main.FALSE
2699 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002700 main.log.error( self.name + ": EOF exception found" )
2701 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002702 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002703 except Exception:
2704 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002705 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002706
kelvin-onlabd3b64892015-01-20 13:26:24 -08002707 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002708 """
2709 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002710 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002711 self.handle.sendline( "sh sudo pkill tcpdump" )
2712 self.handle.expect( "mininet>" )
2713 self.handle.sendline( "" )
2714 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002715 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002716 main.log.error( self.name + ": TIMEOUT exception found" )
2717 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002718 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002719 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002720 main.log.error( self.name + ": EOF exception found" )
2721 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002722 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002723 except Exception:
2724 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002725 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002726
Jon Halld80cc142015-07-06 13:36:05 -07002727 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002728 """
2729 Read ports from a Mininet switch.
2730
2731 Returns a json structure containing information about the
2732 ports of the given switch.
2733 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002734 try:
2735 response = self.getInterfaces( nodeName )
2736 # TODO: Sanity check on response. log if no such switch exists
2737 ports = []
2738 for line in response.split( "\n" ):
2739 if not line.startswith( "name=" ):
2740 continue
2741 portVars = {}
2742 for var in line.split( "," ):
2743 key, value = var.split( "=" )
2744 portVars[ key ] = value
2745 isUp = portVars.pop( 'enabled', "True" )
2746 isUp = "True" in isUp
2747 if verbose:
2748 main.log.info( "Reading switch port %s(%s)" %
2749 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2750 mac = portVars[ 'mac' ]
2751 if mac == 'None':
2752 mac = None
2753 ips = []
2754 ip = portVars[ 'ip' ]
2755 if ip == 'None':
2756 ip = None
2757 ips.append( ip )
2758 name = portVars[ 'name' ]
2759 if name == 'None':
2760 name = None
2761 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2762 if name == 'lo':
2763 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2764 else:
2765 portNo = re.search( portRe, name ).group( 'port' )
2766 ports.append( { 'of_port': portNo,
2767 'mac': str( mac ).replace( '\'', '' ),
2768 'name': name,
2769 'ips': ips,
2770 'enabled': isUp } )
2771 return ports
2772 except pexpect.EOF:
2773 main.log.error( self.name + ": EOF exception found" )
2774 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002775 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002776 except Exception:
2777 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002778 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002779
You Wangdb8cd0a2016-05-26 15:19:45 -07002780 def getOVSPorts( self, nodeName ):
2781 """
2782 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2783
2784 Returns a list of dictionaries containing information about each
2785 port of the given switch.
2786 """
2787 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2788 try:
2789 response = self.execute(
2790 cmd=command,
2791 prompt="mininet>",
You Wang7d14d642019-01-23 15:10:08 -08002792 timeout=10,
2793 logCmd=False )
You Wangdb8cd0a2016-05-26 15:19:45 -07002794 ports = []
2795 if response:
2796 for line in response.split( "\n" ):
2797 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2798 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002799 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002800 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2801 result = re.search( pattern, line )
2802 if result:
2803 index = result.group( 'index' )
2804 name = result.group( 'name' )
2805 # This port number is extracted from port name
2806 port = result.group( 'port' )
2807 mac = result.group( 'mac' )
2808 ports.append( { 'index': index,
2809 'name': name,
2810 'port': port,
2811 'mac': mac } )
2812 return ports
2813 except pexpect.EOF:
2814 main.log.error( self.name + ": EOF exception found" )
2815 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002816 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002817 except Exception:
2818 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002819 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002820
You Wang7d14d642019-01-23 15:10:08 -08002821 def getSwitches( self, verbose=False, updateTimeout=1000, switchClasses=None ):
Jon Hallafa8a472015-06-12 14:02:42 -07002822 """
2823 Read switches from Mininet.
2824
2825 Returns a dictionary whose keys are the switch names and the value is
2826 a dictionary containing information about the switch.
2827 """
Jon Halla22481b2015-07-28 17:46:01 -07002828 # NOTE: To support new Mininet switch classes, just append the new
2829 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002830
Jon Halla22481b2015-07-28 17:46:01 -07002831 # Regex patterns to parse 'dump' output
2832 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002833 # <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 -07002834 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002835 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2836 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2837 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
You Wang7d14d642019-01-23 15:10:08 -08002838 if not switchClasses:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002839 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
You Wang7d14d642019-01-23 15:10:08 -08002840 try:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002841 swRE = r"<(?P<class>" + switchClasses + r")" +\
2842 r"(?P<options>\{.*\})?\s" +\
2843 r"(?P<name>[^:]+)\:\s" +\
2844 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2845 r"\spid=(?P<pid>(\d)+)"
2846 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002847 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002848 output = {}
2849 dump = self.dump().split( "\n" )
2850 for line in dump:
2851 result = re.search( swRE, line, re.I )
2852 if result:
2853 name = result.group( 'name' )
2854 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2855 pid = result.group( 'pid' )
2856 swClass = result.group( 'class' )
2857 options = result.group( 'options' )
2858 if verbose:
2859 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2860 ports = self.getPorts( name )
2861 output[ name ] = { "dpid": dpid,
2862 "ports": ports,
2863 "swClass": swClass,
2864 "pid": pid,
2865 "options": options }
2866 return output
2867 except pexpect.EOF:
2868 main.log.error( self.name + ": EOF exception found" )
2869 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002870 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002871 except Exception:
2872 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002873 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002874
You Wangd66de192018-04-30 17:30:12 -07002875 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002876 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2877 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002878 """
2879 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002880 Optional:
2881 hostClass: it is used to match the class of the mininet host. It
2882 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002883 Returns a dictionary whose keys are the host names and the value is
2884 a dictionary containing information about the host.
2885 """
2886 # Regex patterns to parse dump output
2887 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002888 # <Host h1: pid=12725>
2889 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2890 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2891 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002892 # NOTE: Does not correctly match hosts with multi-links
2893 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2894 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002895 try:
You Wang53dba1e2018-02-02 17:45:44 -08002896 if not isinstance( hostClass, types.ListType ):
2897 hostClass = [ str( hostClass ) ]
2898 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002899 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2900 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2901 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002902 if update:
2903 # update mn port info
2904 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002905 # Get mininet dump
2906 dump = self.dump().split( "\n" )
2907 hosts = {}
2908 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002909 result = re.search( hostRE, line )
2910 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002911 name = result.group( 'name' )
2912 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002913 if getInterfaces:
2914 response = self.getInterfaces( name )
2915 # Populate interface info
2916 for line in response.split( "\n" ):
2917 if line.startswith( "name=" ):
2918 portVars = {}
2919 for var in line.split( "," ):
2920 key, value = var.split( "=" )
2921 portVars[ key ] = value
2922 isUp = portVars.pop( 'enabled', "True" )
2923 isUp = "True" in isUp
2924 if verbose:
2925 main.log.info( "Reading host port %s(%s)" %
2926 ( portVars[ 'name' ],
2927 portVars[ 'mac' ] ) )
2928 mac = portVars[ 'mac' ]
2929 if mac == 'None':
2930 mac = None
2931 ips = []
2932 ip = portVars[ 'ip' ]
2933 if ip == 'None':
2934 ip = None
2935 ips.append( ip )
2936 intfName = portVars[ 'name' ]
2937 if name == 'None':
2938 name = None
2939 interfaces.append( {
2940 "name": intfName,
2941 "ips": ips,
2942 "mac": str( mac ),
2943 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002944 hosts[ name ] = { "interfaces": interfaces }
2945 return hosts
2946 except pexpect.EOF:
2947 main.log.error( self.name + ": EOF exception found" )
2948 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002949 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002950 except Exception:
2951 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002952 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002953
You Wang7d14d642019-01-23 15:10:08 -08002954 def getLinks( self, timeout=20, updateTimeout=1000, excludeNodes=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002955 """
2956 Gathers information about current Mininet links. These links may not
2957 be up if one of the ports is down.
2958
2959 Returns a list of dictionaries with link endpoints.
2960
2961 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002962 { 'node1': str( node1 name )
2963 'node2': str( node2 name )
2964 'port1': str( port1 of_port )
2965 'port2': str( port2 of_port ) }
You Wang7d14d642019-01-23 15:10:08 -08002966
2967 If either node1 or node2 name starts with any of the strings sepcified
2968 in excludeNodes, the link will be excluded from the returned value
2969
Jon Hallafa8a472015-06-12 14:02:42 -07002970 Note: The port number returned is the eth#, not necessarily the of_port
2971 number. In Mininet, for OVS switch, these should be the same. For
2972 hosts, this is just the eth#.
2973 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002974 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002975 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002976 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002977
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002978 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002979 # s1-eth3<->s2-eth1 (OK OK)
2980 # s13-eth3<->h27-eth0 (OK OK)
You Wang7d14d642019-01-23 15:10:08 -08002981 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d\.]+)\<\-\>" +\
2982 "(?P<node2>[\w]+)\-eth(?P<port2>[\d\.]+)"
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002983 links = []
2984 for line in response:
2985 match = re.search( linkRE, line )
2986 if match:
2987 node1 = match.group( 'node1' )
2988 node2 = match.group( 'node2' )
You Wang7d14d642019-01-23 15:10:08 -08002989 if any( node1.startswith( node ) for node in excludeNodes ) or \
2990 any( node2.startswith( node ) for node in excludeNodes ):
2991 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002992 port1 = match.group( 'port1' )
2993 port2 = match.group( 'port2' )
2994 links.append( { 'node1': node1,
2995 'node2': node2,
2996 'port1': port1,
2997 'port2': port2 } )
2998 return links
2999
3000 except pexpect.EOF:
3001 main.log.error( self.name + ": EOF exception found" )
3002 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003003 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003004 except Exception:
3005 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003006 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003007
3008 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003009 """
3010 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003011 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003012
Jon Hallafa8a472015-06-12 14:02:42 -07003013 Dependencies:
3014 1. numpy - "sudo pip install numpy"
3015 """
3016 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003017 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003018 try:
3019 mnDPIDs = []
3020 for swName, switch in switches.iteritems():
3021 mnDPIDs.append( switch[ 'dpid' ].lower() )
3022 mnDPIDs.sort()
3023 if switchesJson == "": # if rest call fails
3024 main.log.error(
3025 self.name +
3026 ".compareSwitches(): Empty JSON object given from ONOS" )
3027 return main.FALSE
3028 onos = switchesJson
3029 onosDPIDs = []
3030 for switch in onos:
3031 if switch[ 'available' ]:
3032 onosDPIDs.append(
3033 switch[ 'id' ].replace(
3034 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003035 '' ).replace(
3036 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003037 '' ).lower() )
3038 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003039
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003040 if mnDPIDs != onosDPIDs:
3041 switchResults = main.FALSE
3042 main.log.error( "Switches in MN but not in ONOS:" )
3043 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3044 main.log.error( str( list1 ) )
3045 main.log.error( "Switches in ONOS but not in MN:" )
3046 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3047 main.log.error( str( list2 ) )
3048 else: # list of dpid's match in onos and mn
3049 switchResults = main.TRUE
3050 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003051
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003052 # FIXME: this does not look for extra ports in ONOS, only checks that
3053 # ONOS has what is in MN
3054 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003055
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003056 # PORTS
3057 for name, mnSwitch in switches.iteritems():
3058 mnPorts = []
3059 onosPorts = []
3060 switchResult = main.TRUE
3061 for port in mnSwitch[ 'ports' ]:
3062 if port[ 'enabled' ]:
3063 mnPorts.append( int( port[ 'of_port' ] ) )
3064 for onosSwitch in portsJson:
3065 if onosSwitch[ 'device' ][ 'available' ]:
3066 if onosSwitch[ 'device' ][ 'id' ].replace(
3067 ':',
3068 '' ).replace(
3069 "of",
3070 '' ) == mnSwitch[ 'dpid' ]:
3071 for port in onosSwitch[ 'ports' ]:
3072 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003073 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003074 # onosPorts.append( 'local' )
3075 onosPorts.append( long( uint64( -2 ) ) )
3076 else:
3077 onosPorts.append( int( port[ 'port' ] ) )
3078 break
3079 mnPorts.sort( key=float )
3080 onosPorts.sort( key=float )
3081
3082 mnPortsLog = mnPorts
3083 onosPortsLog = onosPorts
3084 mnPorts = [ x for x in mnPorts ]
3085 onosPorts = [ x for x in onosPorts ]
3086
3087 # TODO: handle other reserved port numbers besides LOCAL
3088 # NOTE: Reserved ports
3089 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3090 # long( uint64( -2 ) )
3091 for mnPort in mnPortsLog:
3092 if mnPort in onosPorts:
3093 # don't set results to true here as this is just one of
3094 # many checks and it might override a failure
3095 mnPorts.remove( mnPort )
3096 onosPorts.remove( mnPort )
3097
3098 # NOTE: OVS reports this as down since there is no link
3099 # So ignoring these for now
3100 # TODO: Come up with a better way of handling these
3101 if 65534 in mnPorts:
3102 mnPorts.remove( 65534 )
3103 if long( uint64( -2 ) ) in onosPorts:
3104 onosPorts.remove( long( uint64( -2 ) ) )
3105 if len( mnPorts ): # the ports of this switch don't match
3106 switchResult = main.FALSE
3107 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3108 if len( onosPorts ): # the ports of this switch don't match
3109 switchResult = main.FALSE
3110 main.log.warn(
3111 "Ports in ONOS but not MN: " +
3112 str( onosPorts ) )
3113 if switchResult == main.FALSE:
3114 main.log.error(
3115 "The list of ports for switch %s(%s) does not match:" %
3116 ( name, mnSwitch[ 'dpid' ] ) )
3117 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3118 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3119 portsResults = portsResults and switchResult
3120 finalResults = finalResults and portsResults
3121 return finalResults
3122 except pexpect.EOF:
3123 main.log.error( self.name + ": EOF exception found" )
3124 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003125 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003126 except Exception:
3127 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003128 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003129
Jon Hallafa8a472015-06-12 14:02:42 -07003130 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003131 """
3132 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003133 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003134
Jon Hallafa8a472015-06-12 14:02:42 -07003135 """
Jon Hall7eb38402015-01-08 17:19:54 -08003136 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003137 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003138 try:
3139 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003140
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003141 mnLinks = []
3142 for l in links:
3143 try:
3144 node1 = switches[ l[ 'node1' ] ]
3145 node2 = switches[ l[ 'node2' ] ]
3146 enabled = True
3147 for port in node1[ 'ports' ]:
3148 if port[ 'of_port' ] == l[ 'port1' ]:
3149 enabled = enabled and port[ 'enabled' ]
3150 for port in node2[ 'ports' ]:
3151 if port[ 'of_port' ] == l[ 'port2' ]:
3152 enabled = enabled and port[ 'enabled' ]
3153 if enabled:
3154 mnLinks.append( l )
3155 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003156 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003157 if 2 * len( mnLinks ) == len( onos ):
3158 linkResults = main.TRUE
3159 else:
3160 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003161 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003162 "Mininet has " + str( len( mnLinks ) ) +
3163 " bidirectional links and ONOS has " +
3164 str( len( onos ) ) + " unidirectional links" )
3165
3166 # iterate through MN links and check if an ONOS link exists in
3167 # both directions
3168 for link in mnLinks:
3169 # TODO: Find a more efficient search method
3170 node1 = None
3171 port1 = None
3172 node2 = None
3173 port2 = None
3174 firstDir = main.FALSE
3175 secondDir = main.FALSE
3176 for swName, switch in switches.iteritems():
3177 if swName == link[ 'node1' ]:
3178 node1 = switch[ 'dpid' ]
3179 for port in switch[ 'ports' ]:
3180 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3181 port1 = port[ 'of_port' ]
3182 if node1 is not None and node2 is not None:
3183 break
3184 if swName == link[ 'node2' ]:
3185 node2 = switch[ 'dpid' ]
3186 for port in switch[ 'ports' ]:
3187 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3188 port2 = port[ 'of_port' ]
3189 if node1 is not None and node2 is not None:
3190 break
3191
3192 for onosLink in onos:
3193 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3194 ":", '' ).replace( "of", '' )
3195 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3196 ":", '' ).replace( "of", '' )
3197 onosPort1 = onosLink[ 'src' ][ 'port' ]
3198 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3199
3200 # check onos link from node1 to node2
3201 if str( onosNode1 ) == str( node1 ) and str(
3202 onosNode2 ) == str( node2 ):
3203 if int( onosPort1 ) == int( port1 ) and int(
3204 onosPort2 ) == int( port2 ):
3205 firstDir = main.TRUE
3206 else:
Jon Hallab611372018-02-21 15:26:05 -08003207 # The right switches, but wrong ports, could be
3208 # another link between these devices, or onos
3209 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003210 main.log.warn(
3211 'The port numbers do not match for ' +
3212 str( link ) +
3213 ' between ONOS and MN. When checking ONOS for ' +
3214 'link %s/%s -> %s/%s' %
3215 ( node1, port1, node2, port2 ) +
3216 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003217 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3218 '. This could be another link between these devices' +
3219 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003220
3221 # check onos link from node2 to node1
3222 elif ( str( onosNode1 ) == str( node2 ) and
3223 str( onosNode2 ) == str( node1 ) ):
3224 if ( int( onosPort1 ) == int( port2 )
3225 and int( onosPort2 ) == int( port1 ) ):
3226 secondDir = main.TRUE
3227 else:
Jon Hallab611372018-02-21 15:26:05 -08003228 # The right switches, but wrong ports, could be
3229 # another link between these devices, or onos
3230 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003231 main.log.warn(
3232 'The port numbers do not match for ' +
3233 str( link ) +
3234 ' between ONOS and MN. When checking ONOS for ' +
3235 'link %s/%s -> %s/%s' %
3236 ( node1, port1, node2, port2 ) +
3237 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003238 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3239 '. This could be another link between these devices' +
3240 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003241 else: # this is not the link you're looking for
3242 pass
3243 if not firstDir:
3244 main.log.error(
3245 'ONOS does not have the link %s/%s -> %s/%s' %
3246 ( node1, port1, node2, port2 ) )
3247 if not secondDir:
3248 main.log.error(
3249 'ONOS does not have the link %s/%s -> %s/%s' %
3250 ( node2, port2, node1, port1 ) )
3251 linkResults = linkResults and firstDir and secondDir
3252 return linkResults
3253 except pexpect.EOF:
3254 main.log.error( self.name + ": EOF exception found" )
3255 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003256 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003257 except Exception:
3258 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003259 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003260
Jon Hallafa8a472015-06-12 14:02:42 -07003261 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003262 """
Jon Hallafa8a472015-06-12 14:02:42 -07003263 Compare mn and onos Hosts.
3264 Since Mininet hosts are quiet, ONOS will only know of them when they
3265 speak. For this reason, we will only check that the hosts in ONOS
3266 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003267
Jon Hallafa8a472015-06-12 14:02:42 -07003268 Arguments:
3269 hostsJson: parsed json object from the onos hosts api
3270 Returns:
3271 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003272 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003273 try:
3274 hostResults = main.TRUE
3275 for onosHost in hostsJson:
3276 onosMAC = onosHost[ 'mac' ].lower()
3277 match = False
3278 for mnHost, info in hosts.iteritems():
3279 for mnIntf in info[ 'interfaces' ]:
3280 if onosMAC == mnIntf[ 'mac' ].lower():
3281 match = True
3282 for ip in mnIntf[ 'ips' ]:
3283 if ip in onosHost[ 'ipAddresses' ]:
3284 pass # all is well
3285 else:
3286 # misssing ip
3287 main.log.error( "ONOS host " +
3288 onosHost[ 'id' ] +
3289 " has a different IP(" +
3290 str( onosHost[ 'ipAddresses' ] ) +
3291 ") than the Mininet host(" +
3292 str( ip ) +
3293 ")." )
3294 output = json.dumps(
3295 onosHost,
3296 sort_keys=True,
3297 indent=4,
3298 separators=( ',', ': ' ) )
3299 main.log.info( output )
3300 hostResults = main.FALSE
3301 if not match:
3302 hostResults = main.FALSE
3303 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3304 "corresponding Mininet host." )
3305 output = json.dumps( onosHost,
3306 sort_keys=True,
3307 indent=4,
3308 separators=( ',', ': ' ) )
3309 main.log.info( output )
3310 return hostResults
3311 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003312 main.log.error( self.name + ": EOF exception found" )
3313 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003314 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003315 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003316 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003317 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003318
You Wangd66de192018-04-30 17:30:12 -07003319 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003320 """
3321 Description:
3322 Verify that all hosts have IP address assigned to them
3323 Optional:
3324 hostList: If specified, verifications only happen to the hosts
3325 in hostList
3326 prefix: at least one of the ip address assigned to the host
3327 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003328 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003329 Returns:
3330 main.TRUE if all hosts have specific IP address assigned;
3331 main.FALSE otherwise
3332 """
3333 try:
You Wangd66de192018-04-30 17:30:12 -07003334 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003335 if not hostList:
3336 hostList = hosts.keys()
3337 for hostName in hosts.keys():
3338 if hostName not in hostList:
3339 continue
3340 ipList = []
3341 self.handle.sendline( str( hostName ) + " ip a" )
3342 self.handle.expect( "mininet>" )
3343 ipa = self.handle.before
3344 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3345 ipList += re.findall( ipv4Pattern, ipa )
3346 # It's tricky to make regex for IPv6 addresses and this one is simplified
3347 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})/'
3348 ipList += re.findall( ipv6Pattern, ipa )
3349 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3350 if not ipList:
3351 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3352 else:
3353 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3354 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3355 else:
3356 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3357 hostList.remove( hostName )
3358 return main.FALSE if hostList else main.TRUE
3359 except KeyError:
3360 main.log.exception( self.name + ": host data not as expected: " + hosts )
3361 return None
3362 except pexpect.EOF:
3363 main.log.error( self.name + ": EOF exception found" )
3364 main.log.error( self.name + ": " + self.handle.before )
3365 main.cleanAndExit()
3366 except Exception:
3367 main.log.exception( self.name + ": Uncaught exception" )
3368 return None
3369
Jon Hallafa8a472015-06-12 14:02:42 -07003370 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003371 """
3372 Returns a list of all hosts
3373 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003374 try:
3375 self.handle.sendline( "" )
3376 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003377
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003378 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3379 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003380
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003381 handlePy = self.handle.before
3382 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3383 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003384
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003385 self.handle.sendline( "" )
3386 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003387
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003388 hostStr = handlePy.replace( "]", "" )
3389 hostStr = hostStr.replace( "'", "" )
3390 hostStr = hostStr.replace( "[", "" )
3391 hostStr = hostStr.replace( " ", "" )
3392 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003393
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003394 return hostList
3395 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003396 main.log.error( self.name + ": TIMEOUT exception found" )
3397 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003398 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003399 except pexpect.EOF:
3400 main.log.error( self.name + ": EOF exception found" )
3401 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003402 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003403 except Exception:
3404 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003405 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003406
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003407 def getSwitch( self ):
3408 """
3409 Returns a list of all switches
3410 Again, don't ask question just use it...
3411 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003412 try:
3413 # get host list...
3414 hostList = self.getHosts()
3415 # Make host set
3416 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003417
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003418 # Getting all the nodes in mininet
3419 self.handle.sendline( "" )
3420 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003421
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003422 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3423 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003424
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003425 handlePy = self.handle.before
3426 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3427 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003428
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003429 self.handle.sendline( "" )
3430 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003431
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003432 nodesStr = handlePy.replace( "]", "" )
3433 nodesStr = nodesStr.replace( "'", "" )
3434 nodesStr = nodesStr.replace( "[", "" )
3435 nodesStr = nodesStr.replace( " ", "" )
3436 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003437
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003438 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003439 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003440 nodesSet.discard( 'c0' )
3441 nodesSet.discard( 'c1' )
3442 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003443
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003444 switchSet = nodesSet - hostSet
3445 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003446
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003447 return switchList
3448 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003449 main.log.error( self.name + ": TIMEOUT exception found" )
3450 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003451 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003452 except pexpect.EOF:
3453 main.log.error( self.name + ": EOF exception found" )
3454 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003455 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003456 except Exception:
3457 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003458 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003459
You Wang7d14d642019-01-23 15:10:08 -08003460 def getGraphDict( self, timeout=60, useId=True, includeHost=False,
3461 switchClasses=None, excludeNodes=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07003462 """
3463 Return a dictionary which describes the latest Mininet topology data as a
3464 graph.
3465 An example of the dictionary:
3466 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3467 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3468 Each vertex should at least have an 'edges' attribute which describes the
3469 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003470 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003471 list of attributes.
3472 An example of the edges dictionary:
3473 'edges': { vertex2: { 'port': ..., 'weight': ... },
3474 vertex3: { 'port': ..., 'weight': ... } }
3475 If useId == True, dpid/mac will be used instead of names to identify
3476 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3477 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003478 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003479 in topology data.
You Wang7d14d642019-01-23 15:10:08 -08003480 if switchClasses == None, default switchClasses will be used when calling
3481 getSwitches method.
3482 excludeNodes will be passed to getLinks method to exclude unexpected links.
You Wangdb8cd0a2016-05-26 15:19:45 -07003483 Note that link or switch that are brought down by 'link x x down' or 'switch
3484 x down' commands still show in the output of Mininet CLI commands such as
3485 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3486 recommended to use delLink() or delSwitch functions to simulate link/switch
3487 down, and addLink() or addSwitch to add them back.
3488 """
3489 graphDict = {}
3490 try:
You Wang7d14d642019-01-23 15:10:08 -08003491 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003492 portDict = {}
You Wang7d14d642019-01-23 15:10:08 -08003493 switches = self.getSwitches( switchClasses=switchClasses )
You Wangdb8cd0a2016-05-26 15:19:45 -07003494 if includeHost:
3495 hosts = self.getHosts()
3496 for link in links:
3497 # FIXME: support 'includeHost' argument
3498 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3499 continue
3500 nodeName1 = link[ 'node1' ]
3501 nodeName2 = link[ 'node2' ]
You Wang7d14d642019-01-23 15:10:08 -08003502 if not self.getOVSPorts( nodeName1 ) or not self.getOVSPorts( nodeName2 ):
3503 # The device is probably offline
3504 continue
You Wangdb8cd0a2016-05-26 15:19:45 -07003505 port1 = link[ 'port1' ]
3506 port2 = link[ 'port2' ]
3507 # Loop for two nodes
3508 for i in range( 2 ):
3509 # Get port index from OVS
3510 # The index extracted from port name may be inconsistent with ONOS
3511 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003512 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003513 portList = self.getOVSPorts( nodeName1 )
3514 if len( portList ) == 0:
3515 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3516 return None
3517 portDict[ nodeName1 ] = portList
3518 for port in portDict[ nodeName1 ]:
3519 if port[ 'port' ] == port1:
3520 portIndex = port[ 'index' ]
3521 break
3522 if portIndex == -1:
3523 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3524 return None
3525 if useId:
3526 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3527 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3528 else:
3529 node1 = nodeName1
3530 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003531 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003532 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003533 graphDict[ node1 ] = { 'edges': {},
3534 'dpid': switches[ nodeName1 ][ 'dpid' ],
3535 'name': nodeName1,
3536 'ports': switches[ nodeName1 ][ 'ports' ],
3537 'swClass': switches[ nodeName1 ][ 'swClass' ],
3538 'pid': switches[ nodeName1 ][ 'pid' ],
3539 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003540 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003541 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003542 else:
3543 # Assert node2 is not connected to any current links of node1
You Wang7d14d642019-01-23 15:10:08 -08003544 # assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
3545 pass
3546 for port in switches[ nodeName1 ][ 'ports' ]:
3547 if port[ 'of_port' ] == str( portIndex ):
3548 # Use -1 as index for disabled port
3549 if port[ 'enabled' ] == True:
3550 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
3551 else:
3552 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': -1 }
You Wangdb8cd0a2016-05-26 15:19:45 -07003553 # Swap two nodes/ports
3554 nodeName1, nodeName2 = nodeName2, nodeName1
3555 port1, port2 = port2, port1
You Wang7d14d642019-01-23 15:10:08 -08003556 # Remove links with disabled ports
3557 linksToRemove = []
3558 for node, edges in graphDict.items():
3559 for neighbor, port in edges[ 'edges' ].items():
3560 if port[ 'port' ] == -1:
3561 linksToRemove.append( ( node, neighbor ) )
3562 for node1, node2 in linksToRemove:
3563 for i in range( 2 ):
3564 if graphDict.get( node1 )[ 'edges' ].get( node2 ):
3565 graphDict[ node1 ][ 'edges' ].pop( node2 )
3566 node1, node2 = node2, node1
You Wangdb8cd0a2016-05-26 15:19:45 -07003567 return graphDict
3568 except KeyError:
3569 main.log.exception( self.name + ": KeyError exception found" )
3570 return None
3571 except AssertionError:
3572 main.log.exception( self.name + ": AssertionError exception found" )
3573 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003574 except pexpect.EOF:
3575 main.log.error( self.name + ": EOF exception found" )
3576 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003577 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003578 except Exception:
3579 main.log.exception( self.name + ": Uncaught exception" )
3580 return None
3581
Devin Lima7cfdbd2017-09-29 15:02:22 -07003582 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003583 """
3584 updates the port address and status information for
3585 each port in mn"""
3586 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003587 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003588 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003589 self.handle.sendline( "" )
3590 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003591
Jon Hall7eb38402015-01-08 17:19:54 -08003592 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003593 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003594
Jon Hall7eb38402015-01-08 17:19:54 -08003595 self.handle.sendline( "" )
3596 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003597
Jon Hallb1290e82014-11-18 16:17:48 -05003598 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003599 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003600 main.log.error( self.name + ": TIMEOUT exception found" )
3601 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003602 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003603 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003604 main.log.error( self.name + ": EOF exception found" )
3605 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003606 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003607 except Exception:
3608 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003609 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003610
Jon Halld80cc142015-07-06 13:36:05 -07003611 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003612 """
3613 Add vlan tag to a host.
3614 Dependencies:
3615 This class depends on the "vlan" package
3616 $ sudo apt-get install vlan
3617 Configuration:
3618 Load the 8021q module into the kernel
3619 $sudo modprobe 8021q
3620
3621 To make this setup permanent:
3622 $ sudo su -c 'echo "8021q" >> /etc/modules'
3623 """
3624 if self.handle:
3625 try:
Jon Halld80cc142015-07-06 13:36:05 -07003626 # get the ip address of the host
3627 main.log.info( "Get the ip address of the host" )
3628 ipaddr = self.getIPAddress( host )
3629 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003630
Jon Halld80cc142015-07-06 13:36:05 -07003631 # remove IP from interface intf
3632 # Ex: h1 ifconfig h1-eth0 inet 0
3633 main.log.info( "Remove IP from interface " )
3634 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3635 self.handle.sendline( cmd2 )
3636 self.handle.expect( "mininet>" )
3637 response = self.handle.before
3638 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003639
Jon Halld80cc142015-07-06 13:36:05 -07003640 # create VLAN interface
3641 # Ex: h1 vconfig add h1-eth0 100
3642 main.log.info( "Create Vlan" )
3643 cmd3 = host + " vconfig add " + intf + " " + vlan
3644 self.handle.sendline( cmd3 )
3645 self.handle.expect( "mininet>" )
3646 response = self.handle.before
3647 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003648
Jon Halld80cc142015-07-06 13:36:05 -07003649 # assign the host's IP to the VLAN interface
3650 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3651 main.log.info( "Assign the host IP to the vlan interface" )
3652 vintf = intf + "." + vlan
3653 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3654 self.handle.sendline( cmd4 )
3655 self.handle.expect( "mininet>" )
3656 response = self.handle.before
3657 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003658
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003659 # update Mininet node variables
3660 main.log.info( "Update Mininet node variables" )
3661 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3662 self.handle.sendline( cmd5 )
3663 self.handle.expect( "mininet>" )
3664 response = self.handle.before
3665 main.log.info( "====> %s ", response )
3666
3667 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3668 self.handle.sendline( cmd6 )
3669 self.handle.expect( "mininet>" )
3670 response = self.handle.before
3671 main.log.info( "====> %s ", response )
3672
3673 return main.TRUE
3674 except pexpect.TIMEOUT:
3675 main.log.error( self.name + ": TIMEOUT exception found" )
3676 main.log.error( self.name + ": " + self.handle.before )
3677 main.cleanAndExit()
3678 except pexpect.EOF:
3679 main.log.error( self.name + ": EOF exception found" )
3680 main.log.error( self.name + ": " + self.handle.before )
3681 return main.FALSE
3682 except Exception:
3683 main.log.exception( self.name + ": Uncaught exception!" )
3684 return main.FALSE
3685
3686 def removeVLAN( self, host, intf ):
3687 """
3688 Remove vlan tag from a host.
3689 Dependencies:
3690 This class depends on the "vlan" package
3691 $ sudo apt-get install vlan
3692 Configuration:
3693 Load the 8021q module into the kernel
3694 $sudo modprobe 8021q
3695
3696 To make this setup permanent:
3697 $ sudo su -c 'echo "8021q" >> /etc/modules'
3698 """
3699 if self.handle:
3700 try:
3701 # get the ip address of the host
3702 main.log.info( "Get the ip address of the host" )
3703 ipaddr = self.getIPAddress( host )
3704
3705 # remove VLAN interface
3706 # Ex: h1 vconfig rem h1-eth0.100
3707 main.log.info( "Remove Vlan interface" )
3708 cmd2 = host + " vconfig rem " + intf
3709 self.handle.sendline( cmd2 )
3710 self.handle.expect( "mininet>" )
3711 response = self.handle.before
3712 main.log.info( "====> %s ", response )
3713
3714 # assign the host's IP to the original interface
3715 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3716 main.log.info( "Assign the host IP to the original interface" )
3717 original_intf = intf.split(".")[0]
3718 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3719 self.handle.sendline( cmd3 )
3720 self.handle.expect( "mininet>" )
3721 response = self.handle.before
3722 main.log.info( "====> %s ", response )
3723
3724 # update Mininet node variables
3725 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3726 self.handle.sendline( cmd4 )
3727 self.handle.expect( "mininet>" )
3728 response = self.handle.before
3729 main.log.info( "====> %s ", response )
3730
3731 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3732 self.handle.sendline( cmd5 )
3733 self.handle.expect( "mininet>" )
3734 response = self.handle.before
3735 main.log.info( "====> %s ", response )
3736
kaouthera3f13ca22015-05-05 15:01:41 -07003737 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003738 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003739 main.log.error( self.name + ": TIMEOUT exception found" )
3740 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003741 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003742 except pexpect.EOF:
3743 main.log.error( self.name + ": EOF exception found" )
3744 main.log.error( self.name + ": " + self.handle.before )
3745 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003746 except Exception:
3747 main.log.exception( self.name + ": Uncaught exception!" )
3748 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003749
Jon Hall892818c2015-10-20 17:58:34 -07003750 def createHostComponent( self, name ):
3751 """
3752 Creates a new mininet cli component with the same parameters as self.
3753 This new component is intended to be used to login to the hosts created
3754 by mininet.
3755
3756 Arguments:
3757 name - The string of the name of this component. The new component
3758 will be assigned to main.<name> .
3759 In addition, main.<name>.name = str( name )
3760 """
3761 try:
3762 # look to see if this component already exists
3763 getattr( main, name )
3764 except AttributeError:
3765 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003766 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3767 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003768 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003769 except pexpect.EOF:
3770 main.log.error( self.name + ": EOF exception found" )
3771 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003772 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003773 except Exception:
3774 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003775 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003776 else:
3777 # namespace is not clear!
3778 main.log.error( name + " component already exists!" )
3779 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003780 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003781
3782 def removeHostComponent( self, name ):
3783 """
3784 Remove host component
3785 Arguments:
3786 name - The string of the name of the component to delete.
3787 """
3788 try:
3789 # Get host component
3790 component = getattr( main, name )
3791 except AttributeError:
3792 main.log.error( "Component " + name + " does not exist." )
3793 return
3794 try:
3795 # Disconnect from component
3796 component.disconnect()
You Wangf32c6ed2018-08-23 17:10:22 -07003797 component.close_log_handles()
Jon Hall892818c2015-10-20 17:58:34 -07003798 # Delete component
3799 delattr( main, name )
3800 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003801 del( main.componentDictionary[ name ] )
You Wangf32c6ed2018-08-23 17:10:22 -07003802 except StandardError:
3803 self.log.exception( "Exception while closing log files for " + name )
3804 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003805 except pexpect.EOF:
3806 main.log.error( self.name + ": EOF exception found" )
3807 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003808 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003809 except Exception:
3810 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003811 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003812
3813 def startHostCli( self, host=None ):
3814 """
3815 Use the mininet m utility to connect to the host's cli
3816 """
3817 # These are fields that can be used by scapy packets. Initialized to None
3818 self.hostIp = None
3819 self.hostMac = None
3820 try:
3821 if not host:
3822 host = self.name
3823 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003824 self.handle.sendline( "cd" )
3825 self.handle.expect( self.hostPrompt )
3826 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003827 self.handle.expect( self.hostPrompt )
3828 return main.TRUE
3829 except pexpect.TIMEOUT:
3830 main.log.exception( self.name + ": Command timed out" )
3831 return main.FALSE
3832 except pexpect.EOF:
3833 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003834 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003835 except Exception:
3836 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003837 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003838
YPZhang801d46d2016-08-08 13:26:28 -07003839 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003840 '''
3841
YPZhang801d46d2016-08-08 13:26:28 -07003842 Args:
3843 devicename: switch name
3844 intf: port name on switch
3845 status: up or down
3846
3847 Returns: boolean to show success change status
3848
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003849 '''
YPZhang801d46d2016-08-08 13:26:28 -07003850 if status == "down" or status == "up":
3851 try:
3852 cmd = devicename + " ifconfig " + intf + " " + status
3853 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003854 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003855 return main.TRUE
3856 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003857 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003858 return main.FALSE
3859 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003860 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003861 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003862 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003863 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003864 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003865 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003866 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003867 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003868 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003869 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003870 return main.FALSE
3871
You Wang6e5b48e2018-07-23 16:17:38 -07003872 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003873 """
You Wang6e5b48e2018-07-23 16:17:38 -07003874 Moves a host from one switch to another on the fly
3875 Optional:
3876 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3877 prefixLen: length of the host IP prefix
3878 ipv6: move an IPv6 host if True
3879 intfSuffix: suffix of the new interface after host movement
3880 vlan: vlan ID of the host. Use None for non-vlan host
3881 Note: The intf between host and oldSw when detached
3882 using detach(), will still show up in the 'net'
3883 cmd, because switch.detach() doesn't affect switch.intfs[]
3884 ( which is correct behavior since the interfaces
3885 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003886 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003887 if self.handle:
3888 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003889 newIntf = "%s-%s" % ( host, intfSuffix )
3890 commands = [
3891 # Bring link between oldSw-host down
3892 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3893 # Determine hostintf and Oldswitchintf
3894 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
3895 ]
3896 # Determine ip address of the host-oldSw interface
3897 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3898 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3899 commands += [
3900 # Determine mac address of the host-oldSw interface
3901 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3902 # Detach interface between oldSw-host
3903 "px " + oldSw + ".detach( sintf )",
3904 # Add link between host-newSw
3905 "py net.addLink(" + host + "," + newSw + ")",
3906 # Determine hostintf and Newswitchintf
3907 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3908 # Attach interface between newSw-host
3909 "px " + newSw + ".attach( sintf )",
3910 ]
3911 if vlan:
3912 vlanIntf = "%s.%s" % ( newIntf, vlan )
3913 commands += [
3914 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
3915 host + " ip link set up %s" % vlanIntf,
3916 "px hintf.name = '" + vlanIntf + "'",
3917 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
3918 ]
3919 newIntf = vlanIntf
3920 commands += [
3921 # Set mac address of the host-newSw interface
3922 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
3923 # Set IP address of the host-newSw interface
3924 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
3925 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
3926 ]
3927 if ipv6:
3928 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
3929 commands += [
3930 "net",
3931 host + " ifconfig"
3932 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003933 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003934 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003935 self.handle.sendline( cmd )
3936 self.handle.expect( "mininet>" )
3937 main.log.info( "====> %s ", self.handle.before )
3938 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003939 except pexpect.TIMEOUT:
3940 main.log.error( self.name + ": TIMEOUT exception found" )
3941 main.log.error( self.name + ": " + self.handle.before )
3942 main.cleanAndExit()
3943 except pexpect.EOF:
3944 main.log.error( self.name + ": EOF exception found" )
3945 main.log.error( self.name + ": " + self.handle.before )
3946 return main.FALSE
3947 except Exception:
3948 main.log.exception( self.name + ": Uncaught exception!" )
3949 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07003950
You Wang6e5b48e2018-07-23 16:17:38 -07003951 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
3952 macAddr=None, prefixLen=None, ipv6=False,
3953 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07003954 """
You Wang6e5b48e2018-07-23 16:17:38 -07003955 Moves a dual-homed host from one switch-pair to another pair on the fly
3956 Optional:
3957 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3958 prefixLen: length of the host IP prefix
3959 ipv6: move an IPv6 host if True
3960 intfSuffix1: suffix of the first new interface
3961 intfSuffix2: suffix of the second new interface
3962 bondSuffix: suffix of the new bond interface
3963 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07003964 """
You Wang7ea90582018-07-19 15:27:58 -07003965 if self.handle:
3966 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003967 bondIntf = "%s-%s" % ( host, bondSuffix )
3968 newIntf = "%s-%s" % ( host, intfSuffix1 )
3969 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07003970 commands = [
3971 # Bring link between oldSw-host down
3972 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3973 # Bring link between oldPairSw-host down
3974 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
3975 # Determine hostintf and Oldswitchintf
3976 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07003977 ]
3978 # Determine ip address of the host-oldSw interface
3979 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3980 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3981 commands += [
3982 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07003983 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3984 # Detach interface between oldSw-host
3985 "px " + oldSw + ".detach( sintf )",
3986 # Determine hostintf and Oldpairswitchintf
3987 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
3988 # Detach interface between oldPairSw-host
3989 "px " + oldPairSw + ".detach( sintfpair )",
3990 # Add link between host-newSw
3991 "py net.addLink(" + host + "," + newSw + ", 2)",
3992 # Add link between host-newPairSw
3993 "py net.addLink(" + host + "," + newPairSw + ")",
3994 # Determine hostintf and Newswitchintf
3995 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3996 # Determine hostintf and NewPairswitchintf
3997 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
3998 # Attach interface between newSw-host
3999 "px " + newSw + ".attach( sintf )",
4000 # Attach interface between newPairSw-host
4001 "px " + newPairSw + ".attach( sintfpair )",
4002 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07004003 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004004 host + ' ip link set %s down' % newIntf,
4005 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004006 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
4007 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07004008 host + ' ip addr flush dev %s' % newIntf,
4009 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004010 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004011 "px lowestIntf = min( [ hintf, hintfpair ] )",
4012 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07004013 "px lowestIntf.name = '" + bondIntf + "'",
4014 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07004015 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
4016 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07004017 ]
4018 if vlan:
4019 vlanIntf = "%s.%s" % ( bondIntf, vlan )
4020 commands += [
4021 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
4022 host + " ip link set up %s" % vlanIntf,
4023 "px lowestIntf.name = '" + vlanIntf + "'",
4024 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
4025 ]
4026 bondIntf = vlanIntf
4027 commands += [
4028 # Set macaddress of the host-newSw interface
4029 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07004030 # Set ipaddress of the host-newSw interface
4031 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
4032 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07004033 ]
You Wang6e5b48e2018-07-23 16:17:38 -07004034 if ipv6:
4035 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
4036 commands += [
4037 "net",
4038 host + " ifconfig"
4039 ]
You Wang7ea90582018-07-19 15:27:58 -07004040 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004041 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07004042 self.handle.sendline( cmd )
4043 self.handle.expect( "mininet>" )
4044 main.log.info( "====> %s ", self.handle.before )
4045 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07004046 except pexpect.TIMEOUT:
4047 main.log.error( self.name + ": TIMEOUT exception found" )
4048 main.log.error( self.name + ": " + self.handle.before )
4049 main.cleanAndExit()
4050 except pexpect.EOF:
4051 main.log.error( self.name + ": EOF exception found" )
4052 main.log.error( self.name + ": " + self.handle.before )
4053 return main.FALSE
4054 except Exception:
4055 main.log.exception( self.name + ": Uncaught exception!" )
4056 return main.FALSE
4057
adminbae64d82013-08-01 10:50:15 -07004058if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004059 sys.modules[ __name__ ] = MininetCliDriver()