blob: 27e1bf6d703336d211be14fd3007c986ce117582 [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 Wang7d14d642019-01-23 15:10:08 -08001934 def getSwitchRandom( self, timeout=60, nonCut=True, switchClasses=None, excludeNodes=[] ):
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 Wangdb8cd0a2016-05-26 15:19:45 -07001943 Returns the name of the chosen switch.
1944 """
1945 import random
1946 candidateSwitches = []
1947 try:
1948 if not nonCut:
You Wang7d14d642019-01-23 15:10:08 -08001949 switches = self.getSwitches( timeout=timeout, switchClasses=switchClasses )
You Wangdb8cd0a2016-05-26 15:19:45 -07001950 assert len( switches ) != 0
1951 for switchName in switches.keys():
1952 candidateSwitches.append( switchName )
1953 else:
You Wang7d14d642019-01-23 15:10:08 -08001954 graphDict = self.getGraphDict( timeout=timeout, useId=False,
1955 switchClasses=switchClasses,
1956 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001957 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001958 return None
1959 self.graph.update( graphDict )
1960 candidateSwitches = self.graph.getNonCutVertices()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001961 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001962 return None
1963 elif len( candidateSwitches ) == 0:
1964 main.log.info( self.name + ": No candidate switch for deletion" )
1965 return None
1966 else:
1967 switch = random.sample( candidateSwitches, 1 )
1968 return switch[ 0 ]
1969 except KeyError:
1970 main.log.exception( self.name + ": KeyError exception found" )
1971 return None
1972 except AssertionError:
1973 main.log.exception( self.name + ": AssertionError exception found" )
1974 return None
1975 except Exception:
1976 main.log.exception( self.name + ": Uncaught exception" )
1977 return None
1978
1979 def delSwitchRandom( self, timeout=60, nonCut=True ):
1980 """
1981 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001982 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001983 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001984 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07001985 otherwise it just randomly delete one switch from all current
1986 switches in Mininet.
1987 Returns the name of the deleted switch
1988 """
1989 try:
1990 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001991 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001992 return None
1993 else:
1994 deletionResult = self.delSwitch( switch )
1995 if deletionResult:
1996 return switch
1997 else:
1998 return None
1999 except Exception:
2000 main.log.exception( self.name + ": Uncaught exception" )
2001 return None
2002
kelvin-onlabd3b64892015-01-20 13:26:24 -08002003 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002004 """
2005 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002006 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002007 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002008 NOTE: cannot currently specify what type of link
2009 required params:
2010 node1 = the string node name of the first endpoint of the link
2011 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002012 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002013 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002014 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002015 response = self.execute(
2016 cmd=command,
2017 prompt="mininet>",
2018 timeout=10 )
2019 if re.search( "doesnt exist!", response ):
2020 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002021 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002022 elif re.search( "Error", response ):
2023 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002024 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002025 elif re.search( "usage:", response ):
2026 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002027 return main.FALSE
2028 else:
2029 return main.TRUE
2030 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002031 main.log.error( self.name + ": EOF exception found" )
2032 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002033 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002034 except Exception:
2035 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002036 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002037
kelvin-onlabd3b64892015-01-20 13:26:24 -08002038 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002039 """
2040 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002041 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002042 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002043 required params:
2044 node1 = the string node name of the first endpoint of the link
2045 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002046 returns: main.FALSE on an error, else main.TRUE
2047 """
Jon Hallffb386d2014-11-21 13:43:38 -08002048 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002049 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002050 response = self.execute(
2051 cmd=command,
2052 prompt="mininet>",
2053 timeout=10 )
2054 if re.search( "no node named", response ):
2055 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002056 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002057 elif re.search( "Error", response ):
2058 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002059 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002060 elif re.search( "usage:", response ):
2061 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002062 return main.FALSE
2063 else:
2064 return main.TRUE
2065 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002066 main.log.error( self.name + ": EOF exception found" )
2067 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002068 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002069 except Exception:
2070 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002071 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002072
You Wang7d14d642019-01-23 15:10:08 -08002073 def getLinkRandom( self, timeout=60, nonCut=True, switchClasses=None, excludeNodes=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07002074 """
2075 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002076 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002077 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002078 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002079 it just randomly returns one link from all current links in
2080 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08002081 excludeNodes will be passed to getLinks method to exclude unexpected links.
You Wangdb8cd0a2016-05-26 15:19:45 -07002082 Returns the link as a list, e.g. [ 's1', 's2' ]
2083 """
2084 import random
2085 candidateLinks = []
2086 try:
2087 if not nonCut:
You Wang7d14d642019-01-23 15:10:08 -08002088 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07002089 assert len( links ) != 0
2090 for link in links:
2091 # Exclude host-switch link
2092 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2093 continue
2094 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2095 else:
You Wang7d14d642019-01-23 15:10:08 -08002096 graphDict = self.getGraphDict( timeout=timeout, useId=False,
2097 switchClasses=switchClasses,
2098 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002099 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002100 return None
2101 self.graph.update( graphDict )
2102 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002103 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002104 return None
2105 elif len( candidateLinks ) == 0:
2106 main.log.info( self.name + ": No candidate link for deletion" )
2107 return None
2108 else:
2109 link = random.sample( candidateLinks, 1 )
2110 return link[ 0 ]
2111 except KeyError:
2112 main.log.exception( self.name + ": KeyError exception found" )
2113 return None
2114 except AssertionError:
2115 main.log.exception( self.name + ": AssertionError exception found" )
2116 return None
2117 except Exception:
2118 main.log.exception( self.name + ": Uncaught exception" )
2119 return None
2120
2121 def delLinkRandom( self, timeout=60, nonCut=True ):
2122 """
2123 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002124 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002125 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002126 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002127 otherwise it just randomly delete one link from all current links
2128 in Mininet.
2129 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2130 """
2131 try:
2132 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002133 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002134 return None
2135 else:
2136 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2137 if deletionResult:
2138 return link
2139 else:
2140 return None
2141 except Exception:
2142 main.log.exception( self.name + ": Uncaught exception" )
2143 return None
2144
kelvin-onlabd3b64892015-01-20 13:26:24 -08002145 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002146 """
Jon Hallb1290e82014-11-18 16:17:48 -05002147 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002148 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002149 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002150 NOTE: cannot currently specify what type of host
2151 required params:
2152 hostname = the string hostname
2153 optional key-value params
2154 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002155 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002156 """
2157 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002158 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002159 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002160 response = self.execute(
2161 cmd=command,
2162 prompt="mininet>",
2163 timeout=10 )
2164 if re.search( "already exists!", response ):
2165 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002166 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002167 elif re.search( "doesnt exists!", response ):
2168 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002169 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002170 elif re.search( "Error", response ):
2171 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002172 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002173 elif re.search( "usage:", response ):
2174 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002175 return main.FALSE
2176 else:
2177 return main.TRUE
2178 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002179 main.log.error( self.name + ": EOF exception found" )
2180 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002181 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002182 except Exception:
2183 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002184 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002185
kelvin-onlabd3b64892015-01-20 13:26:24 -08002186 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002187 """
2188 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002189 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002190 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002191 NOTE: this uses a custom mn function
2192 required params:
2193 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002194 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002195 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002196 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002197 response = self.execute(
2198 cmd=command,
2199 prompt="mininet>",
2200 timeout=10 )
2201 if re.search( "no host named", response ):
2202 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002203 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002204 elif re.search( "Error", response ):
2205 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002206 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002207 elif re.search( "usage:", response ):
2208 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002209 return main.FALSE
2210 else:
2211 return main.TRUE
2212 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002213 main.log.error( self.name + ": EOF exception found" )
2214 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002215 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002216 except Exception:
2217 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002218 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002219
Jon Hall7eb38402015-01-08 17:19:54 -08002220 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002221 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002222 Called at the end of the test to stop the mininet and
2223 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002224 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002225 try:
2226 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002227 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002228 timeout=2 )
2229 response = main.TRUE
2230 if i == 0:
2231 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002232 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002233 return main.TRUE
2234 # print "Disconnecting Mininet"
2235 if self.handle:
2236 self.handle.sendline( "exit" )
2237 self.handle.expect( "exit" )
2238 self.handle.expect( "(.*)" )
2239 else:
2240 main.log.error( "Connection failed to the host" )
2241 return response
2242 except pexpect.EOF:
2243 main.log.error( self.name + ": EOF exception found" )
2244 main.log.error( self.name + ": " + self.handle.before )
You Wangd4fae5c2018-08-22 13:56:49 -07002245 # Do not exit the entire test when pexpect.EOF is caught
2246 # FIXME: We might need to do something else here
2247 return main.ERROR
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002248 except Exception:
2249 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002250 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002251
Devin Lima7cfdbd2017-09-29 15:02:22 -07002252 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002253 """
Jon Hall21270ac2015-02-16 17:59:55 -08002254 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002255 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002256 main.FALSE if the pexpect handle does not exist.
2257
Jon Halld61331b2015-02-17 16:35:47 -08002258 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002259 """
Jon Halld61331b2015-02-17 16:35:47 -08002260 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002261 response = ''
2262 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002263 try:
Jon Halld80cc142015-07-06 13:36:05 -07002264 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002265 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002266 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002267 pexpect.EOF,
2268 pexpect.TIMEOUT ],
2269 timeout )
2270 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002271 main.log.info( "Exiting mininet.." )
2272 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002273 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002274 prompt=self.prompt,
2275 timeout=exitTimeout )
2276 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002277 self.handle.sendline( "sudo mn -c" )
2278 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002279
Jeremyd9e4eb12016-04-13 12:09:06 -07002280 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002281 main.log.info( " Mininet trying to exit while not " +
2282 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002283 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002284 elif i == 2:
2285 main.log.error( "Something went wrong exiting mininet" )
2286 elif i == 3: # timeout
2287 main.log.error( "Something went wrong exiting mininet " +
2288 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002289
You Wang18db8592018-04-02 13:52:03 -07002290 self.handle.sendline( "" )
2291 self.handle.expect( self.prompt )
2292 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2293
Hari Krishnab35c6d02015-03-18 11:13:51 -07002294 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002295 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002296 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002297 self.handle.sendline(
2298 "sudo kill -9 \`ps -ef | grep \"" +
2299 fileName +
2300 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002301 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002302 main.log.error( self.name + ": TIMEOUT exception found" )
2303 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002304 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002305 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002306 main.log.error( self.name + ": EOF exception found" )
2307 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002308 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002309 except Exception:
2310 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002311 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002312 else:
2313 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002314 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002315 return response
2316
YPZhang26a139e2016-04-25 14:01:55 -07002317 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002318 """
2319 Description:
2320 Sends arp message from mininet host for hosts discovery
2321 Required:
2322 host - hosts name
2323 Optional:
2324 ip - ip address that does not exist in the network so there would
2325 be no reply.
2326 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002327 if ethDevice:
2328 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002329 cmd = srcHost + " arping -c1 "
2330 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002331 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 -07002332 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002333 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002334 if output:
2335 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002336 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002337 i = self.handle.expect( [ "mininet>", "arping: " ] )
2338 if i == 0:
2339 return main.TRUE
2340 elif i == 1:
2341 response = self.handle.before + self.handle.after
2342 self.handle.expect( "mininet>" )
2343 response += self.handle.before + self.handle.after
2344 main.log.warn( "Error sending arping, output was: " +
2345 response )
2346 return main.FALSE
2347 except pexpect.TIMEOUT:
2348 main.log.error( self.name + ": TIMEOUT exception found" )
2349 main.log.warn( self.handle.before )
2350 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002351 except pexpect.EOF:
2352 main.log.error( self.name + ": EOF exception found" )
2353 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002354 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002355 except Exception:
2356 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002357 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002358
Jon Hall7eb38402015-01-08 17:19:54 -08002359 def decToHex( self, num ):
2360 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002361
Jon Hall7eb38402015-01-08 17:19:54 -08002362 def getSwitchFlowCount( self, switch ):
2363 """
2364 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002365 if self.handle:
2366 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2367 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002368 response = self.execute(
2369 cmd=cmd,
2370 prompt="mininet>",
2371 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002372 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002373 main.log.error( self.name + ": EOF exception found" )
2374 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002375 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002376 except Exception:
2377 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002378 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002379 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002380 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002381 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002382 main.log.info(
2383 "Couldn't find flows on switch %s, found: %s" %
2384 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002385 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002386 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002387 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002388 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002389
Jon Hall9ed8f372016-02-24 17:34:07 -08002390 def checkFlows( self, sw, dumpFormat=None ):
2391 if dumpFormat:
2392 command = "sh ovs-ofctl -F " + \
2393 dumpFormat + " dump-flows " + str( sw )
2394 else:
2395 command = "sh ovs-ofctl dump-flows " + str( sw )
2396 try:
2397 response = self.execute(
2398 cmd=command,
2399 prompt="mininet>",
2400 timeout=10 )
2401 return response
2402 except pexpect.EOF:
2403 main.log.error( self.name + ": EOF exception found" )
2404 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002405 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002406 except Exception:
2407 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002408 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002409
GlennRC68467eb2015-11-16 18:01:01 -08002410 def flowTableComp( self, flowTable1, flowTable2 ):
2411 # This function compares the selctors and treatments of each flow
2412 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002413 assert flowTable1, "flowTable1 is empty or None"
2414 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002415 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002416 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002417 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002418 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002419 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2420 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002421 for field in dFields:
2422 try:
2423 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002424 except KeyError:
2425 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002426 try:
2427 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002428 except KeyError:
2429 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002430 for i in range( len( flowTable1 ) ):
2431 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002432 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002433 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002434 returnValue = main.FALSE
2435 break
2436 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002437 except AssertionError:
2438 main.log.exception( "Nothing to compare" )
2439 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002440 except Exception:
2441 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002442 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002443
GlennRC528ad292015-11-12 10:38:18 -08002444 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002445 '''
GlennRC956ea742015-11-05 16:14:15 -08002446 Discription: Parses flows into json format.
2447 NOTE: this can parse any string thats separated with commas
2448 Arguments:
2449 Required:
2450 flows: a list of strings that represnt flows
2451 Optional:
2452 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2453 debug: prints out the final result
2454 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002455 '''
GlennRC528ad292015-11-12 10:38:18 -08002456 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002457 try:
2458 for flow in flowTable:
2459 jsonFlow = {}
2460 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002461 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002462 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002463 for i in range( len( parsedFlow ) ):
2464 item = parsedFlow[ i ]
2465 if item[ 0 ] == " ":
2466 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002467 # grab the selector and treatment from the parsed flow
2468 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002469 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002470 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002471 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002472 index = 0
2473 # parse the flags
2474 # NOTE: This only parses one flag
2475 flag = {}
2476 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002477 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002478 index += 1
2479 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002480 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002481 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002482 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002483 # the priority is stuck in the selecter so put it back
2484 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002485 if 'priority' in sel[0]:
2486 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002487 # parse selector
2488 criteria = []
2489 for item in sel:
2490 # this is the type of the packet e.g. "arp"
2491 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002492 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002493 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002494 field = item.split( "=" )
2495 criteria.append( { field[ 0 ]: field[ 1 ] } )
2496 selector = { "selector": { "criteria": sorted( criteria ) } }
2497 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002498 # get rid of the action part e.g. "action=output:2"
2499 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002500 treat = treat.split( "=" )
2501 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002502 # parse treatment
2503 action = []
2504 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002505 if ":" in item:
2506 field = item.split( ":" )
2507 action.append( { field[ 0 ]: field[ 1 ] } )
2508 else:
2509 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2510 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002511 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002512 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002513 # parse the rest of the flow
2514 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002515 field = item.split( "=" )
2516 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002517 # add the treatment and the selector to the json flow
2518 jsonFlow.update( selector )
2519 jsonFlow.update( treatment )
2520 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002521
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002522 if debug:
2523 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002524
You Wang91c37cf2016-05-23 09:39:42 -07002525 # add the json flow to the json flow table
2526 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002527
You Wang91c37cf2016-05-23 09:39:42 -07002528 return jsonFlowTable
2529
2530 except IndexError:
2531 main.log.exception( self.name + ": IndexError found" )
2532 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002533 except pexpect.EOF:
2534 main.log.error( self.name + ": EOF exception found" )
2535 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002536 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002537 except Exception:
2538 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002539 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002540
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002541 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002542 '''
2543 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002544 Each element is a flow.
2545 Arguments:
2546 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002547 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002548 a list of switches.
2549 Optional:
2550 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2551 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002552 '''
GlennRC956ea742015-11-05 16:14:15 -08002553 try:
2554 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002555 if isinstance( sw, list ):
2556 switches.extend( sw )
2557 else:
2558 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002559
2560 flows = []
2561 for s in switches:
2562 cmd = "sh ovs-ofctl dump-flows " + s
2563
GlennRC528ad292015-11-12 10:38:18 -08002564 if "1.0" == version:
2565 cmd += " -F OpenFlow10-table_id"
2566 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002567 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002568
2569 main.log.info( "Sending: " + cmd )
2570 self.handle.sendline( cmd )
2571 self.handle.expect( "mininet>" )
2572 response = self.handle.before
2573 response = response.split( "\r\n" )
2574 # dump the first two elements and the last
2575 # the first element is the command that was sent
2576 # the second is the table header
2577 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002578 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002579 flows.extend( response )
2580
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002581 if debug:
2582 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002583
GlennRC528ad292015-11-12 10:38:18 -08002584 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002585
GlennRC956ea742015-11-05 16:14:15 -08002586 except pexpect.EOF:
2587 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002588 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002589 except Exception:
2590 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002591 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002592
2593 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002594 '''
GlennRC956ea742015-11-05 16:14:15 -08002595 Discription: Checks whether the ID provided matches a flow ID in Mininet
2596 Arguments:
2597 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002598 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002599 a list of switches.
2600 flowId: the flow ID in hex format. Can also be a list of IDs
2601 Optional:
2602 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2603 debug: prints out the final result
2604 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2605 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002606 '''
GlennRC956ea742015-11-05 16:14:15 -08002607 try:
2608 main.log.info( "Getting flows from Mininet" )
2609 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002610 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002611 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002612
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002613 if debug:
2614 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002615
2616 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002617 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002618 result = False
2619 for f in flows:
2620 if flowId in f.get( 'cookie' ):
2621 result = True
2622 break
2623 # flowId is a list
2624 else:
2625 result = True
2626 # Get flow IDs from Mininet
2627 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2628 # Save the IDs that are not in Mininet
2629 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2630
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002631 if debug:
2632 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002633
2634 # Print out the IDs that are not in Mininet
2635 if absentIds:
2636 main.log.warn( "Absent ids: {}".format( absentIds ) )
2637 result = False
2638
2639 return main.TRUE if result else main.FALSE
2640
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002641 except pexpect.EOF:
2642 main.log.error( self.name + ": EOF exception found" )
2643 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002644 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002645 except Exception:
2646 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002647 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002648
Charles Chan029be652015-08-24 01:46:10 +08002649 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002650 """
Jon Hallefbd9792015-03-05 16:11:36 -08002651 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002652 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002653 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002654 self.handle.sendline( "" )
2655 self.handle.expect( "mininet>" )
2656 self.handle.sendline(
2657 "sh sudo tcpdump -n -i " +
2658 intf +
2659 " " +
2660 port +
2661 " -w " +
2662 filename.strip() +
2663 " &" )
2664 self.handle.sendline( "" )
2665 i = self.handle.expect( [ 'No\ssuch\device',
2666 'listening\son',
2667 pexpect.TIMEOUT,
2668 "mininet>" ],
2669 timeout=10 )
2670 main.log.warn( self.handle.before + self.handle.after )
2671 self.handle.sendline( "" )
2672 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002673 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002674 main.log.error(
2675 self.name +
2676 ": tcpdump - No such device exists. " +
2677 "tcpdump attempted on: " +
2678 intf )
admin2a9548d2014-06-17 14:08:07 -07002679 return main.FALSE
2680 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002681 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002682 return main.TRUE
2683 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002684 main.log.error(
2685 self.name +
2686 ": tcpdump command timed out! Check interface name," +
2687 " given interface was: " +
2688 intf )
admin2a9548d2014-06-17 14:08:07 -07002689 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002690 elif i == 3:
2691 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002692 return main.TRUE
2693 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002694 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002695 return main.FALSE
2696 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002697 main.log.error( self.name + ": EOF exception found" )
2698 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002699 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002700 except Exception:
2701 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002702 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002703
kelvin-onlabd3b64892015-01-20 13:26:24 -08002704 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002705 """
2706 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002707 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002708 self.handle.sendline( "sh sudo pkill tcpdump" )
2709 self.handle.expect( "mininet>" )
2710 self.handle.sendline( "" )
2711 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002712 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002713 main.log.error( self.name + ": TIMEOUT exception found" )
2714 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002715 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002716 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002717 main.log.error( self.name + ": EOF exception found" )
2718 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002719 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002720 except Exception:
2721 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002722 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002723
Jon Halld80cc142015-07-06 13:36:05 -07002724 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002725 """
2726 Read ports from a Mininet switch.
2727
2728 Returns a json structure containing information about the
2729 ports of the given switch.
2730 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002731 try:
2732 response = self.getInterfaces( nodeName )
2733 # TODO: Sanity check on response. log if no such switch exists
2734 ports = []
2735 for line in response.split( "\n" ):
2736 if not line.startswith( "name=" ):
2737 continue
2738 portVars = {}
2739 for var in line.split( "," ):
2740 key, value = var.split( "=" )
2741 portVars[ key ] = value
2742 isUp = portVars.pop( 'enabled', "True" )
2743 isUp = "True" in isUp
2744 if verbose:
2745 main.log.info( "Reading switch port %s(%s)" %
2746 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2747 mac = portVars[ 'mac' ]
2748 if mac == 'None':
2749 mac = None
2750 ips = []
2751 ip = portVars[ 'ip' ]
2752 if ip == 'None':
2753 ip = None
2754 ips.append( ip )
2755 name = portVars[ 'name' ]
2756 if name == 'None':
2757 name = None
2758 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2759 if name == 'lo':
2760 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2761 else:
2762 portNo = re.search( portRe, name ).group( 'port' )
2763 ports.append( { 'of_port': portNo,
2764 'mac': str( mac ).replace( '\'', '' ),
2765 'name': name,
2766 'ips': ips,
2767 'enabled': isUp } )
2768 return ports
2769 except pexpect.EOF:
2770 main.log.error( self.name + ": EOF exception found" )
2771 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002772 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002773 except Exception:
2774 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002775 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002776
You Wangdb8cd0a2016-05-26 15:19:45 -07002777 def getOVSPorts( self, nodeName ):
2778 """
2779 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2780
2781 Returns a list of dictionaries containing information about each
2782 port of the given switch.
2783 """
2784 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2785 try:
2786 response = self.execute(
2787 cmd=command,
2788 prompt="mininet>",
You Wang7d14d642019-01-23 15:10:08 -08002789 timeout=10,
2790 logCmd=False )
You Wangdb8cd0a2016-05-26 15:19:45 -07002791 ports = []
2792 if response:
2793 for line in response.split( "\n" ):
2794 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2795 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002796 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002797 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2798 result = re.search( pattern, line )
2799 if result:
2800 index = result.group( 'index' )
2801 name = result.group( 'name' )
2802 # This port number is extracted from port name
2803 port = result.group( 'port' )
2804 mac = result.group( 'mac' )
2805 ports.append( { 'index': index,
2806 'name': name,
2807 'port': port,
2808 'mac': mac } )
2809 return ports
2810 except pexpect.EOF:
2811 main.log.error( self.name + ": EOF exception found" )
2812 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002813 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002814 except Exception:
2815 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002816 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002817
You Wang7d14d642019-01-23 15:10:08 -08002818 def getSwitches( self, verbose=False, updateTimeout=1000, switchClasses=None ):
Jon Hallafa8a472015-06-12 14:02:42 -07002819 """
2820 Read switches from Mininet.
2821
2822 Returns a dictionary whose keys are the switch names and the value is
2823 a dictionary containing information about the switch.
2824 """
Jon Halla22481b2015-07-28 17:46:01 -07002825 # NOTE: To support new Mininet switch classes, just append the new
2826 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002827
Jon Halla22481b2015-07-28 17:46:01 -07002828 # Regex patterns to parse 'dump' output
2829 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002830 # <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 -07002831 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002832 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2833 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2834 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
You Wang7d14d642019-01-23 15:10:08 -08002835 if not switchClasses:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002836 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
You Wang7d14d642019-01-23 15:10:08 -08002837 try:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002838 swRE = r"<(?P<class>" + switchClasses + r")" +\
2839 r"(?P<options>\{.*\})?\s" +\
2840 r"(?P<name>[^:]+)\:\s" +\
2841 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2842 r"\spid=(?P<pid>(\d)+)"
2843 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002844 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002845 output = {}
2846 dump = self.dump().split( "\n" )
2847 for line in dump:
2848 result = re.search( swRE, line, re.I )
2849 if result:
2850 name = result.group( 'name' )
2851 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2852 pid = result.group( 'pid' )
2853 swClass = result.group( 'class' )
2854 options = result.group( 'options' )
2855 if verbose:
2856 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2857 ports = self.getPorts( name )
2858 output[ name ] = { "dpid": dpid,
2859 "ports": ports,
2860 "swClass": swClass,
2861 "pid": pid,
2862 "options": options }
2863 return output
2864 except pexpect.EOF:
2865 main.log.error( self.name + ": EOF exception found" )
2866 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002867 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002868 except Exception:
2869 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002870 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002871
You Wangd66de192018-04-30 17:30:12 -07002872 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002873 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2874 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002875 """
2876 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002877 Optional:
2878 hostClass: it is used to match the class of the mininet host. It
2879 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002880 Returns a dictionary whose keys are the host names and the value is
2881 a dictionary containing information about the host.
2882 """
2883 # Regex patterns to parse dump output
2884 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002885 # <Host h1: pid=12725>
2886 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2887 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2888 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002889 # NOTE: Does not correctly match hosts with multi-links
2890 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2891 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002892 try:
You Wang53dba1e2018-02-02 17:45:44 -08002893 if not isinstance( hostClass, types.ListType ):
2894 hostClass = [ str( hostClass ) ]
2895 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002896 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2897 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2898 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002899 if update:
2900 # update mn port info
2901 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002902 # Get mininet dump
2903 dump = self.dump().split( "\n" )
2904 hosts = {}
2905 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002906 result = re.search( hostRE, line )
2907 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002908 name = result.group( 'name' )
2909 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002910 if getInterfaces:
2911 response = self.getInterfaces( name )
2912 # Populate interface info
2913 for line in response.split( "\n" ):
2914 if line.startswith( "name=" ):
2915 portVars = {}
2916 for var in line.split( "," ):
2917 key, value = var.split( "=" )
2918 portVars[ key ] = value
2919 isUp = portVars.pop( 'enabled', "True" )
2920 isUp = "True" in isUp
2921 if verbose:
2922 main.log.info( "Reading host port %s(%s)" %
2923 ( portVars[ 'name' ],
2924 portVars[ 'mac' ] ) )
2925 mac = portVars[ 'mac' ]
2926 if mac == 'None':
2927 mac = None
2928 ips = []
2929 ip = portVars[ 'ip' ]
2930 if ip == 'None':
2931 ip = None
2932 ips.append( ip )
2933 intfName = portVars[ 'name' ]
2934 if name == 'None':
2935 name = None
2936 interfaces.append( {
2937 "name": intfName,
2938 "ips": ips,
2939 "mac": str( mac ),
2940 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002941 hosts[ name ] = { "interfaces": interfaces }
2942 return hosts
2943 except pexpect.EOF:
2944 main.log.error( self.name + ": EOF exception found" )
2945 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002946 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002947 except Exception:
2948 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002949 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002950
You Wang7d14d642019-01-23 15:10:08 -08002951 def getLinks( self, timeout=20, updateTimeout=1000, excludeNodes=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002952 """
2953 Gathers information about current Mininet links. These links may not
2954 be up if one of the ports is down.
2955
2956 Returns a list of dictionaries with link endpoints.
2957
2958 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002959 { 'node1': str( node1 name )
2960 'node2': str( node2 name )
2961 'port1': str( port1 of_port )
2962 'port2': str( port2 of_port ) }
You Wang7d14d642019-01-23 15:10:08 -08002963
2964 If either node1 or node2 name starts with any of the strings sepcified
2965 in excludeNodes, the link will be excluded from the returned value
2966
Jon Hallafa8a472015-06-12 14:02:42 -07002967 Note: The port number returned is the eth#, not necessarily the of_port
2968 number. In Mininet, for OVS switch, these should be the same. For
2969 hosts, this is just the eth#.
2970 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002971 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002972 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002973 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002974
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002975 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002976 # s1-eth3<->s2-eth1 (OK OK)
2977 # s13-eth3<->h27-eth0 (OK OK)
You Wang7d14d642019-01-23 15:10:08 -08002978 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d\.]+)\<\-\>" +\
2979 "(?P<node2>[\w]+)\-eth(?P<port2>[\d\.]+)"
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002980 links = []
2981 for line in response:
2982 match = re.search( linkRE, line )
2983 if match:
2984 node1 = match.group( 'node1' )
2985 node2 = match.group( 'node2' )
You Wang7d14d642019-01-23 15:10:08 -08002986 if any( node1.startswith( node ) for node in excludeNodes ) or \
2987 any( node2.startswith( node ) for node in excludeNodes ):
2988 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002989 port1 = match.group( 'port1' )
2990 port2 = match.group( 'port2' )
2991 links.append( { 'node1': node1,
2992 'node2': node2,
2993 'port1': port1,
2994 'port2': port2 } )
2995 return links
2996
2997 except pexpect.EOF:
2998 main.log.error( self.name + ": EOF exception found" )
2999 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003000 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003001 except Exception:
3002 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003003 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003004
3005 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003006 """
3007 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003008 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003009
Jon Hallafa8a472015-06-12 14:02:42 -07003010 Dependencies:
3011 1. numpy - "sudo pip install numpy"
3012 """
3013 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003014 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003015 try:
3016 mnDPIDs = []
3017 for swName, switch in switches.iteritems():
3018 mnDPIDs.append( switch[ 'dpid' ].lower() )
3019 mnDPIDs.sort()
3020 if switchesJson == "": # if rest call fails
3021 main.log.error(
3022 self.name +
3023 ".compareSwitches(): Empty JSON object given from ONOS" )
3024 return main.FALSE
3025 onos = switchesJson
3026 onosDPIDs = []
3027 for switch in onos:
3028 if switch[ 'available' ]:
3029 onosDPIDs.append(
3030 switch[ 'id' ].replace(
3031 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003032 '' ).replace(
3033 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003034 '' ).lower() )
3035 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003036
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003037 if mnDPIDs != onosDPIDs:
3038 switchResults = main.FALSE
3039 main.log.error( "Switches in MN but not in ONOS:" )
3040 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3041 main.log.error( str( list1 ) )
3042 main.log.error( "Switches in ONOS but not in MN:" )
3043 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3044 main.log.error( str( list2 ) )
3045 else: # list of dpid's match in onos and mn
3046 switchResults = main.TRUE
3047 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003048
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003049 # FIXME: this does not look for extra ports in ONOS, only checks that
3050 # ONOS has what is in MN
3051 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003052
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003053 # PORTS
3054 for name, mnSwitch in switches.iteritems():
3055 mnPorts = []
3056 onosPorts = []
3057 switchResult = main.TRUE
3058 for port in mnSwitch[ 'ports' ]:
3059 if port[ 'enabled' ]:
3060 mnPorts.append( int( port[ 'of_port' ] ) )
3061 for onosSwitch in portsJson:
3062 if onosSwitch[ 'device' ][ 'available' ]:
3063 if onosSwitch[ 'device' ][ 'id' ].replace(
3064 ':',
3065 '' ).replace(
3066 "of",
3067 '' ) == mnSwitch[ 'dpid' ]:
3068 for port in onosSwitch[ 'ports' ]:
3069 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003070 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003071 # onosPorts.append( 'local' )
3072 onosPorts.append( long( uint64( -2 ) ) )
3073 else:
3074 onosPorts.append( int( port[ 'port' ] ) )
3075 break
3076 mnPorts.sort( key=float )
3077 onosPorts.sort( key=float )
3078
3079 mnPortsLog = mnPorts
3080 onosPortsLog = onosPorts
3081 mnPorts = [ x for x in mnPorts ]
3082 onosPorts = [ x for x in onosPorts ]
3083
3084 # TODO: handle other reserved port numbers besides LOCAL
3085 # NOTE: Reserved ports
3086 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3087 # long( uint64( -2 ) )
3088 for mnPort in mnPortsLog:
3089 if mnPort in onosPorts:
3090 # don't set results to true here as this is just one of
3091 # many checks and it might override a failure
3092 mnPorts.remove( mnPort )
3093 onosPorts.remove( mnPort )
3094
3095 # NOTE: OVS reports this as down since there is no link
3096 # So ignoring these for now
3097 # TODO: Come up with a better way of handling these
3098 if 65534 in mnPorts:
3099 mnPorts.remove( 65534 )
3100 if long( uint64( -2 ) ) in onosPorts:
3101 onosPorts.remove( long( uint64( -2 ) ) )
3102 if len( mnPorts ): # the ports of this switch don't match
3103 switchResult = main.FALSE
3104 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3105 if len( onosPorts ): # the ports of this switch don't match
3106 switchResult = main.FALSE
3107 main.log.warn(
3108 "Ports in ONOS but not MN: " +
3109 str( onosPorts ) )
3110 if switchResult == main.FALSE:
3111 main.log.error(
3112 "The list of ports for switch %s(%s) does not match:" %
3113 ( name, mnSwitch[ 'dpid' ] ) )
3114 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3115 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3116 portsResults = portsResults and switchResult
3117 finalResults = finalResults and portsResults
3118 return finalResults
3119 except pexpect.EOF:
3120 main.log.error( self.name + ": EOF exception found" )
3121 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003122 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003123 except Exception:
3124 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003125 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003126
Jon Hallafa8a472015-06-12 14:02:42 -07003127 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003128 """
3129 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003130 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003131
Jon Hallafa8a472015-06-12 14:02:42 -07003132 """
Jon Hall7eb38402015-01-08 17:19:54 -08003133 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003134 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003135 try:
3136 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003137
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003138 mnLinks = []
3139 for l in links:
3140 try:
3141 node1 = switches[ l[ 'node1' ] ]
3142 node2 = switches[ l[ 'node2' ] ]
3143 enabled = True
3144 for port in node1[ 'ports' ]:
3145 if port[ 'of_port' ] == l[ 'port1' ]:
3146 enabled = enabled and port[ 'enabled' ]
3147 for port in node2[ 'ports' ]:
3148 if port[ 'of_port' ] == l[ 'port2' ]:
3149 enabled = enabled and port[ 'enabled' ]
3150 if enabled:
3151 mnLinks.append( l )
3152 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003153 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003154 if 2 * len( mnLinks ) == len( onos ):
3155 linkResults = main.TRUE
3156 else:
3157 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003158 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003159 "Mininet has " + str( len( mnLinks ) ) +
3160 " bidirectional links and ONOS has " +
3161 str( len( onos ) ) + " unidirectional links" )
3162
3163 # iterate through MN links and check if an ONOS link exists in
3164 # both directions
3165 for link in mnLinks:
3166 # TODO: Find a more efficient search method
3167 node1 = None
3168 port1 = None
3169 node2 = None
3170 port2 = None
3171 firstDir = main.FALSE
3172 secondDir = main.FALSE
3173 for swName, switch in switches.iteritems():
3174 if swName == link[ 'node1' ]:
3175 node1 = switch[ 'dpid' ]
3176 for port in switch[ 'ports' ]:
3177 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3178 port1 = port[ 'of_port' ]
3179 if node1 is not None and node2 is not None:
3180 break
3181 if swName == link[ 'node2' ]:
3182 node2 = switch[ 'dpid' ]
3183 for port in switch[ 'ports' ]:
3184 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3185 port2 = port[ 'of_port' ]
3186 if node1 is not None and node2 is not None:
3187 break
3188
3189 for onosLink in onos:
3190 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3191 ":", '' ).replace( "of", '' )
3192 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3193 ":", '' ).replace( "of", '' )
3194 onosPort1 = onosLink[ 'src' ][ 'port' ]
3195 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3196
3197 # check onos link from node1 to node2
3198 if str( onosNode1 ) == str( node1 ) and str(
3199 onosNode2 ) == str( node2 ):
3200 if int( onosPort1 ) == int( port1 ) and int(
3201 onosPort2 ) == int( port2 ):
3202 firstDir = main.TRUE
3203 else:
Jon Hallab611372018-02-21 15:26:05 -08003204 # The right switches, but wrong ports, could be
3205 # another link between these devices, or onos
3206 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003207 main.log.warn(
3208 'The port numbers do not match for ' +
3209 str( link ) +
3210 ' between ONOS and MN. When checking ONOS for ' +
3211 'link %s/%s -> %s/%s' %
3212 ( node1, port1, node2, port2 ) +
3213 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003214 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3215 '. This could be another link between these devices' +
3216 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003217
3218 # check onos link from node2 to node1
3219 elif ( str( onosNode1 ) == str( node2 ) and
3220 str( onosNode2 ) == str( node1 ) ):
3221 if ( int( onosPort1 ) == int( port2 )
3222 and int( onosPort2 ) == int( port1 ) ):
3223 secondDir = main.TRUE
3224 else:
Jon Hallab611372018-02-21 15:26:05 -08003225 # The right switches, but wrong ports, could be
3226 # another link between these devices, or onos
3227 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003228 main.log.warn(
3229 'The port numbers do not match for ' +
3230 str( link ) +
3231 ' between ONOS and MN. When checking ONOS for ' +
3232 'link %s/%s -> %s/%s' %
3233 ( node1, port1, node2, port2 ) +
3234 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003235 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3236 '. This could be another link between these devices' +
3237 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003238 else: # this is not the link you're looking for
3239 pass
3240 if not firstDir:
3241 main.log.error(
3242 'ONOS does not have the link %s/%s -> %s/%s' %
3243 ( node1, port1, node2, port2 ) )
3244 if not secondDir:
3245 main.log.error(
3246 'ONOS does not have the link %s/%s -> %s/%s' %
3247 ( node2, port2, node1, port1 ) )
3248 linkResults = linkResults and firstDir and secondDir
3249 return linkResults
3250 except pexpect.EOF:
3251 main.log.error( self.name + ": EOF exception found" )
3252 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003253 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003254 except Exception:
3255 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003256 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003257
Jon Hallafa8a472015-06-12 14:02:42 -07003258 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003259 """
Jon Hallafa8a472015-06-12 14:02:42 -07003260 Compare mn and onos Hosts.
3261 Since Mininet hosts are quiet, ONOS will only know of them when they
3262 speak. For this reason, we will only check that the hosts in ONOS
3263 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003264
Jon Hallafa8a472015-06-12 14:02:42 -07003265 Arguments:
3266 hostsJson: parsed json object from the onos hosts api
3267 Returns:
3268 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003269 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003270 try:
3271 hostResults = main.TRUE
3272 for onosHost in hostsJson:
3273 onosMAC = onosHost[ 'mac' ].lower()
3274 match = False
3275 for mnHost, info in hosts.iteritems():
3276 for mnIntf in info[ 'interfaces' ]:
3277 if onosMAC == mnIntf[ 'mac' ].lower():
3278 match = True
3279 for ip in mnIntf[ 'ips' ]:
3280 if ip in onosHost[ 'ipAddresses' ]:
3281 pass # all is well
3282 else:
3283 # misssing ip
3284 main.log.error( "ONOS host " +
3285 onosHost[ 'id' ] +
3286 " has a different IP(" +
3287 str( onosHost[ 'ipAddresses' ] ) +
3288 ") than the Mininet host(" +
3289 str( ip ) +
3290 ")." )
3291 output = json.dumps(
3292 onosHost,
3293 sort_keys=True,
3294 indent=4,
3295 separators=( ',', ': ' ) )
3296 main.log.info( output )
3297 hostResults = main.FALSE
3298 if not match:
3299 hostResults = main.FALSE
3300 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3301 "corresponding Mininet host." )
3302 output = json.dumps( onosHost,
3303 sort_keys=True,
3304 indent=4,
3305 separators=( ',', ': ' ) )
3306 main.log.info( output )
3307 return hostResults
3308 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003309 main.log.error( self.name + ": EOF exception found" )
3310 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003311 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003312 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003313 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003314 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003315
You Wangd66de192018-04-30 17:30:12 -07003316 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003317 """
3318 Description:
3319 Verify that all hosts have IP address assigned to them
3320 Optional:
3321 hostList: If specified, verifications only happen to the hosts
3322 in hostList
3323 prefix: at least one of the ip address assigned to the host
3324 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003325 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003326 Returns:
3327 main.TRUE if all hosts have specific IP address assigned;
3328 main.FALSE otherwise
3329 """
3330 try:
You Wangd66de192018-04-30 17:30:12 -07003331 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003332 if not hostList:
3333 hostList = hosts.keys()
3334 for hostName in hosts.keys():
3335 if hostName not in hostList:
3336 continue
3337 ipList = []
3338 self.handle.sendline( str( hostName ) + " ip a" )
3339 self.handle.expect( "mininet>" )
3340 ipa = self.handle.before
3341 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3342 ipList += re.findall( ipv4Pattern, ipa )
3343 # It's tricky to make regex for IPv6 addresses and this one is simplified
3344 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})/'
3345 ipList += re.findall( ipv6Pattern, ipa )
3346 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3347 if not ipList:
3348 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3349 else:
3350 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3351 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3352 else:
3353 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3354 hostList.remove( hostName )
3355 return main.FALSE if hostList else main.TRUE
3356 except KeyError:
3357 main.log.exception( self.name + ": host data not as expected: " + hosts )
3358 return None
3359 except pexpect.EOF:
3360 main.log.error( self.name + ": EOF exception found" )
3361 main.log.error( self.name + ": " + self.handle.before )
3362 main.cleanAndExit()
3363 except Exception:
3364 main.log.exception( self.name + ": Uncaught exception" )
3365 return None
3366
Jon Hallafa8a472015-06-12 14:02:42 -07003367 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003368 """
3369 Returns a list of all hosts
3370 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003371 try:
3372 self.handle.sendline( "" )
3373 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003374
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003375 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3376 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003377
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003378 handlePy = self.handle.before
3379 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3380 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003381
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003382 self.handle.sendline( "" )
3383 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003384
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003385 hostStr = handlePy.replace( "]", "" )
3386 hostStr = hostStr.replace( "'", "" )
3387 hostStr = hostStr.replace( "[", "" )
3388 hostStr = hostStr.replace( " ", "" )
3389 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003390
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003391 return hostList
3392 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003393 main.log.error( self.name + ": TIMEOUT exception found" )
3394 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003395 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003396 except pexpect.EOF:
3397 main.log.error( self.name + ": EOF exception found" )
3398 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003399 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003400 except Exception:
3401 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003402 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003403
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003404 def getSwitch( self ):
3405 """
3406 Returns a list of all switches
3407 Again, don't ask question just use it...
3408 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003409 try:
3410 # get host list...
3411 hostList = self.getHosts()
3412 # Make host set
3413 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003414
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003415 # Getting all the nodes in mininet
3416 self.handle.sendline( "" )
3417 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003418
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003419 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3420 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003421
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003422 handlePy = self.handle.before
3423 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3424 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003425
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003426 self.handle.sendline( "" )
3427 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003428
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003429 nodesStr = handlePy.replace( "]", "" )
3430 nodesStr = nodesStr.replace( "'", "" )
3431 nodesStr = nodesStr.replace( "[", "" )
3432 nodesStr = nodesStr.replace( " ", "" )
3433 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003434
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003435 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003436 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003437 nodesSet.discard( 'c0' )
3438 nodesSet.discard( 'c1' )
3439 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003440
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003441 switchSet = nodesSet - hostSet
3442 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003443
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003444 return switchList
3445 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003446 main.log.error( self.name + ": TIMEOUT exception found" )
3447 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003448 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003449 except pexpect.EOF:
3450 main.log.error( self.name + ": EOF exception found" )
3451 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003452 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003453 except Exception:
3454 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003455 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003456
You Wang7d14d642019-01-23 15:10:08 -08003457 def getGraphDict( self, timeout=60, useId=True, includeHost=False,
3458 switchClasses=None, excludeNodes=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07003459 """
3460 Return a dictionary which describes the latest Mininet topology data as a
3461 graph.
3462 An example of the dictionary:
3463 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3464 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3465 Each vertex should at least have an 'edges' attribute which describes the
3466 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003467 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003468 list of attributes.
3469 An example of the edges dictionary:
3470 'edges': { vertex2: { 'port': ..., 'weight': ... },
3471 vertex3: { 'port': ..., 'weight': ... } }
3472 If useId == True, dpid/mac will be used instead of names to identify
3473 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3474 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003475 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003476 in topology data.
You Wang7d14d642019-01-23 15:10:08 -08003477 if switchClasses == None, default switchClasses will be used when calling
3478 getSwitches method.
3479 excludeNodes will be passed to getLinks method to exclude unexpected links.
You Wangdb8cd0a2016-05-26 15:19:45 -07003480 Note that link or switch that are brought down by 'link x x down' or 'switch
3481 x down' commands still show in the output of Mininet CLI commands such as
3482 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3483 recommended to use delLink() or delSwitch functions to simulate link/switch
3484 down, and addLink() or addSwitch to add them back.
3485 """
3486 graphDict = {}
3487 try:
You Wang7d14d642019-01-23 15:10:08 -08003488 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003489 portDict = {}
You Wang7d14d642019-01-23 15:10:08 -08003490 switches = self.getSwitches( switchClasses=switchClasses )
You Wangdb8cd0a2016-05-26 15:19:45 -07003491 if includeHost:
3492 hosts = self.getHosts()
3493 for link in links:
3494 # FIXME: support 'includeHost' argument
3495 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3496 continue
3497 nodeName1 = link[ 'node1' ]
3498 nodeName2 = link[ 'node2' ]
You Wang7d14d642019-01-23 15:10:08 -08003499 if not self.getOVSPorts( nodeName1 ) or not self.getOVSPorts( nodeName2 ):
3500 # The device is probably offline
3501 continue
You Wangdb8cd0a2016-05-26 15:19:45 -07003502 port1 = link[ 'port1' ]
3503 port2 = link[ 'port2' ]
3504 # Loop for two nodes
3505 for i in range( 2 ):
3506 # Get port index from OVS
3507 # The index extracted from port name may be inconsistent with ONOS
3508 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003509 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003510 portList = self.getOVSPorts( nodeName1 )
3511 if len( portList ) == 0:
3512 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3513 return None
3514 portDict[ nodeName1 ] = portList
3515 for port in portDict[ nodeName1 ]:
3516 if port[ 'port' ] == port1:
3517 portIndex = port[ 'index' ]
3518 break
3519 if portIndex == -1:
3520 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3521 return None
3522 if useId:
3523 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3524 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3525 else:
3526 node1 = nodeName1
3527 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003528 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003529 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003530 graphDict[ node1 ] = { 'edges': {},
3531 'dpid': switches[ nodeName1 ][ 'dpid' ],
3532 'name': nodeName1,
3533 'ports': switches[ nodeName1 ][ 'ports' ],
3534 'swClass': switches[ nodeName1 ][ 'swClass' ],
3535 'pid': switches[ nodeName1 ][ 'pid' ],
3536 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003537 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003538 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003539 else:
3540 # Assert node2 is not connected to any current links of node1
You Wang7d14d642019-01-23 15:10:08 -08003541 # assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
3542 pass
3543 for port in switches[ nodeName1 ][ 'ports' ]:
3544 if port[ 'of_port' ] == str( portIndex ):
3545 # Use -1 as index for disabled port
3546 if port[ 'enabled' ] == True:
3547 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
3548 else:
3549 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': -1 }
You Wangdb8cd0a2016-05-26 15:19:45 -07003550 # Swap two nodes/ports
3551 nodeName1, nodeName2 = nodeName2, nodeName1
3552 port1, port2 = port2, port1
You Wang7d14d642019-01-23 15:10:08 -08003553 # Remove links with disabled ports
3554 linksToRemove = []
3555 for node, edges in graphDict.items():
3556 for neighbor, port in edges[ 'edges' ].items():
3557 if port[ 'port' ] == -1:
3558 linksToRemove.append( ( node, neighbor ) )
3559 for node1, node2 in linksToRemove:
3560 for i in range( 2 ):
3561 if graphDict.get( node1 )[ 'edges' ].get( node2 ):
3562 graphDict[ node1 ][ 'edges' ].pop( node2 )
3563 node1, node2 = node2, node1
You Wangdb8cd0a2016-05-26 15:19:45 -07003564 return graphDict
3565 except KeyError:
3566 main.log.exception( self.name + ": KeyError exception found" )
3567 return None
3568 except AssertionError:
3569 main.log.exception( self.name + ": AssertionError exception found" )
3570 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003571 except pexpect.EOF:
3572 main.log.error( self.name + ": EOF exception found" )
3573 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003574 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003575 except Exception:
3576 main.log.exception( self.name + ": Uncaught exception" )
3577 return None
3578
Devin Lima7cfdbd2017-09-29 15:02:22 -07003579 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003580 """
3581 updates the port address and status information for
3582 each port in mn"""
3583 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003584 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003585 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003586 self.handle.sendline( "" )
3587 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003588
Jon Hall7eb38402015-01-08 17:19:54 -08003589 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003590 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003591
Jon Hall7eb38402015-01-08 17:19:54 -08003592 self.handle.sendline( "" )
3593 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003594
Jon Hallb1290e82014-11-18 16:17:48 -05003595 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003596 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003597 main.log.error( self.name + ": TIMEOUT exception found" )
3598 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003599 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003600 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003601 main.log.error( self.name + ": EOF exception found" )
3602 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003603 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003604 except Exception:
3605 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003606 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003607
Jon Halld80cc142015-07-06 13:36:05 -07003608 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003609 """
3610 Add vlan tag to a host.
3611 Dependencies:
3612 This class depends on the "vlan" package
3613 $ sudo apt-get install vlan
3614 Configuration:
3615 Load the 8021q module into the kernel
3616 $sudo modprobe 8021q
3617
3618 To make this setup permanent:
3619 $ sudo su -c 'echo "8021q" >> /etc/modules'
3620 """
3621 if self.handle:
3622 try:
Jon Halld80cc142015-07-06 13:36:05 -07003623 # get the ip address of the host
3624 main.log.info( "Get the ip address of the host" )
3625 ipaddr = self.getIPAddress( host )
3626 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003627
Jon Halld80cc142015-07-06 13:36:05 -07003628 # remove IP from interface intf
3629 # Ex: h1 ifconfig h1-eth0 inet 0
3630 main.log.info( "Remove IP from interface " )
3631 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3632 self.handle.sendline( cmd2 )
3633 self.handle.expect( "mininet>" )
3634 response = self.handle.before
3635 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003636
Jon Halld80cc142015-07-06 13:36:05 -07003637 # create VLAN interface
3638 # Ex: h1 vconfig add h1-eth0 100
3639 main.log.info( "Create Vlan" )
3640 cmd3 = host + " vconfig add " + intf + " " + vlan
3641 self.handle.sendline( cmd3 )
3642 self.handle.expect( "mininet>" )
3643 response = self.handle.before
3644 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003645
Jon Halld80cc142015-07-06 13:36:05 -07003646 # assign the host's IP to the VLAN interface
3647 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3648 main.log.info( "Assign the host IP to the vlan interface" )
3649 vintf = intf + "." + vlan
3650 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3651 self.handle.sendline( cmd4 )
3652 self.handle.expect( "mininet>" )
3653 response = self.handle.before
3654 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003655
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003656 # update Mininet node variables
3657 main.log.info( "Update Mininet node variables" )
3658 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3659 self.handle.sendline( cmd5 )
3660 self.handle.expect( "mininet>" )
3661 response = self.handle.before
3662 main.log.info( "====> %s ", response )
3663
3664 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3665 self.handle.sendline( cmd6 )
3666 self.handle.expect( "mininet>" )
3667 response = self.handle.before
3668 main.log.info( "====> %s ", response )
3669
3670 return main.TRUE
3671 except pexpect.TIMEOUT:
3672 main.log.error( self.name + ": TIMEOUT exception found" )
3673 main.log.error( self.name + ": " + self.handle.before )
3674 main.cleanAndExit()
3675 except pexpect.EOF:
3676 main.log.error( self.name + ": EOF exception found" )
3677 main.log.error( self.name + ": " + self.handle.before )
3678 return main.FALSE
3679 except Exception:
3680 main.log.exception( self.name + ": Uncaught exception!" )
3681 return main.FALSE
3682
3683 def removeVLAN( self, host, intf ):
3684 """
3685 Remove vlan tag from a host.
3686 Dependencies:
3687 This class depends on the "vlan" package
3688 $ sudo apt-get install vlan
3689 Configuration:
3690 Load the 8021q module into the kernel
3691 $sudo modprobe 8021q
3692
3693 To make this setup permanent:
3694 $ sudo su -c 'echo "8021q" >> /etc/modules'
3695 """
3696 if self.handle:
3697 try:
3698 # get the ip address of the host
3699 main.log.info( "Get the ip address of the host" )
3700 ipaddr = self.getIPAddress( host )
3701
3702 # remove VLAN interface
3703 # Ex: h1 vconfig rem h1-eth0.100
3704 main.log.info( "Remove Vlan interface" )
3705 cmd2 = host + " vconfig rem " + intf
3706 self.handle.sendline( cmd2 )
3707 self.handle.expect( "mininet>" )
3708 response = self.handle.before
3709 main.log.info( "====> %s ", response )
3710
3711 # assign the host's IP to the original interface
3712 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3713 main.log.info( "Assign the host IP to the original interface" )
3714 original_intf = intf.split(".")[0]
3715 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3716 self.handle.sendline( cmd3 )
3717 self.handle.expect( "mininet>" )
3718 response = self.handle.before
3719 main.log.info( "====> %s ", response )
3720
3721 # update Mininet node variables
3722 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3723 self.handle.sendline( cmd4 )
3724 self.handle.expect( "mininet>" )
3725 response = self.handle.before
3726 main.log.info( "====> %s ", response )
3727
3728 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3729 self.handle.sendline( cmd5 )
3730 self.handle.expect( "mininet>" )
3731 response = self.handle.before
3732 main.log.info( "====> %s ", response )
3733
kaouthera3f13ca22015-05-05 15:01:41 -07003734 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003735 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003736 main.log.error( self.name + ": TIMEOUT exception found" )
3737 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003738 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003739 except pexpect.EOF:
3740 main.log.error( self.name + ": EOF exception found" )
3741 main.log.error( self.name + ": " + self.handle.before )
3742 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003743 except Exception:
3744 main.log.exception( self.name + ": Uncaught exception!" )
3745 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003746
Jon Hall892818c2015-10-20 17:58:34 -07003747 def createHostComponent( self, name ):
3748 """
3749 Creates a new mininet cli component with the same parameters as self.
3750 This new component is intended to be used to login to the hosts created
3751 by mininet.
3752
3753 Arguments:
3754 name - The string of the name of this component. The new component
3755 will be assigned to main.<name> .
3756 In addition, main.<name>.name = str( name )
3757 """
3758 try:
3759 # look to see if this component already exists
3760 getattr( main, name )
3761 except AttributeError:
3762 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003763 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3764 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003765 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003766 except pexpect.EOF:
3767 main.log.error( self.name + ": EOF exception found" )
3768 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003769 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003770 except Exception:
3771 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003772 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003773 else:
3774 # namespace is not clear!
3775 main.log.error( name + " component already exists!" )
3776 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003777 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003778
3779 def removeHostComponent( self, name ):
3780 """
3781 Remove host component
3782 Arguments:
3783 name - The string of the name of the component to delete.
3784 """
3785 try:
3786 # Get host component
3787 component = getattr( main, name )
3788 except AttributeError:
3789 main.log.error( "Component " + name + " does not exist." )
3790 return
3791 try:
3792 # Disconnect from component
3793 component.disconnect()
You Wangf32c6ed2018-08-23 17:10:22 -07003794 component.close_log_handles()
Jon Hall892818c2015-10-20 17:58:34 -07003795 # Delete component
3796 delattr( main, name )
3797 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003798 del( main.componentDictionary[ name ] )
You Wangf32c6ed2018-08-23 17:10:22 -07003799 except StandardError:
3800 self.log.exception( "Exception while closing log files for " + name )
3801 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003802 except pexpect.EOF:
3803 main.log.error( self.name + ": EOF exception found" )
3804 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003805 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003806 except Exception:
3807 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003808 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003809
3810 def startHostCli( self, host=None ):
3811 """
3812 Use the mininet m utility to connect to the host's cli
3813 """
3814 # These are fields that can be used by scapy packets. Initialized to None
3815 self.hostIp = None
3816 self.hostMac = None
3817 try:
3818 if not host:
3819 host = self.name
3820 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003821 self.handle.sendline( "cd" )
3822 self.handle.expect( self.hostPrompt )
3823 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003824 self.handle.expect( self.hostPrompt )
3825 return main.TRUE
3826 except pexpect.TIMEOUT:
3827 main.log.exception( self.name + ": Command timed out" )
3828 return main.FALSE
3829 except pexpect.EOF:
3830 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003831 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003832 except Exception:
3833 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003834 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003835
YPZhang801d46d2016-08-08 13:26:28 -07003836 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003837 '''
3838
YPZhang801d46d2016-08-08 13:26:28 -07003839 Args:
3840 devicename: switch name
3841 intf: port name on switch
3842 status: up or down
3843
3844 Returns: boolean to show success change status
3845
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003846 '''
YPZhang801d46d2016-08-08 13:26:28 -07003847 if status == "down" or status == "up":
3848 try:
3849 cmd = devicename + " ifconfig " + intf + " " + status
3850 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003851 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003852 return main.TRUE
3853 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003854 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003855 return main.FALSE
3856 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003857 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003858 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003859 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003860 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003861 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003862 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003863 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003864 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003865 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003866 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003867 return main.FALSE
3868
You Wang6e5b48e2018-07-23 16:17:38 -07003869 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003870 """
You Wang6e5b48e2018-07-23 16:17:38 -07003871 Moves a host from one switch to another on the fly
3872 Optional:
3873 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3874 prefixLen: length of the host IP prefix
3875 ipv6: move an IPv6 host if True
3876 intfSuffix: suffix of the new interface after host movement
3877 vlan: vlan ID of the host. Use None for non-vlan host
3878 Note: The intf between host and oldSw when detached
3879 using detach(), will still show up in the 'net'
3880 cmd, because switch.detach() doesn't affect switch.intfs[]
3881 ( which is correct behavior since the interfaces
3882 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003883 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003884 if self.handle:
3885 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003886 newIntf = "%s-%s" % ( host, intfSuffix )
3887 commands = [
3888 # Bring link between oldSw-host down
3889 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3890 # Determine hostintf and Oldswitchintf
3891 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
3892 ]
3893 # Determine ip address of the host-oldSw interface
3894 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3895 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3896 commands += [
3897 # Determine mac address of the host-oldSw interface
3898 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3899 # Detach interface between oldSw-host
3900 "px " + oldSw + ".detach( sintf )",
3901 # Add link between host-newSw
3902 "py net.addLink(" + host + "," + newSw + ")",
3903 # Determine hostintf and Newswitchintf
3904 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3905 # Attach interface between newSw-host
3906 "px " + newSw + ".attach( sintf )",
3907 ]
3908 if vlan:
3909 vlanIntf = "%s.%s" % ( newIntf, vlan )
3910 commands += [
3911 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
3912 host + " ip link set up %s" % vlanIntf,
3913 "px hintf.name = '" + vlanIntf + "'",
3914 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
3915 ]
3916 newIntf = vlanIntf
3917 commands += [
3918 # Set mac address of the host-newSw interface
3919 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
3920 # Set IP address of the host-newSw interface
3921 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
3922 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
3923 ]
3924 if ipv6:
3925 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
3926 commands += [
3927 "net",
3928 host + " ifconfig"
3929 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003930 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003931 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003932 self.handle.sendline( cmd )
3933 self.handle.expect( "mininet>" )
3934 main.log.info( "====> %s ", self.handle.before )
3935 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003936 except pexpect.TIMEOUT:
3937 main.log.error( self.name + ": TIMEOUT exception found" )
3938 main.log.error( self.name + ": " + self.handle.before )
3939 main.cleanAndExit()
3940 except pexpect.EOF:
3941 main.log.error( self.name + ": EOF exception found" )
3942 main.log.error( self.name + ": " + self.handle.before )
3943 return main.FALSE
3944 except Exception:
3945 main.log.exception( self.name + ": Uncaught exception!" )
3946 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07003947
You Wang6e5b48e2018-07-23 16:17:38 -07003948 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
3949 macAddr=None, prefixLen=None, ipv6=False,
3950 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07003951 """
You Wang6e5b48e2018-07-23 16:17:38 -07003952 Moves a dual-homed host from one switch-pair to another pair on the fly
3953 Optional:
3954 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3955 prefixLen: length of the host IP prefix
3956 ipv6: move an IPv6 host if True
3957 intfSuffix1: suffix of the first new interface
3958 intfSuffix2: suffix of the second new interface
3959 bondSuffix: suffix of the new bond interface
3960 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07003961 """
You Wang7ea90582018-07-19 15:27:58 -07003962 if self.handle:
3963 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003964 bondIntf = "%s-%s" % ( host, bondSuffix )
3965 newIntf = "%s-%s" % ( host, intfSuffix1 )
3966 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07003967 commands = [
3968 # Bring link between oldSw-host down
3969 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3970 # Bring link between oldPairSw-host down
3971 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
3972 # Determine hostintf and Oldswitchintf
3973 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07003974 ]
3975 # Determine ip address of the host-oldSw interface
3976 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3977 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3978 commands += [
3979 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07003980 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3981 # Detach interface between oldSw-host
3982 "px " + oldSw + ".detach( sintf )",
3983 # Determine hostintf and Oldpairswitchintf
3984 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
3985 # Detach interface between oldPairSw-host
3986 "px " + oldPairSw + ".detach( sintfpair )",
3987 # Add link between host-newSw
3988 "py net.addLink(" + host + "," + newSw + ", 2)",
3989 # Add link between host-newPairSw
3990 "py net.addLink(" + host + "," + newPairSw + ")",
3991 # Determine hostintf and Newswitchintf
3992 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3993 # Determine hostintf and NewPairswitchintf
3994 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
3995 # Attach interface between newSw-host
3996 "px " + newSw + ".attach( sintf )",
3997 # Attach interface between newPairSw-host
3998 "px " + newPairSw + ".attach( sintfpair )",
3999 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07004000 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004001 host + ' ip link set %s down' % newIntf,
4002 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004003 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
4004 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07004005 host + ' ip addr flush dev %s' % newIntf,
4006 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004007 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004008 "px lowestIntf = min( [ hintf, hintfpair ] )",
4009 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07004010 "px lowestIntf.name = '" + bondIntf + "'",
4011 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07004012 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
4013 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07004014 ]
4015 if vlan:
4016 vlanIntf = "%s.%s" % ( bondIntf, vlan )
4017 commands += [
4018 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
4019 host + " ip link set up %s" % vlanIntf,
4020 "px lowestIntf.name = '" + vlanIntf + "'",
4021 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
4022 ]
4023 bondIntf = vlanIntf
4024 commands += [
4025 # Set macaddress of the host-newSw interface
4026 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07004027 # Set ipaddress of the host-newSw interface
4028 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
4029 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07004030 ]
You Wang6e5b48e2018-07-23 16:17:38 -07004031 if ipv6:
4032 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
4033 commands += [
4034 "net",
4035 host + " ifconfig"
4036 ]
You Wang7ea90582018-07-19 15:27:58 -07004037 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004038 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07004039 self.handle.sendline( cmd )
4040 self.handle.expect( "mininet>" )
4041 main.log.info( "====> %s ", self.handle.before )
4042 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07004043 except pexpect.TIMEOUT:
4044 main.log.error( self.name + ": TIMEOUT exception found" )
4045 main.log.error( self.name + ": " + self.handle.before )
4046 main.cleanAndExit()
4047 except pexpect.EOF:
4048 main.log.error( self.name + ": EOF exception found" )
4049 main.log.error( self.name + ": " + self.handle.before )
4050 return main.FALSE
4051 except Exception:
4052 main.log.exception( self.name + ": Uncaught exception!" )
4053 return main.FALSE
4054
adminbae64d82013-08-01 10:50:15 -07004055if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004056 sys.modules[ __name__ ] = MininetCliDriver()