blob: 64e267a6c88f42935937529d286ba998d9fdbc30 [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 Wang32833172018-10-23 15:19:31 -0700605 intf = hosts[host]['interfaces'][0]['name']
606 cmd = "{} ndisc6 -r 1 -w {} {} {}".format( host, wait, dstIp6, intf )
607 main.log.debug( "Sending IPv6 ND from host {}".format( host ) )
You Wang48381752018-05-07 13:50:57 -0700608 else:
609 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
610 discoveryResult = main.FALSE
611 if cmd:
You Wang0b82aa52018-06-06 14:33:58 -0700612 self.handle.sendline( flushCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700613 self.handle.expect( "mininet>" )
You Wang48381752018-05-07 13:50:57 -0700614 self.handle.sendline( cmd )
Jon Halla604fd42018-05-04 14:27:27 -0700615 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700616 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700617 except pexpect.TIMEOUT:
618 main.log.exception( self.name + ": TIMEOUT exception" )
619 response = self.handle.before
620 # NOTE: Send ctrl-c to make sure command is stopped
621 self.handle.send( "\x03" )
622 self.handle.expect( "Interrupt" )
623 response += self.handle.before + self.handle.after
624 self.handle.expect( "mininet>" )
625 response += self.handle.before + self.handle.after
626 main.log.debug( response )
627 return main.FALSE
628 except pexpect.EOF:
629 main.log.error( self.name + ": EOF exception found" )
630 main.log.error( self.name + ": " + self.handle.before )
631 main.cleanAndExit()
632 except Exception:
633 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800634 main.cleanAndExit()
635
636 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
637 """
638 Verify ping from each host in srcList to each host in dstList
639
640 acceptableFailed: max number of acceptable failed pings
641
642 Returns main.TRUE if all src hosts can reach all dst hosts
643 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
644 """
645 try:
646 main.log.info( "Verifying ping from each src host to each dst host" )
647 isReachable = main.TRUE
648 wait = int( wait )
649 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
650 pingResponse = "Ping output:\n"
651 failedPingsTotal = 0
652 for host in srcList:
653 pingResponse += str( str( host ) + " -> " )
654 for temp in dstList:
655 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700656 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
657 assert dstIP, "Not able to get IP address of host {}".format( temp )
658 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800659 while failedPings <= acceptableFailed:
660 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
661 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700662 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800663 response = self.handle.before
664 if re.search( ',\s0\%\spacket\sloss', response ):
665 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800666 break
667 else:
668 failedPings += 1
669 time.sleep(1)
670 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700671 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800672 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700673 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800674 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700675 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800676 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700677 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700678 except AssertionError:
679 main.log.exception( "" )
680 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700681 except pexpect.TIMEOUT:
682 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800683 response = self.handle.before
684 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700685 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800686 self.handle.expect( "Interrupt" )
687 response += self.handle.before + self.handle.after
688 self.handle.expect( "mininet>" )
689 response += self.handle.before + self.handle.after
690 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700691 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700692 except pexpect.EOF:
693 main.log.error( self.name + ": EOF exception found" )
694 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700695 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700696 except Exception:
697 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700698 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700699
Jon Hall7eb38402015-01-08 17:19:54 -0800700 def pingHost( self, **pingParams ):
701 """
Jon Hall3b489db2015-10-05 14:38:37 -0700702 Ping from one mininet host to another
703 Currently the only supported Params: SRC, TARGET, and WAIT
704 """
705 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700706 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700707 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800708 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700709 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700710 try:
Jon Hall61282e32015-03-19 11:34:11 -0700711 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800712 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700713 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700714 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700715 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800716 main.log.error(
717 self.name +
718 ": timeout when waiting for response from mininet" )
719 main.log.error( "response: " + str( self.handle.before ) )
720 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700721 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800722 main.log.error(
723 self.name +
724 ": timeout when waiting for response from mininet" )
725 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700726 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700727 if re.search( ',\s0\%\spacket\sloss', response ):
728 main.log.info( self.name + ": no packets lost, host is reachable" )
729 return main.TRUE
730 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800731 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700732 self.name +
733 ": PACKET LOST, HOST IS NOT REACHABLE" )
734 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800735 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800736 main.log.error( self.name + ": EOF exception found" )
737 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700738 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700739 except Exception:
740 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700741 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700742
743 def ping6pair( self, **pingParams ):
744 """
GlennRC2cf7d952015-09-11 16:32:13 -0700745 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700746 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000747 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700748 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
749 """
Jon Hall3b489db2015-10-05 14:38:37 -0700750 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700751 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700752 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530753 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700754 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700755 try:
756 main.log.info( "Sending: " + command )
757 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700758 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700759 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700760 if i == 1:
761 main.log.error(
762 self.name +
763 ": timeout when waiting for response from mininet" )
764 main.log.error( "response: " + str( self.handle.before ) )
765 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
766 if i == 1:
767 main.log.error(
768 self.name +
769 ": timeout when waiting for response from mininet" )
770 main.log.error( "response: " + str( self.handle.before ) )
771 response = self.handle.before
772 main.log.info( self.name + ": Ping Response: " + response )
773 if re.search( ',\s0\%\spacket\sloss', response ):
774 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700775 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700776 else:
alisone4121a92016-11-22 16:31:36 -0800777 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700778 self.name +
779 ": PACKET LOST, HOST IS NOT REACHABLE" )
780 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700781 except pexpect.EOF:
782 main.log.error( self.name + ": EOF exception found" )
783 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700784 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700785 except Exception:
786 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700787 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800788
You Wangdb927a52016-02-26 11:03:28 -0800789 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
790 """
791 Description:
792 Ping a set of destination host from host CLI.
793 Logging into a Mininet host CLI is required before calling this funtion.
794 Params:
795 dstIPList is a list of destination ip addresses
796 Returns:
797 main.TRUE if the destination host is reachable
798 main.FALSE otherwise
799 """
800 isReachable = main.TRUE
801 wait = int( wait )
802 cmd = "ping"
803 if IPv6:
804 cmd = cmd + "6"
805 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
806 try:
807 for dstIP in dstIPList:
808 pingCmd = cmd + " " + dstIP
809 self.handle.sendline( pingCmd )
810 i = self.handle.expect( [ self.hostPrompt,
811 '\*\*\* Unknown command: ' + pingCmd,
812 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700813 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700814 # For some reason we need to send something
815 # Otherwise ping results won't be read by handle
816 self.handle.sendline( "" )
817 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800818 if i == 0:
819 response = self.handle.before
820 if not re.search( ',\s0\%\spacket\sloss', response ):
821 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
822 isReachable = main.FALSE
823 elif i == 1:
824 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700825 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800826 elif i == 2:
827 main.log.error( self.name + ": timeout when waiting for response" )
828 isReachable = main.FALSE
829 else:
830 main.log.error( self.name + ": unknown response: " + self.handle.before )
831 isReachable = main.FALSE
832 except pexpect.TIMEOUT:
833 main.log.exception( self.name + ": TIMEOUT exception" )
You Wangd4fae5c2018-08-22 13:56:49 -0700834 self.exitFromCmd( [ self.hostPrompt, self.bashPrompt ] )
You Wangdb927a52016-02-26 11:03:28 -0800835 isReachable = main.FALSE
836 except pexpect.EOF:
837 main.log.error( self.name + ": EOF exception found" )
838 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700839 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800840 except Exception:
841 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700842 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800843 return isReachable
844
Jon Hall7eb38402015-01-08 17:19:54 -0800845 def checkIP( self, host ):
846 """
847 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700848 try:
849 if self.handle:
850 try:
851 response = self.execute(
852 cmd=host +
853 " ifconfig",
854 prompt="mininet>",
855 timeout=10 )
856 except pexpect.EOF:
857 main.log.error( self.name + ": EOF exception found" )
858 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700859 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700860
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700861 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
862 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
863 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
864 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
865 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
866 "[0-9]|25[0-5]|[0-9]{1,2})"
867 # pattern = "inet addr:10.0.0.6"
868 if re.search( pattern, response ):
869 main.log.info( self.name + ": Host Ip configured properly" )
870 return main.TRUE
871 else:
872 main.log.error( self.name + ": Host IP not found" )
873 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700874 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700875 main.log.error( self.name + ": Connection failed to the host" )
876 except Exception:
877 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700878 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800879
Jon Hall7eb38402015-01-08 17:19:54 -0800880 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800881 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700882 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800883 response = self.execute(
884 cmd="h1 /usr/sbin/sshd -D&",
885 prompt="mininet>",
886 timeout=10 )
887 response = self.execute(
888 cmd="h4 /usr/sbin/sshd -D&",
889 prompt="mininet>",
890 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700891 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800892 vars( self )[ key ] = connectargs[ key ]
893 response = self.execute(
894 cmd="xterm h1 h4 ",
895 prompt="mininet>",
896 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800897 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800898 main.log.error( self.name + ": EOF exception found" )
899 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700900 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700901 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800902 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700903 if self.flag == 0:
904 self.flag = 1
905 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800906 else:
adminbae64d82013-08-01 10:50:15 -0700907 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800908
Jon Hall7eb38402015-01-08 17:19:54 -0800909 def changeIP( self, host, intf, newIP, newNetmask ):
910 """
911 Changes the ip address of a host on the fly
912 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800913 if self.handle:
914 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800915 cmd = host + " ifconfig " + intf + " " + \
916 newIP + " " + 'netmask' + " " + newNetmask
917 self.handle.sendline( cmd )
918 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800919 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800920 main.log.info( "response = " + response )
921 main.log.info(
922 "Ip of host " +
923 host +
924 " changed to new IP " +
925 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800926 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700927 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700928 main.log.error( self.name + ": TIMEOUT exception found" )
929 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700930 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800931 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800932 main.log.error( self.name + ": EOF exception found" )
933 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800934 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700935 except Exception:
936 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700937 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800938
Jon Hall7eb38402015-01-08 17:19:54 -0800939 def changeDefaultGateway( self, host, newGW ):
940 """
941 Changes the default gateway of a host
942 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800943 if self.handle:
944 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800945 cmd = host + " route add default gw " + newGW
946 self.handle.sendline( cmd )
947 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800948 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800949 main.log.info( "response = " + response )
950 main.log.info(
951 "Default gateway of host " +
952 host +
953 " changed to " +
954 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800955 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700956 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700957 main.log.error( self.name + ": TIMEOUT exception found" )
958 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700959 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800960 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800961 main.log.error( self.name + ": EOF exception found" )
962 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800963 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700964 except Exception:
965 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700966 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800967
You Wange24d6272018-03-27 21:18:50 -0700968 def addRoute( self, host, dstIP, interface, ipv6=False ):
969 """
970 Add a route to host
971 Ex: h1 route add -host 224.2.0.1 h1-eth0
972 """
973 if self.handle:
974 try:
975 cmd = str( host )
976 if ipv6:
977 cmd += " route -A inet6 add "
978 else:
979 cmd += " route add -host "
980 cmd += str( dstIP ) + " " + str( interface )
981 self.handle.sendline( cmd )
982 self.handle.expect( "mininet>" )
983 response = self.handle.before
984 main.log.debug( "response = " + response )
985 return main.TRUE
986 except pexpect.TIMEOUT:
987 main.log.error( self.name + ": TIMEOUT exception found" )
988 main.log.error( self.name + ": " + self.handle.before )
989 main.cleanAndExit()
990 except pexpect.EOF:
991 main.log.error( self.name + ": EOF exception found" )
992 main.log.error( self.name + ": " + self.handle.before )
993 return main.FALSE
994 except Exception:
995 main.log.exception( self.name + ": Uncaught exception!" )
996 main.cleanAndExit()
997
Jon Hall7eb38402015-01-08 17:19:54 -0800998 def addStaticMACAddress( self, host, GW, macaddr ):
999 """
Jon Hallefbd9792015-03-05 16:11:36 -08001000 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001001 if self.handle:
1002 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001003 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1004 cmd = host + " arp -s " + GW + " " + macaddr
1005 self.handle.sendline( cmd )
1006 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001007 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001008 main.log.info( "response = " + response )
1009 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001010 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001011 GW +
1012 " changed to " +
1013 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001014 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001015 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001016 main.log.error( self.name + ": TIMEOUT exception found" )
1017 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001018 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001019 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001020 main.log.error( self.name + ": EOF exception found" )
1021 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001022 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001023 except Exception:
1024 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001025 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001026
Jon Hall7eb38402015-01-08 17:19:54 -08001027 def verifyStaticGWandMAC( self, host ):
1028 """
1029 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001030 if self.handle:
1031 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001032 # h1 arp -an
1033 cmd = host + " arp -an "
1034 self.handle.sendline( cmd )
1035 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001036 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001037 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001038 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001039 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001040 main.log.error( self.name + ": TIMEOUT exception found" )
1041 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001042 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001043 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001044 main.log.error( self.name + ": EOF exception found" )
1045 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001046 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001047 except Exception:
1048 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001049 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001050
Jon Hall7eb38402015-01-08 17:19:54 -08001051 def getMacAddress( self, host ):
1052 """
1053 Verifies the host's ip configured or not."""
1054 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001055 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001056 response = self.execute(
1057 cmd=host +
1058 " ifconfig",
1059 prompt="mininet>",
1060 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001061 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001062 main.log.error( self.name + ": EOF exception found" )
1063 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001064 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001065 except Exception:
1066 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001067 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001068
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001069 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001070 macAddressSearch = re.search( pattern, response, re.I )
1071 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001072 main.log.info(
1073 self.name +
1074 ": Mac-Address of Host " +
1075 host +
1076 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001077 macAddress )
1078 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001079 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001080 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001081
Jon Hall7eb38402015-01-08 17:19:54 -08001082 def getInterfaceMACAddress( self, host, interface ):
1083 """
1084 Return the IP address of the interface on the given host"""
1085 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001086 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001087 response = self.execute( cmd=host + " ifconfig " + interface,
1088 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001089 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001090 main.log.error( self.name + ": EOF exception found" )
1091 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001092 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001093 except Exception:
1094 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001095 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001096
1097 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001098 macAddressSearch = re.search( pattern, response, re.I )
1099 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001100 main.log.info( "No mac address found in %s" % response )
1101 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001102 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001103 main.log.info(
1104 "Mac-Address of " +
1105 host +
1106 ":" +
1107 interface +
1108 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001109 macAddress )
1110 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001111 else:
1112 main.log.error( "Connection failed to the host" )
1113
You Wang5da39c82018-04-26 22:55:08 -07001114 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001115 """
1116 Verifies the host's ip configured or not."""
1117 if self.handle:
1118 try:
1119 response = self.execute(
1120 cmd=host +
1121 " ifconfig",
1122 prompt="mininet>",
1123 timeout=10 )
1124 except pexpect.EOF:
1125 main.log.error( self.name + ": EOF exception found" )
1126 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001127 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001128 except Exception:
1129 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001130 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001131
sathishmad953462015-12-03 17:42:07 +05301132 pattern = ''
1133 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001134 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301135 else:
Jon Hall439c8912016-04-15 02:22:03 -07001136 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001137 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001138 if not ipAddressSearch:
1139 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001140 main.log.info(
1141 self.name +
1142 ": IP-Address of Host " +
1143 host +
1144 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001145 ipAddressSearch.group( 1 ) )
1146 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001147 else:
1148 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001149
Jon Hall7eb38402015-01-08 17:19:54 -08001150 def getSwitchDPID( self, switch ):
1151 """
1152 return the datapath ID of the switch"""
1153 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001154 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001155 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001156 response = self.execute(
1157 cmd=cmd,
1158 prompt="mininet>",
1159 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001160 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001161 main.log.error( self.name + ": EOF exception found" )
1162 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001163 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001164 except Exception:
1165 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001166 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001167 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001168 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001169 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001170 main.log.info(
1171 "Couldn't find DPID for switch %s, found: %s" %
1172 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001173 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001174 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001175 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001176 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001177
Jon Hall7eb38402015-01-08 17:19:54 -08001178 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001179 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001180 self.handle.sendline( "" )
1181 self.expect( "mininet>" )
1182 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001183 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001184 response = self.execute(
1185 cmd=cmd,
1186 prompt="mininet>",
1187 timeout=10 )
1188 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001189 response = self.handle.before
1190 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001191 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001192 main.log.error( self.name + ": TIMEOUT exception found" )
1193 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001194 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001195 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001196 main.log.error( self.name + ": EOF exception found" )
1197 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001198 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001199 except Exception:
1200 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001201 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001202
Jon Hall7eb38402015-01-08 17:19:54 -08001203 def getInterfaces( self, node ):
1204 """
1205 return information dict about interfaces connected to the node"""
1206 if self.handle:
1207 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001208 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001209 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001210 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001211 response = self.execute(
1212 cmd=cmd,
1213 prompt="mininet>",
You Wang7d14d642019-01-23 15:10:08 -08001214 timeout=10,
1215 logCmd=False )
Jon Hallfbc828e2015-01-06 17:30:19 -08001216 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001217 main.log.error( self.name + ": EOF exception found" )
1218 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001219 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001220 except Exception:
1221 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001222 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001223 return response
1224 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001225 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001226
Jon Hall7eb38402015-01-08 17:19:54 -08001227 def dump( self ):
1228 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001229 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001230 response = self.execute(
1231 cmd='dump',
1232 prompt='mininet>',
1233 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001234 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001235 main.log.error( self.name + ": EOF exception found" )
1236 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001237 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001238 except Exception:
1239 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001240 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001241 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001242
Jon Hall7eb38402015-01-08 17:19:54 -08001243 def intfs( self ):
1244 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001245 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001246 response = self.execute(
1247 cmd='intfs',
1248 prompt='mininet>',
1249 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001250 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001251 main.log.error( self.name + ": EOF exception found" )
1252 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001253 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001254 except Exception:
1255 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001256 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001257 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001258
Jon Hall7eb38402015-01-08 17:19:54 -08001259 def net( self ):
1260 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001261 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001262 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001263 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001264 main.log.error( self.name + ": EOF exception found" )
1265 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001266 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001267 except Exception:
1268 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001269 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001270 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001271
Devin Lima7cfdbd2017-09-29 15:02:22 -07001272 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001273 main.log.info( self.name + ": List network links" )
1274 try:
1275 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001276 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001277 except pexpect.EOF:
1278 main.log.error( self.name + ": EOF exception found" )
1279 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001280 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001281 except Exception:
1282 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001283 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001284 return response
1285
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001286 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001287 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001288 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001289
kelvin-onlab7cce9382015-07-17 10:21:03 -07001290 @parm:
1291 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1292 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001293 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001294 try:
1295 for host1 in hosts:
1296 for host2 in hosts:
1297 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001298 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1299 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001300 except Exception:
1301 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001302 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001303
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001304 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001305 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001306 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1307 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001308
kelvin-onlab7cce9382015-07-17 10:21:03 -07001309 @parm:
1310 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1311 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001312 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001313 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1314 try:
1315 # Setup the mininet command
1316 cmd1 = 'iperf ' + host1 + " " + host2
1317 self.handle.sendline( cmd1 )
1318 outcome = self.handle.expect( "mininet>", timeout )
1319 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001320
kelvin-onlab7cce9382015-07-17 10:21:03 -07001321 # checks if there are results in the mininet response
1322 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001323 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001324 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001325 response = response.split( "\r\n" )
1326 response = response[ len( response )-2 ]
1327 response = response.split( ": " )
1328 response = response[ len( response )-1 ]
1329 response = response.replace( "[", "" )
1330 response = response.replace( "]", "" )
1331 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001332
kelvin-onlab7cce9382015-07-17 10:21:03 -07001333 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001334 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001335
kelvin-onlab7cce9382015-07-17 10:21:03 -07001336 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001337 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001338 if len( bandwidth ) == 2:
1339 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001340 return main.TRUE
1341 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001342 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001343 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001344 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001345 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001346 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001347 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001348 main.log.error( self.name + ": TIMEOUT exception found" )
1349 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001350 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001351 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001352 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001353 self.handle.expect( "Interrupt" )
1354 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001355 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001356 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001357 main.log.error( self.name + ": EOF exception found" )
1358 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001359 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001360 except Exception:
1361 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001362 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001363
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001364 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001365 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1366 try:
1367 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001368 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001369 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001370 outcome1 = self.handle.expect( "mininet>" )
1371 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001372 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001373 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001374 response1 = self.handle.before
1375 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001376 print response1, response2
1377 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001378 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001379 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001380 return main.TRUE
1381 else:
1382 main.log.error( self.name + ": iperf test failed" )
1383 return main.FALSE
1384 except pexpect.TIMEOUT:
1385 main.log.error( self.name + ": TIMEOUT exception found" )
1386 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001387 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001388 self.handle.expect( "Interrupt" )
1389 self.handle.expect( "mininet>" )
1390 return main.FALSE
1391 except pexpect.EOF:
1392 main.log.error( self.name + ": EOF exception found" )
1393 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001394 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001395 except Exception:
1396 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001397 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001398
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001399 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001400 '''
GlennRC61321f22015-07-16 13:36:54 -07001401 Runs the iperfudp function with a given set of hosts and specified
1402 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001403
GlennRC61321f22015-07-16 13:36:54 -07001404 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001405 bandwidth: the targeted bandwidth, in megabits ('M')
1406 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001407 try:
1408 for host1 in hosts:
1409 for host2 in hosts:
1410 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001411 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1412 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001413 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001414 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001415 return main.FALSE
1416 except Exception:
1417 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001418 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001419
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001420 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001421 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001422 Creates an iperf UDP test with a specific bandwidth.
1423 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001424
kelvin-onlab7cce9382015-07-17 10:21:03 -07001425 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001426 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1427 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001428 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001429 try:
1430 # setup the mininet command
1431 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001432 self.handle.sendline( cmd )
1433 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001434 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001435
kelvin-onlab7cce9382015-07-17 10:21:03 -07001436 # check if there are in results in the mininet response
1437 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001438 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001439 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001440 response = response.split( "\r\n" )
1441 response = response[ len( response )-2 ]
1442 response = response.split( ": " )
1443 response = response[ len( response )-1 ]
1444 response = response.replace( "[", "" )
1445 response = response.replace( "]", "" )
1446 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001447
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001448 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001449
kelvin-onlab7cce9382015-07-17 10:21:03 -07001450 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001451 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001452 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001453 # if one entry is blank then something is wrong
1454 for item in mnBandwidth:
1455 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001456 main.log.error( self.name + ": Could not parse iperf output" )
1457 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001458 return main.FALSE
1459 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001460 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001461 return main.TRUE
1462 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001463 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001464 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001465
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001466 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001467 main.log.error( self.name + ": TIMEOUT exception found" )
1468 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001469 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001470 except pexpect.EOF:
1471 main.log.error( self.name + ": EOF exception found" )
1472 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001473 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001474 except Exception:
1475 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001476 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001477
Jon Hall7eb38402015-01-08 17:19:54 -08001478 def nodes( self ):
1479 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001480 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001481 response = self.execute(
1482 cmd='nodes',
1483 prompt='mininet>',
1484 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001485 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001486 main.log.error( self.name + ": EOF exception found" )
1487 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001488 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001489 except Exception:
1490 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001491 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001492 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001493
Jon Hall7eb38402015-01-08 17:19:54 -08001494 def pingpair( self ):
1495 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001496 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001497 response = self.execute(
1498 cmd='pingpair',
1499 prompt='mininet>',
1500 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001501 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001502 main.log.error( self.name + ": EOF exception found" )
1503 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001504 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001505 except Exception:
1506 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001507 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001508
Jon Hall7eb38402015-01-08 17:19:54 -08001509 if re.search( ',\s0\%\spacket\sloss', response ):
1510 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001511 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001512 else:
alisone4121a92016-11-22 16:31:36 -08001513 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001514 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001515
Jon Hall7eb38402015-01-08 17:19:54 -08001516 def link( self, **linkargs ):
1517 """
GlennRCed771242016-01-13 17:02:47 -08001518 Bring link( s ) between two nodes up or down
1519 """
Jon Hall6094a362014-04-11 14:46:56 -07001520 try:
GlennRCed771242016-01-13 17:02:47 -08001521 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1522 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1523 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1524 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1525
1526 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1527 cmd = "link {} {} {}".format( end1, end2, option )
1528 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001529 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001530 response = self.handle.before
1531 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001532 if "not in network" in response:
1533 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1534 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001535 return main.TRUE
1536 except pexpect.TIMEOUT:
1537 main.log.exception( self.name + ": Command timed out" )
1538 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001539 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001540 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001541 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001542 except Exception:
1543 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001544 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001545
pingping-lin8244a3b2015-09-16 13:36:56 -07001546 def switch( self, **switchargs ):
1547 """
1548 start/stop a switch
1549 """
1550 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1551 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1552 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1553 command = "switch " + str( sw ) + " " + str( option )
1554 main.log.info( command )
1555 try:
1556 self.handle.sendline( command )
1557 self.handle.expect( "mininet>" )
1558 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001559 main.log.error( self.name + ": TIMEOUT exception found" )
1560 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001561 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001562 except pexpect.EOF:
1563 main.log.error( self.name + ": EOF exception found" )
1564 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001565 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001566 return main.TRUE
1567
pingping-lin5bb663b2015-09-24 11:47:50 -07001568 def node( self, nodeName, commandStr ):
1569 """
1570 Carry out a command line on a given node
1571 @parm:
1572 nodeName: the node name in Mininet testbed
1573 commandStr: the command line will be carried out on the node
1574 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1575 """
1576 command = str( nodeName ) + " " + str( commandStr )
1577 main.log.info( command )
1578
1579 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001580 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001581 if re.search( "Unknown command", response ):
1582 main.log.warn( response )
1583 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001584 if re.search( "Permission denied", response ):
1585 main.log.warn( response )
1586 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001587 except pexpect.EOF:
1588 main.log.error( self.name + ": EOF exception found" )
1589 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001590 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001591 main.log.info( " response is :" )
1592 main.log.info( response )
1593 return response
1594
Jon Hall7eb38402015-01-08 17:19:54 -08001595 def yank( self, **yankargs ):
1596 """
1597 yank a mininet switch interface to a host"""
1598 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001599 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001600 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1601 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001602 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001603 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001604 response = self.execute(
1605 cmd=command,
1606 prompt="mininet>",
1607 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001608 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001609 main.log.error( self.name + ": EOF exception found" )
1610 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001611 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001612 except Exception:
1613 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001614 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001615 return main.TRUE
1616
Jon Hall7eb38402015-01-08 17:19:54 -08001617 def plug( self, **plugargs ):
1618 """
1619 plug the yanked mininet switch interface to a switch"""
1620 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001621 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001622 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1623 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001624 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001625 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001626 response = self.execute(
1627 cmd=command,
1628 prompt="mininet>",
1629 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001630 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001631 main.log.error( self.name + ": EOF exception found" )
1632 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001633 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001634 except Exception:
1635 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001636 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001637 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001638
Jon Hall7eb38402015-01-08 17:19:54 -08001639 def dpctl( self, **dpctlargs ):
1640 """
1641 Run dpctl command on all switches."""
1642 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001643 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001644 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1645 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1646 command = "dpctl " + cmd + " " + str( cmdargs )
1647 try:
1648 response = self.execute(
1649 cmd=command,
1650 prompt="mininet>",
1651 timeout=10 )
1652 except pexpect.EOF:
1653 main.log.error( self.name + ": EOF exception found" )
1654 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001655 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001656 except Exception:
1657 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001658 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001659 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001660
kelvin-onlabd3b64892015-01-20 13:26:24 -08001661 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001662 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001663 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001664 try:
1665 fileInput = path + '/lib/Mininet/INSTALL'
1666 version = super( Mininet, self ).getVersion()
1667 pattern = 'Mininet\s\w\.\w\.\w\w*'
1668 for line in open( fileInput, 'r' ).readlines():
1669 result = re.match( pattern, line )
1670 if result:
1671 version = result.group( 0 )
1672 return version
1673 except Exception:
1674 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001675 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001676
kelvin-onlabd3b64892015-01-20 13:26:24 -08001677 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001678 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001679 Parameters:
1680 sw: The name of an OVS switch. Example "s1"
1681 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001682 The output of the command from the mininet cli
1683 or main.FALSE on timeout"""
1684 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001685 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001686 response = self.execute(
1687 cmd=command,
1688 prompt="mininet>",
1689 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001690 if response:
Jon Hallab611372018-02-21 15:26:05 -08001691 if "no bridge named" in response:
1692 main.log.error( self.name + ": Error in getSwController: " +
1693 self.handle.before )
1694 return main.FALSE
1695 else:
1696 return response
admin2a9548d2014-06-17 14:08:07 -07001697 else:
1698 return main.FALSE
1699 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001700 main.log.error( self.name + ": EOF exception found" )
1701 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001702 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001703 except Exception:
1704 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001705 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001706
Charles Chan029be652015-08-24 01:46:10 +08001707 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001708 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001709 Description:
1710 Assign switches to the controllers ( for ovs use only )
1711 Required:
1712 sw - Name of the switch. This can be a list or a string.
1713 ip - Ip addresses of controllers. This can be a list or a string.
1714 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001715 port - ONOS use port 6653, if no list of ports is passed, then
1716 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001717 ptcp - ptcp number, This can be a string or a list that has
1718 the same length as switch. This is optional and not required
1719 when using ovs switches.
1720 NOTE: If switches and ptcp are given in a list type they should have the
1721 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1722 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001723
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001724 Return:
1725 Returns main.TRUE if mininet correctly assigned switches to
1726 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001727 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001728 """
1729 assignResult = main.TRUE
1730 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001731 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001732 command = "sh ovs-vsctl set-controller "
1733 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001734 try:
1735 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001736 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001737 if isinstance( port, types.StringType ) or \
1738 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001739 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001740 elif isinstance( port, types.ListType ):
1741 main.log.error( self.name + ": Only one controller " +
1742 "assigned and a list of ports has" +
1743 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001744 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001745 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001746 main.log.error( self.name + ": Invalid controller port " +
1747 "number. Please specify correct " +
1748 "controller port" )
1749 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001750
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001751 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001752 if isinstance( port, types.StringType ) or \
1753 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001754 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001755 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1756 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001757 elif isinstance( port, types.ListType ):
1758 if ( len( ip ) != len( port ) ):
1759 main.log.error( self.name + ": Port list = " +
1760 str( len( port ) ) +
1761 "should be the same as controller" +
1762 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001763 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001764 else:
1765 onosIp = ""
1766 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001767 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1768 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001769 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001770 main.log.error( self.name + ": Invalid controller port " +
1771 "number. Please specify correct " +
1772 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001773 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001774 else:
1775 main.log.error( self.name + ": Invalid ip address" )
1776 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001777
1778 if isinstance( sw, types.StringType ):
1779 command += sw + " "
1780 if ptcp:
1781 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001782 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001783 elif isinstance( ptcp, types.ListType ):
1784 main.log.error( self.name + ": Only one switch is " +
1785 "being set and multiple PTCP is " +
1786 "being passed " )
1787 else:
1788 main.log.error( self.name + ": Invalid PTCP" )
1789 ptcp = ""
1790 command += onosIp
1791 commandList.append( command )
1792
1793 elif isinstance( sw, types.ListType ):
1794 if ptcp:
1795 if isinstance( ptcp, types.ListType ):
1796 if len( ptcp ) != len( sw ):
1797 main.log.error( self.name + ": PTCP length = " +
1798 str( len( ptcp ) ) +
1799 " is not the same as switch" +
1800 " length = " +
1801 str( len( sw ) ) )
1802 return main.FALSE
1803 else:
1804 for switch, ptcpNum in zip( sw, ptcp ):
1805 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001806 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001807 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001808 tempCmd += onosIp
1809 commandList.append( tempCmd )
1810 else:
1811 main.log.error( self.name + ": Invalid PTCP" )
1812 return main.FALSE
1813 else:
1814 for switch in sw:
1815 tempCmd = "sh ovs-vsctl set-controller "
1816 tempCmd += switch + " " + onosIp
1817 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001818 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001819 main.log.error( self.name + ": Invalid switch type " )
1820 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001821
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001822 for cmd in commandList:
1823 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001824 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08001825 if "no bridge named" in self.handle.before:
1826 main.log.error( self.name + ": Error in assignSwController: " +
1827 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001828 except pexpect.TIMEOUT:
1829 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1830 return main.FALSE
1831 except pexpect.EOF:
1832 main.log.error( self.name + ": EOF exception found" )
1833 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001834 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001835 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001836 except pexpect.EOF:
1837 main.log.error( self.name + ": EOF exception found" )
1838 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001839 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001840 except Exception:
1841 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001842 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001843
kelvin-onlabd3b64892015-01-20 13:26:24 -08001844 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001845 """
1846 Removes the controller target from sw"""
1847 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001848 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001849 response = self.execute(
1850 cmd=command,
1851 prompt="mininet>",
1852 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001853 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001854 main.log.error( self.name + ": EOF exception found" )
1855 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001856 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001857 except Exception:
1858 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001859 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001860 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001861 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001862
kelvin-onlabd3b64892015-01-20 13:26:24 -08001863 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001864 """
Jon Hallb1290e82014-11-18 16:17:48 -05001865 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001866 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001867 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001868 NOTE: cannot currently specify what type of switch
1869 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001870 sw = name of the new switch as a string
1871 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001872 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001873 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001874 """
1875 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001876 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001877 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001878 response = self.execute(
1879 cmd=command,
1880 prompt="mininet>",
1881 timeout=10 )
1882 if re.search( "already exists!", response ):
1883 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001884 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001885 elif re.search( "Error", response ):
1886 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001887 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001888 elif re.search( "usage:", response ):
1889 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001890 return main.FALSE
1891 else:
1892 return main.TRUE
1893 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001894 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001895 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001896 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001897 except Exception:
1898 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001899 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001900
kelvin-onlabd3b64892015-01-20 13:26:24 -08001901 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001902 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001903 delete a switch from the mininet topology
1904 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001905 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001906 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001907 sw = name of the switch as a string
1908 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001909 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001910 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001911 response = self.execute(
1912 cmd=command,
1913 prompt="mininet>",
1914 timeout=10 )
1915 if re.search( "no switch named", response ):
1916 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001917 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001918 elif re.search( "Error", response ):
1919 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001920 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001921 elif re.search( "usage:", response ):
1922 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001923 return main.FALSE
1924 else:
1925 return main.TRUE
1926 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001927 main.log.error( self.name + ": EOF exception found" )
1928 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001929 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001930 except Exception:
1931 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001932 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001933
You Wanga9a5e002019-01-31 12:33:26 -08001934 def getSwitchRandom( self, timeout=60, nonCut=True, switchClasses=None, excludeNodes=[], excludeSwitches=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07001935 """
1936 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001937 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001938 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001939 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07001940 it just randomly returns one switch from all current switches in
1941 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08001942 excludeNodes will be pased to getGraphDict method
You Wanga9a5e002019-01-31 12:33:26 -08001943 Switches specified in excludeSwitches will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07001944 Returns the name of the chosen switch.
1945 """
1946 import random
1947 candidateSwitches = []
1948 try:
1949 if not nonCut:
You Wang7d14d642019-01-23 15:10:08 -08001950 switches = self.getSwitches( timeout=timeout, switchClasses=switchClasses )
You Wangdb8cd0a2016-05-26 15:19:45 -07001951 assert len( switches ) != 0
1952 for switchName in switches.keys():
1953 candidateSwitches.append( switchName )
1954 else:
You Wang7d14d642019-01-23 15:10:08 -08001955 graphDict = self.getGraphDict( timeout=timeout, useId=False,
1956 switchClasses=switchClasses,
1957 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001958 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001959 return None
1960 self.graph.update( graphDict )
1961 candidateSwitches = self.graph.getNonCutVertices()
You Wanga9a5e002019-01-31 12:33:26 -08001962 candidateSwitches = [ switch for switch in candidateSwitches if switch not in excludeSwitches ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001963 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001964 return None
1965 elif len( candidateSwitches ) == 0:
1966 main.log.info( self.name + ": No candidate switch for deletion" )
1967 return None
1968 else:
1969 switch = random.sample( candidateSwitches, 1 )
1970 return switch[ 0 ]
1971 except KeyError:
1972 main.log.exception( self.name + ": KeyError exception found" )
1973 return None
1974 except AssertionError:
1975 main.log.exception( self.name + ": AssertionError exception found" )
1976 return None
1977 except Exception:
1978 main.log.exception( self.name + ": Uncaught exception" )
1979 return None
1980
1981 def delSwitchRandom( self, timeout=60, nonCut=True ):
1982 """
1983 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001984 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001985 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001986 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07001987 otherwise it just randomly delete one switch from all current
1988 switches in Mininet.
1989 Returns the name of the deleted switch
1990 """
1991 try:
1992 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001993 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001994 return None
1995 else:
1996 deletionResult = self.delSwitch( switch )
1997 if deletionResult:
1998 return switch
1999 else:
2000 return None
2001 except Exception:
2002 main.log.exception( self.name + ": Uncaught exception" )
2003 return None
2004
kelvin-onlabd3b64892015-01-20 13:26:24 -08002005 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002006 """
2007 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002008 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002009 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002010 NOTE: cannot currently specify what type of link
2011 required params:
2012 node1 = the string node name of the first endpoint of the link
2013 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002014 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002015 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002016 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002017 response = self.execute(
2018 cmd=command,
2019 prompt="mininet>",
2020 timeout=10 )
2021 if re.search( "doesnt exist!", response ):
2022 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002023 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002024 elif re.search( "Error", response ):
2025 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002026 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002027 elif re.search( "usage:", response ):
2028 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002029 return main.FALSE
2030 else:
2031 return main.TRUE
2032 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002033 main.log.error( self.name + ": EOF exception found" )
2034 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002035 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002036 except Exception:
2037 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002038 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002039
kelvin-onlabd3b64892015-01-20 13:26:24 -08002040 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002041 """
2042 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002043 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002044 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002045 required params:
2046 node1 = the string node name of the first endpoint of the link
2047 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002048 returns: main.FALSE on an error, else main.TRUE
2049 """
Jon Hallffb386d2014-11-21 13:43:38 -08002050 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002051 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002052 response = self.execute(
2053 cmd=command,
2054 prompt="mininet>",
2055 timeout=10 )
2056 if re.search( "no node named", response ):
2057 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002058 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002059 elif re.search( "Error", response ):
2060 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002061 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002062 elif re.search( "usage:", response ):
2063 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002064 return main.FALSE
2065 else:
2066 return main.TRUE
2067 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002068 main.log.error( self.name + ": EOF exception found" )
2069 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002070 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002071 except Exception:
2072 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002073 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002074
You Wang7d14d642019-01-23 15:10:08 -08002075 def getLinkRandom( self, timeout=60, nonCut=True, switchClasses=None, excludeNodes=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07002076 """
2077 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002078 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002079 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002080 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002081 it just randomly returns one link from all current links in
2082 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08002083 excludeNodes will be passed to getLinks method to exclude unexpected links.
You Wangdb8cd0a2016-05-26 15:19:45 -07002084 Returns the link as a list, e.g. [ 's1', 's2' ]
2085 """
2086 import random
2087 candidateLinks = []
2088 try:
2089 if not nonCut:
You Wang7d14d642019-01-23 15:10:08 -08002090 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07002091 assert len( links ) != 0
2092 for link in links:
2093 # Exclude host-switch link
2094 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2095 continue
2096 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2097 else:
You Wang7d14d642019-01-23 15:10:08 -08002098 graphDict = self.getGraphDict( timeout=timeout, useId=False,
2099 switchClasses=switchClasses,
2100 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002101 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002102 return None
2103 self.graph.update( graphDict )
2104 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002105 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002106 return None
2107 elif len( candidateLinks ) == 0:
2108 main.log.info( self.name + ": No candidate link for deletion" )
2109 return None
2110 else:
2111 link = random.sample( candidateLinks, 1 )
2112 return link[ 0 ]
2113 except KeyError:
2114 main.log.exception( self.name + ": KeyError exception found" )
2115 return None
2116 except AssertionError:
2117 main.log.exception( self.name + ": AssertionError exception found" )
2118 return None
2119 except Exception:
2120 main.log.exception( self.name + ": Uncaught exception" )
2121 return None
2122
2123 def delLinkRandom( self, timeout=60, nonCut=True ):
2124 """
2125 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002126 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002127 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002128 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002129 otherwise it just randomly delete one link from all current links
2130 in Mininet.
2131 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2132 """
2133 try:
2134 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002135 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002136 return None
2137 else:
2138 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2139 if deletionResult:
2140 return link
2141 else:
2142 return None
2143 except Exception:
2144 main.log.exception( self.name + ": Uncaught exception" )
2145 return None
2146
kelvin-onlabd3b64892015-01-20 13:26:24 -08002147 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002148 """
Jon Hallb1290e82014-11-18 16:17:48 -05002149 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002150 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002151 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002152 NOTE: cannot currently specify what type of host
2153 required params:
2154 hostname = the string hostname
2155 optional key-value params
2156 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002157 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002158 """
2159 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002160 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002161 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002162 response = self.execute(
2163 cmd=command,
2164 prompt="mininet>",
2165 timeout=10 )
2166 if re.search( "already exists!", response ):
2167 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002168 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002169 elif re.search( "doesnt exists!", response ):
2170 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002171 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002172 elif re.search( "Error", response ):
2173 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002174 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002175 elif re.search( "usage:", response ):
2176 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002177 return main.FALSE
2178 else:
2179 return main.TRUE
2180 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002181 main.log.error( self.name + ": EOF exception found" )
2182 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002183 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002184 except Exception:
2185 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002186 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002187
kelvin-onlabd3b64892015-01-20 13:26:24 -08002188 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002189 """
2190 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002191 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002192 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002193 NOTE: this uses a custom mn function
2194 required params:
2195 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002196 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002197 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002198 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002199 response = self.execute(
2200 cmd=command,
2201 prompt="mininet>",
2202 timeout=10 )
2203 if re.search( "no host named", response ):
2204 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002205 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002206 elif re.search( "Error", response ):
2207 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002208 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002209 elif re.search( "usage:", response ):
2210 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002211 return main.FALSE
2212 else:
2213 return main.TRUE
2214 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002215 main.log.error( self.name + ": EOF exception found" )
2216 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002217 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002218 except Exception:
2219 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002220 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002221
Jon Hall7eb38402015-01-08 17:19:54 -08002222 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002223 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002224 Called at the end of the test to stop the mininet and
2225 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002226 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002227 try:
2228 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002229 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002230 timeout=2 )
2231 response = main.TRUE
2232 if i == 0:
2233 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002234 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002235 return main.TRUE
2236 # print "Disconnecting Mininet"
2237 if self.handle:
2238 self.handle.sendline( "exit" )
2239 self.handle.expect( "exit" )
2240 self.handle.expect( "(.*)" )
2241 else:
2242 main.log.error( "Connection failed to the host" )
2243 return response
2244 except pexpect.EOF:
2245 main.log.error( self.name + ": EOF exception found" )
2246 main.log.error( self.name + ": " + self.handle.before )
You Wangd4fae5c2018-08-22 13:56:49 -07002247 # Do not exit the entire test when pexpect.EOF is caught
2248 # FIXME: We might need to do something else here
2249 return main.ERROR
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002250 except Exception:
2251 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002252 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002253
Devin Lima7cfdbd2017-09-29 15:02:22 -07002254 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002255 """
Jon Hall21270ac2015-02-16 17:59:55 -08002256 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002257 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002258 main.FALSE if the pexpect handle does not exist.
2259
Jon Halld61331b2015-02-17 16:35:47 -08002260 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002261 """
Jon Halld61331b2015-02-17 16:35:47 -08002262 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002263 response = ''
2264 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002265 try:
Jon Halld80cc142015-07-06 13:36:05 -07002266 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002267 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002268 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002269 pexpect.EOF,
2270 pexpect.TIMEOUT ],
2271 timeout )
2272 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002273 main.log.info( "Exiting mininet.." )
2274 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002275 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002276 prompt=self.prompt,
2277 timeout=exitTimeout )
2278 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002279 self.handle.sendline( "sudo mn -c" )
2280 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002281
Jeremyd9e4eb12016-04-13 12:09:06 -07002282 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002283 main.log.info( " Mininet trying to exit while not " +
2284 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002285 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002286 elif i == 2:
2287 main.log.error( "Something went wrong exiting mininet" )
2288 elif i == 3: # timeout
2289 main.log.error( "Something went wrong exiting mininet " +
2290 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002291
You Wang18db8592018-04-02 13:52:03 -07002292 self.handle.sendline( "" )
2293 self.handle.expect( self.prompt )
2294 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2295
Hari Krishnab35c6d02015-03-18 11:13:51 -07002296 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002297 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002298 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002299 self.handle.sendline(
2300 "sudo kill -9 \`ps -ef | grep \"" +
2301 fileName +
2302 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002303 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002304 main.log.error( self.name + ": TIMEOUT exception found" )
2305 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002306 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002307 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002308 main.log.error( self.name + ": EOF exception found" )
2309 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002310 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002311 except Exception:
2312 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002313 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002314 else:
2315 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002316 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002317 return response
2318
YPZhang26a139e2016-04-25 14:01:55 -07002319 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002320 """
2321 Description:
2322 Sends arp message from mininet host for hosts discovery
2323 Required:
2324 host - hosts name
2325 Optional:
2326 ip - ip address that does not exist in the network so there would
2327 be no reply.
2328 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002329 if ethDevice:
2330 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002331 cmd = srcHost + " arping -c1 "
2332 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002333 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 -07002334 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002335 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002336 if output:
2337 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002338 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002339 i = self.handle.expect( [ "mininet>", "arping: " ] )
2340 if i == 0:
2341 return main.TRUE
2342 elif i == 1:
2343 response = self.handle.before + self.handle.after
2344 self.handle.expect( "mininet>" )
2345 response += self.handle.before + self.handle.after
2346 main.log.warn( "Error sending arping, output was: " +
2347 response )
2348 return main.FALSE
2349 except pexpect.TIMEOUT:
2350 main.log.error( self.name + ": TIMEOUT exception found" )
2351 main.log.warn( self.handle.before )
2352 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002353 except pexpect.EOF:
2354 main.log.error( self.name + ": EOF exception found" )
2355 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002356 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002357 except Exception:
2358 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002359 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002360
Jon Hall7eb38402015-01-08 17:19:54 -08002361 def decToHex( self, num ):
2362 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002363
Jon Hall7eb38402015-01-08 17:19:54 -08002364 def getSwitchFlowCount( self, switch ):
2365 """
2366 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002367 if self.handle:
2368 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2369 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002370 response = self.execute(
2371 cmd=cmd,
2372 prompt="mininet>",
2373 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002374 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002375 main.log.error( self.name + ": EOF exception found" )
2376 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002377 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002378 except Exception:
2379 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002380 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002381 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002382 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002383 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002384 main.log.info(
2385 "Couldn't find flows on switch %s, found: %s" %
2386 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002387 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002388 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002389 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002390 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002391
Jon Hall9ed8f372016-02-24 17:34:07 -08002392 def checkFlows( self, sw, dumpFormat=None ):
2393 if dumpFormat:
2394 command = "sh ovs-ofctl -F " + \
2395 dumpFormat + " dump-flows " + str( sw )
2396 else:
2397 command = "sh ovs-ofctl dump-flows " + str( sw )
2398 try:
2399 response = self.execute(
2400 cmd=command,
2401 prompt="mininet>",
2402 timeout=10 )
2403 return response
2404 except pexpect.EOF:
2405 main.log.error( self.name + ": EOF exception found" )
2406 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002407 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002408 except Exception:
2409 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002410 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002411
GlennRC68467eb2015-11-16 18:01:01 -08002412 def flowTableComp( self, flowTable1, flowTable2 ):
2413 # This function compares the selctors and treatments of each flow
2414 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002415 assert flowTable1, "flowTable1 is empty or None"
2416 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002417 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002418 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002419 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002420 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002421 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2422 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002423 for field in dFields:
2424 try:
2425 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002426 except KeyError:
2427 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002428 try:
2429 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002430 except KeyError:
2431 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002432 for i in range( len( flowTable1 ) ):
2433 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002434 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002435 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002436 returnValue = main.FALSE
2437 break
2438 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002439 except AssertionError:
2440 main.log.exception( "Nothing to compare" )
2441 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002442 except Exception:
2443 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002444 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002445
GlennRC528ad292015-11-12 10:38:18 -08002446 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002447 '''
GlennRC956ea742015-11-05 16:14:15 -08002448 Discription: Parses flows into json format.
2449 NOTE: this can parse any string thats separated with commas
2450 Arguments:
2451 Required:
2452 flows: a list of strings that represnt flows
2453 Optional:
2454 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2455 debug: prints out the final result
2456 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002457 '''
GlennRC528ad292015-11-12 10:38:18 -08002458 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002459 try:
2460 for flow in flowTable:
2461 jsonFlow = {}
2462 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002463 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002464 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002465 for i in range( len( parsedFlow ) ):
2466 item = parsedFlow[ i ]
2467 if item[ 0 ] == " ":
2468 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002469 # grab the selector and treatment from the parsed flow
2470 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002471 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002472 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002473 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002474 index = 0
2475 # parse the flags
2476 # NOTE: This only parses one flag
2477 flag = {}
2478 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002479 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002480 index += 1
2481 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002482 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002483 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002484 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002485 # the priority is stuck in the selecter so put it back
2486 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002487 if 'priority' in sel[0]:
2488 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002489 # parse selector
2490 criteria = []
2491 for item in sel:
2492 # this is the type of the packet e.g. "arp"
2493 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002494 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002495 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002496 field = item.split( "=" )
2497 criteria.append( { field[ 0 ]: field[ 1 ] } )
2498 selector = { "selector": { "criteria": sorted( criteria ) } }
2499 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002500 # get rid of the action part e.g. "action=output:2"
2501 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002502 treat = treat.split( "=" )
2503 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002504 # parse treatment
2505 action = []
2506 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002507 if ":" in item:
2508 field = item.split( ":" )
2509 action.append( { field[ 0 ]: field[ 1 ] } )
2510 else:
2511 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2512 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002513 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002514 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002515 # parse the rest of the flow
2516 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002517 field = item.split( "=" )
2518 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002519 # add the treatment and the selector to the json flow
2520 jsonFlow.update( selector )
2521 jsonFlow.update( treatment )
2522 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002523
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002524 if debug:
2525 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002526
You Wang91c37cf2016-05-23 09:39:42 -07002527 # add the json flow to the json flow table
2528 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002529
You Wang91c37cf2016-05-23 09:39:42 -07002530 return jsonFlowTable
2531
2532 except IndexError:
2533 main.log.exception( self.name + ": IndexError found" )
2534 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002535 except pexpect.EOF:
2536 main.log.error( self.name + ": EOF exception found" )
2537 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002538 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002539 except Exception:
2540 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002541 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002542
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002543 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002544 '''
2545 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002546 Each element is a flow.
2547 Arguments:
2548 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002549 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002550 a list of switches.
2551 Optional:
2552 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2553 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002554 '''
GlennRC956ea742015-11-05 16:14:15 -08002555 try:
2556 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002557 if isinstance( sw, list ):
2558 switches.extend( sw )
2559 else:
2560 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002561
2562 flows = []
2563 for s in switches:
2564 cmd = "sh ovs-ofctl dump-flows " + s
2565
GlennRC528ad292015-11-12 10:38:18 -08002566 if "1.0" == version:
2567 cmd += " -F OpenFlow10-table_id"
2568 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002569 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002570
2571 main.log.info( "Sending: " + cmd )
2572 self.handle.sendline( cmd )
2573 self.handle.expect( "mininet>" )
2574 response = self.handle.before
2575 response = response.split( "\r\n" )
2576 # dump the first two elements and the last
2577 # the first element is the command that was sent
2578 # the second is the table header
2579 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002580 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002581 flows.extend( response )
2582
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002583 if debug:
2584 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002585
GlennRC528ad292015-11-12 10:38:18 -08002586 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002587
GlennRC956ea742015-11-05 16:14:15 -08002588 except pexpect.EOF:
2589 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002590 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002591 except Exception:
2592 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002593 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002594
2595 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002596 '''
GlennRC956ea742015-11-05 16:14:15 -08002597 Discription: Checks whether the ID provided matches a flow ID in Mininet
2598 Arguments:
2599 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002600 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002601 a list of switches.
2602 flowId: the flow ID in hex format. Can also be a list of IDs
2603 Optional:
2604 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2605 debug: prints out the final result
2606 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2607 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002608 '''
GlennRC956ea742015-11-05 16:14:15 -08002609 try:
2610 main.log.info( "Getting flows from Mininet" )
2611 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002612 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002613 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002614
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002615 if debug:
2616 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002617
2618 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002619 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002620 result = False
2621 for f in flows:
2622 if flowId in f.get( 'cookie' ):
2623 result = True
2624 break
2625 # flowId is a list
2626 else:
2627 result = True
2628 # Get flow IDs from Mininet
2629 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2630 # Save the IDs that are not in Mininet
2631 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2632
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002633 if debug:
2634 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002635
2636 # Print out the IDs that are not in Mininet
2637 if absentIds:
2638 main.log.warn( "Absent ids: {}".format( absentIds ) )
2639 result = False
2640
2641 return main.TRUE if result else main.FALSE
2642
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002643 except pexpect.EOF:
2644 main.log.error( self.name + ": EOF exception found" )
2645 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002646 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002647 except Exception:
2648 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002649 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002650
Charles Chan029be652015-08-24 01:46:10 +08002651 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002652 """
Jon Hallefbd9792015-03-05 16:11:36 -08002653 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002654 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002655 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002656 self.handle.sendline( "" )
2657 self.handle.expect( "mininet>" )
2658 self.handle.sendline(
2659 "sh sudo tcpdump -n -i " +
2660 intf +
2661 " " +
2662 port +
2663 " -w " +
2664 filename.strip() +
2665 " &" )
2666 self.handle.sendline( "" )
2667 i = self.handle.expect( [ 'No\ssuch\device',
2668 'listening\son',
2669 pexpect.TIMEOUT,
2670 "mininet>" ],
2671 timeout=10 )
2672 main.log.warn( self.handle.before + self.handle.after )
2673 self.handle.sendline( "" )
2674 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002675 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002676 main.log.error(
2677 self.name +
2678 ": tcpdump - No such device exists. " +
2679 "tcpdump attempted on: " +
2680 intf )
admin2a9548d2014-06-17 14:08:07 -07002681 return main.FALSE
2682 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002683 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002684 return main.TRUE
2685 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002686 main.log.error(
2687 self.name +
2688 ": tcpdump command timed out! Check interface name," +
2689 " given interface was: " +
2690 intf )
admin2a9548d2014-06-17 14:08:07 -07002691 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002692 elif i == 3:
2693 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002694 return main.TRUE
2695 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002696 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002697 return main.FALSE
2698 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002699 main.log.error( self.name + ": EOF exception found" )
2700 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002701 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002702 except Exception:
2703 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002704 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002705
kelvin-onlabd3b64892015-01-20 13:26:24 -08002706 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002707 """
2708 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002709 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002710 self.handle.sendline( "sh sudo pkill tcpdump" )
2711 self.handle.expect( "mininet>" )
2712 self.handle.sendline( "" )
2713 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002714 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002715 main.log.error( self.name + ": TIMEOUT exception found" )
2716 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002717 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002718 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002719 main.log.error( self.name + ": EOF exception found" )
2720 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002721 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002722 except Exception:
2723 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002724 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002725
Jon Halld80cc142015-07-06 13:36:05 -07002726 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002727 """
2728 Read ports from a Mininet switch.
2729
2730 Returns a json structure containing information about the
2731 ports of the given switch.
2732 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002733 try:
2734 response = self.getInterfaces( nodeName )
2735 # TODO: Sanity check on response. log if no such switch exists
2736 ports = []
2737 for line in response.split( "\n" ):
2738 if not line.startswith( "name=" ):
2739 continue
2740 portVars = {}
2741 for var in line.split( "," ):
2742 key, value = var.split( "=" )
2743 portVars[ key ] = value
2744 isUp = portVars.pop( 'enabled', "True" )
2745 isUp = "True" in isUp
2746 if verbose:
2747 main.log.info( "Reading switch port %s(%s)" %
2748 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2749 mac = portVars[ 'mac' ]
2750 if mac == 'None':
2751 mac = None
2752 ips = []
2753 ip = portVars[ 'ip' ]
2754 if ip == 'None':
2755 ip = None
2756 ips.append( ip )
2757 name = portVars[ 'name' ]
2758 if name == 'None':
2759 name = None
2760 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2761 if name == 'lo':
2762 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2763 else:
2764 portNo = re.search( portRe, name ).group( 'port' )
2765 ports.append( { 'of_port': portNo,
2766 'mac': str( mac ).replace( '\'', '' ),
2767 'name': name,
2768 'ips': ips,
2769 'enabled': isUp } )
2770 return ports
2771 except pexpect.EOF:
2772 main.log.error( self.name + ": EOF exception found" )
2773 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002774 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002775 except Exception:
2776 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002777 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002778
You Wangdb8cd0a2016-05-26 15:19:45 -07002779 def getOVSPorts( self, nodeName ):
2780 """
2781 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2782
2783 Returns a list of dictionaries containing information about each
2784 port of the given switch.
2785 """
2786 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2787 try:
2788 response = self.execute(
2789 cmd=command,
2790 prompt="mininet>",
You Wang7d14d642019-01-23 15:10:08 -08002791 timeout=10,
2792 logCmd=False )
You Wangdb8cd0a2016-05-26 15:19:45 -07002793 ports = []
2794 if response:
2795 for line in response.split( "\n" ):
2796 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2797 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002798 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002799 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2800 result = re.search( pattern, line )
2801 if result:
2802 index = result.group( 'index' )
2803 name = result.group( 'name' )
2804 # This port number is extracted from port name
2805 port = result.group( 'port' )
2806 mac = result.group( 'mac' )
2807 ports.append( { 'index': index,
2808 'name': name,
2809 'port': port,
2810 'mac': mac } )
2811 return ports
2812 except pexpect.EOF:
2813 main.log.error( self.name + ": EOF exception found" )
2814 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002815 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002816 except Exception:
2817 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002818 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002819
You Wang7d14d642019-01-23 15:10:08 -08002820 def getSwitches( self, verbose=False, updateTimeout=1000, switchClasses=None ):
Jon Hallafa8a472015-06-12 14:02:42 -07002821 """
2822 Read switches from Mininet.
2823
2824 Returns a dictionary whose keys are the switch names and the value is
2825 a dictionary containing information about the switch.
2826 """
Jon Halla22481b2015-07-28 17:46:01 -07002827 # NOTE: To support new Mininet switch classes, just append the new
2828 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002829
Jon Halla22481b2015-07-28 17:46:01 -07002830 # Regex patterns to parse 'dump' output
2831 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002832 # <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 -07002833 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002834 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2835 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2836 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
You Wang7d14d642019-01-23 15:10:08 -08002837 if not switchClasses:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002838 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
You Wang7d14d642019-01-23 15:10:08 -08002839 try:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002840 swRE = r"<(?P<class>" + switchClasses + r")" +\
2841 r"(?P<options>\{.*\})?\s" +\
2842 r"(?P<name>[^:]+)\:\s" +\
2843 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2844 r"\spid=(?P<pid>(\d)+)"
2845 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002846 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002847 output = {}
2848 dump = self.dump().split( "\n" )
2849 for line in dump:
2850 result = re.search( swRE, line, re.I )
2851 if result:
2852 name = result.group( 'name' )
2853 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2854 pid = result.group( 'pid' )
2855 swClass = result.group( 'class' )
2856 options = result.group( 'options' )
2857 if verbose:
2858 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2859 ports = self.getPorts( name )
2860 output[ name ] = { "dpid": dpid,
2861 "ports": ports,
2862 "swClass": swClass,
2863 "pid": pid,
2864 "options": options }
2865 return output
2866 except pexpect.EOF:
2867 main.log.error( self.name + ": EOF exception found" )
2868 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002869 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002870 except Exception:
2871 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002872 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002873
You Wangd66de192018-04-30 17:30:12 -07002874 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002875 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2876 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002877 """
2878 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002879 Optional:
2880 hostClass: it is used to match the class of the mininet host. It
2881 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002882 Returns a dictionary whose keys are the host names and the value is
2883 a dictionary containing information about the host.
2884 """
2885 # Regex patterns to parse dump output
2886 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002887 # <Host h1: pid=12725>
2888 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2889 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2890 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002891 # NOTE: Does not correctly match hosts with multi-links
2892 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2893 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002894 try:
You Wang53dba1e2018-02-02 17:45:44 -08002895 if not isinstance( hostClass, types.ListType ):
2896 hostClass = [ str( hostClass ) ]
2897 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002898 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2899 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2900 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002901 if update:
2902 # update mn port info
2903 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002904 # Get mininet dump
2905 dump = self.dump().split( "\n" )
2906 hosts = {}
2907 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002908 result = re.search( hostRE, line )
2909 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002910 name = result.group( 'name' )
2911 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002912 if getInterfaces:
2913 response = self.getInterfaces( name )
2914 # Populate interface info
2915 for line in response.split( "\n" ):
2916 if line.startswith( "name=" ):
2917 portVars = {}
2918 for var in line.split( "," ):
2919 key, value = var.split( "=" )
2920 portVars[ key ] = value
2921 isUp = portVars.pop( 'enabled', "True" )
2922 isUp = "True" in isUp
2923 if verbose:
2924 main.log.info( "Reading host port %s(%s)" %
2925 ( portVars[ 'name' ],
2926 portVars[ 'mac' ] ) )
2927 mac = portVars[ 'mac' ]
2928 if mac == 'None':
2929 mac = None
2930 ips = []
2931 ip = portVars[ 'ip' ]
2932 if ip == 'None':
2933 ip = None
2934 ips.append( ip )
2935 intfName = portVars[ 'name' ]
2936 if name == 'None':
2937 name = None
2938 interfaces.append( {
2939 "name": intfName,
2940 "ips": ips,
2941 "mac": str( mac ),
2942 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002943 hosts[ name ] = { "interfaces": interfaces }
2944 return hosts
2945 except pexpect.EOF:
2946 main.log.error( self.name + ": EOF exception found" )
2947 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002948 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002949 except Exception:
2950 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002951 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002952
You Wang7d14d642019-01-23 15:10:08 -08002953 def getLinks( self, timeout=20, updateTimeout=1000, excludeNodes=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002954 """
2955 Gathers information about current Mininet links. These links may not
2956 be up if one of the ports is down.
2957
2958 Returns a list of dictionaries with link endpoints.
2959
2960 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002961 { 'node1': str( node1 name )
2962 'node2': str( node2 name )
2963 'port1': str( port1 of_port )
2964 'port2': str( port2 of_port ) }
You Wang7d14d642019-01-23 15:10:08 -08002965
2966 If either node1 or node2 name starts with any of the strings sepcified
2967 in excludeNodes, the link will be excluded from the returned value
2968
Jon Hallafa8a472015-06-12 14:02:42 -07002969 Note: The port number returned is the eth#, not necessarily the of_port
2970 number. In Mininet, for OVS switch, these should be the same. For
2971 hosts, this is just the eth#.
2972 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002973 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002974 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002975 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002976
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002977 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002978 # s1-eth3<->s2-eth1 (OK OK)
2979 # s13-eth3<->h27-eth0 (OK OK)
You Wang7d14d642019-01-23 15:10:08 -08002980 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d\.]+)\<\-\>" +\
2981 "(?P<node2>[\w]+)\-eth(?P<port2>[\d\.]+)"
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002982 links = []
2983 for line in response:
2984 match = re.search( linkRE, line )
2985 if match:
2986 node1 = match.group( 'node1' )
2987 node2 = match.group( 'node2' )
You Wang7d14d642019-01-23 15:10:08 -08002988 if any( node1.startswith( node ) for node in excludeNodes ) or \
2989 any( node2.startswith( node ) for node in excludeNodes ):
2990 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002991 port1 = match.group( 'port1' )
2992 port2 = match.group( 'port2' )
2993 links.append( { 'node1': node1,
2994 'node2': node2,
2995 'port1': port1,
2996 'port2': port2 } )
2997 return links
2998
2999 except pexpect.EOF:
3000 main.log.error( self.name + ": EOF exception found" )
3001 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003002 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003003 except Exception:
3004 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003005 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003006
3007 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003008 """
3009 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003010 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003011
Jon Hallafa8a472015-06-12 14:02:42 -07003012 Dependencies:
3013 1. numpy - "sudo pip install numpy"
3014 """
3015 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003016 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003017 try:
3018 mnDPIDs = []
3019 for swName, switch in switches.iteritems():
3020 mnDPIDs.append( switch[ 'dpid' ].lower() )
3021 mnDPIDs.sort()
3022 if switchesJson == "": # if rest call fails
3023 main.log.error(
3024 self.name +
3025 ".compareSwitches(): Empty JSON object given from ONOS" )
3026 return main.FALSE
3027 onos = switchesJson
3028 onosDPIDs = []
3029 for switch in onos:
3030 if switch[ 'available' ]:
3031 onosDPIDs.append(
3032 switch[ 'id' ].replace(
3033 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003034 '' ).replace(
3035 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003036 '' ).lower() )
3037 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003038
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003039 if mnDPIDs != onosDPIDs:
3040 switchResults = main.FALSE
3041 main.log.error( "Switches in MN but not in ONOS:" )
3042 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3043 main.log.error( str( list1 ) )
3044 main.log.error( "Switches in ONOS but not in MN:" )
3045 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3046 main.log.error( str( list2 ) )
3047 else: # list of dpid's match in onos and mn
3048 switchResults = main.TRUE
3049 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003050
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003051 # FIXME: this does not look for extra ports in ONOS, only checks that
3052 # ONOS has what is in MN
3053 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003054
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003055 # PORTS
3056 for name, mnSwitch in switches.iteritems():
3057 mnPorts = []
3058 onosPorts = []
3059 switchResult = main.TRUE
3060 for port in mnSwitch[ 'ports' ]:
3061 if port[ 'enabled' ]:
3062 mnPorts.append( int( port[ 'of_port' ] ) )
3063 for onosSwitch in portsJson:
3064 if onosSwitch[ 'device' ][ 'available' ]:
3065 if onosSwitch[ 'device' ][ 'id' ].replace(
3066 ':',
3067 '' ).replace(
3068 "of",
3069 '' ) == mnSwitch[ 'dpid' ]:
3070 for port in onosSwitch[ 'ports' ]:
3071 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003072 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003073 # onosPorts.append( 'local' )
3074 onosPorts.append( long( uint64( -2 ) ) )
3075 else:
3076 onosPorts.append( int( port[ 'port' ] ) )
3077 break
3078 mnPorts.sort( key=float )
3079 onosPorts.sort( key=float )
3080
3081 mnPortsLog = mnPorts
3082 onosPortsLog = onosPorts
3083 mnPorts = [ x for x in mnPorts ]
3084 onosPorts = [ x for x in onosPorts ]
3085
3086 # TODO: handle other reserved port numbers besides LOCAL
3087 # NOTE: Reserved ports
3088 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3089 # long( uint64( -2 ) )
3090 for mnPort in mnPortsLog:
3091 if mnPort in onosPorts:
3092 # don't set results to true here as this is just one of
3093 # many checks and it might override a failure
3094 mnPorts.remove( mnPort )
3095 onosPorts.remove( mnPort )
3096
3097 # NOTE: OVS reports this as down since there is no link
3098 # So ignoring these for now
3099 # TODO: Come up with a better way of handling these
3100 if 65534 in mnPorts:
3101 mnPorts.remove( 65534 )
3102 if long( uint64( -2 ) ) in onosPorts:
3103 onosPorts.remove( long( uint64( -2 ) ) )
3104 if len( mnPorts ): # the ports of this switch don't match
3105 switchResult = main.FALSE
3106 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3107 if len( onosPorts ): # the ports of this switch don't match
3108 switchResult = main.FALSE
3109 main.log.warn(
3110 "Ports in ONOS but not MN: " +
3111 str( onosPorts ) )
3112 if switchResult == main.FALSE:
3113 main.log.error(
3114 "The list of ports for switch %s(%s) does not match:" %
3115 ( name, mnSwitch[ 'dpid' ] ) )
3116 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3117 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3118 portsResults = portsResults and switchResult
3119 finalResults = finalResults and portsResults
3120 return finalResults
3121 except pexpect.EOF:
3122 main.log.error( self.name + ": EOF exception found" )
3123 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003124 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003125 except Exception:
3126 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003127 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003128
Jon Hallafa8a472015-06-12 14:02:42 -07003129 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003130 """
3131 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003132 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003133
Jon Hallafa8a472015-06-12 14:02:42 -07003134 """
Jon Hall7eb38402015-01-08 17:19:54 -08003135 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003136 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003137 try:
3138 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003139
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003140 mnLinks = []
3141 for l in links:
3142 try:
3143 node1 = switches[ l[ 'node1' ] ]
3144 node2 = switches[ l[ 'node2' ] ]
3145 enabled = True
3146 for port in node1[ 'ports' ]:
3147 if port[ 'of_port' ] == l[ 'port1' ]:
3148 enabled = enabled and port[ 'enabled' ]
3149 for port in node2[ 'ports' ]:
3150 if port[ 'of_port' ] == l[ 'port2' ]:
3151 enabled = enabled and port[ 'enabled' ]
3152 if enabled:
3153 mnLinks.append( l )
3154 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003155 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003156 if 2 * len( mnLinks ) == len( onos ):
3157 linkResults = main.TRUE
3158 else:
3159 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003160 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003161 "Mininet has " + str( len( mnLinks ) ) +
3162 " bidirectional links and ONOS has " +
3163 str( len( onos ) ) + " unidirectional links" )
3164
3165 # iterate through MN links and check if an ONOS link exists in
3166 # both directions
3167 for link in mnLinks:
3168 # TODO: Find a more efficient search method
3169 node1 = None
3170 port1 = None
3171 node2 = None
3172 port2 = None
3173 firstDir = main.FALSE
3174 secondDir = main.FALSE
3175 for swName, switch in switches.iteritems():
3176 if swName == link[ 'node1' ]:
3177 node1 = switch[ 'dpid' ]
3178 for port in switch[ 'ports' ]:
3179 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3180 port1 = port[ 'of_port' ]
3181 if node1 is not None and node2 is not None:
3182 break
3183 if swName == link[ 'node2' ]:
3184 node2 = switch[ 'dpid' ]
3185 for port in switch[ 'ports' ]:
3186 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3187 port2 = port[ 'of_port' ]
3188 if node1 is not None and node2 is not None:
3189 break
3190
3191 for onosLink in onos:
3192 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3193 ":", '' ).replace( "of", '' )
3194 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3195 ":", '' ).replace( "of", '' )
3196 onosPort1 = onosLink[ 'src' ][ 'port' ]
3197 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3198
3199 # check onos link from node1 to node2
3200 if str( onosNode1 ) == str( node1 ) and str(
3201 onosNode2 ) == str( node2 ):
3202 if int( onosPort1 ) == int( port1 ) and int(
3203 onosPort2 ) == int( port2 ):
3204 firstDir = main.TRUE
3205 else:
Jon Hallab611372018-02-21 15:26:05 -08003206 # The right switches, but wrong ports, could be
3207 # another link between these devices, or onos
3208 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003209 main.log.warn(
3210 'The port numbers do not match for ' +
3211 str( link ) +
3212 ' between ONOS and MN. When checking ONOS for ' +
3213 'link %s/%s -> %s/%s' %
3214 ( node1, port1, node2, port2 ) +
3215 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003216 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3217 '. This could be another link between these devices' +
3218 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003219
3220 # check onos link from node2 to node1
3221 elif ( str( onosNode1 ) == str( node2 ) and
3222 str( onosNode2 ) == str( node1 ) ):
3223 if ( int( onosPort1 ) == int( port2 )
3224 and int( onosPort2 ) == int( port1 ) ):
3225 secondDir = main.TRUE
3226 else:
Jon Hallab611372018-02-21 15:26:05 -08003227 # The right switches, but wrong ports, could be
3228 # another link between these devices, or onos
3229 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003230 main.log.warn(
3231 'The port numbers do not match for ' +
3232 str( link ) +
3233 ' between ONOS and MN. When checking ONOS for ' +
3234 'link %s/%s -> %s/%s' %
3235 ( node1, port1, node2, port2 ) +
3236 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003237 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3238 '. This could be another link between these devices' +
3239 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003240 else: # this is not the link you're looking for
3241 pass
3242 if not firstDir:
3243 main.log.error(
3244 'ONOS does not have the link %s/%s -> %s/%s' %
3245 ( node1, port1, node2, port2 ) )
3246 if not secondDir:
3247 main.log.error(
3248 'ONOS does not have the link %s/%s -> %s/%s' %
3249 ( node2, port2, node1, port1 ) )
3250 linkResults = linkResults and firstDir and secondDir
3251 return linkResults
3252 except pexpect.EOF:
3253 main.log.error( self.name + ": EOF exception found" )
3254 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003255 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003256 except Exception:
3257 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003258 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003259
Jon Hallafa8a472015-06-12 14:02:42 -07003260 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003261 """
Jon Hallafa8a472015-06-12 14:02:42 -07003262 Compare mn and onos Hosts.
3263 Since Mininet hosts are quiet, ONOS will only know of them when they
3264 speak. For this reason, we will only check that the hosts in ONOS
3265 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003266
Jon Hallafa8a472015-06-12 14:02:42 -07003267 Arguments:
3268 hostsJson: parsed json object from the onos hosts api
3269 Returns:
3270 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003271 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003272 try:
3273 hostResults = main.TRUE
3274 for onosHost in hostsJson:
3275 onosMAC = onosHost[ 'mac' ].lower()
3276 match = False
3277 for mnHost, info in hosts.iteritems():
3278 for mnIntf in info[ 'interfaces' ]:
3279 if onosMAC == mnIntf[ 'mac' ].lower():
3280 match = True
3281 for ip in mnIntf[ 'ips' ]:
3282 if ip in onosHost[ 'ipAddresses' ]:
3283 pass # all is well
3284 else:
3285 # misssing ip
3286 main.log.error( "ONOS host " +
3287 onosHost[ 'id' ] +
3288 " has a different IP(" +
3289 str( onosHost[ 'ipAddresses' ] ) +
3290 ") than the Mininet host(" +
3291 str( ip ) +
3292 ")." )
3293 output = json.dumps(
3294 onosHost,
3295 sort_keys=True,
3296 indent=4,
3297 separators=( ',', ': ' ) )
3298 main.log.info( output )
3299 hostResults = main.FALSE
3300 if not match:
3301 hostResults = main.FALSE
3302 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3303 "corresponding Mininet host." )
3304 output = json.dumps( onosHost,
3305 sort_keys=True,
3306 indent=4,
3307 separators=( ',', ': ' ) )
3308 main.log.info( output )
3309 return hostResults
3310 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003311 main.log.error( self.name + ": EOF exception found" )
3312 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003313 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003314 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003315 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003316 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003317
You Wangd66de192018-04-30 17:30:12 -07003318 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003319 """
3320 Description:
3321 Verify that all hosts have IP address assigned to them
3322 Optional:
3323 hostList: If specified, verifications only happen to the hosts
3324 in hostList
3325 prefix: at least one of the ip address assigned to the host
3326 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003327 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003328 Returns:
3329 main.TRUE if all hosts have specific IP address assigned;
3330 main.FALSE otherwise
3331 """
3332 try:
You Wangd66de192018-04-30 17:30:12 -07003333 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003334 if not hostList:
3335 hostList = hosts.keys()
3336 for hostName in hosts.keys():
3337 if hostName not in hostList:
3338 continue
3339 ipList = []
3340 self.handle.sendline( str( hostName ) + " ip a" )
3341 self.handle.expect( "mininet>" )
3342 ipa = self.handle.before
3343 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3344 ipList += re.findall( ipv4Pattern, ipa )
3345 # It's tricky to make regex for IPv6 addresses and this one is simplified
3346 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})/'
3347 ipList += re.findall( ipv6Pattern, ipa )
3348 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3349 if not ipList:
3350 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3351 else:
3352 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3353 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3354 else:
3355 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3356 hostList.remove( hostName )
3357 return main.FALSE if hostList else main.TRUE
3358 except KeyError:
3359 main.log.exception( self.name + ": host data not as expected: " + hosts )
3360 return None
3361 except pexpect.EOF:
3362 main.log.error( self.name + ": EOF exception found" )
3363 main.log.error( self.name + ": " + self.handle.before )
3364 main.cleanAndExit()
3365 except Exception:
3366 main.log.exception( self.name + ": Uncaught exception" )
3367 return None
3368
Jon Hallafa8a472015-06-12 14:02:42 -07003369 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003370 """
3371 Returns a list of all hosts
3372 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003373 try:
3374 self.handle.sendline( "" )
3375 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003376
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003377 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3378 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003379
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003380 handlePy = self.handle.before
3381 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3382 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003383
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003384 self.handle.sendline( "" )
3385 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003386
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003387 hostStr = handlePy.replace( "]", "" )
3388 hostStr = hostStr.replace( "'", "" )
3389 hostStr = hostStr.replace( "[", "" )
3390 hostStr = hostStr.replace( " ", "" )
3391 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003392
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003393 return hostList
3394 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003395 main.log.error( self.name + ": TIMEOUT exception found" )
3396 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003397 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003398 except pexpect.EOF:
3399 main.log.error( self.name + ": EOF exception found" )
3400 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003401 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003402 except Exception:
3403 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003404 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003405
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003406 def getSwitch( self ):
3407 """
3408 Returns a list of all switches
3409 Again, don't ask question just use it...
3410 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003411 try:
3412 # get host list...
3413 hostList = self.getHosts()
3414 # Make host set
3415 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003416
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003417 # Getting all the nodes in mininet
3418 self.handle.sendline( "" )
3419 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003420
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003421 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3422 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003423
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003424 handlePy = self.handle.before
3425 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3426 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003427
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003428 self.handle.sendline( "" )
3429 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003430
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003431 nodesStr = handlePy.replace( "]", "" )
3432 nodesStr = nodesStr.replace( "'", "" )
3433 nodesStr = nodesStr.replace( "[", "" )
3434 nodesStr = nodesStr.replace( " ", "" )
3435 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003436
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003437 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003438 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003439 nodesSet.discard( 'c0' )
3440 nodesSet.discard( 'c1' )
3441 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003442
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003443 switchSet = nodesSet - hostSet
3444 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003445
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003446 return switchList
3447 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003448 main.log.error( self.name + ": TIMEOUT exception found" )
3449 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003450 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003451 except pexpect.EOF:
3452 main.log.error( self.name + ": EOF exception found" )
3453 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003454 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003455 except Exception:
3456 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003457 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003458
You Wang7d14d642019-01-23 15:10:08 -08003459 def getGraphDict( self, timeout=60, useId=True, includeHost=False,
3460 switchClasses=None, excludeNodes=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07003461 """
3462 Return a dictionary which describes the latest Mininet topology data as a
3463 graph.
3464 An example of the dictionary:
3465 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3466 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3467 Each vertex should at least have an 'edges' attribute which describes the
3468 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003469 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003470 list of attributes.
3471 An example of the edges dictionary:
3472 'edges': { vertex2: { 'port': ..., 'weight': ... },
3473 vertex3: { 'port': ..., 'weight': ... } }
3474 If useId == True, dpid/mac will be used instead of names to identify
3475 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3476 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003477 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003478 in topology data.
You Wang7d14d642019-01-23 15:10:08 -08003479 if switchClasses == None, default switchClasses will be used when calling
3480 getSwitches method.
3481 excludeNodes will be passed to getLinks method to exclude unexpected links.
You Wangdb8cd0a2016-05-26 15:19:45 -07003482 Note that link or switch that are brought down by 'link x x down' or 'switch
3483 x down' commands still show in the output of Mininet CLI commands such as
3484 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3485 recommended to use delLink() or delSwitch functions to simulate link/switch
3486 down, and addLink() or addSwitch to add them back.
3487 """
3488 graphDict = {}
3489 try:
You Wang7d14d642019-01-23 15:10:08 -08003490 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003491 portDict = {}
You Wang7d14d642019-01-23 15:10:08 -08003492 switches = self.getSwitches( switchClasses=switchClasses )
You Wangdb8cd0a2016-05-26 15:19:45 -07003493 if includeHost:
3494 hosts = self.getHosts()
3495 for link in links:
3496 # FIXME: support 'includeHost' argument
3497 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3498 continue
3499 nodeName1 = link[ 'node1' ]
3500 nodeName2 = link[ 'node2' ]
You Wang7d14d642019-01-23 15:10:08 -08003501 if not self.getOVSPorts( nodeName1 ) or not self.getOVSPorts( nodeName2 ):
3502 # The device is probably offline
3503 continue
You Wangdb8cd0a2016-05-26 15:19:45 -07003504 port1 = link[ 'port1' ]
3505 port2 = link[ 'port2' ]
3506 # Loop for two nodes
3507 for i in range( 2 ):
3508 # Get port index from OVS
3509 # The index extracted from port name may be inconsistent with ONOS
3510 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003511 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003512 portList = self.getOVSPorts( nodeName1 )
3513 if len( portList ) == 0:
3514 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3515 return None
3516 portDict[ nodeName1 ] = portList
3517 for port in portDict[ nodeName1 ]:
3518 if port[ 'port' ] == port1:
3519 portIndex = port[ 'index' ]
3520 break
3521 if portIndex == -1:
3522 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3523 return None
3524 if useId:
3525 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3526 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3527 else:
3528 node1 = nodeName1
3529 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003530 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003531 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003532 graphDict[ node1 ] = { 'edges': {},
3533 'dpid': switches[ nodeName1 ][ 'dpid' ],
3534 'name': nodeName1,
3535 'ports': switches[ nodeName1 ][ 'ports' ],
3536 'swClass': switches[ nodeName1 ][ 'swClass' ],
3537 'pid': switches[ nodeName1 ][ 'pid' ],
3538 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003539 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003540 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003541 else:
3542 # Assert node2 is not connected to any current links of node1
You Wang7d14d642019-01-23 15:10:08 -08003543 # assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
3544 pass
3545 for port in switches[ nodeName1 ][ 'ports' ]:
3546 if port[ 'of_port' ] == str( portIndex ):
3547 # Use -1 as index for disabled port
3548 if port[ 'enabled' ] == True:
3549 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
3550 else:
3551 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': -1 }
You Wangdb8cd0a2016-05-26 15:19:45 -07003552 # Swap two nodes/ports
3553 nodeName1, nodeName2 = nodeName2, nodeName1
3554 port1, port2 = port2, port1
You Wang7d14d642019-01-23 15:10:08 -08003555 # Remove links with disabled ports
3556 linksToRemove = []
3557 for node, edges in graphDict.items():
3558 for neighbor, port in edges[ 'edges' ].items():
3559 if port[ 'port' ] == -1:
3560 linksToRemove.append( ( node, neighbor ) )
3561 for node1, node2 in linksToRemove:
3562 for i in range( 2 ):
3563 if graphDict.get( node1 )[ 'edges' ].get( node2 ):
3564 graphDict[ node1 ][ 'edges' ].pop( node2 )
3565 node1, node2 = node2, node1
You Wangdb8cd0a2016-05-26 15:19:45 -07003566 return graphDict
3567 except KeyError:
3568 main.log.exception( self.name + ": KeyError exception found" )
3569 return None
3570 except AssertionError:
3571 main.log.exception( self.name + ": AssertionError exception found" )
3572 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003573 except pexpect.EOF:
3574 main.log.error( self.name + ": EOF exception found" )
3575 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003576 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003577 except Exception:
3578 main.log.exception( self.name + ": Uncaught exception" )
3579 return None
3580
Devin Lima7cfdbd2017-09-29 15:02:22 -07003581 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003582 """
3583 updates the port address and status information for
3584 each port in mn"""
3585 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003586 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003587 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003588 self.handle.sendline( "" )
3589 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003590
Jon Hall7eb38402015-01-08 17:19:54 -08003591 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003592 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003593
Jon Hall7eb38402015-01-08 17:19:54 -08003594 self.handle.sendline( "" )
3595 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003596
Jon Hallb1290e82014-11-18 16:17:48 -05003597 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003598 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003599 main.log.error( self.name + ": TIMEOUT exception found" )
3600 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003601 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003602 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003603 main.log.error( self.name + ": EOF exception found" )
3604 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003605 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003606 except Exception:
3607 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003608 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003609
Jon Halld80cc142015-07-06 13:36:05 -07003610 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003611 """
3612 Add vlan tag to a host.
3613 Dependencies:
3614 This class depends on the "vlan" package
3615 $ sudo apt-get install vlan
3616 Configuration:
3617 Load the 8021q module into the kernel
3618 $sudo modprobe 8021q
3619
3620 To make this setup permanent:
3621 $ sudo su -c 'echo "8021q" >> /etc/modules'
3622 """
3623 if self.handle:
3624 try:
Jon Halld80cc142015-07-06 13:36:05 -07003625 # get the ip address of the host
3626 main.log.info( "Get the ip address of the host" )
3627 ipaddr = self.getIPAddress( host )
3628 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003629
Jon Halld80cc142015-07-06 13:36:05 -07003630 # remove IP from interface intf
3631 # Ex: h1 ifconfig h1-eth0 inet 0
3632 main.log.info( "Remove IP from interface " )
3633 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3634 self.handle.sendline( cmd2 )
3635 self.handle.expect( "mininet>" )
3636 response = self.handle.before
3637 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003638
Jon Halld80cc142015-07-06 13:36:05 -07003639 # create VLAN interface
3640 # Ex: h1 vconfig add h1-eth0 100
3641 main.log.info( "Create Vlan" )
3642 cmd3 = host + " vconfig add " + intf + " " + vlan
3643 self.handle.sendline( cmd3 )
3644 self.handle.expect( "mininet>" )
3645 response = self.handle.before
3646 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003647
Jon Halld80cc142015-07-06 13:36:05 -07003648 # assign the host's IP to the VLAN interface
3649 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3650 main.log.info( "Assign the host IP to the vlan interface" )
3651 vintf = intf + "." + vlan
3652 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3653 self.handle.sendline( cmd4 )
3654 self.handle.expect( "mininet>" )
3655 response = self.handle.before
3656 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003657
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003658 # update Mininet node variables
3659 main.log.info( "Update Mininet node variables" )
3660 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3661 self.handle.sendline( cmd5 )
3662 self.handle.expect( "mininet>" )
3663 response = self.handle.before
3664 main.log.info( "====> %s ", response )
3665
3666 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3667 self.handle.sendline( cmd6 )
3668 self.handle.expect( "mininet>" )
3669 response = self.handle.before
3670 main.log.info( "====> %s ", response )
3671
3672 return main.TRUE
3673 except pexpect.TIMEOUT:
3674 main.log.error( self.name + ": TIMEOUT exception found" )
3675 main.log.error( self.name + ": " + self.handle.before )
3676 main.cleanAndExit()
3677 except pexpect.EOF:
3678 main.log.error( self.name + ": EOF exception found" )
3679 main.log.error( self.name + ": " + self.handle.before )
3680 return main.FALSE
3681 except Exception:
3682 main.log.exception( self.name + ": Uncaught exception!" )
3683 return main.FALSE
3684
3685 def removeVLAN( self, host, intf ):
3686 """
3687 Remove vlan tag from a host.
3688 Dependencies:
3689 This class depends on the "vlan" package
3690 $ sudo apt-get install vlan
3691 Configuration:
3692 Load the 8021q module into the kernel
3693 $sudo modprobe 8021q
3694
3695 To make this setup permanent:
3696 $ sudo su -c 'echo "8021q" >> /etc/modules'
3697 """
3698 if self.handle:
3699 try:
3700 # get the ip address of the host
3701 main.log.info( "Get the ip address of the host" )
3702 ipaddr = self.getIPAddress( host )
3703
3704 # remove VLAN interface
3705 # Ex: h1 vconfig rem h1-eth0.100
3706 main.log.info( "Remove Vlan interface" )
3707 cmd2 = host + " vconfig rem " + intf
3708 self.handle.sendline( cmd2 )
3709 self.handle.expect( "mininet>" )
3710 response = self.handle.before
3711 main.log.info( "====> %s ", response )
3712
3713 # assign the host's IP to the original interface
3714 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3715 main.log.info( "Assign the host IP to the original interface" )
3716 original_intf = intf.split(".")[0]
3717 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3718 self.handle.sendline( cmd3 )
3719 self.handle.expect( "mininet>" )
3720 response = self.handle.before
3721 main.log.info( "====> %s ", response )
3722
3723 # update Mininet node variables
3724 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3725 self.handle.sendline( cmd4 )
3726 self.handle.expect( "mininet>" )
3727 response = self.handle.before
3728 main.log.info( "====> %s ", response )
3729
3730 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3731 self.handle.sendline( cmd5 )
3732 self.handle.expect( "mininet>" )
3733 response = self.handle.before
3734 main.log.info( "====> %s ", response )
3735
kaouthera3f13ca22015-05-05 15:01:41 -07003736 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003737 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003738 main.log.error( self.name + ": TIMEOUT exception found" )
3739 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003740 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003741 except pexpect.EOF:
3742 main.log.error( self.name + ": EOF exception found" )
3743 main.log.error( self.name + ": " + self.handle.before )
3744 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003745 except Exception:
3746 main.log.exception( self.name + ": Uncaught exception!" )
3747 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003748
Jon Hall892818c2015-10-20 17:58:34 -07003749 def createHostComponent( self, name ):
3750 """
3751 Creates a new mininet cli component with the same parameters as self.
3752 This new component is intended to be used to login to the hosts created
3753 by mininet.
3754
3755 Arguments:
3756 name - The string of the name of this component. The new component
3757 will be assigned to main.<name> .
3758 In addition, main.<name>.name = str( name )
3759 """
3760 try:
3761 # look to see if this component already exists
3762 getattr( main, name )
3763 except AttributeError:
3764 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003765 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3766 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003767 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003768 except pexpect.EOF:
3769 main.log.error( self.name + ": EOF exception found" )
3770 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003771 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003772 except Exception:
3773 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003774 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003775 else:
3776 # namespace is not clear!
3777 main.log.error( name + " component already exists!" )
3778 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003779 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003780
3781 def removeHostComponent( self, name ):
3782 """
3783 Remove host component
3784 Arguments:
3785 name - The string of the name of the component to delete.
3786 """
3787 try:
3788 # Get host component
3789 component = getattr( main, name )
3790 except AttributeError:
3791 main.log.error( "Component " + name + " does not exist." )
3792 return
3793 try:
3794 # Disconnect from component
3795 component.disconnect()
You Wangf32c6ed2018-08-23 17:10:22 -07003796 component.close_log_handles()
Jon Hall892818c2015-10-20 17:58:34 -07003797 # Delete component
3798 delattr( main, name )
3799 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003800 del( main.componentDictionary[ name ] )
You Wangf32c6ed2018-08-23 17:10:22 -07003801 except StandardError:
3802 self.log.exception( "Exception while closing log files for " + name )
3803 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003804 except pexpect.EOF:
3805 main.log.error( self.name + ": EOF exception found" )
3806 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003807 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003808 except Exception:
3809 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003810 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003811
3812 def startHostCli( self, host=None ):
3813 """
3814 Use the mininet m utility to connect to the host's cli
3815 """
3816 # These are fields that can be used by scapy packets. Initialized to None
3817 self.hostIp = None
3818 self.hostMac = None
3819 try:
3820 if not host:
3821 host = self.name
3822 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003823 self.handle.sendline( "cd" )
3824 self.handle.expect( self.hostPrompt )
3825 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003826 self.handle.expect( self.hostPrompt )
3827 return main.TRUE
3828 except pexpect.TIMEOUT:
3829 main.log.exception( self.name + ": Command timed out" )
3830 return main.FALSE
3831 except pexpect.EOF:
3832 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003833 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003834 except Exception:
3835 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003836 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003837
YPZhang801d46d2016-08-08 13:26:28 -07003838 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003839 '''
3840
YPZhang801d46d2016-08-08 13:26:28 -07003841 Args:
3842 devicename: switch name
3843 intf: port name on switch
3844 status: up or down
3845
3846 Returns: boolean to show success change status
3847
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003848 '''
YPZhang801d46d2016-08-08 13:26:28 -07003849 if status == "down" or status == "up":
3850 try:
3851 cmd = devicename + " ifconfig " + intf + " " + status
3852 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003853 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003854 return main.TRUE
3855 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003856 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003857 return main.FALSE
3858 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003859 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003860 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003861 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003862 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003863 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003864 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003865 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003866 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003867 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003868 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003869 return main.FALSE
3870
You Wang6e5b48e2018-07-23 16:17:38 -07003871 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003872 """
You Wang6e5b48e2018-07-23 16:17:38 -07003873 Moves a host from one switch to another on the fly
3874 Optional:
3875 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3876 prefixLen: length of the host IP prefix
3877 ipv6: move an IPv6 host if True
3878 intfSuffix: suffix of the new interface after host movement
3879 vlan: vlan ID of the host. Use None for non-vlan host
3880 Note: The intf between host and oldSw when detached
3881 using detach(), will still show up in the 'net'
3882 cmd, because switch.detach() doesn't affect switch.intfs[]
3883 ( which is correct behavior since the interfaces
3884 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003885 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003886 if self.handle:
3887 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003888 newIntf = "%s-%s" % ( host, intfSuffix )
3889 commands = [
3890 # Bring link between oldSw-host down
3891 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3892 # Determine hostintf and Oldswitchintf
3893 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
3894 ]
3895 # Determine ip address of the host-oldSw interface
3896 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3897 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3898 commands += [
3899 # Determine mac address of the host-oldSw interface
3900 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3901 # Detach interface between oldSw-host
3902 "px " + oldSw + ".detach( sintf )",
3903 # Add link between host-newSw
3904 "py net.addLink(" + host + "," + newSw + ")",
3905 # Determine hostintf and Newswitchintf
3906 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3907 # Attach interface between newSw-host
3908 "px " + newSw + ".attach( sintf )",
3909 ]
3910 if vlan:
3911 vlanIntf = "%s.%s" % ( newIntf, vlan )
3912 commands += [
3913 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
3914 host + " ip link set up %s" % vlanIntf,
3915 "px hintf.name = '" + vlanIntf + "'",
3916 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
3917 ]
3918 newIntf = vlanIntf
3919 commands += [
3920 # Set mac address of the host-newSw interface
3921 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
3922 # Set IP address of the host-newSw interface
3923 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
3924 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
3925 ]
3926 if ipv6:
3927 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
3928 commands += [
3929 "net",
3930 host + " ifconfig"
3931 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003932 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003933 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003934 self.handle.sendline( cmd )
3935 self.handle.expect( "mininet>" )
3936 main.log.info( "====> %s ", self.handle.before )
3937 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003938 except pexpect.TIMEOUT:
3939 main.log.error( self.name + ": TIMEOUT exception found" )
3940 main.log.error( self.name + ": " + self.handle.before )
3941 main.cleanAndExit()
3942 except pexpect.EOF:
3943 main.log.error( self.name + ": EOF exception found" )
3944 main.log.error( self.name + ": " + self.handle.before )
3945 return main.FALSE
3946 except Exception:
3947 main.log.exception( self.name + ": Uncaught exception!" )
3948 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07003949
You Wang6e5b48e2018-07-23 16:17:38 -07003950 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
3951 macAddr=None, prefixLen=None, ipv6=False,
3952 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07003953 """
You Wang6e5b48e2018-07-23 16:17:38 -07003954 Moves a dual-homed host from one switch-pair to another pair on the fly
3955 Optional:
3956 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3957 prefixLen: length of the host IP prefix
3958 ipv6: move an IPv6 host if True
3959 intfSuffix1: suffix of the first new interface
3960 intfSuffix2: suffix of the second new interface
3961 bondSuffix: suffix of the new bond interface
3962 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07003963 """
You Wang7ea90582018-07-19 15:27:58 -07003964 if self.handle:
3965 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003966 bondIntf = "%s-%s" % ( host, bondSuffix )
3967 newIntf = "%s-%s" % ( host, intfSuffix1 )
3968 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07003969 commands = [
3970 # Bring link between oldSw-host down
3971 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3972 # Bring link between oldPairSw-host down
3973 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
3974 # Determine hostintf and Oldswitchintf
3975 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07003976 ]
3977 # Determine ip address of the host-oldSw interface
3978 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3979 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3980 commands += [
3981 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07003982 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3983 # Detach interface between oldSw-host
3984 "px " + oldSw + ".detach( sintf )",
3985 # Determine hostintf and Oldpairswitchintf
3986 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
3987 # Detach interface between oldPairSw-host
3988 "px " + oldPairSw + ".detach( sintfpair )",
3989 # Add link between host-newSw
3990 "py net.addLink(" + host + "," + newSw + ", 2)",
3991 # Add link between host-newPairSw
3992 "py net.addLink(" + host + "," + newPairSw + ")",
3993 # Determine hostintf and Newswitchintf
3994 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3995 # Determine hostintf and NewPairswitchintf
3996 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
3997 # Attach interface between newSw-host
3998 "px " + newSw + ".attach( sintf )",
3999 # Attach interface between newPairSw-host
4000 "px " + newPairSw + ".attach( sintfpair )",
4001 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07004002 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004003 host + ' ip link set %s down' % newIntf,
4004 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004005 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
4006 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07004007 host + ' ip addr flush dev %s' % newIntf,
4008 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004009 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004010 "px lowestIntf = min( [ hintf, hintfpair ] )",
4011 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07004012 "px lowestIntf.name = '" + bondIntf + "'",
4013 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07004014 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
4015 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07004016 ]
4017 if vlan:
4018 vlanIntf = "%s.%s" % ( bondIntf, vlan )
4019 commands += [
4020 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
4021 host + " ip link set up %s" % vlanIntf,
4022 "px lowestIntf.name = '" + vlanIntf + "'",
4023 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
4024 ]
4025 bondIntf = vlanIntf
4026 commands += [
4027 # Set macaddress of the host-newSw interface
4028 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07004029 # Set ipaddress of the host-newSw interface
4030 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
4031 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07004032 ]
You Wang6e5b48e2018-07-23 16:17:38 -07004033 if ipv6:
4034 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
4035 commands += [
4036 "net",
4037 host + " ifconfig"
4038 ]
You Wang7ea90582018-07-19 15:27:58 -07004039 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004040 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07004041 self.handle.sendline( cmd )
4042 self.handle.expect( "mininet>" )
4043 main.log.info( "====> %s ", self.handle.before )
4044 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07004045 except pexpect.TIMEOUT:
4046 main.log.error( self.name + ": TIMEOUT exception found" )
4047 main.log.error( self.name + ": " + self.handle.before )
4048 main.cleanAndExit()
4049 except pexpect.EOF:
4050 main.log.error( self.name + ": EOF exception found" )
4051 main.log.error( self.name + ": " + self.handle.before )
4052 return main.FALSE
4053 except Exception:
4054 main.log.exception( self.name + ": Uncaught exception!" )
4055 return main.FALSE
4056
adminbae64d82013-08-01 10:50:15 -07004057if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004058 sys.modules[ __name__ ] = MininetCliDriver()