blob: 84930de3f790dd5b504012ed80055e6c3e851240 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
Jon Hall7eb38402015-01-08 17:19:54 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004Copyright 2012 Open Networking Foundation (ONF)
adminbae64d82013-08-01 10:50:15 -07005
Jeremy Songsterae01bba2016-07-11 15:39:17 -07006Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
7the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
8or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
adminbae64d82013-08-01 10:50:15 -07009
Jon Hall7eb38402015-01-08 17:19:54 -080010TestON is free software: you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation, either version 2 of the License, or
13( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070014
Jon Hall7eb38402015-01-08 17:19:54 -080015TestON is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070019
Jon Hall7eb38402015-01-08 17:19:54 -080020You should have received a copy of the GNU General Public License
21along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070022
Jon Hallbe6dfc42015-01-12 17:37:25 -080023MininetCliDriver is the basic driver which will handle the Mininet functions
24
25Some functions rely on a modified version of Mininet. These functions
26should all be noted in the comments. To get this MN version run these commands
27from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080028 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080029 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080030 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080031 git pull
32
Jon Hall272a4db2015-01-12 17:43:48 -080033
34 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080035changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070036import pexpect
adminbae64d82013-08-01 10:50:15 -070037import re
38import sys
kelvin-onlabfa6ada82015-06-11 13:06:24 -070039import types
kelvin-onlaba4074292015-07-09 15:19:49 -070040import os
Devin Lima7cfdbd2017-09-29 15:02:22 -070041import time
Jon Hall1ccf82c2014-10-15 14:55:16 -040042from math import pow
adminbae64d82013-08-01 10:50:15 -070043from drivers.common.cli.emulatordriver import Emulator
You Wangdb8cd0a2016-05-26 15:19:45 -070044from core.graph import Graph
adminbae64d82013-08-01 10:50:15 -070045
Jon Hall7eb38402015-01-08 17:19:54 -080046
kelvin-onlab50907142015-04-01 13:37:45 -070047class MininetCliDriver( Emulator ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -070048
Jon Hall7eb38402015-01-08 17:19:54 -080049 """
50 MininetCliDriver is the basic driver which will handle
51 the Mininet functions"""
52 def __init__( self ):
Devin Limdc78e202017-06-09 18:30:07 -070053 super( MininetCliDriver, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070054 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080055 self.name = None
kelvin-onlabd9e23de2015-08-06 10:34:44 -070056 self.home = None
Jon Hall7eb38402015-01-08 17:19:54 -080057 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070058 self.flag = 0
Jon Hall892818c2015-10-20 17:58:34 -070059 # TODO: Refactor driver to use these everywhere
60 self.mnPrompt = "mininet>"
61 self.hostPrompt = "~#"
62 self.bashPrompt = "\$"
63 self.scapyPrompt = ">>>"
You Wangdb8cd0a2016-05-26 15:19:45 -070064 self.graph = Graph()
adminbae64d82013-08-01 10:50:15 -070065
Jon Hall7eb38402015-01-08 17:19:54 -080066 def connect( self, **connectargs ):
67 """
68 Here the main is the TestON instance after creating
69 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080070 try:
71 for key in connectargs:
72 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070073 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080074 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070075 for key in self.options:
76 if key == "home":
77 self.home = self.options[ 'home' ]
78 break
79 if self.home is None or self.home == "":
80 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070081
82 try:
Jon Hall892818c2015-10-20 17:58:34 -070083 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070084 self.ip_address = os.getenv( str( self.ip_address ) )
85 else:
86 main.log.info( self.name +
87 ": Trying to connect to " +
88 self.ip_address )
89
90 except KeyError:
91 main.log.info( "Invalid host name," +
92 " connecting to local host instead" )
93 self.ip_address = 'localhost'
94 except Exception as inst:
95 main.log.error( "Uncaught exception: " + str( inst ) )
96
kelvin-onlaba1484582015-02-02 15:46:20 -080097 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070098 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080099 self ).connect(
100 user_name=self.user_name,
101 ip_address=self.ip_address,
102 port=None,
103 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -0800104
kelvin-onlaba1484582015-02-02 15:46:20 -0800105 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -0800106 main.log.info( "Connection successful to the host " +
107 self.user_name +
108 "@" +
109 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800110 return main.TRUE
111 else:
112 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800113 self.user_name +
114 "@" +
115 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800116 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800117 return main.FALSE
118 except pexpect.EOF:
119 main.log.error( self.name + ": EOF exception found" )
120 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700121 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800122 except Exception:
123 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700124 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -0800125
kelvin-onlab10e8d392015-06-03 13:53:45 -0700126 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800127 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700128 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000129 Starts Mininet accepts a topology(.py) file and/or an optional
kelvin-onlabf512e942015-06-08 19:42:59 -0700130 argument, to start the mininet, as a parameter.
131 Can also send regular mininet command to load up desired topology.
alison12f34c32016-06-10 14:39:21 -0700132 Eg. Pass in a string 'mn --topo=tree,3,3' to mnCmd
kelvin-onlabf512e942015-06-08 19:42:59 -0700133 Options:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000134 topoFile = file path for topology file (.py)
kelvin-onlabf512e942015-06-08 19:42:59 -0700135 args = extra option added when starting the topology from the file
136 mnCmd = Mininet command use to start topology
137 Returns:
138 main.TRUE if the mininet starts successfully, main.FALSE
139 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800140 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700141 try:
142 if self.handle:
143 # make sure old networks are cleaned up
144 main.log.info( self.name +
145 ": Clearing any residual state or processes" )
146 self.handle.sendline( "sudo mn -c" )
147 i = self.handle.expect( [ 'password\sfor\s',
148 'Cleanup\scomplete',
Jon Hallefbd9792015-03-05 16:11:36 -0800149 pexpect.EOF,
150 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700151 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800152 if i == 0:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700153 # Sudo asking for password
154 main.log.info( self.name + ": Sending sudo password" )
155 self.handle.sendline( self.pwd )
Jon Hall173f2a02018-01-11 13:56:37 -0800156 i = self.handle.expect( [ '%s:' % self.user_name,
Devin Limdc78e202017-06-09 18:30:07 -0700157 self.prompt,
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700158 pexpect.EOF,
159 pexpect.TIMEOUT ],
160 timeout )
161 if i == 1:
162 main.log.info( self.name + ": Clean" )
Jon Hall689d8e42015-04-03 13:59:24 -0700163 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700164 main.log.error( self.name + ": Connection terminated" )
165 elif i == 3: # timeout
166 main.log.error( self.name + ": Something while cleaning " +
167 "Mininet took too long... " )
168 # Craft the string to start mininet
169 cmdString = "sudo "
170 if not mnCmd:
171 if topoFile is None or topoFile == '': # If no file is given
172 main.log.info( self.name + ": building fresh Mininet" )
173 cmdString += "mn "
174 if args is None or args == '':
175 # If no args given, use args from .topo file
176 args = self.options[ 'arg1' ] +\
177 " " + self.options[ 'arg2' ] +\
178 " --mac --controller " +\
179 self.options[ 'controller' ] + " " +\
180 self.options[ 'arg3' ]
181 else: # else only use given args
182 pass
183 # TODO: allow use of topo args and method args?
184 else: # Use given topology file
185 main.log.info(
186 "Starting Mininet from topo file " +
187 topoFile )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700188 cmdString += "-E python " + topoFile + " "
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700189 if args is None:
190 args = ''
191 # TODO: allow use of args from .topo file?
192 cmdString += args
193 else:
194 main.log.info( "Starting Mininet topology using '" + mnCmd +
195 "' command" )
196 cmdString += mnCmd
197 # Send the command and check if network started
198 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -0700199 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700200 main.log.info( "Sending '" + cmdString + "' to " + self.name )
201 self.handle.sendline( cmdString )
Devin Lima7cfdbd2017-09-29 15:02:22 -0700202 startTime = time.time()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700203 while True:
204 i = self.handle.expect( [ 'mininet>',
Jon Hallbc743112018-04-18 11:09:01 -0700205 'Exception|Error',
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700206 '\*\*\*',
207 pexpect.EOF,
Jon Hallab611372018-02-21 15:26:05 -0800208 pexpect.TIMEOUT,
209 "No such file or directory"],
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700210 timeout )
211 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -0700212 main.log.info( self.name + ": Mininet built\nTime Took : " + str( time.time() - startTime ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700213 return main.TRUE
214 elif i == 1:
215 response = str( self.handle.before +
216 self.handle.after )
Devin Limdc78e202017-06-09 18:30:07 -0700217 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700218 response += str( self.handle.before +
219 self.handle.after )
220 main.log.error(
221 self.name +
222 ": Launching Mininet failed: " + response )
223 return main.FALSE
224 elif i == 2:
225 self.handle.expect( [ "\n",
226 pexpect.EOF,
227 pexpect.TIMEOUT ],
228 timeout )
229 main.log.info( self.handle.before )
230 elif i == 3:
231 main.log.error( self.name + ": Connection timeout" )
232 return main.FALSE
233 elif i == 4: # timeout
234 main.log.error(
235 self.name +
236 ": Something took too long... " )
Jon Hallbc743112018-04-18 11:09:01 -0700237 main.log.debug( self.handle.before + self.handle.after )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700238 return main.FALSE
Jon Hallab611372018-02-21 15:26:05 -0800239 elif i == 5:
240 main.log.error( self.name + ": " + self.handle.before + self.handle.after )
241 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700242 # Why did we hit this part?
243 main.log.error( "startNet did not return correctly" )
244 return main.FASLE
245 else: # if no handle
246 main.log.error( self.name + ": Connection failed to the host " +
247 self.user_name + "@" + self.ip_address )
248 main.log.error( self.name + ": Failed to connect to the Mininet" )
249 return main.FALSE
250 except pexpect.TIMEOUT:
251 main.log.exception( self.name + ": TIMEOUT exception found while starting Mininet" )
252 main.log.error( self.name + ": " + self.handle.before )
adminbae64d82013-08-01 10:50:15 -0700253 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700254 except pexpect.EOF:
255 main.log.error( self.name + ": EOF exception found" )
256 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700257 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700258 except Exception:
259 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700260 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800261
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800262 def numSwitchesNlinks( self, topoType, depth, fanout ):
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700263 try:
264 if topoType == 'tree':
265 # In tree topology, if fanout arg is not given, by default it is 2
266 if fanout is None:
267 fanout = 2
268 k = 0
269 count = 0
270 while( k <= depth - 1 ):
271 count = count + pow( fanout, k )
272 k = k + 1
273 numSwitches = count
274 while( k <= depth - 2 ):
275 # depth-2 gives you only core links and not considering
276 # edge links as seen by ONOS. If all the links including
277 # edge links are required, do depth-1
278 count = count + pow( fanout, k )
279 k = k + 1
280 numLinks = count * fanout
281 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
282 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800283
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700284 elif topoType == 'linear':
285 # In linear topology, if fanout or numHostsPerSw is not given,
286 # by default it is 1
287 if fanout is None:
288 fanout = 1
289 numSwitches = depth
290 numHostsPerSw = fanout
291 totalNumHosts = numSwitches * numHostsPerSw
292 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hallab611372018-02-21 15:26:05 -0800293 main.log.debug( "num_switches for %s(%d,%d) = %d and links=%d" %
294 ( topoType, depth, fanout, numSwitches, numLinks ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700295 topoDict = { "num_switches": int( numSwitches ),
296 "num_corelinks": int( numLinks ) }
297 return topoDict
298 except Exception:
299 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700300 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400301
kelvin-onlabd3b64892015-01-20 13:26:24 -0800302 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700303 """
304 Calculate the number of switches and links in a topo."""
305 # TODO: combine this function and numSwitchesNlinks
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700306 try:
307 argList = self.options[ 'arg1' ].split( "," )
308 topoArgList = argList[ 0 ].split( " " )
309 argList = map( int, argList[ 1: ] )
310 topoArgList = topoArgList[ 1: ] + argList
Jon Hall689d8e42015-04-03 13:59:24 -0700311
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700312 topoDict = self.numSwitchesNlinks( *topoArgList )
313 return topoDict
314 except Exception:
315 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700316 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400317
GlennRCf07c44a2015-09-18 13:33:46 -0700318 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800319 """
320 Verifies the reachability of the hosts using pingall command.
321 Optional parameter timeout allows you to specify how long to
322 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700323 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700324 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700325 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700326 ping
327 acceptableFailed - Set the number of acceptable failed pings for the
328 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800329 Returns:
330 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700331 otherwise main.FALSE
332 """
333 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700334 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700335 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700336 if self.handle:
337 main.log.info(
338 self.name +
339 ": Checking reachabilty to the hosts using pingall" )
340 response = ""
341 failedPings = 0
342 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700343 cmd = "pingall"
344 if protocol == "IPv6":
345 cmd = "py net.pingAll6()"
346 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700347 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700348 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700349 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700350 pexpect.EOF,
351 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700352 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700353 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700354 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700355 response += self.handle.before
356 break
357 elif i == 1:
358 response += self.handle.before + self.handle.after
359 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700360 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700361 returnValue = main.FALSE
362 if shortCircuit:
363 main.log.error( self.name +
364 ": Aborting pingall - "
365 + str( failedPings ) +
366 " pings failed" )
367 break
Jon Hall390696c2015-05-05 17:13:41 -0700368 if ( time.time() - startTime ) > timeout:
369 returnValue = main.FALSE
370 main.log.error( self.name +
371 ": Aborting pingall - " +
372 "Function took too long " )
373 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700374 elif i == 2:
375 main.log.error( self.name +
376 ": EOF exception found" )
377 main.log.error( self.name + ": " +
378 self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700379 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700380 elif i == 3:
381 response += self.handle.before
382 main.log.error( self.name +
383 ": TIMEOUT exception found" )
384 main.log.error( self.name +
385 ": " +
386 str( response ) )
387 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800388 self.handle.send( "\x03" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700389 self.handle.expect( "Interrupt" )
390 self.handle.expect( "mininet>" )
391 break
392 pattern = "Results\:"
393 main.log.info( "Pingall output: " + str( response ) )
394 if re.search( pattern, response ):
395 main.log.info( self.name + ": Pingall finished with "
396 + str( failedPings ) + " failed pings" )
397 return returnValue
398 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700399 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800400 self.handle.send( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700401 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700402 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700403 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700404 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700405 main.log.error( self.name + ": Connection failed to the host" )
Devin Lim44075962017-08-11 10:56:37 -0700406 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700407 except pexpect.TIMEOUT:
408 if response:
409 main.log.info( "Pingall output: " + str( response ) )
410 main.log.error( self.name + ": pexpect.TIMEOUT found" )
411 return main.FALSE
412 except pexpect.EOF:
413 main.log.error( self.name + ": EOF exception found" )
414 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700415 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -0700416
Jon Hall7eb38402015-01-08 17:19:54 -0800417 def fpingHost( self, **pingParams ):
418 """
419 Uses the fping package for faster pinging...
420 *requires fping to be installed on machine running mininet"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700421 try:
422 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
423 command = args[ "SRC" ] + \
424 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
425 self.handle.sendline( command )
426 self.handle.expect(
427 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
428 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
429 response = self.handle.before
430 if re.search( ":\s-", response ):
431 main.log.info( self.name + ": Ping fail" )
432 return main.FALSE
433 elif re.search( ":\s\d{1,2}\.\d\d", response ):
434 main.log.info( self.name + ": Ping good!" )
435 return main.TRUE
436 main.log.info( self.name + ": Install fping on mininet machine... " )
437 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700438 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700439 except Exception:
440 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700441 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700442
Jon Hall3b489db2015-10-05 14:38:37 -0700443 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400444 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700445 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700446
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400447 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700448 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700449
450 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400451 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700452
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400453 Returns main.FALSE if one or more of hosts specified
454 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700455 wait = int( wait )
456 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400457
458 try:
459 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700460
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400461 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700462 pingResponse = "IPv4 ping across specified hosts\n"
463 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400464 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700465 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400466 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700467 pingList = hostList[ :listIndex ] + \
468 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700469
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700470 pingResponse += str( str( host ) + " -> " )
GlennRCd10d3cc2015-09-24 12:47:16 -0700471
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400472 for temp in pingList:
473 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700474 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700475 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700476 self.handle.expect( "mininet>", timeout=wait + 5 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400477 response = self.handle.before
478 if re.search( ',\s0\%\spacket\sloss', response ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700479 pingResponse += str( " h" + str( temp[ 1: ] ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400480 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700481 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400482 # One of the host to host pair is unreachable
483 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700484 failedPings += 1
You Wang11f9ead2018-03-21 14:34:59 -0700485 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
GlennRCd10d3cc2015-09-24 12:47:16 -0700486 pingResponse += "\n"
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700487 main.log.info( pingResponse + "Failed pings: " + str( failedPings ) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700488 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700489 except pexpect.TIMEOUT:
490 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800491 response = self.handle.before
492 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700493 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800494 self.handle.expect( "Interrupt" )
495 response += self.handle.before + self.handle.after
496 self.handle.expect( "mininet>" )
497 response += self.handle.before + self.handle.after
498 main.log.debug( response )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700499 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400500 except pexpect.EOF:
501 main.log.error( self.name + ": EOF exception found" )
502 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700503 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700504 except Exception:
505 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700506 main.cleanAndExit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400507
You Wangf19d9f42018-02-23 16:34:19 -0800508 def pingIpv6Hosts( self, hostList, wait=1, acceptableFailed=0 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700509 """
You Wangf19d9f42018-02-23 16:34:19 -0800510 IPv6 ping all hosts in hostList.
511
512 acceptableFailed: max number of acceptable failed pings
Hari Krishna9592fc82015-07-31 15:11:15 -0700513
Jon Hall3b489db2015-10-05 14:38:37 -0700514 Returns main.TRUE if all hosts specified can reach each other
Jon Hall3b489db2015-10-05 14:38:37 -0700515 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700516 """
517 try:
518 main.log.info( "Testing reachability between specified IPv6 hosts" )
519 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700520 wait = int( wait )
521 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700522 pingResponse = "IPv6 Pingall output:\n"
You Wangf19d9f42018-02-23 16:34:19 -0800523 failedPingsTotal = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700524 for host in hostList:
525 listIndex = hostList.index( host )
526 # List of hosts to ping other than itself
527 pingList = hostList[ :listIndex ] + \
528 hostList[ ( listIndex + 1 ): ]
529
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700530 pingResponse += str( str( host ) + " -> " )
GlennRC2cf7d952015-09-11 16:32:13 -0700531
Hari Krishna9592fc82015-07-31 15:11:15 -0700532 for temp in pingList:
533 # Current host pings all other hosts specified
You Wangf19d9f42018-02-23 16:34:19 -0800534 failedPings = 0
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700535 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
You Wangf19d9f42018-02-23 16:34:19 -0800536 while failedPings <= acceptableFailed:
537 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
538 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700539 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangf19d9f42018-02-23 16:34:19 -0800540 response = self.handle.before
541 if re.search( ',\s0\%\spacket\sloss', response ):
You Wangba231e72018-03-01 13:18:21 -0800542 pingResponse += " " + str( temp )
543 break
544 else:
545 failedPings += 1
546 time.sleep(1)
547 if failedPings > acceptableFailed:
548 # One of the host to host pair is unreachable
549 pingResponse += " X"
550 isReachable = main.FALSE
551 failedPingsTotal += 1
You Wang11f9ead2018-03-21 14:34:59 -0700552 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
You Wangba231e72018-03-01 13:18:21 -0800553 pingResponse += "\n"
554 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
555 return isReachable
556
557 except pexpect.TIMEOUT:
558 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800559 response = self.handle.before
560 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700561 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800562 self.handle.expect( "Interrupt" )
563 response += self.handle.before + self.handle.after
564 self.handle.expect( "mininet>" )
565 response += self.handle.before + self.handle.after
566 main.log.debug( response )
You Wangba231e72018-03-01 13:18:21 -0800567 return main.FALSE
568 except pexpect.EOF:
569 main.log.error( self.name + ": EOF exception found" )
570 main.log.error( self.name + ": " + self.handle.before )
571 main.cleanAndExit()
572 except Exception:
573 main.log.exception( self.name + ": Uncaught exception!" )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700574
575 main.cleanAndExit()
576
You Wang48381752018-05-07 13:50:57 -0700577 def discoverHosts( self, hostList=[], wait=1, dstIp="6.6.6.6", dstIp6="1020::3fe" ):
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700578 '''
You Wang48381752018-05-07 13:50:57 -0700579 Hosts in hostList will do a single ping to a non-existent address for ONOS to
580 discover them. A host will use ping/ping6 to send echo requests depending on if
581 it has IPv4/IPv6 addresses configured.
582 Optional:
583 hostList: a list of names of the hosts that need to be discovered. If not
584 specified mininet will send ping from all the hosts
585 wait: timeout for IPv4/IPv6 echo requests
586 dstIp: destination address used by IPv4 hosts
587 dstIp6: destination address used by IPv6 hosts
588 Returns:
589 main.TRUE if all ping packets were successfully sent. Otherwise main.FALSE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700590 '''
591 try:
You Wang48381752018-05-07 13:50:57 -0700592 if not hostList:
593 hosts = self.getHosts( getInterfaces=False )
594 hostList = hosts.keys()
595 discoveryResult = main.TRUE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700596 for host in hostList:
You Wang0b82aa52018-06-06 14:33:58 -0700597 flushCmd = ""
You Wang48381752018-05-07 13:50:57 -0700598 cmd = ""
599 if self.getIPAddress( host ):
You Wang0b82aa52018-06-06 14:33:58 -0700600 flushCmd = "{} ip neigh flush all".format( host )
You Wang48381752018-05-07 13:50:57 -0700601 cmd = "{} ping -c 1 -i 1 -W {} {}".format( host, wait, dstIp )
602 main.log.debug( "Sending IPv4 probe ping from host {}".format( host ) )
603 elif self.getIPAddress( host, proto='IPV6' ):
You Wang0b82aa52018-06-06 14:33:58 -0700604 flushCmd = "{} ip -6 neigh flush all".format( host )
You Wang48381752018-05-07 13:50:57 -0700605 cmd = "{} ping6 -c 1 -i 1 -W {} {}".format( host, wait, dstIp6 )
606 main.log.debug( "Sending IPv6 probe ping from host {}".format( host ) )
607 else:
608 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
609 discoveryResult = main.FALSE
610 if cmd:
You Wang0b82aa52018-06-06 14:33:58 -0700611 self.handle.sendline( flushCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700612 self.handle.expect( "mininet>" )
You Wang48381752018-05-07 13:50:57 -0700613 self.handle.sendline( cmd )
Jon Halla604fd42018-05-04 14:27:27 -0700614 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700615 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700616 except pexpect.TIMEOUT:
617 main.log.exception( self.name + ": TIMEOUT exception" )
618 response = self.handle.before
619 # NOTE: Send ctrl-c to make sure command is stopped
620 self.handle.send( "\x03" )
621 self.handle.expect( "Interrupt" )
622 response += self.handle.before + self.handle.after
623 self.handle.expect( "mininet>" )
624 response += self.handle.before + self.handle.after
625 main.log.debug( response )
626 return main.FALSE
627 except pexpect.EOF:
628 main.log.error( self.name + ": EOF exception found" )
629 main.log.error( self.name + ": " + self.handle.before )
630 main.cleanAndExit()
631 except Exception:
632 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800633 main.cleanAndExit()
634
635 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
636 """
637 Verify ping from each host in srcList to each host in dstList
638
639 acceptableFailed: max number of acceptable failed pings
640
641 Returns main.TRUE if all src hosts can reach all dst hosts
642 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
643 """
644 try:
645 main.log.info( "Verifying ping from each src host to each dst host" )
646 isReachable = main.TRUE
647 wait = int( wait )
648 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
649 pingResponse = "Ping output:\n"
650 failedPingsTotal = 0
651 for host in srcList:
652 pingResponse += str( str( host ) + " -> " )
653 for temp in dstList:
654 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700655 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
656 assert dstIP, "Not able to get IP address of host {}".format( temp )
657 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800658 while failedPings <= acceptableFailed:
659 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
660 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700661 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800662 response = self.handle.before
663 if re.search( ',\s0\%\spacket\sloss', response ):
664 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800665 break
666 else:
667 failedPings += 1
668 time.sleep(1)
669 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700670 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800671 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700672 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800673 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700674 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800675 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700676 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700677 except AssertionError:
678 main.log.exception( "" )
679 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700680 except pexpect.TIMEOUT:
681 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800682 response = self.handle.before
683 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700684 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800685 self.handle.expect( "Interrupt" )
686 response += self.handle.before + self.handle.after
687 self.handle.expect( "mininet>" )
688 response += self.handle.before + self.handle.after
689 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700690 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700691 except pexpect.EOF:
692 main.log.error( self.name + ": EOF exception found" )
693 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700694 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700695 except Exception:
696 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700697 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700698
Jon Hall7eb38402015-01-08 17:19:54 -0800699 def pingHost( self, **pingParams ):
700 """
Jon Hall3b489db2015-10-05 14:38:37 -0700701 Ping from one mininet host to another
702 Currently the only supported Params: SRC, TARGET, and WAIT
703 """
704 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700705 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700706 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800707 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700708 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700709 try:
Jon Hall61282e32015-03-19 11:34:11 -0700710 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800711 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700712 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700713 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700714 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800715 main.log.error(
716 self.name +
717 ": timeout when waiting for response from mininet" )
718 main.log.error( "response: " + str( self.handle.before ) )
719 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700720 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800721 main.log.error(
722 self.name +
723 ": timeout when waiting for response from mininet" )
724 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700725 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700726 if re.search( ',\s0\%\spacket\sloss', response ):
727 main.log.info( self.name + ": no packets lost, host is reachable" )
728 return main.TRUE
729 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800730 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700731 self.name +
732 ": PACKET LOST, HOST IS NOT REACHABLE" )
733 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800734 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800735 main.log.error( self.name + ": EOF exception found" )
736 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700737 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700738 except Exception:
739 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700740 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700741
742 def ping6pair( self, **pingParams ):
743 """
GlennRC2cf7d952015-09-11 16:32:13 -0700744 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700745 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000746 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700747 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
748 """
Jon Hall3b489db2015-10-05 14:38:37 -0700749 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700750 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700751 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530752 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700753 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700754 try:
755 main.log.info( "Sending: " + command )
756 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700757 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700758 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700759 if i == 1:
760 main.log.error(
761 self.name +
762 ": timeout when waiting for response from mininet" )
763 main.log.error( "response: " + str( self.handle.before ) )
764 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
765 if i == 1:
766 main.log.error(
767 self.name +
768 ": timeout when waiting for response from mininet" )
769 main.log.error( "response: " + str( self.handle.before ) )
770 response = self.handle.before
771 main.log.info( self.name + ": Ping Response: " + response )
772 if re.search( ',\s0\%\spacket\sloss', response ):
773 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700774 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700775 else:
alisone4121a92016-11-22 16:31:36 -0800776 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700777 self.name +
778 ": PACKET LOST, HOST IS NOT REACHABLE" )
779 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700780 except pexpect.EOF:
781 main.log.error( self.name + ": EOF exception found" )
782 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700783 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700784 except Exception:
785 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700786 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800787
You Wangdb927a52016-02-26 11:03:28 -0800788 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
789 """
790 Description:
791 Ping a set of destination host from host CLI.
792 Logging into a Mininet host CLI is required before calling this funtion.
793 Params:
794 dstIPList is a list of destination ip addresses
795 Returns:
796 main.TRUE if the destination host is reachable
797 main.FALSE otherwise
798 """
799 isReachable = main.TRUE
800 wait = int( wait )
801 cmd = "ping"
802 if IPv6:
803 cmd = cmd + "6"
804 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
805 try:
806 for dstIP in dstIPList:
807 pingCmd = cmd + " " + dstIP
808 self.handle.sendline( pingCmd )
809 i = self.handle.expect( [ self.hostPrompt,
810 '\*\*\* Unknown command: ' + pingCmd,
811 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700812 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700813 # For some reason we need to send something
814 # Otherwise ping results won't be read by handle
815 self.handle.sendline( "" )
816 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800817 if i == 0:
818 response = self.handle.before
819 if not re.search( ',\s0\%\spacket\sloss', response ):
820 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
821 isReachable = main.FALSE
822 elif i == 1:
823 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700824 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800825 elif i == 2:
826 main.log.error( self.name + ": timeout when waiting for response" )
827 isReachable = main.FALSE
828 else:
829 main.log.error( self.name + ": unknown response: " + self.handle.before )
830 isReachable = main.FALSE
831 except pexpect.TIMEOUT:
832 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800833 response = self.handle.before
834 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700835 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800836 self.handle.expect( "Interrupt" )
837 response += self.handle.before + self.handle.after
838 self.handle.expect( "mininet>" )
839 response += self.handle.before + self.handle.after
840 main.log.debug( response )
You Wangdb927a52016-02-26 11:03:28 -0800841 isReachable = main.FALSE
842 except pexpect.EOF:
843 main.log.error( self.name + ": EOF exception found" )
844 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700845 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800846 except Exception:
847 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700848 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800849 return isReachable
850
Jon Hall7eb38402015-01-08 17:19:54 -0800851 def checkIP( self, host ):
852 """
853 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700854 try:
855 if self.handle:
856 try:
857 response = self.execute(
858 cmd=host +
859 " ifconfig",
860 prompt="mininet>",
861 timeout=10 )
862 except pexpect.EOF:
863 main.log.error( self.name + ": EOF exception found" )
864 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700865 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700866
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700867 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
868 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
869 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
870 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
871 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
872 "[0-9]|25[0-5]|[0-9]{1,2})"
873 # pattern = "inet addr:10.0.0.6"
874 if re.search( pattern, response ):
875 main.log.info( self.name + ": Host Ip configured properly" )
876 return main.TRUE
877 else:
878 main.log.error( self.name + ": Host IP not found" )
879 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700880 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700881 main.log.error( self.name + ": Connection failed to the host" )
882 except Exception:
883 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700884 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800885
Jon Hall7eb38402015-01-08 17:19:54 -0800886 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800887 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700888 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800889 response = self.execute(
890 cmd="h1 /usr/sbin/sshd -D&",
891 prompt="mininet>",
892 timeout=10 )
893 response = self.execute(
894 cmd="h4 /usr/sbin/sshd -D&",
895 prompt="mininet>",
896 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700897 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800898 vars( self )[ key ] = connectargs[ key ]
899 response = self.execute(
900 cmd="xterm h1 h4 ",
901 prompt="mininet>",
902 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800903 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800904 main.log.error( self.name + ": EOF exception found" )
905 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700906 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700907 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800908 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700909 if self.flag == 0:
910 self.flag = 1
911 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800912 else:
adminbae64d82013-08-01 10:50:15 -0700913 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800914
Jon Hall7eb38402015-01-08 17:19:54 -0800915 def changeIP( self, host, intf, newIP, newNetmask ):
916 """
917 Changes the ip address of a host on the fly
918 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800919 if self.handle:
920 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800921 cmd = host + " ifconfig " + intf + " " + \
922 newIP + " " + 'netmask' + " " + newNetmask
923 self.handle.sendline( cmd )
924 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800925 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800926 main.log.info( "response = " + response )
927 main.log.info(
928 "Ip of host " +
929 host +
930 " changed to new IP " +
931 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800932 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700933 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700934 main.log.error( self.name + ": TIMEOUT exception found" )
935 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700936 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800937 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800938 main.log.error( self.name + ": EOF exception found" )
939 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800940 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700941 except Exception:
942 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700943 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800944
Jon Hall7eb38402015-01-08 17:19:54 -0800945 def changeDefaultGateway( self, host, newGW ):
946 """
947 Changes the default gateway of a host
948 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800949 if self.handle:
950 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800951 cmd = host + " route add default gw " + newGW
952 self.handle.sendline( cmd )
953 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800954 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800955 main.log.info( "response = " + response )
956 main.log.info(
957 "Default gateway of host " +
958 host +
959 " changed to " +
960 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800961 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700962 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700963 main.log.error( self.name + ": TIMEOUT exception found" )
964 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700965 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800966 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800967 main.log.error( self.name + ": EOF exception found" )
968 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800969 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700970 except Exception:
971 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700972 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800973
You Wange24d6272018-03-27 21:18:50 -0700974 def addRoute( self, host, dstIP, interface, ipv6=False ):
975 """
976 Add a route to host
977 Ex: h1 route add -host 224.2.0.1 h1-eth0
978 """
979 if self.handle:
980 try:
981 cmd = str( host )
982 if ipv6:
983 cmd += " route -A inet6 add "
984 else:
985 cmd += " route add -host "
986 cmd += str( dstIP ) + " " + str( interface )
987 self.handle.sendline( cmd )
988 self.handle.expect( "mininet>" )
989 response = self.handle.before
990 main.log.debug( "response = " + response )
991 return main.TRUE
992 except pexpect.TIMEOUT:
993 main.log.error( self.name + ": TIMEOUT exception found" )
994 main.log.error( self.name + ": " + self.handle.before )
995 main.cleanAndExit()
996 except pexpect.EOF:
997 main.log.error( self.name + ": EOF exception found" )
998 main.log.error( self.name + ": " + self.handle.before )
999 return main.FALSE
1000 except Exception:
1001 main.log.exception( self.name + ": Uncaught exception!" )
1002 main.cleanAndExit()
1003
Jon Hall7eb38402015-01-08 17:19:54 -08001004 def addStaticMACAddress( self, host, GW, macaddr ):
1005 """
Jon Hallefbd9792015-03-05 16:11:36 -08001006 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001007 if self.handle:
1008 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001009 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1010 cmd = host + " arp -s " + GW + " " + macaddr
1011 self.handle.sendline( cmd )
1012 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001013 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001014 main.log.info( "response = " + response )
1015 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001016 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001017 GW +
1018 " changed to " +
1019 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001020 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001021 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001022 main.log.error( self.name + ": TIMEOUT exception found" )
1023 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001024 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001025 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001026 main.log.error( self.name + ": EOF exception found" )
1027 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001028 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001029 except Exception:
1030 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001031 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001032
Jon Hall7eb38402015-01-08 17:19:54 -08001033 def verifyStaticGWandMAC( self, host ):
1034 """
1035 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001036 if self.handle:
1037 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001038 # h1 arp -an
1039 cmd = host + " arp -an "
1040 self.handle.sendline( cmd )
1041 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001042 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001043 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001044 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001045 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001046 main.log.error( self.name + ": TIMEOUT exception found" )
1047 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001048 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001049 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001050 main.log.error( self.name + ": EOF exception found" )
1051 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001052 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001053 except Exception:
1054 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001055 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001056
Jon Hall7eb38402015-01-08 17:19:54 -08001057 def getMacAddress( self, host ):
1058 """
1059 Verifies the host's ip configured or not."""
1060 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001061 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001062 response = self.execute(
1063 cmd=host +
1064 " ifconfig",
1065 prompt="mininet>",
1066 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001067 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001068 main.log.error( self.name + ": EOF exception found" )
1069 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001070 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001071 except Exception:
1072 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001073 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001074
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001075 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001076 macAddressSearch = re.search( pattern, response, re.I )
1077 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001078 main.log.info(
1079 self.name +
1080 ": Mac-Address of Host " +
1081 host +
1082 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001083 macAddress )
1084 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001085 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001086 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001087
Jon Hall7eb38402015-01-08 17:19:54 -08001088 def getInterfaceMACAddress( self, host, interface ):
1089 """
1090 Return the IP address of the interface on the given host"""
1091 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001092 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001093 response = self.execute( cmd=host + " ifconfig " + interface,
1094 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001095 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001096 main.log.error( self.name + ": EOF exception found" )
1097 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001098 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001099 except Exception:
1100 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001101 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001102
1103 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001104 macAddressSearch = re.search( pattern, response, re.I )
1105 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001106 main.log.info( "No mac address found in %s" % response )
1107 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001108 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001109 main.log.info(
1110 "Mac-Address of " +
1111 host +
1112 ":" +
1113 interface +
1114 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001115 macAddress )
1116 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001117 else:
1118 main.log.error( "Connection failed to the host" )
1119
You Wang5da39c82018-04-26 22:55:08 -07001120 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001121 """
1122 Verifies the host's ip configured or not."""
1123 if self.handle:
1124 try:
1125 response = self.execute(
1126 cmd=host +
1127 " ifconfig",
1128 prompt="mininet>",
1129 timeout=10 )
1130 except pexpect.EOF:
1131 main.log.error( self.name + ": EOF exception found" )
1132 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001133 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001134 except Exception:
1135 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001136 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001137
sathishmad953462015-12-03 17:42:07 +05301138 pattern = ''
1139 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001140 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301141 else:
Jon Hall439c8912016-04-15 02:22:03 -07001142 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001143 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001144 if not ipAddressSearch:
1145 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001146 main.log.info(
1147 self.name +
1148 ": IP-Address of Host " +
1149 host +
1150 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001151 ipAddressSearch.group( 1 ) )
1152 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001153 else:
1154 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001155
Jon Hall7eb38402015-01-08 17:19:54 -08001156 def getSwitchDPID( self, switch ):
1157 """
1158 return the datapath ID of the switch"""
1159 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001160 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001161 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001162 response = self.execute(
1163 cmd=cmd,
1164 prompt="mininet>",
1165 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001166 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001167 main.log.error( self.name + ": EOF exception found" )
1168 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001169 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001170 except Exception:
1171 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001172 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001173 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001174 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001175 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001176 main.log.info(
1177 "Couldn't find DPID for switch %s, found: %s" %
1178 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001179 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001180 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001181 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001182 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001183
Jon Hall7eb38402015-01-08 17:19:54 -08001184 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001185 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001186 self.handle.sendline( "" )
1187 self.expect( "mininet>" )
1188 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001189 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001190 response = self.execute(
1191 cmd=cmd,
1192 prompt="mininet>",
1193 timeout=10 )
1194 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001195 response = self.handle.before
1196 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001197 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001198 main.log.error( self.name + ": TIMEOUT exception found" )
1199 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001200 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001201 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001202 main.log.error( self.name + ": EOF exception found" )
1203 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001204 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001205 except Exception:
1206 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001207 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001208
Jon Hall7eb38402015-01-08 17:19:54 -08001209 def getInterfaces( self, node ):
1210 """
1211 return information dict about interfaces connected to the node"""
1212 if self.handle:
1213 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001214 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001215 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001216 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001217 response = self.execute(
1218 cmd=cmd,
1219 prompt="mininet>",
1220 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001221 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001222 main.log.error( self.name + ": EOF exception found" )
1223 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001224 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001225 except Exception:
1226 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001227 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001228 return response
1229 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001230 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001231
Jon Hall7eb38402015-01-08 17:19:54 -08001232 def dump( self ):
1233 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001234 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001235 response = self.execute(
1236 cmd='dump',
1237 prompt='mininet>',
1238 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001239 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001240 main.log.error( self.name + ": EOF exception found" )
1241 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001242 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001243 except Exception:
1244 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001245 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001246 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001247
Jon Hall7eb38402015-01-08 17:19:54 -08001248 def intfs( self ):
1249 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001250 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001251 response = self.execute(
1252 cmd='intfs',
1253 prompt='mininet>',
1254 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001255 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001256 main.log.error( self.name + ": EOF exception found" )
1257 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001258 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001259 except Exception:
1260 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001261 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001262 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001263
Jon Hall7eb38402015-01-08 17:19:54 -08001264 def net( self ):
1265 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001266 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001267 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001268 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001269 main.log.error( self.name + ": EOF exception found" )
1270 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001271 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001272 except Exception:
1273 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001274 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001275 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001276
Devin Lima7cfdbd2017-09-29 15:02:22 -07001277 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001278 main.log.info( self.name + ": List network links" )
1279 try:
1280 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001281 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001282 except pexpect.EOF:
1283 main.log.error( self.name + ": EOF exception found" )
1284 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001285 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001286 except Exception:
1287 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001288 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001289 return response
1290
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001291 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001292 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001293 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001294
kelvin-onlab7cce9382015-07-17 10:21:03 -07001295 @parm:
1296 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1297 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001298 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001299 try:
1300 for host1 in hosts:
1301 for host2 in hosts:
1302 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001303 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1304 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001305 except Exception:
1306 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001307 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001308
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001309 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001310 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001311 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1312 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001313
kelvin-onlab7cce9382015-07-17 10:21:03 -07001314 @parm:
1315 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1316 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001317 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001318 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1319 try:
1320 # Setup the mininet command
1321 cmd1 = 'iperf ' + host1 + " " + host2
1322 self.handle.sendline( cmd1 )
1323 outcome = self.handle.expect( "mininet>", timeout )
1324 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001325
kelvin-onlab7cce9382015-07-17 10:21:03 -07001326 # checks if there are results in the mininet response
1327 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001328 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001329 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001330 response = response.split( "\r\n" )
1331 response = response[ len( response )-2 ]
1332 response = response.split( ": " )
1333 response = response[ len( response )-1 ]
1334 response = response.replace( "[", "" )
1335 response = response.replace( "]", "" )
1336 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001337
kelvin-onlab7cce9382015-07-17 10:21:03 -07001338 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001339 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001340
kelvin-onlab7cce9382015-07-17 10:21:03 -07001341 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001342 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001343 if len( bandwidth ) == 2:
1344 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001345 return main.TRUE
1346 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001347 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001348 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001349 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001350 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001351 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001352 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001353 main.log.error( self.name + ": TIMEOUT exception found" )
1354 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001355 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001356 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001357 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001358 self.handle.expect( "Interrupt" )
1359 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001360 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001361 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001362 main.log.error( self.name + ": EOF exception found" )
1363 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001364 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001365 except Exception:
1366 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001367 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001368
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001369 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001370 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1371 try:
1372 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001373 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001374 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001375 outcome1 = self.handle.expect( "mininet>" )
1376 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001377 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001378 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001379 response1 = self.handle.before
1380 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001381 print response1, response2
1382 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001383 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001384 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001385 return main.TRUE
1386 else:
1387 main.log.error( self.name + ": iperf test failed" )
1388 return main.FALSE
1389 except pexpect.TIMEOUT:
1390 main.log.error( self.name + ": TIMEOUT exception found" )
1391 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001392 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001393 self.handle.expect( "Interrupt" )
1394 self.handle.expect( "mininet>" )
1395 return main.FALSE
1396 except pexpect.EOF:
1397 main.log.error( self.name + ": EOF exception found" )
1398 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001399 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001400 except Exception:
1401 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001402 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001403
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001404 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001405 '''
GlennRC61321f22015-07-16 13:36:54 -07001406 Runs the iperfudp function with a given set of hosts and specified
1407 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001408
GlennRC61321f22015-07-16 13:36:54 -07001409 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001410 bandwidth: the targeted bandwidth, in megabits ('M')
1411 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001412 try:
1413 for host1 in hosts:
1414 for host2 in hosts:
1415 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001416 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1417 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001418 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001419 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001420 return main.FALSE
1421 except Exception:
1422 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001423 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001424
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001425 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001426 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001427 Creates an iperf UDP test with a specific bandwidth.
1428 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001429
kelvin-onlab7cce9382015-07-17 10:21:03 -07001430 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001431 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1432 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001433 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001434 try:
1435 # setup the mininet command
1436 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001437 self.handle.sendline( cmd )
1438 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001439 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001440
kelvin-onlab7cce9382015-07-17 10:21:03 -07001441 # check if there are in results in the mininet response
1442 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001443 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001444 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001445 response = response.split( "\r\n" )
1446 response = response[ len( response )-2 ]
1447 response = response.split( ": " )
1448 response = response[ len( response )-1 ]
1449 response = response.replace( "[", "" )
1450 response = response.replace( "]", "" )
1451 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001452
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001453 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001454
kelvin-onlab7cce9382015-07-17 10:21:03 -07001455 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001456 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001457 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001458 # if one entry is blank then something is wrong
1459 for item in mnBandwidth:
1460 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001461 main.log.error( self.name + ": Could not parse iperf output" )
1462 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001463 return main.FALSE
1464 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001465 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001466 return main.TRUE
1467 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001468 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001469 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001470
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001471 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001472 main.log.error( self.name + ": TIMEOUT exception found" )
1473 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001474 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001475 except pexpect.EOF:
1476 main.log.error( self.name + ": EOF exception found" )
1477 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001478 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001479 except Exception:
1480 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001481 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001482
Jon Hall7eb38402015-01-08 17:19:54 -08001483 def nodes( self ):
1484 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001485 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001486 response = self.execute(
1487 cmd='nodes',
1488 prompt='mininet>',
1489 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001490 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001491 main.log.error( self.name + ": EOF exception found" )
1492 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001493 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001494 except Exception:
1495 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001496 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001497 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001498
Jon Hall7eb38402015-01-08 17:19:54 -08001499 def pingpair( self ):
1500 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001501 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001502 response = self.execute(
1503 cmd='pingpair',
1504 prompt='mininet>',
1505 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001506 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001507 main.log.error( self.name + ": EOF exception found" )
1508 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001509 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001510 except Exception:
1511 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001512 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001513
Jon Hall7eb38402015-01-08 17:19:54 -08001514 if re.search( ',\s0\%\spacket\sloss', response ):
1515 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001516 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001517 else:
alisone4121a92016-11-22 16:31:36 -08001518 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001519 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001520
Jon Hall7eb38402015-01-08 17:19:54 -08001521 def link( self, **linkargs ):
1522 """
GlennRCed771242016-01-13 17:02:47 -08001523 Bring link( s ) between two nodes up or down
1524 """
Jon Hall6094a362014-04-11 14:46:56 -07001525 try:
GlennRCed771242016-01-13 17:02:47 -08001526 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1527 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1528 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1529 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1530
1531 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1532 cmd = "link {} {} {}".format( end1, end2, option )
1533 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001534 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001535 response = self.handle.before
1536 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001537 if "not in network" in response:
1538 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1539 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001540 return main.TRUE
1541 except pexpect.TIMEOUT:
1542 main.log.exception( self.name + ": Command timed out" )
1543 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001544 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001545 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001546 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001547 except Exception:
1548 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001549 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001550
pingping-lin8244a3b2015-09-16 13:36:56 -07001551 def switch( self, **switchargs ):
1552 """
1553 start/stop a switch
1554 """
1555 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1556 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1557 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1558 command = "switch " + str( sw ) + " " + str( option )
1559 main.log.info( command )
1560 try:
1561 self.handle.sendline( command )
1562 self.handle.expect( "mininet>" )
1563 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001564 main.log.error( self.name + ": TIMEOUT exception found" )
1565 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001566 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001567 except pexpect.EOF:
1568 main.log.error( self.name + ": EOF exception found" )
1569 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001570 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001571 return main.TRUE
1572
pingping-lin5bb663b2015-09-24 11:47:50 -07001573 def node( self, nodeName, commandStr ):
1574 """
1575 Carry out a command line on a given node
1576 @parm:
1577 nodeName: the node name in Mininet testbed
1578 commandStr: the command line will be carried out on the node
1579 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1580 """
1581 command = str( nodeName ) + " " + str( commandStr )
1582 main.log.info( command )
1583
1584 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001585 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001586 if re.search( "Unknown command", response ):
1587 main.log.warn( response )
1588 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001589 if re.search( "Permission denied", response ):
1590 main.log.warn( response )
1591 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001592 except pexpect.EOF:
1593 main.log.error( self.name + ": EOF exception found" )
1594 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001595 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001596 main.log.info( " response is :" )
1597 main.log.info( response )
1598 return response
1599
Jon Hall7eb38402015-01-08 17:19:54 -08001600 def yank( self, **yankargs ):
1601 """
1602 yank a mininet switch interface to a host"""
1603 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001604 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001605 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1606 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001607 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001608 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001609 response = self.execute(
1610 cmd=command,
1611 prompt="mininet>",
1612 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001613 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001614 main.log.error( self.name + ": EOF exception found" )
1615 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001616 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001617 except Exception:
1618 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001619 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001620 return main.TRUE
1621
Jon Hall7eb38402015-01-08 17:19:54 -08001622 def plug( self, **plugargs ):
1623 """
1624 plug the yanked mininet switch interface to a switch"""
1625 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001626 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001627 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1628 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001629 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001630 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001631 response = self.execute(
1632 cmd=command,
1633 prompt="mininet>",
1634 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001635 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001636 main.log.error( self.name + ": EOF exception found" )
1637 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001638 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001639 except Exception:
1640 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001641 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001642 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001643
Jon Hall7eb38402015-01-08 17:19:54 -08001644 def dpctl( self, **dpctlargs ):
1645 """
1646 Run dpctl command on all switches."""
1647 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001648 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001649 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1650 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1651 command = "dpctl " + cmd + " " + str( cmdargs )
1652 try:
1653 response = self.execute(
1654 cmd=command,
1655 prompt="mininet>",
1656 timeout=10 )
1657 except pexpect.EOF:
1658 main.log.error( self.name + ": EOF exception found" )
1659 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001660 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001661 except Exception:
1662 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001663 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001664 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001665
kelvin-onlabd3b64892015-01-20 13:26:24 -08001666 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001667 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001668 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001669 try:
1670 fileInput = path + '/lib/Mininet/INSTALL'
1671 version = super( Mininet, self ).getVersion()
1672 pattern = 'Mininet\s\w\.\w\.\w\w*'
1673 for line in open( fileInput, 'r' ).readlines():
1674 result = re.match( pattern, line )
1675 if result:
1676 version = result.group( 0 )
1677 return version
1678 except Exception:
1679 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001680 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001681
kelvin-onlabd3b64892015-01-20 13:26:24 -08001682 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001683 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001684 Parameters:
1685 sw: The name of an OVS switch. Example "s1"
1686 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001687 The output of the command from the mininet cli
1688 or main.FALSE on timeout"""
1689 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001690 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001691 response = self.execute(
1692 cmd=command,
1693 prompt="mininet>",
1694 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001695 if response:
Jon Hallab611372018-02-21 15:26:05 -08001696 if "no bridge named" in response:
1697 main.log.error( self.name + ": Error in getSwController: " +
1698 self.handle.before )
1699 return main.FALSE
1700 else:
1701 return response
admin2a9548d2014-06-17 14:08:07 -07001702 else:
1703 return main.FALSE
1704 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001705 main.log.error( self.name + ": EOF exception found" )
1706 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001707 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001708 except Exception:
1709 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001710 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001711
Charles Chan029be652015-08-24 01:46:10 +08001712 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001713 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001714 Description:
1715 Assign switches to the controllers ( for ovs use only )
1716 Required:
1717 sw - Name of the switch. This can be a list or a string.
1718 ip - Ip addresses of controllers. This can be a list or a string.
1719 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001720 port - ONOS use port 6653, if no list of ports is passed, then
1721 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001722 ptcp - ptcp number, This can be a string or a list that has
1723 the same length as switch. This is optional and not required
1724 when using ovs switches.
1725 NOTE: If switches and ptcp are given in a list type they should have the
1726 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1727 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001728
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001729 Return:
1730 Returns main.TRUE if mininet correctly assigned switches to
1731 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001732 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001733 """
1734 assignResult = main.TRUE
1735 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001736 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001737 command = "sh ovs-vsctl set-controller "
1738 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001739 try:
1740 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001741 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001742 if isinstance( port, types.StringType ) or \
1743 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001744 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001745 elif isinstance( port, types.ListType ):
1746 main.log.error( self.name + ": Only one controller " +
1747 "assigned and a list of ports has" +
1748 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001749 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001750 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001751 main.log.error( self.name + ": Invalid controller port " +
1752 "number. Please specify correct " +
1753 "controller port" )
1754 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001755
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001756 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001757 if isinstance( port, types.StringType ) or \
1758 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001759 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001760 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1761 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001762 elif isinstance( port, types.ListType ):
1763 if ( len( ip ) != len( port ) ):
1764 main.log.error( self.name + ": Port list = " +
1765 str( len( port ) ) +
1766 "should be the same as controller" +
1767 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001768 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001769 else:
1770 onosIp = ""
1771 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001772 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1773 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001774 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001775 main.log.error( self.name + ": Invalid controller port " +
1776 "number. Please specify correct " +
1777 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001778 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001779 else:
1780 main.log.error( self.name + ": Invalid ip address" )
1781 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001782
1783 if isinstance( sw, types.StringType ):
1784 command += sw + " "
1785 if ptcp:
1786 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001787 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001788 elif isinstance( ptcp, types.ListType ):
1789 main.log.error( self.name + ": Only one switch is " +
1790 "being set and multiple PTCP is " +
1791 "being passed " )
1792 else:
1793 main.log.error( self.name + ": Invalid PTCP" )
1794 ptcp = ""
1795 command += onosIp
1796 commandList.append( command )
1797
1798 elif isinstance( sw, types.ListType ):
1799 if ptcp:
1800 if isinstance( ptcp, types.ListType ):
1801 if len( ptcp ) != len( sw ):
1802 main.log.error( self.name + ": PTCP length = " +
1803 str( len( ptcp ) ) +
1804 " is not the same as switch" +
1805 " length = " +
1806 str( len( sw ) ) )
1807 return main.FALSE
1808 else:
1809 for switch, ptcpNum in zip( sw, ptcp ):
1810 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001811 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001812 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001813 tempCmd += onosIp
1814 commandList.append( tempCmd )
1815 else:
1816 main.log.error( self.name + ": Invalid PTCP" )
1817 return main.FALSE
1818 else:
1819 for switch in sw:
1820 tempCmd = "sh ovs-vsctl set-controller "
1821 tempCmd += switch + " " + onosIp
1822 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001823 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001824 main.log.error( self.name + ": Invalid switch type " )
1825 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001826
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001827 for cmd in commandList:
1828 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001829 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08001830 if "no bridge named" in self.handle.before:
1831 main.log.error( self.name + ": Error in assignSwController: " +
1832 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001833 except pexpect.TIMEOUT:
1834 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1835 return main.FALSE
1836 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 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001841 except pexpect.EOF:
1842 main.log.error( self.name + ": EOF exception found" )
1843 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001844 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001845 except Exception:
1846 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001847 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001848
kelvin-onlabd3b64892015-01-20 13:26:24 -08001849 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001850 """
1851 Removes the controller target from sw"""
1852 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001853 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001854 response = self.execute(
1855 cmd=command,
1856 prompt="mininet>",
1857 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001858 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001859 main.log.error( self.name + ": EOF exception found" )
1860 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001861 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001862 except Exception:
1863 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001864 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001865 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001866 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001867
kelvin-onlabd3b64892015-01-20 13:26:24 -08001868 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001869 """
Jon Hallb1290e82014-11-18 16:17:48 -05001870 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001871 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001872 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001873 NOTE: cannot currently specify what type of switch
1874 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001875 sw = name of the new switch as a string
1876 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001877 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001878 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001879 """
1880 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001881 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001882 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001883 response = self.execute(
1884 cmd=command,
1885 prompt="mininet>",
1886 timeout=10 )
1887 if re.search( "already exists!", response ):
1888 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001889 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001890 elif re.search( "Error", response ):
1891 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001892 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001893 elif re.search( "usage:", response ):
1894 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001895 return main.FALSE
1896 else:
1897 return main.TRUE
1898 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001899 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001900 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001901 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001902 except Exception:
1903 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001904 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001905
kelvin-onlabd3b64892015-01-20 13:26:24 -08001906 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001907 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001908 delete a switch from the mininet topology
1909 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001910 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001911 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001912 sw = name of the switch as a string
1913 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001914 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001915 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001916 response = self.execute(
1917 cmd=command,
1918 prompt="mininet>",
1919 timeout=10 )
1920 if re.search( "no switch named", response ):
1921 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001922 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001923 elif re.search( "Error", response ):
1924 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001925 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001926 elif re.search( "usage:", response ):
1927 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001928 return main.FALSE
1929 else:
1930 return main.TRUE
1931 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001932 main.log.error( self.name + ": EOF exception found" )
1933 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001934 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001935 except Exception:
1936 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001937 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001938
You Wangdb8cd0a2016-05-26 15:19:45 -07001939 def getSwitchRandom( self, timeout=60, nonCut=True ):
1940 """
1941 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001942 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001943 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001944 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07001945 it just randomly returns one switch from all current switches in
1946 Mininet.
1947 Returns the name of the chosen switch.
1948 """
1949 import random
1950 candidateSwitches = []
1951 try:
1952 if not nonCut:
1953 switches = self.getSwitches( timeout=timeout )
1954 assert len( switches ) != 0
1955 for switchName in switches.keys():
1956 candidateSwitches.append( switchName )
1957 else:
1958 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001959 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001960 return None
1961 self.graph.update( graphDict )
1962 candidateSwitches = self.graph.getNonCutVertices()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001963 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001964 return None
1965 elif len( candidateSwitches ) == 0:
1966 main.log.info( self.name + ": No candidate switch for deletion" )
1967 return None
1968 else:
1969 switch = random.sample( candidateSwitches, 1 )
1970 return switch[ 0 ]
1971 except KeyError:
1972 main.log.exception( self.name + ": KeyError exception found" )
1973 return None
1974 except AssertionError:
1975 main.log.exception( self.name + ": AssertionError exception found" )
1976 return None
1977 except Exception:
1978 main.log.exception( self.name + ": Uncaught exception" )
1979 return None
1980
1981 def delSwitchRandom( self, timeout=60, nonCut=True ):
1982 """
1983 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001984 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001985 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001986 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07001987 otherwise it just randomly delete one switch from all current
1988 switches in Mininet.
1989 Returns the name of the deleted switch
1990 """
1991 try:
1992 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001993 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001994 return None
1995 else:
1996 deletionResult = self.delSwitch( switch )
1997 if deletionResult:
1998 return switch
1999 else:
2000 return None
2001 except Exception:
2002 main.log.exception( self.name + ": Uncaught exception" )
2003 return None
2004
kelvin-onlabd3b64892015-01-20 13:26:24 -08002005 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002006 """
2007 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002008 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002009 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002010 NOTE: cannot currently specify what type of link
2011 required params:
2012 node1 = the string node name of the first endpoint of the link
2013 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002014 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002015 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002016 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002017 response = self.execute(
2018 cmd=command,
2019 prompt="mininet>",
2020 timeout=10 )
2021 if re.search( "doesnt exist!", response ):
2022 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002023 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002024 elif re.search( "Error", response ):
2025 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002026 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002027 elif re.search( "usage:", response ):
2028 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002029 return main.FALSE
2030 else:
2031 return main.TRUE
2032 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002033 main.log.error( self.name + ": EOF exception found" )
2034 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002035 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002036 except Exception:
2037 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002038 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002039
kelvin-onlabd3b64892015-01-20 13:26:24 -08002040 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002041 """
2042 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002043 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002044 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002045 required params:
2046 node1 = the string node name of the first endpoint of the link
2047 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002048 returns: main.FALSE on an error, else main.TRUE
2049 """
Jon Hallffb386d2014-11-21 13:43:38 -08002050 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002051 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002052 response = self.execute(
2053 cmd=command,
2054 prompt="mininet>",
2055 timeout=10 )
2056 if re.search( "no node named", response ):
2057 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002058 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002059 elif re.search( "Error", response ):
2060 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002061 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002062 elif re.search( "usage:", response ):
2063 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002064 return main.FALSE
2065 else:
2066 return main.TRUE
2067 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002068 main.log.error( self.name + ": EOF exception found" )
2069 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002070 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002071 except Exception:
2072 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002073 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002074
You Wangdb8cd0a2016-05-26 15:19:45 -07002075 def getLinkRandom( self, timeout=60, nonCut=True ):
2076 """
2077 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002078 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002079 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002080 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002081 it just randomly returns one link from all current links in
2082 Mininet.
2083 Returns the link as a list, e.g. [ 's1', 's2' ]
2084 """
2085 import random
2086 candidateLinks = []
2087 try:
2088 if not nonCut:
2089 links = self.getLinks( timeout=timeout )
2090 assert len( links ) != 0
2091 for link in links:
2092 # Exclude host-switch link
2093 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2094 continue
2095 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2096 else:
2097 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002098 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002099 return None
2100 self.graph.update( graphDict )
2101 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002102 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002103 return None
2104 elif len( candidateLinks ) == 0:
2105 main.log.info( self.name + ": No candidate link for deletion" )
2106 return None
2107 else:
2108 link = random.sample( candidateLinks, 1 )
2109 return link[ 0 ]
2110 except KeyError:
2111 main.log.exception( self.name + ": KeyError exception found" )
2112 return None
2113 except AssertionError:
2114 main.log.exception( self.name + ": AssertionError exception found" )
2115 return None
2116 except Exception:
2117 main.log.exception( self.name + ": Uncaught exception" )
2118 return None
2119
2120 def delLinkRandom( self, timeout=60, nonCut=True ):
2121 """
2122 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002123 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002124 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002125 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002126 otherwise it just randomly delete one link from all current links
2127 in Mininet.
2128 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2129 """
2130 try:
2131 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002132 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002133 return None
2134 else:
2135 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2136 if deletionResult:
2137 return link
2138 else:
2139 return None
2140 except Exception:
2141 main.log.exception( self.name + ": Uncaught exception" )
2142 return None
2143
kelvin-onlabd3b64892015-01-20 13:26:24 -08002144 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002145 """
Jon Hallb1290e82014-11-18 16:17:48 -05002146 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002147 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002148 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002149 NOTE: cannot currently specify what type of host
2150 required params:
2151 hostname = the string hostname
2152 optional key-value params
2153 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002154 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002155 """
2156 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002157 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002158 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002159 response = self.execute(
2160 cmd=command,
2161 prompt="mininet>",
2162 timeout=10 )
2163 if re.search( "already exists!", response ):
2164 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002165 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002166 elif re.search( "doesnt exists!", response ):
2167 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002168 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002169 elif re.search( "Error", response ):
2170 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002171 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002172 elif re.search( "usage:", response ):
2173 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002174 return main.FALSE
2175 else:
2176 return main.TRUE
2177 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002178 main.log.error( self.name + ": EOF exception found" )
2179 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002180 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002181 except Exception:
2182 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002183 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002184
kelvin-onlabd3b64892015-01-20 13:26:24 -08002185 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002186 """
2187 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002188 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002189 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002190 NOTE: this uses a custom mn function
2191 required params:
2192 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002193 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002194 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002195 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002196 response = self.execute(
2197 cmd=command,
2198 prompt="mininet>",
2199 timeout=10 )
2200 if re.search( "no host named", response ):
2201 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002202 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002203 elif re.search( "Error", response ):
2204 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002205 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002206 elif re.search( "usage:", response ):
2207 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002208 return main.FALSE
2209 else:
2210 return main.TRUE
2211 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002212 main.log.error( self.name + ": EOF exception found" )
2213 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002214 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002215 except Exception:
2216 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002217 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002218
Jon Hall7eb38402015-01-08 17:19:54 -08002219 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002220 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002221 Called at the end of the test to stop the mininet and
2222 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002223 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002224 try:
2225 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002226 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002227 timeout=2 )
2228 response = main.TRUE
2229 if i == 0:
2230 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002231 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002232 return main.TRUE
2233 # print "Disconnecting Mininet"
2234 if self.handle:
2235 self.handle.sendline( "exit" )
2236 self.handle.expect( "exit" )
2237 self.handle.expect( "(.*)" )
2238 else:
2239 main.log.error( "Connection failed to the host" )
2240 return response
2241 except pexpect.EOF:
2242 main.log.error( self.name + ": EOF exception found" )
2243 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002244 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002245 except Exception:
2246 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002247 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002248
Devin Lima7cfdbd2017-09-29 15:02:22 -07002249 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002250 """
Jon Hall21270ac2015-02-16 17:59:55 -08002251 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002252 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002253 main.FALSE if the pexpect handle does not exist.
2254
Jon Halld61331b2015-02-17 16:35:47 -08002255 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002256 """
Jon Halld61331b2015-02-17 16:35:47 -08002257 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002258 response = ''
2259 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002260 try:
Jon Halld80cc142015-07-06 13:36:05 -07002261 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002262 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002263 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002264 pexpect.EOF,
2265 pexpect.TIMEOUT ],
2266 timeout )
2267 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002268 main.log.info( "Exiting mininet.." )
2269 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002270 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002271 prompt=self.prompt,
2272 timeout=exitTimeout )
2273 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002274 self.handle.sendline( "sudo mn -c" )
2275 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002276
Jeremyd9e4eb12016-04-13 12:09:06 -07002277 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002278 main.log.info( " Mininet trying to exit while not " +
2279 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002280 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002281 elif i == 2:
2282 main.log.error( "Something went wrong exiting mininet" )
2283 elif i == 3: # timeout
2284 main.log.error( "Something went wrong exiting mininet " +
2285 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002286
You Wang18db8592018-04-02 13:52:03 -07002287 self.handle.sendline( "" )
2288 self.handle.expect( self.prompt )
2289 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2290
Hari Krishnab35c6d02015-03-18 11:13:51 -07002291 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002292 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002293 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002294 self.handle.sendline(
2295 "sudo kill -9 \`ps -ef | grep \"" +
2296 fileName +
2297 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002298 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002299 main.log.error( self.name + ": TIMEOUT exception found" )
2300 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002301 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002302 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002303 main.log.error( self.name + ": EOF exception found" )
2304 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002305 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002306 except Exception:
2307 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002308 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002309 else:
2310 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002311 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002312 return response
2313
YPZhang26a139e2016-04-25 14:01:55 -07002314 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002315 """
2316 Description:
2317 Sends arp message from mininet host for hosts discovery
2318 Required:
2319 host - hosts name
2320 Optional:
2321 ip - ip address that does not exist in the network so there would
2322 be no reply.
2323 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002324 if ethDevice:
2325 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002326 cmd = srcHost + " arping -c1 "
2327 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002328 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 -07002329 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002330 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002331 if output:
2332 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002333 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002334 i = self.handle.expect( [ "mininet>", "arping: " ] )
2335 if i == 0:
2336 return main.TRUE
2337 elif i == 1:
2338 response = self.handle.before + self.handle.after
2339 self.handle.expect( "mininet>" )
2340 response += self.handle.before + self.handle.after
2341 main.log.warn( "Error sending arping, output was: " +
2342 response )
2343 return main.FALSE
2344 except pexpect.TIMEOUT:
2345 main.log.error( self.name + ": TIMEOUT exception found" )
2346 main.log.warn( self.handle.before )
2347 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002348 except pexpect.EOF:
2349 main.log.error( self.name + ": EOF exception found" )
2350 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002351 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002352 except Exception:
2353 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002354 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002355
Jon Hall7eb38402015-01-08 17:19:54 -08002356 def decToHex( self, num ):
2357 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002358
Jon Hall7eb38402015-01-08 17:19:54 -08002359 def getSwitchFlowCount( self, switch ):
2360 """
2361 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002362 if self.handle:
2363 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2364 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002365 response = self.execute(
2366 cmd=cmd,
2367 prompt="mininet>",
2368 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002369 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002370 main.log.error( self.name + ": EOF exception found" )
2371 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002372 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002373 except Exception:
2374 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002375 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002376 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002377 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002378 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002379 main.log.info(
2380 "Couldn't find flows on switch %s, found: %s" %
2381 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002382 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002383 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002384 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002385 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002386
Jon Hall9ed8f372016-02-24 17:34:07 -08002387 def checkFlows( self, sw, dumpFormat=None ):
2388 if dumpFormat:
2389 command = "sh ovs-ofctl -F " + \
2390 dumpFormat + " dump-flows " + str( sw )
2391 else:
2392 command = "sh ovs-ofctl dump-flows " + str( sw )
2393 try:
2394 response = self.execute(
2395 cmd=command,
2396 prompt="mininet>",
2397 timeout=10 )
2398 return response
2399 except pexpect.EOF:
2400 main.log.error( self.name + ": EOF exception found" )
2401 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002402 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002403 except Exception:
2404 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002405 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002406
GlennRC68467eb2015-11-16 18:01:01 -08002407 def flowTableComp( self, flowTable1, flowTable2 ):
2408 # This function compares the selctors and treatments of each flow
2409 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002410 assert flowTable1, "flowTable1 is empty or None"
2411 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002412 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002413 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002414 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002415 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002416 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2417 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002418 for field in dFields:
2419 try:
2420 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002421 except KeyError:
2422 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002423 try:
2424 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002425 except KeyError:
2426 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002427 for i in range( len( flowTable1 ) ):
2428 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002429 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002430 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002431 returnValue = main.FALSE
2432 break
2433 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002434 except AssertionError:
2435 main.log.exception( "Nothing to compare" )
2436 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002437 except Exception:
2438 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002439 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002440
GlennRC528ad292015-11-12 10:38:18 -08002441 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002442 '''
GlennRC956ea742015-11-05 16:14:15 -08002443 Discription: Parses flows into json format.
2444 NOTE: this can parse any string thats separated with commas
2445 Arguments:
2446 Required:
2447 flows: a list of strings that represnt flows
2448 Optional:
2449 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2450 debug: prints out the final result
2451 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002452 '''
GlennRC528ad292015-11-12 10:38:18 -08002453 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002454 try:
2455 for flow in flowTable:
2456 jsonFlow = {}
2457 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002458 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002459 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002460 for i in range( len( parsedFlow ) ):
2461 item = parsedFlow[ i ]
2462 if item[ 0 ] == " ":
2463 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002464 # grab the selector and treatment from the parsed flow
2465 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002466 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002467 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002468 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002469 index = 0
2470 # parse the flags
2471 # NOTE: This only parses one flag
2472 flag = {}
2473 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002474 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002475 index += 1
2476 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002477 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002478 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002479 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002480 # the priority is stuck in the selecter so put it back
2481 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002482 if 'priority' in sel[0]:
2483 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002484 # parse selector
2485 criteria = []
2486 for item in sel:
2487 # this is the type of the packet e.g. "arp"
2488 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002489 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002490 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002491 field = item.split( "=" )
2492 criteria.append( { field[ 0 ]: field[ 1 ] } )
2493 selector = { "selector": { "criteria": sorted( criteria ) } }
2494 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002495 # get rid of the action part e.g. "action=output:2"
2496 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002497 treat = treat.split( "=" )
2498 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002499 # parse treatment
2500 action = []
2501 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002502 if ":" in item:
2503 field = item.split( ":" )
2504 action.append( { field[ 0 ]: field[ 1 ] } )
2505 else:
2506 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2507 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002508 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002509 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002510 # parse the rest of the flow
2511 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002512 field = item.split( "=" )
2513 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002514 # add the treatment and the selector to the json flow
2515 jsonFlow.update( selector )
2516 jsonFlow.update( treatment )
2517 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002518
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002519 if debug:
2520 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002521
You Wang91c37cf2016-05-23 09:39:42 -07002522 # add the json flow to the json flow table
2523 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002524
You Wang91c37cf2016-05-23 09:39:42 -07002525 return jsonFlowTable
2526
2527 except IndexError:
2528 main.log.exception( self.name + ": IndexError found" )
2529 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002530 except pexpect.EOF:
2531 main.log.error( self.name + ": EOF exception found" )
2532 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002533 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002534 except Exception:
2535 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002536 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002537
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002538 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002539 '''
2540 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002541 Each element is a flow.
2542 Arguments:
2543 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002544 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002545 a list of switches.
2546 Optional:
2547 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2548 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002549 '''
GlennRC956ea742015-11-05 16:14:15 -08002550 try:
2551 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002552 if isinstance( sw, list ):
2553 switches.extend( sw )
2554 else:
2555 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002556
2557 flows = []
2558 for s in switches:
2559 cmd = "sh ovs-ofctl dump-flows " + s
2560
GlennRC528ad292015-11-12 10:38:18 -08002561 if "1.0" == version:
2562 cmd += " -F OpenFlow10-table_id"
2563 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002564 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002565
2566 main.log.info( "Sending: " + cmd )
2567 self.handle.sendline( cmd )
2568 self.handle.expect( "mininet>" )
2569 response = self.handle.before
2570 response = response.split( "\r\n" )
2571 # dump the first two elements and the last
2572 # the first element is the command that was sent
2573 # the second is the table header
2574 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002575 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002576 flows.extend( response )
2577
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002578 if debug:
2579 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002580
GlennRC528ad292015-11-12 10:38:18 -08002581 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002582
GlennRC956ea742015-11-05 16:14:15 -08002583 except pexpect.EOF:
2584 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002585 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002586 except Exception:
2587 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002588 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002589
2590 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002591 '''
GlennRC956ea742015-11-05 16:14:15 -08002592 Discription: Checks whether the ID provided matches a flow ID in Mininet
2593 Arguments:
2594 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002595 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002596 a list of switches.
2597 flowId: the flow ID in hex format. Can also be a list of IDs
2598 Optional:
2599 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2600 debug: prints out the final result
2601 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2602 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002603 '''
GlennRC956ea742015-11-05 16:14:15 -08002604 try:
2605 main.log.info( "Getting flows from Mininet" )
2606 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002607 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002608 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002609
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002610 if debug:
2611 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002612
2613 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002614 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002615 result = False
2616 for f in flows:
2617 if flowId in f.get( 'cookie' ):
2618 result = True
2619 break
2620 # flowId is a list
2621 else:
2622 result = True
2623 # Get flow IDs from Mininet
2624 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2625 # Save the IDs that are not in Mininet
2626 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2627
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002628 if debug:
2629 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002630
2631 # Print out the IDs that are not in Mininet
2632 if absentIds:
2633 main.log.warn( "Absent ids: {}".format( absentIds ) )
2634 result = False
2635
2636 return main.TRUE if result else main.FALSE
2637
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002638 except pexpect.EOF:
2639 main.log.error( self.name + ": EOF exception found" )
2640 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002641 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002642 except Exception:
2643 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002644 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002645
Charles Chan029be652015-08-24 01:46:10 +08002646 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002647 """
Jon Hallefbd9792015-03-05 16:11:36 -08002648 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002649 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002650 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002651 self.handle.sendline( "" )
2652 self.handle.expect( "mininet>" )
2653 self.handle.sendline(
2654 "sh sudo tcpdump -n -i " +
2655 intf +
2656 " " +
2657 port +
2658 " -w " +
2659 filename.strip() +
2660 " &" )
2661 self.handle.sendline( "" )
2662 i = self.handle.expect( [ 'No\ssuch\device',
2663 'listening\son',
2664 pexpect.TIMEOUT,
2665 "mininet>" ],
2666 timeout=10 )
2667 main.log.warn( self.handle.before + self.handle.after )
2668 self.handle.sendline( "" )
2669 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002670 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002671 main.log.error(
2672 self.name +
2673 ": tcpdump - No such device exists. " +
2674 "tcpdump attempted on: " +
2675 intf )
admin2a9548d2014-06-17 14:08:07 -07002676 return main.FALSE
2677 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002678 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002679 return main.TRUE
2680 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002681 main.log.error(
2682 self.name +
2683 ": tcpdump command timed out! Check interface name," +
2684 " given interface was: " +
2685 intf )
admin2a9548d2014-06-17 14:08:07 -07002686 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002687 elif i == 3:
2688 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002689 return main.TRUE
2690 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002691 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002692 return main.FALSE
2693 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002694 main.log.error( self.name + ": EOF exception found" )
2695 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002696 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002697 except Exception:
2698 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002699 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002700
kelvin-onlabd3b64892015-01-20 13:26:24 -08002701 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002702 """
2703 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002704 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002705 self.handle.sendline( "sh sudo pkill tcpdump" )
2706 self.handle.expect( "mininet>" )
2707 self.handle.sendline( "" )
2708 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002709 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002710 main.log.error( self.name + ": TIMEOUT exception found" )
2711 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002712 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002713 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002714 main.log.error( self.name + ": EOF exception found" )
2715 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002716 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002717 except Exception:
2718 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002719 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002720
Jon Halld80cc142015-07-06 13:36:05 -07002721 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002722 """
2723 Read ports from a Mininet switch.
2724
2725 Returns a json structure containing information about the
2726 ports of the given switch.
2727 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002728 try:
2729 response = self.getInterfaces( nodeName )
2730 # TODO: Sanity check on response. log if no such switch exists
2731 ports = []
2732 for line in response.split( "\n" ):
2733 if not line.startswith( "name=" ):
2734 continue
2735 portVars = {}
2736 for var in line.split( "," ):
2737 key, value = var.split( "=" )
2738 portVars[ key ] = value
2739 isUp = portVars.pop( 'enabled', "True" )
2740 isUp = "True" in isUp
2741 if verbose:
2742 main.log.info( "Reading switch port %s(%s)" %
2743 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2744 mac = portVars[ 'mac' ]
2745 if mac == 'None':
2746 mac = None
2747 ips = []
2748 ip = portVars[ 'ip' ]
2749 if ip == 'None':
2750 ip = None
2751 ips.append( ip )
2752 name = portVars[ 'name' ]
2753 if name == 'None':
2754 name = None
2755 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2756 if name == 'lo':
2757 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2758 else:
2759 portNo = re.search( portRe, name ).group( 'port' )
2760 ports.append( { 'of_port': portNo,
2761 'mac': str( mac ).replace( '\'', '' ),
2762 'name': name,
2763 'ips': ips,
2764 'enabled': isUp } )
2765 return ports
2766 except pexpect.EOF:
2767 main.log.error( self.name + ": EOF exception found" )
2768 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002769 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002770 except Exception:
2771 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002772 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002773
You Wangdb8cd0a2016-05-26 15:19:45 -07002774 def getOVSPorts( self, nodeName ):
2775 """
2776 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2777
2778 Returns a list of dictionaries containing information about each
2779 port of the given switch.
2780 """
2781 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2782 try:
2783 response = self.execute(
2784 cmd=command,
2785 prompt="mininet>",
2786 timeout=10 )
2787 ports = []
2788 if response:
2789 for line in response.split( "\n" ):
2790 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2791 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002792 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002793 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2794 result = re.search( pattern, line )
2795 if result:
2796 index = result.group( 'index' )
2797 name = result.group( 'name' )
2798 # This port number is extracted from port name
2799 port = result.group( 'port' )
2800 mac = result.group( 'mac' )
2801 ports.append( { 'index': index,
2802 'name': name,
2803 'port': port,
2804 'mac': mac } )
2805 return ports
2806 except pexpect.EOF:
2807 main.log.error( self.name + ": EOF exception found" )
2808 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002809 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002810 except Exception:
2811 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002812 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002813
Devin Lima7cfdbd2017-09-29 15:02:22 -07002814 def getSwitches( self, verbose=False, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002815 """
2816 Read switches from Mininet.
2817
2818 Returns a dictionary whose keys are the switch names and the value is
2819 a dictionary containing information about the switch.
2820 """
Jon Halla22481b2015-07-28 17:46:01 -07002821 # NOTE: To support new Mininet switch classes, just append the new
2822 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002823
Jon Halla22481b2015-07-28 17:46:01 -07002824 # Regex patterns to parse 'dump' output
2825 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002826 # <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 -07002827 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002828 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2829 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2830 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002831 try:
2832 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2833 swRE = r"<(?P<class>" + switchClasses + r")" +\
2834 r"(?P<options>\{.*\})?\s" +\
2835 r"(?P<name>[^:]+)\:\s" +\
2836 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2837 r"\spid=(?P<pid>(\d)+)"
2838 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002839 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002840 output = {}
2841 dump = self.dump().split( "\n" )
2842 for line in dump:
2843 result = re.search( swRE, line, re.I )
2844 if result:
2845 name = result.group( 'name' )
2846 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2847 pid = result.group( 'pid' )
2848 swClass = result.group( 'class' )
2849 options = result.group( 'options' )
2850 if verbose:
2851 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2852 ports = self.getPorts( name )
2853 output[ name ] = { "dpid": dpid,
2854 "ports": ports,
2855 "swClass": swClass,
2856 "pid": pid,
2857 "options": options }
2858 return output
2859 except pexpect.EOF:
2860 main.log.error( self.name + ": EOF exception found" )
2861 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002862 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002863 except Exception:
2864 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002865 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002866
You Wangd66de192018-04-30 17:30:12 -07002867 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002868 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2869 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002870 """
2871 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002872 Optional:
2873 hostClass: it is used to match the class of the mininet host. It
2874 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002875 Returns a dictionary whose keys are the host names and the value is
2876 a dictionary containing information about the host.
2877 """
2878 # Regex patterns to parse dump output
2879 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002880 # <Host h1: pid=12725>
2881 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2882 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2883 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002884 # NOTE: Does not correctly match hosts with multi-links
2885 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2886 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002887 try:
You Wang53dba1e2018-02-02 17:45:44 -08002888 if not isinstance( hostClass, types.ListType ):
2889 hostClass = [ str( hostClass ) ]
2890 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002891 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2892 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2893 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002894 if update:
2895 # update mn port info
2896 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002897 # Get mininet dump
2898 dump = self.dump().split( "\n" )
2899 hosts = {}
2900 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002901 result = re.search( hostRE, line )
2902 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002903 name = result.group( 'name' )
2904 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002905 if getInterfaces:
2906 response = self.getInterfaces( name )
2907 # Populate interface info
2908 for line in response.split( "\n" ):
2909 if line.startswith( "name=" ):
2910 portVars = {}
2911 for var in line.split( "," ):
2912 key, value = var.split( "=" )
2913 portVars[ key ] = value
2914 isUp = portVars.pop( 'enabled', "True" )
2915 isUp = "True" in isUp
2916 if verbose:
2917 main.log.info( "Reading host port %s(%s)" %
2918 ( portVars[ 'name' ],
2919 portVars[ 'mac' ] ) )
2920 mac = portVars[ 'mac' ]
2921 if mac == 'None':
2922 mac = None
2923 ips = []
2924 ip = portVars[ 'ip' ]
2925 if ip == 'None':
2926 ip = None
2927 ips.append( ip )
2928 intfName = portVars[ 'name' ]
2929 if name == 'None':
2930 name = None
2931 interfaces.append( {
2932 "name": intfName,
2933 "ips": ips,
2934 "mac": str( mac ),
2935 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002936 hosts[ name ] = { "interfaces": interfaces }
2937 return hosts
2938 except pexpect.EOF:
2939 main.log.error( self.name + ": EOF exception found" )
2940 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002941 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002942 except Exception:
2943 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002944 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002945
Devin Lima7cfdbd2017-09-29 15:02:22 -07002946 def getLinks( self, timeout=20, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002947 """
2948 Gathers information about current Mininet links. These links may not
2949 be up if one of the ports is down.
2950
2951 Returns a list of dictionaries with link endpoints.
2952
2953 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002954 { 'node1': str( node1 name )
2955 'node2': str( node2 name )
2956 'port1': str( port1 of_port )
2957 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002958 Note: The port number returned is the eth#, not necessarily the of_port
2959 number. In Mininet, for OVS switch, these should be the same. For
2960 hosts, this is just the eth#.
2961 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002962 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002963 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002964 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002965
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002966 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002967 # s1-eth3<->s2-eth1 (OK OK)
2968 # s13-eth3<->h27-eth0 (OK OK)
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002969 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2970 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2971 links = []
2972 for line in response:
2973 match = re.search( linkRE, line )
2974 if match:
2975 node1 = match.group( 'node1' )
2976 node2 = match.group( 'node2' )
2977 port1 = match.group( 'port1' )
2978 port2 = match.group( 'port2' )
2979 links.append( { 'node1': node1,
2980 'node2': node2,
2981 'port1': port1,
2982 'port2': port2 } )
2983 return links
2984
2985 except pexpect.EOF:
2986 main.log.error( self.name + ": EOF exception found" )
2987 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002988 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002989 except Exception:
2990 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002991 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002992
2993 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002994 """
2995 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002996 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002997
Jon Hallafa8a472015-06-12 14:02:42 -07002998 Dependencies:
2999 1. numpy - "sudo pip install numpy"
3000 """
3001 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003002 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003003 try:
3004 mnDPIDs = []
3005 for swName, switch in switches.iteritems():
3006 mnDPIDs.append( switch[ 'dpid' ].lower() )
3007 mnDPIDs.sort()
3008 if switchesJson == "": # if rest call fails
3009 main.log.error(
3010 self.name +
3011 ".compareSwitches(): Empty JSON object given from ONOS" )
3012 return main.FALSE
3013 onos = switchesJson
3014 onosDPIDs = []
3015 for switch in onos:
3016 if switch[ 'available' ]:
3017 onosDPIDs.append(
3018 switch[ 'id' ].replace(
3019 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003020 '' ).replace(
3021 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003022 '' ).lower() )
3023 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003024
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003025 if mnDPIDs != onosDPIDs:
3026 switchResults = main.FALSE
3027 main.log.error( "Switches in MN but not in ONOS:" )
3028 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3029 main.log.error( str( list1 ) )
3030 main.log.error( "Switches in ONOS but not in MN:" )
3031 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3032 main.log.error( str( list2 ) )
3033 else: # list of dpid's match in onos and mn
3034 switchResults = main.TRUE
3035 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003036
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003037 # FIXME: this does not look for extra ports in ONOS, only checks that
3038 # ONOS has what is in MN
3039 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003040
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003041 # PORTS
3042 for name, mnSwitch in switches.iteritems():
3043 mnPorts = []
3044 onosPorts = []
3045 switchResult = main.TRUE
3046 for port in mnSwitch[ 'ports' ]:
3047 if port[ 'enabled' ]:
3048 mnPorts.append( int( port[ 'of_port' ] ) )
3049 for onosSwitch in portsJson:
3050 if onosSwitch[ 'device' ][ 'available' ]:
3051 if onosSwitch[ 'device' ][ 'id' ].replace(
3052 ':',
3053 '' ).replace(
3054 "of",
3055 '' ) == mnSwitch[ 'dpid' ]:
3056 for port in onosSwitch[ 'ports' ]:
3057 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003058 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003059 # onosPorts.append( 'local' )
3060 onosPorts.append( long( uint64( -2 ) ) )
3061 else:
3062 onosPorts.append( int( port[ 'port' ] ) )
3063 break
3064 mnPorts.sort( key=float )
3065 onosPorts.sort( key=float )
3066
3067 mnPortsLog = mnPorts
3068 onosPortsLog = onosPorts
3069 mnPorts = [ x for x in mnPorts ]
3070 onosPorts = [ x for x in onosPorts ]
3071
3072 # TODO: handle other reserved port numbers besides LOCAL
3073 # NOTE: Reserved ports
3074 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3075 # long( uint64( -2 ) )
3076 for mnPort in mnPortsLog:
3077 if mnPort in onosPorts:
3078 # don't set results to true here as this is just one of
3079 # many checks and it might override a failure
3080 mnPorts.remove( mnPort )
3081 onosPorts.remove( mnPort )
3082
3083 # NOTE: OVS reports this as down since there is no link
3084 # So ignoring these for now
3085 # TODO: Come up with a better way of handling these
3086 if 65534 in mnPorts:
3087 mnPorts.remove( 65534 )
3088 if long( uint64( -2 ) ) in onosPorts:
3089 onosPorts.remove( long( uint64( -2 ) ) )
3090 if len( mnPorts ): # the ports of this switch don't match
3091 switchResult = main.FALSE
3092 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3093 if len( onosPorts ): # the ports of this switch don't match
3094 switchResult = main.FALSE
3095 main.log.warn(
3096 "Ports in ONOS but not MN: " +
3097 str( onosPorts ) )
3098 if switchResult == main.FALSE:
3099 main.log.error(
3100 "The list of ports for switch %s(%s) does not match:" %
3101 ( name, mnSwitch[ 'dpid' ] ) )
3102 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3103 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3104 portsResults = portsResults and switchResult
3105 finalResults = finalResults and portsResults
3106 return finalResults
3107 except pexpect.EOF:
3108 main.log.error( self.name + ": EOF exception found" )
3109 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003110 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003111 except Exception:
3112 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003113 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003114
Jon Hallafa8a472015-06-12 14:02:42 -07003115 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003116 """
3117 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003118 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003119
Jon Hallafa8a472015-06-12 14:02:42 -07003120 """
Jon Hall7eb38402015-01-08 17:19:54 -08003121 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003122 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003123 try:
3124 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003125
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003126 mnLinks = []
3127 for l in links:
3128 try:
3129 node1 = switches[ l[ 'node1' ] ]
3130 node2 = switches[ l[ 'node2' ] ]
3131 enabled = True
3132 for port in node1[ 'ports' ]:
3133 if port[ 'of_port' ] == l[ 'port1' ]:
3134 enabled = enabled and port[ 'enabled' ]
3135 for port in node2[ 'ports' ]:
3136 if port[ 'of_port' ] == l[ 'port2' ]:
3137 enabled = enabled and port[ 'enabled' ]
3138 if enabled:
3139 mnLinks.append( l )
3140 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003141 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003142 if 2 * len( mnLinks ) == len( onos ):
3143 linkResults = main.TRUE
3144 else:
3145 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003146 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003147 "Mininet has " + str( len( mnLinks ) ) +
3148 " bidirectional links and ONOS has " +
3149 str( len( onos ) ) + " unidirectional links" )
3150
3151 # iterate through MN links and check if an ONOS link exists in
3152 # both directions
3153 for link in mnLinks:
3154 # TODO: Find a more efficient search method
3155 node1 = None
3156 port1 = None
3157 node2 = None
3158 port2 = None
3159 firstDir = main.FALSE
3160 secondDir = main.FALSE
3161 for swName, switch in switches.iteritems():
3162 if swName == link[ 'node1' ]:
3163 node1 = switch[ 'dpid' ]
3164 for port in switch[ 'ports' ]:
3165 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3166 port1 = port[ 'of_port' ]
3167 if node1 is not None and node2 is not None:
3168 break
3169 if swName == link[ 'node2' ]:
3170 node2 = switch[ 'dpid' ]
3171 for port in switch[ 'ports' ]:
3172 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3173 port2 = port[ 'of_port' ]
3174 if node1 is not None and node2 is not None:
3175 break
3176
3177 for onosLink in onos:
3178 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3179 ":", '' ).replace( "of", '' )
3180 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3181 ":", '' ).replace( "of", '' )
3182 onosPort1 = onosLink[ 'src' ][ 'port' ]
3183 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3184
3185 # check onos link from node1 to node2
3186 if str( onosNode1 ) == str( node1 ) and str(
3187 onosNode2 ) == str( node2 ):
3188 if int( onosPort1 ) == int( port1 ) and int(
3189 onosPort2 ) == int( port2 ):
3190 firstDir = main.TRUE
3191 else:
Jon Hallab611372018-02-21 15:26:05 -08003192 # The right switches, but wrong ports, could be
3193 # another link between these devices, or onos
3194 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003195 main.log.warn(
3196 'The port numbers do not match for ' +
3197 str( link ) +
3198 ' between ONOS and MN. When checking ONOS for ' +
3199 'link %s/%s -> %s/%s' %
3200 ( node1, port1, node2, port2 ) +
3201 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003202 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3203 '. This could be another link between these devices' +
3204 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003205
3206 # check onos link from node2 to node1
3207 elif ( str( onosNode1 ) == str( node2 ) and
3208 str( onosNode2 ) == str( node1 ) ):
3209 if ( int( onosPort1 ) == int( port2 )
3210 and int( onosPort2 ) == int( port1 ) ):
3211 secondDir = main.TRUE
3212 else:
Jon Hallab611372018-02-21 15:26:05 -08003213 # The right switches, but wrong ports, could be
3214 # another link between these devices, or onos
3215 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003216 main.log.warn(
3217 'The port numbers do not match for ' +
3218 str( link ) +
3219 ' between ONOS and MN. When checking ONOS for ' +
3220 'link %s/%s -> %s/%s' %
3221 ( node1, port1, node2, port2 ) +
3222 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003223 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3224 '. This could be another link between these devices' +
3225 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003226 else: # this is not the link you're looking for
3227 pass
3228 if not firstDir:
3229 main.log.error(
3230 'ONOS does not have the link %s/%s -> %s/%s' %
3231 ( node1, port1, node2, port2 ) )
3232 if not secondDir:
3233 main.log.error(
3234 'ONOS does not have the link %s/%s -> %s/%s' %
3235 ( node2, port2, node1, port1 ) )
3236 linkResults = linkResults and firstDir and secondDir
3237 return linkResults
3238 except pexpect.EOF:
3239 main.log.error( self.name + ": EOF exception found" )
3240 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003241 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003242 except Exception:
3243 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003244 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003245
Jon Hallafa8a472015-06-12 14:02:42 -07003246 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003247 """
Jon Hallafa8a472015-06-12 14:02:42 -07003248 Compare mn and onos Hosts.
3249 Since Mininet hosts are quiet, ONOS will only know of them when they
3250 speak. For this reason, we will only check that the hosts in ONOS
3251 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003252
Jon Hallafa8a472015-06-12 14:02:42 -07003253 Arguments:
3254 hostsJson: parsed json object from the onos hosts api
3255 Returns:
3256 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003257 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003258 try:
3259 hostResults = main.TRUE
3260 for onosHost in hostsJson:
3261 onosMAC = onosHost[ 'mac' ].lower()
3262 match = False
3263 for mnHost, info in hosts.iteritems():
3264 for mnIntf in info[ 'interfaces' ]:
3265 if onosMAC == mnIntf[ 'mac' ].lower():
3266 match = True
3267 for ip in mnIntf[ 'ips' ]:
3268 if ip in onosHost[ 'ipAddresses' ]:
3269 pass # all is well
3270 else:
3271 # misssing ip
3272 main.log.error( "ONOS host " +
3273 onosHost[ 'id' ] +
3274 " has a different IP(" +
3275 str( onosHost[ 'ipAddresses' ] ) +
3276 ") than the Mininet host(" +
3277 str( ip ) +
3278 ")." )
3279 output = json.dumps(
3280 onosHost,
3281 sort_keys=True,
3282 indent=4,
3283 separators=( ',', ': ' ) )
3284 main.log.info( output )
3285 hostResults = main.FALSE
3286 if not match:
3287 hostResults = main.FALSE
3288 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3289 "corresponding Mininet host." )
3290 output = json.dumps( onosHost,
3291 sort_keys=True,
3292 indent=4,
3293 separators=( ',', ': ' ) )
3294 main.log.info( output )
3295 return hostResults
3296 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003297 main.log.error( self.name + ": EOF exception found" )
3298 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003299 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003300 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003301 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003302 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003303
You Wangd66de192018-04-30 17:30:12 -07003304 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003305 """
3306 Description:
3307 Verify that all hosts have IP address assigned to them
3308 Optional:
3309 hostList: If specified, verifications only happen to the hosts
3310 in hostList
3311 prefix: at least one of the ip address assigned to the host
3312 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003313 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003314 Returns:
3315 main.TRUE if all hosts have specific IP address assigned;
3316 main.FALSE otherwise
3317 """
3318 try:
You Wangd66de192018-04-30 17:30:12 -07003319 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003320 if not hostList:
3321 hostList = hosts.keys()
3322 for hostName in hosts.keys():
3323 if hostName not in hostList:
3324 continue
3325 ipList = []
3326 self.handle.sendline( str( hostName ) + " ip a" )
3327 self.handle.expect( "mininet>" )
3328 ipa = self.handle.before
3329 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3330 ipList += re.findall( ipv4Pattern, ipa )
3331 # It's tricky to make regex for IPv6 addresses and this one is simplified
3332 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})/'
3333 ipList += re.findall( ipv6Pattern, ipa )
3334 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3335 if not ipList:
3336 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3337 else:
3338 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3339 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3340 else:
3341 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3342 hostList.remove( hostName )
3343 return main.FALSE if hostList else main.TRUE
3344 except KeyError:
3345 main.log.exception( self.name + ": host data not as expected: " + hosts )
3346 return None
3347 except pexpect.EOF:
3348 main.log.error( self.name + ": EOF exception found" )
3349 main.log.error( self.name + ": " + self.handle.before )
3350 main.cleanAndExit()
3351 except Exception:
3352 main.log.exception( self.name + ": Uncaught exception" )
3353 return None
3354
Jon Hallafa8a472015-06-12 14:02:42 -07003355 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003356 """
3357 Returns a list of all hosts
3358 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003359 try:
3360 self.handle.sendline( "" )
3361 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003362
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003363 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3364 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003365
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003366 handlePy = self.handle.before
3367 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3368 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003369
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003370 self.handle.sendline( "" )
3371 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003372
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003373 hostStr = handlePy.replace( "]", "" )
3374 hostStr = hostStr.replace( "'", "" )
3375 hostStr = hostStr.replace( "[", "" )
3376 hostStr = hostStr.replace( " ", "" )
3377 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003378
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003379 return hostList
3380 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003381 main.log.error( self.name + ": TIMEOUT exception found" )
3382 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003383 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003384 except pexpect.EOF:
3385 main.log.error( self.name + ": EOF exception found" )
3386 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003387 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003388 except Exception:
3389 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003390 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003391
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003392 def getSwitch( self ):
3393 """
3394 Returns a list of all switches
3395 Again, don't ask question just use it...
3396 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003397 try:
3398 # get host list...
3399 hostList = self.getHosts()
3400 # Make host set
3401 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003402
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003403 # Getting all the nodes in mininet
3404 self.handle.sendline( "" )
3405 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003406
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003407 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3408 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003409
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003410 handlePy = self.handle.before
3411 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3412 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003413
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003414 self.handle.sendline( "" )
3415 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003416
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003417 nodesStr = handlePy.replace( "]", "" )
3418 nodesStr = nodesStr.replace( "'", "" )
3419 nodesStr = nodesStr.replace( "[", "" )
3420 nodesStr = nodesStr.replace( " ", "" )
3421 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003422
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003423 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003424 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003425 nodesSet.discard( 'c0' )
3426 nodesSet.discard( 'c1' )
3427 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003428
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003429 switchSet = nodesSet - hostSet
3430 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003431
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003432 return switchList
3433 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003434 main.log.error( self.name + ": TIMEOUT exception found" )
3435 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003436 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003437 except pexpect.EOF:
3438 main.log.error( self.name + ": EOF exception found" )
3439 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003440 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003441 except Exception:
3442 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003443 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003444
You Wangdb8cd0a2016-05-26 15:19:45 -07003445 def getGraphDict( self, timeout=60, useId=True, includeHost=False ):
3446 """
3447 Return a dictionary which describes the latest Mininet topology data as a
3448 graph.
3449 An example of the dictionary:
3450 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3451 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3452 Each vertex should at least have an 'edges' attribute which describes the
3453 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003454 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003455 list of attributes.
3456 An example of the edges dictionary:
3457 'edges': { vertex2: { 'port': ..., 'weight': ... },
3458 vertex3: { 'port': ..., 'weight': ... } }
3459 If useId == True, dpid/mac will be used instead of names to identify
3460 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3461 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003462 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003463 in topology data.
3464 Note that link or switch that are brought down by 'link x x down' or 'switch
3465 x down' commands still show in the output of Mininet CLI commands such as
3466 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3467 recommended to use delLink() or delSwitch functions to simulate link/switch
3468 down, and addLink() or addSwitch to add them back.
3469 """
3470 graphDict = {}
3471 try:
3472 links = self.getLinks( timeout=timeout )
3473 portDict = {}
3474 if useId:
3475 switches = self.getSwitches()
3476 if includeHost:
3477 hosts = self.getHosts()
3478 for link in links:
3479 # FIXME: support 'includeHost' argument
3480 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3481 continue
3482 nodeName1 = link[ 'node1' ]
3483 nodeName2 = link[ 'node2' ]
3484 port1 = link[ 'port1' ]
3485 port2 = link[ 'port2' ]
3486 # Loop for two nodes
3487 for i in range( 2 ):
3488 # Get port index from OVS
3489 # The index extracted from port name may be inconsistent with ONOS
3490 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003491 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003492 portList = self.getOVSPorts( nodeName1 )
3493 if len( portList ) == 0:
3494 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3495 return None
3496 portDict[ nodeName1 ] = portList
3497 for port in portDict[ nodeName1 ]:
3498 if port[ 'port' ] == port1:
3499 portIndex = port[ 'index' ]
3500 break
3501 if portIndex == -1:
3502 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3503 return None
3504 if useId:
3505 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3506 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3507 else:
3508 node1 = nodeName1
3509 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003510 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003511 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003512 graphDict[ node1 ] = { 'edges': {},
3513 'dpid': switches[ nodeName1 ][ 'dpid' ],
3514 'name': nodeName1,
3515 'ports': switches[ nodeName1 ][ 'ports' ],
3516 'swClass': switches[ nodeName1 ][ 'swClass' ],
3517 'pid': switches[ nodeName1 ][ 'pid' ],
3518 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003519 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003520 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003521 else:
3522 # Assert node2 is not connected to any current links of node1
3523 assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003524 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
You Wangdb8cd0a2016-05-26 15:19:45 -07003525 # Swap two nodes/ports
3526 nodeName1, nodeName2 = nodeName2, nodeName1
3527 port1, port2 = port2, port1
3528 return graphDict
3529 except KeyError:
3530 main.log.exception( self.name + ": KeyError exception found" )
3531 return None
3532 except AssertionError:
3533 main.log.exception( self.name + ": AssertionError exception found" )
3534 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003535 except pexpect.EOF:
3536 main.log.error( self.name + ": EOF exception found" )
3537 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003538 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003539 except Exception:
3540 main.log.exception( self.name + ": Uncaught exception" )
3541 return None
3542
Devin Lima7cfdbd2017-09-29 15:02:22 -07003543 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003544 """
3545 updates the port address and status information for
3546 each port in mn"""
3547 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003548 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003549 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003550 self.handle.sendline( "" )
3551 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003552
Jon Hall7eb38402015-01-08 17:19:54 -08003553 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003554 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003555
Jon Hall7eb38402015-01-08 17:19:54 -08003556 self.handle.sendline( "" )
3557 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003558
Jon Hallb1290e82014-11-18 16:17:48 -05003559 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003560 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003561 main.log.error( self.name + ": TIMEOUT exception found" )
3562 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003563 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003564 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003565 main.log.error( self.name + ": EOF exception found" )
3566 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003567 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003568 except Exception:
3569 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003570 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003571
Jon Halld80cc142015-07-06 13:36:05 -07003572 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003573 """
3574 Add vlan tag to a host.
3575 Dependencies:
3576 This class depends on the "vlan" package
3577 $ sudo apt-get install vlan
3578 Configuration:
3579 Load the 8021q module into the kernel
3580 $sudo modprobe 8021q
3581
3582 To make this setup permanent:
3583 $ sudo su -c 'echo "8021q" >> /etc/modules'
3584 """
3585 if self.handle:
3586 try:
Jon Halld80cc142015-07-06 13:36:05 -07003587 # get the ip address of the host
3588 main.log.info( "Get the ip address of the host" )
3589 ipaddr = self.getIPAddress( host )
3590 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003591
Jon Halld80cc142015-07-06 13:36:05 -07003592 # remove IP from interface intf
3593 # Ex: h1 ifconfig h1-eth0 inet 0
3594 main.log.info( "Remove IP from interface " )
3595 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3596 self.handle.sendline( cmd2 )
3597 self.handle.expect( "mininet>" )
3598 response = self.handle.before
3599 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003600
Jon Halld80cc142015-07-06 13:36:05 -07003601 # create VLAN interface
3602 # Ex: h1 vconfig add h1-eth0 100
3603 main.log.info( "Create Vlan" )
3604 cmd3 = host + " vconfig add " + intf + " " + vlan
3605 self.handle.sendline( cmd3 )
3606 self.handle.expect( "mininet>" )
3607 response = self.handle.before
3608 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003609
Jon Halld80cc142015-07-06 13:36:05 -07003610 # assign the host's IP to the VLAN interface
3611 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3612 main.log.info( "Assign the host IP to the vlan interface" )
3613 vintf = intf + "." + vlan
3614 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3615 self.handle.sendline( cmd4 )
3616 self.handle.expect( "mininet>" )
3617 response = self.handle.before
3618 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003619
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003620 # update Mininet node variables
3621 main.log.info( "Update Mininet node variables" )
3622 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3623 self.handle.sendline( cmd5 )
3624 self.handle.expect( "mininet>" )
3625 response = self.handle.before
3626 main.log.info( "====> %s ", response )
3627
3628 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3629 self.handle.sendline( cmd6 )
3630 self.handle.expect( "mininet>" )
3631 response = self.handle.before
3632 main.log.info( "====> %s ", response )
3633
3634 return main.TRUE
3635 except pexpect.TIMEOUT:
3636 main.log.error( self.name + ": TIMEOUT exception found" )
3637 main.log.error( self.name + ": " + self.handle.before )
3638 main.cleanAndExit()
3639 except pexpect.EOF:
3640 main.log.error( self.name + ": EOF exception found" )
3641 main.log.error( self.name + ": " + self.handle.before )
3642 return main.FALSE
3643 except Exception:
3644 main.log.exception( self.name + ": Uncaught exception!" )
3645 return main.FALSE
3646
3647 def removeVLAN( self, host, intf ):
3648 """
3649 Remove vlan tag from a host.
3650 Dependencies:
3651 This class depends on the "vlan" package
3652 $ sudo apt-get install vlan
3653 Configuration:
3654 Load the 8021q module into the kernel
3655 $sudo modprobe 8021q
3656
3657 To make this setup permanent:
3658 $ sudo su -c 'echo "8021q" >> /etc/modules'
3659 """
3660 if self.handle:
3661 try:
3662 # get the ip address of the host
3663 main.log.info( "Get the ip address of the host" )
3664 ipaddr = self.getIPAddress( host )
3665
3666 # remove VLAN interface
3667 # Ex: h1 vconfig rem h1-eth0.100
3668 main.log.info( "Remove Vlan interface" )
3669 cmd2 = host + " vconfig rem " + intf
3670 self.handle.sendline( cmd2 )
3671 self.handle.expect( "mininet>" )
3672 response = self.handle.before
3673 main.log.info( "====> %s ", response )
3674
3675 # assign the host's IP to the original interface
3676 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3677 main.log.info( "Assign the host IP to the original interface" )
3678 original_intf = intf.split(".")[0]
3679 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3680 self.handle.sendline( cmd3 )
3681 self.handle.expect( "mininet>" )
3682 response = self.handle.before
3683 main.log.info( "====> %s ", response )
3684
3685 # update Mininet node variables
3686 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3687 self.handle.sendline( cmd4 )
3688 self.handle.expect( "mininet>" )
3689 response = self.handle.before
3690 main.log.info( "====> %s ", response )
3691
3692 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3693 self.handle.sendline( cmd5 )
3694 self.handle.expect( "mininet>" )
3695 response = self.handle.before
3696 main.log.info( "====> %s ", response )
3697
kaouthera3f13ca22015-05-05 15:01:41 -07003698 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003699 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003700 main.log.error( self.name + ": TIMEOUT exception found" )
3701 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003702 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003703 except pexpect.EOF:
3704 main.log.error( self.name + ": EOF exception found" )
3705 main.log.error( self.name + ": " + self.handle.before )
3706 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003707 except Exception:
3708 main.log.exception( self.name + ": Uncaught exception!" )
3709 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003710
Jon Hall892818c2015-10-20 17:58:34 -07003711 def createHostComponent( self, name ):
3712 """
3713 Creates a new mininet cli component with the same parameters as self.
3714 This new component is intended to be used to login to the hosts created
3715 by mininet.
3716
3717 Arguments:
3718 name - The string of the name of this component. The new component
3719 will be assigned to main.<name> .
3720 In addition, main.<name>.name = str( name )
3721 """
3722 try:
3723 # look to see if this component already exists
3724 getattr( main, name )
3725 except AttributeError:
3726 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003727 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3728 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003729 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003730 except pexpect.EOF:
3731 main.log.error( self.name + ": EOF exception found" )
3732 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003733 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003734 except Exception:
3735 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003736 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003737 else:
3738 # namespace is not clear!
3739 main.log.error( name + " component already exists!" )
3740 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003741 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003742
3743 def removeHostComponent( self, name ):
3744 """
3745 Remove host component
3746 Arguments:
3747 name - The string of the name of the component to delete.
3748 """
3749 try:
3750 # Get host component
3751 component = getattr( main, name )
3752 except AttributeError:
3753 main.log.error( "Component " + name + " does not exist." )
3754 return
3755 try:
3756 # Disconnect from component
3757 component.disconnect()
3758 # Delete component
3759 delattr( main, name )
3760 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003761 del( main.componentDictionary[ name ] )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003762 except pexpect.EOF:
3763 main.log.error( self.name + ": EOF exception found" )
3764 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003765 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003766 except Exception:
3767 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003768 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003769
3770 def startHostCli( self, host=None ):
3771 """
3772 Use the mininet m utility to connect to the host's cli
3773 """
3774 # These are fields that can be used by scapy packets. Initialized to None
3775 self.hostIp = None
3776 self.hostMac = None
3777 try:
3778 if not host:
3779 host = self.name
3780 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003781 self.handle.sendline( "cd" )
3782 self.handle.expect( self.hostPrompt )
3783 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003784 self.handle.expect( self.hostPrompt )
3785 return main.TRUE
3786 except pexpect.TIMEOUT:
3787 main.log.exception( self.name + ": Command timed out" )
3788 return main.FALSE
3789 except pexpect.EOF:
3790 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003791 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003792 except Exception:
3793 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003794 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003795
YPZhang801d46d2016-08-08 13:26:28 -07003796 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003797 '''
3798
YPZhang801d46d2016-08-08 13:26:28 -07003799 Args:
3800 devicename: switch name
3801 intf: port name on switch
3802 status: up or down
3803
3804 Returns: boolean to show success change status
3805
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003806 '''
YPZhang801d46d2016-08-08 13:26:28 -07003807 if status == "down" or status == "up":
3808 try:
3809 cmd = devicename + " ifconfig " + intf + " " + status
3810 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003811 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003812 return main.TRUE
3813 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003814 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003815 return main.FALSE
3816 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003817 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003818 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003819 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003820 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003821 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003822 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003823 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003824 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003825 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003826 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003827 return main.FALSE
3828
You Wang6e5b48e2018-07-23 16:17:38 -07003829 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003830 """
You Wang6e5b48e2018-07-23 16:17:38 -07003831 Moves a host from one switch to another on the fly
3832 Optional:
3833 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3834 prefixLen: length of the host IP prefix
3835 ipv6: move an IPv6 host if True
3836 intfSuffix: suffix of the new interface after host movement
3837 vlan: vlan ID of the host. Use None for non-vlan host
3838 Note: The intf between host and oldSw when detached
3839 using detach(), will still show up in the 'net'
3840 cmd, because switch.detach() doesn't affect switch.intfs[]
3841 ( which is correct behavior since the interfaces
3842 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003843 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003844 if self.handle:
3845 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003846 newIntf = "%s-%s" % ( host, intfSuffix )
3847 commands = [
3848 # Bring link between oldSw-host down
3849 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3850 # Determine hostintf and Oldswitchintf
3851 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
3852 ]
3853 # Determine ip address of the host-oldSw interface
3854 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3855 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3856 commands += [
3857 # Determine mac address of the host-oldSw interface
3858 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3859 # Detach interface between oldSw-host
3860 "px " + oldSw + ".detach( sintf )",
3861 # Add link between host-newSw
3862 "py net.addLink(" + host + "," + newSw + ")",
3863 # Determine hostintf and Newswitchintf
3864 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3865 # Attach interface between newSw-host
3866 "px " + newSw + ".attach( sintf )",
3867 ]
3868 if vlan:
3869 vlanIntf = "%s.%s" % ( newIntf, vlan )
3870 commands += [
3871 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
3872 host + " ip link set up %s" % vlanIntf,
3873 "px hintf.name = '" + vlanIntf + "'",
3874 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
3875 ]
3876 newIntf = vlanIntf
3877 commands += [
3878 # Set mac address of the host-newSw interface
3879 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
3880 # Set IP address of the host-newSw interface
3881 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
3882 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
3883 ]
3884 if ipv6:
3885 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
3886 commands += [
3887 "net",
3888 host + " ifconfig"
3889 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003890 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003891 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003892 self.handle.sendline( cmd )
3893 self.handle.expect( "mininet>" )
3894 main.log.info( "====> %s ", self.handle.before )
3895 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003896 except pexpect.TIMEOUT:
3897 main.log.error( self.name + ": TIMEOUT exception found" )
3898 main.log.error( self.name + ": " + self.handle.before )
3899 main.cleanAndExit()
3900 except pexpect.EOF:
3901 main.log.error( self.name + ": EOF exception found" )
3902 main.log.error( self.name + ": " + self.handle.before )
3903 return main.FALSE
3904 except Exception:
3905 main.log.exception( self.name + ": Uncaught exception!" )
3906 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07003907
You Wang6e5b48e2018-07-23 16:17:38 -07003908 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
3909 macAddr=None, prefixLen=None, ipv6=False,
3910 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07003911 """
You Wang6e5b48e2018-07-23 16:17:38 -07003912 Moves a dual-homed host from one switch-pair to another pair on the fly
3913 Optional:
3914 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3915 prefixLen: length of the host IP prefix
3916 ipv6: move an IPv6 host if True
3917 intfSuffix1: suffix of the first new interface
3918 intfSuffix2: suffix of the second new interface
3919 bondSuffix: suffix of the new bond interface
3920 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07003921 """
You Wang7ea90582018-07-19 15:27:58 -07003922 if self.handle:
3923 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003924 bondIntf = "%s-%s" % ( host, bondSuffix )
3925 newIntf = "%s-%s" % ( host, intfSuffix1 )
3926 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07003927 commands = [
3928 # Bring link between oldSw-host down
3929 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3930 # Bring link between oldPairSw-host down
3931 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
3932 # Determine hostintf and Oldswitchintf
3933 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07003934 ]
3935 # Determine ip address of the host-oldSw interface
3936 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3937 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3938 commands += [
3939 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07003940 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3941 # Detach interface between oldSw-host
3942 "px " + oldSw + ".detach( sintf )",
3943 # Determine hostintf and Oldpairswitchintf
3944 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
3945 # Detach interface between oldPairSw-host
3946 "px " + oldPairSw + ".detach( sintfpair )",
3947 # Add link between host-newSw
3948 "py net.addLink(" + host + "," + newSw + ", 2)",
3949 # Add link between host-newPairSw
3950 "py net.addLink(" + host + "," + newPairSw + ")",
3951 # Determine hostintf and Newswitchintf
3952 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3953 # Determine hostintf and NewPairswitchintf
3954 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
3955 # Attach interface between newSw-host
3956 "px " + newSw + ".attach( sintf )",
3957 # Attach interface between newPairSw-host
3958 "px " + newPairSw + ".attach( sintfpair )",
3959 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07003960 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07003961 host + ' ip link set %s down' % newIntf,
3962 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07003963 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
3964 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07003965 host + ' ip addr flush dev %s' % newIntf,
3966 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07003967 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07003968 "px lowestIntf = min( [ hintf, hintfpair ] )",
3969 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07003970 "px lowestIntf.name = '" + bondIntf + "'",
3971 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07003972 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
3973 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07003974 ]
3975 if vlan:
3976 vlanIntf = "%s.%s" % ( bondIntf, vlan )
3977 commands += [
3978 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
3979 host + " ip link set up %s" % vlanIntf,
3980 "px lowestIntf.name = '" + vlanIntf + "'",
3981 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
3982 ]
3983 bondIntf = vlanIntf
3984 commands += [
3985 # Set macaddress of the host-newSw interface
3986 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07003987 # Set ipaddress of the host-newSw interface
3988 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
3989 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07003990 ]
You Wang6e5b48e2018-07-23 16:17:38 -07003991 if ipv6:
3992 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
3993 commands += [
3994 "net",
3995 host + " ifconfig"
3996 ]
You Wang7ea90582018-07-19 15:27:58 -07003997 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003998 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07003999 self.handle.sendline( cmd )
4000 self.handle.expect( "mininet>" )
4001 main.log.info( "====> %s ", self.handle.before )
4002 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07004003 except pexpect.TIMEOUT:
4004 main.log.error( self.name + ": TIMEOUT exception found" )
4005 main.log.error( self.name + ": " + self.handle.before )
4006 main.cleanAndExit()
4007 except pexpect.EOF:
4008 main.log.error( self.name + ": EOF exception found" )
4009 main.log.error( self.name + ": " + self.handle.before )
4010 return main.FALSE
4011 except Exception:
4012 main.log.exception( self.name + ": Uncaught exception!" )
4013 return main.FALSE
4014
adminbae64d82013-08-01 10:50:15 -07004015if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004016 sys.modules[ __name__ ] = MininetCliDriver()