blob: 1627603c8e856bd71ec1003094493f68ebf3ec15 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
Jon Hall7eb38402015-01-08 17:19:54 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004Copyright 2012 Open Networking Foundation (ONF)
adminbae64d82013-08-01 10:50:15 -07005
Jeremy Songsterae01bba2016-07-11 15:39:17 -07006Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
7the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
8or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
adminbae64d82013-08-01 10:50:15 -07009
Jon Hall7eb38402015-01-08 17:19:54 -080010TestON is free software: you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation, either version 2 of the License, or
13( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070014
Jon Hall7eb38402015-01-08 17:19:54 -080015TestON is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070019
Jon Hall7eb38402015-01-08 17:19:54 -080020You should have received a copy of the GNU General Public License
21along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070022
Jon Hallbe6dfc42015-01-12 17:37:25 -080023MininetCliDriver is the basic driver which will handle the Mininet functions
24
25Some functions rely on a modified version of Mininet. These functions
26should all be noted in the comments. To get this MN version run these commands
27from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080028 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080029 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080030 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080031 git pull
32
Jon Hall272a4db2015-01-12 17:43:48 -080033
34 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080035changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070036import pexpect
adminbae64d82013-08-01 10:50:15 -070037import re
38import sys
kelvin-onlabfa6ada82015-06-11 13:06:24 -070039import types
kelvin-onlaba4074292015-07-09 15:19:49 -070040import os
Devin Lima7cfdbd2017-09-29 15:02:22 -070041import time
Jon Hall1ccf82c2014-10-15 14:55:16 -040042from math import pow
adminbae64d82013-08-01 10:50:15 -070043from drivers.common.cli.emulatordriver import Emulator
You Wangdb8cd0a2016-05-26 15:19:45 -070044from core.graph import Graph
adminbae64d82013-08-01 10:50:15 -070045
Jon Hall7eb38402015-01-08 17:19:54 -080046
kelvin-onlab50907142015-04-01 13:37:45 -070047class MininetCliDriver( Emulator ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -070048
Jon Hall7eb38402015-01-08 17:19:54 -080049 """
50 MininetCliDriver is the basic driver which will handle
51 the Mininet functions"""
52 def __init__( self ):
Devin Limdc78e202017-06-09 18:30:07 -070053 super( MininetCliDriver, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070054 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080055 self.name = None
kelvin-onlabd9e23de2015-08-06 10:34:44 -070056 self.home = None
Jon Hall7eb38402015-01-08 17:19:54 -080057 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070058 self.flag = 0
Jon Hall892818c2015-10-20 17:58:34 -070059 # TODO: Refactor driver to use these everywhere
60 self.mnPrompt = "mininet>"
61 self.hostPrompt = "~#"
62 self.bashPrompt = "\$"
63 self.scapyPrompt = ">>>"
You Wangdb8cd0a2016-05-26 15:19:45 -070064 self.graph = Graph()
adminbae64d82013-08-01 10:50:15 -070065
Jon Hall7eb38402015-01-08 17:19:54 -080066 def connect( self, **connectargs ):
67 """
68 Here the main is the TestON instance after creating
69 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080070 try:
71 for key in connectargs:
72 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070073 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080074 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070075 for key in self.options:
76 if key == "home":
77 self.home = self.options[ 'home' ]
78 break
79 if self.home is None or self.home == "":
80 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070081
82 try:
Jon Hall892818c2015-10-20 17:58:34 -070083 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070084 self.ip_address = os.getenv( str( self.ip_address ) )
85 else:
86 main.log.info( self.name +
87 ": Trying to connect to " +
88 self.ip_address )
89
90 except KeyError:
91 main.log.info( "Invalid host name," +
92 " connecting to local host instead" )
93 self.ip_address = 'localhost'
94 except Exception as inst:
95 main.log.error( "Uncaught exception: " + str( inst ) )
96
kelvin-onlaba1484582015-02-02 15:46:20 -080097 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070098 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080099 self ).connect(
100 user_name=self.user_name,
101 ip_address=self.ip_address,
102 port=None,
103 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -0800104
kelvin-onlaba1484582015-02-02 15:46:20 -0800105 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -0800106 main.log.info( "Connection successful to the host " +
107 self.user_name +
108 "@" +
109 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800110 return main.TRUE
111 else:
112 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800113 self.user_name +
114 "@" +
115 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800116 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800117 return main.FALSE
118 except pexpect.EOF:
119 main.log.error( self.name + ": EOF exception found" )
120 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700121 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800122 except Exception:
123 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700124 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -0800125
kelvin-onlab10e8d392015-06-03 13:53:45 -0700126 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800127 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700128 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000129 Starts Mininet accepts a topology(.py) file and/or an optional
kelvin-onlabf512e942015-06-08 19:42:59 -0700130 argument, to start the mininet, as a parameter.
131 Can also send regular mininet command to load up desired topology.
alison12f34c32016-06-10 14:39:21 -0700132 Eg. Pass in a string 'mn --topo=tree,3,3' to mnCmd
kelvin-onlabf512e942015-06-08 19:42:59 -0700133 Options:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000134 topoFile = file path for topology file (.py)
kelvin-onlabf512e942015-06-08 19:42:59 -0700135 args = extra option added when starting the topology from the file
136 mnCmd = Mininet command use to start topology
137 Returns:
138 main.TRUE if the mininet starts successfully, main.FALSE
139 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800140 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700141 try:
142 if self.handle:
143 # make sure old networks are cleaned up
144 main.log.info( self.name +
145 ": Clearing any residual state or processes" )
146 self.handle.sendline( "sudo mn -c" )
147 i = self.handle.expect( [ 'password\sfor\s',
148 'Cleanup\scomplete',
Jon Hallefbd9792015-03-05 16:11:36 -0800149 pexpect.EOF,
150 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700151 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800152 if i == 0:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700153 # Sudo asking for password
154 main.log.info( self.name + ": Sending sudo password" )
155 self.handle.sendline( self.pwd )
Jon Hall173f2a02018-01-11 13:56:37 -0800156 i = self.handle.expect( [ '%s:' % self.user_name,
Devin Limdc78e202017-06-09 18:30:07 -0700157 self.prompt,
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700158 pexpect.EOF,
159 pexpect.TIMEOUT ],
160 timeout )
161 if i == 1:
162 main.log.info( self.name + ": Clean" )
Jon Hall689d8e42015-04-03 13:59:24 -0700163 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700164 main.log.error( self.name + ": Connection terminated" )
165 elif i == 3: # timeout
166 main.log.error( self.name + ": Something while cleaning " +
167 "Mininet took too long... " )
168 # Craft the string to start mininet
169 cmdString = "sudo "
170 if not mnCmd:
171 if topoFile is None or topoFile == '': # If no file is given
172 main.log.info( self.name + ": building fresh Mininet" )
173 cmdString += "mn "
174 if args is None or args == '':
175 # If no args given, use args from .topo file
176 args = self.options[ 'arg1' ] +\
177 " " + self.options[ 'arg2' ] +\
178 " --mac --controller " +\
179 self.options[ 'controller' ] + " " +\
180 self.options[ 'arg3' ]
181 else: # else only use given args
182 pass
183 # TODO: allow use of topo args and method args?
184 else: # Use given topology file
185 main.log.info(
186 "Starting Mininet from topo file " +
187 topoFile )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700188 cmdString += "-E python " + topoFile + " "
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700189 if args is None:
190 args = ''
191 # TODO: allow use of args from .topo file?
192 cmdString += args
193 else:
194 main.log.info( "Starting Mininet topology using '" + mnCmd +
195 "' command" )
196 cmdString += mnCmd
197 # Send the command and check if network started
198 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -0700199 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700200 main.log.info( "Sending '" + cmdString + "' to " + self.name )
201 self.handle.sendline( cmdString )
Devin Lima7cfdbd2017-09-29 15:02:22 -0700202 startTime = time.time()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700203 while True:
204 i = self.handle.expect( [ 'mininet>',
Jon Hallbc743112018-04-18 11:09:01 -0700205 'Exception|Error',
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700206 '\*\*\*',
207 pexpect.EOF,
Jon Hallab611372018-02-21 15:26:05 -0800208 pexpect.TIMEOUT,
209 "No such file or directory"],
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700210 timeout )
211 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -0700212 main.log.info( self.name + ": Mininet built\nTime Took : " + str( time.time() - startTime ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700213 return main.TRUE
214 elif i == 1:
215 response = str( self.handle.before +
216 self.handle.after )
Devin Limdc78e202017-06-09 18:30:07 -0700217 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700218 response += str( self.handle.before +
219 self.handle.after )
220 main.log.error(
221 self.name +
222 ": Launching Mininet failed: " + response )
223 return main.FALSE
224 elif i == 2:
225 self.handle.expect( [ "\n",
226 pexpect.EOF,
227 pexpect.TIMEOUT ],
228 timeout )
229 main.log.info( self.handle.before )
230 elif i == 3:
231 main.log.error( self.name + ": Connection timeout" )
232 return main.FALSE
233 elif i == 4: # timeout
234 main.log.error(
235 self.name +
236 ": Something took too long... " )
Jon Hallbc743112018-04-18 11:09:01 -0700237 main.log.debug( self.handle.before + self.handle.after )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700238 return main.FALSE
Jon Hallab611372018-02-21 15:26:05 -0800239 elif i == 5:
240 main.log.error( self.name + ": " + self.handle.before + self.handle.after )
241 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700242 # Why did we hit this part?
243 main.log.error( "startNet did not return correctly" )
244 return main.FASLE
245 else: # if no handle
246 main.log.error( self.name + ": Connection failed to the host " +
247 self.user_name + "@" + self.ip_address )
248 main.log.error( self.name + ": Failed to connect to the Mininet" )
249 return main.FALSE
250 except pexpect.TIMEOUT:
251 main.log.exception( self.name + ": TIMEOUT exception found while starting Mininet" )
252 main.log.error( self.name + ": " + self.handle.before )
adminbae64d82013-08-01 10:50:15 -0700253 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700254 except pexpect.EOF:
255 main.log.error( self.name + ": EOF exception found" )
256 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700257 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700258 except Exception:
259 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700260 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800261
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800262 def numSwitchesNlinks( self, topoType, depth, fanout ):
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700263 try:
264 if topoType == 'tree':
265 # In tree topology, if fanout arg is not given, by default it is 2
266 if fanout is None:
267 fanout = 2
268 k = 0
269 count = 0
270 while( k <= depth - 1 ):
271 count = count + pow( fanout, k )
272 k = k + 1
273 numSwitches = count
274 while( k <= depth - 2 ):
275 # depth-2 gives you only core links and not considering
276 # edge links as seen by ONOS. If all the links including
277 # edge links are required, do depth-1
278 count = count + pow( fanout, k )
279 k = k + 1
280 numLinks = count * fanout
281 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
282 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800283
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700284 elif topoType == 'linear':
285 # In linear topology, if fanout or numHostsPerSw is not given,
286 # by default it is 1
287 if fanout is None:
288 fanout = 1
289 numSwitches = depth
290 numHostsPerSw = fanout
291 totalNumHosts = numSwitches * numHostsPerSw
292 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hallab611372018-02-21 15:26:05 -0800293 main.log.debug( "num_switches for %s(%d,%d) = %d and links=%d" %
294 ( topoType, depth, fanout, numSwitches, numLinks ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700295 topoDict = { "num_switches": int( numSwitches ),
296 "num_corelinks": int( numLinks ) }
297 return topoDict
298 except Exception:
299 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700300 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400301
kelvin-onlabd3b64892015-01-20 13:26:24 -0800302 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700303 """
304 Calculate the number of switches and links in a topo."""
305 # TODO: combine this function and numSwitchesNlinks
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700306 try:
307 argList = self.options[ 'arg1' ].split( "," )
308 topoArgList = argList[ 0 ].split( " " )
309 argList = map( int, argList[ 1: ] )
310 topoArgList = topoArgList[ 1: ] + argList
Jon Hall689d8e42015-04-03 13:59:24 -0700311
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700312 topoDict = self.numSwitchesNlinks( *topoArgList )
313 return topoDict
314 except Exception:
315 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700316 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400317
GlennRCf07c44a2015-09-18 13:33:46 -0700318 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800319 """
320 Verifies the reachability of the hosts using pingall command.
321 Optional parameter timeout allows you to specify how long to
322 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700323 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700324 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700325 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700326 ping
327 acceptableFailed - Set the number of acceptable failed pings for the
328 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800329 Returns:
330 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700331 otherwise main.FALSE
332 """
333 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700334 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700335 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700336 if self.handle:
337 main.log.info(
338 self.name +
339 ": Checking reachabilty to the hosts using pingall" )
340 response = ""
341 failedPings = 0
342 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700343 cmd = "pingall"
344 if protocol == "IPv6":
345 cmd = "py net.pingAll6()"
346 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700347 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700348 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700349 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700350 pexpect.EOF,
351 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700352 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700353 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700354 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700355 response += self.handle.before
356 break
357 elif i == 1:
358 response += self.handle.before + self.handle.after
359 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700360 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700361 returnValue = main.FALSE
362 if shortCircuit:
363 main.log.error( self.name +
364 ": Aborting pingall - "
365 + str( failedPings ) +
366 " pings failed" )
367 break
Jon Hall390696c2015-05-05 17:13:41 -0700368 if ( time.time() - startTime ) > timeout:
369 returnValue = main.FALSE
370 main.log.error( self.name +
371 ": Aborting pingall - " +
372 "Function took too long " )
373 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700374 elif i == 2:
375 main.log.error( self.name +
376 ": EOF exception found" )
377 main.log.error( self.name + ": " +
378 self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700379 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700380 elif i == 3:
381 response += self.handle.before
382 main.log.error( self.name +
383 ": TIMEOUT exception found" )
384 main.log.error( self.name +
385 ": " +
386 str( response ) )
387 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800388 self.handle.send( "\x03" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700389 self.handle.expect( "Interrupt" )
390 self.handle.expect( "mininet>" )
391 break
392 pattern = "Results\:"
393 main.log.info( "Pingall output: " + str( response ) )
394 if re.search( pattern, response ):
395 main.log.info( self.name + ": Pingall finished with "
396 + str( failedPings ) + " failed pings" )
397 return returnValue
398 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700399 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800400 self.handle.send( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700401 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700402 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700403 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700404 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700405 main.log.error( self.name + ": Connection failed to the host" )
Devin Lim44075962017-08-11 10:56:37 -0700406 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700407 except pexpect.TIMEOUT:
408 if response:
409 main.log.info( "Pingall output: " + str( response ) )
410 main.log.error( self.name + ": pexpect.TIMEOUT found" )
411 return main.FALSE
412 except pexpect.EOF:
413 main.log.error( self.name + ": EOF exception found" )
414 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700415 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -0700416
Jon Hall7eb38402015-01-08 17:19:54 -0800417 def fpingHost( self, **pingParams ):
418 """
419 Uses the fping package for faster pinging...
420 *requires fping to be installed on machine running mininet"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700421 try:
422 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
423 command = args[ "SRC" ] + \
424 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
425 self.handle.sendline( command )
426 self.handle.expect(
427 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
428 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
429 response = self.handle.before
430 if re.search( ":\s-", response ):
431 main.log.info( self.name + ": Ping fail" )
432 return main.FALSE
433 elif re.search( ":\s\d{1,2}\.\d\d", response ):
434 main.log.info( self.name + ": Ping good!" )
435 return main.TRUE
436 main.log.info( self.name + ": Install fping on mininet machine... " )
437 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700438 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700439 except Exception:
440 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700441 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700442
Jon Hall3b489db2015-10-05 14:38:37 -0700443 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400444 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700445 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700446
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400447 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700448 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700449
450 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400451 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700452
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400453 Returns main.FALSE if one or more of hosts specified
454 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700455 wait = int( wait )
456 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400457
458 try:
459 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700460
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400461 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700462 pingResponse = "IPv4 ping across specified hosts\n"
463 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400464 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700465 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400466 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700467 pingList = hostList[ :listIndex ] + \
468 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700469
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700470 pingResponse += str( str( host ) + " -> " )
GlennRCd10d3cc2015-09-24 12:47:16 -0700471
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400472 for temp in pingList:
473 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700474 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700475 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700476 self.handle.expect( "mininet>", timeout=wait + 5 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400477 response = self.handle.before
478 if re.search( ',\s0\%\spacket\sloss', response ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700479 pingResponse += str( " h" + str( temp[ 1: ] ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400480 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700481 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400482 # One of the host to host pair is unreachable
483 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700484 failedPings += 1
You Wang11f9ead2018-03-21 14:34:59 -0700485 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
GlennRCd10d3cc2015-09-24 12:47:16 -0700486 pingResponse += "\n"
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700487 main.log.info( pingResponse + "Failed pings: " + str( failedPings ) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700488 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700489 except pexpect.TIMEOUT:
490 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800491 response = self.handle.before
492 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700493 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800494 self.handle.expect( "Interrupt" )
495 response += self.handle.before + self.handle.after
496 self.handle.expect( "mininet>" )
497 response += self.handle.before + self.handle.after
498 main.log.debug( response )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700499 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400500 except pexpect.EOF:
501 main.log.error( self.name + ": EOF exception found" )
502 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700503 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700504 except Exception:
505 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700506 main.cleanAndExit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400507
You Wangf19d9f42018-02-23 16:34:19 -0800508 def pingIpv6Hosts( self, hostList, wait=1, acceptableFailed=0 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700509 """
You Wangf19d9f42018-02-23 16:34:19 -0800510 IPv6 ping all hosts in hostList.
511
512 acceptableFailed: max number of acceptable failed pings
Hari Krishna9592fc82015-07-31 15:11:15 -0700513
Jon Hall3b489db2015-10-05 14:38:37 -0700514 Returns main.TRUE if all hosts specified can reach each other
Jon Hall3b489db2015-10-05 14:38:37 -0700515 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700516 """
517 try:
518 main.log.info( "Testing reachability between specified IPv6 hosts" )
519 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700520 wait = int( wait )
521 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700522 pingResponse = "IPv6 Pingall output:\n"
You Wangf19d9f42018-02-23 16:34:19 -0800523 failedPingsTotal = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700524 for host in hostList:
525 listIndex = hostList.index( host )
526 # List of hosts to ping other than itself
527 pingList = hostList[ :listIndex ] + \
528 hostList[ ( listIndex + 1 ): ]
529
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700530 pingResponse += str( str( host ) + " -> " )
GlennRC2cf7d952015-09-11 16:32:13 -0700531
Hari Krishna9592fc82015-07-31 15:11:15 -0700532 for temp in pingList:
533 # Current host pings all other hosts specified
You Wangf19d9f42018-02-23 16:34:19 -0800534 failedPings = 0
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700535 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
You Wangf19d9f42018-02-23 16:34:19 -0800536 while failedPings <= acceptableFailed:
537 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
538 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700539 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangf19d9f42018-02-23 16:34:19 -0800540 response = self.handle.before
541 if re.search( ',\s0\%\spacket\sloss', response ):
You Wangba231e72018-03-01 13:18:21 -0800542 pingResponse += " " + str( temp )
543 break
544 else:
545 failedPings += 1
546 time.sleep(1)
547 if failedPings > acceptableFailed:
548 # One of the host to host pair is unreachable
549 pingResponse += " X"
550 isReachable = main.FALSE
551 failedPingsTotal += 1
You Wang11f9ead2018-03-21 14:34:59 -0700552 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
You Wangba231e72018-03-01 13:18:21 -0800553 pingResponse += "\n"
554 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
555 return isReachable
556
557 except pexpect.TIMEOUT:
558 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800559 response = self.handle.before
560 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700561 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800562 self.handle.expect( "Interrupt" )
563 response += self.handle.before + self.handle.after
564 self.handle.expect( "mininet>" )
565 response += self.handle.before + self.handle.after
566 main.log.debug( response )
You Wangba231e72018-03-01 13:18:21 -0800567 return main.FALSE
568 except pexpect.EOF:
569 main.log.error( self.name + ": EOF exception found" )
570 main.log.error( self.name + ": " + self.handle.before )
571 main.cleanAndExit()
572 except Exception:
573 main.log.exception( self.name + ": Uncaught exception!" )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700574
575 main.cleanAndExit()
576
You Wang32833172018-10-23 15:19:31 -0700577 def discoverHosts( self, hostList=[], wait=1000, dstIp="6.6.6.6", dstIp6="1020::3fe" ):
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700578 '''
You Wang32833172018-10-23 15:19:31 -0700579 Hosts in hostList will do a single ARP/ND to a non-existent address for ONOS to
580 discover them. A host will use arping/ndisc6 to send ARP/ND depending on if it
581 has IPv4/IPv6 addresses configured.
You Wang48381752018-05-07 13:50:57 -0700582 Optional:
583 hostList: a list of names of the hosts that need to be discovered. If not
584 specified mininet will send ping from all the hosts
You Wang32833172018-10-23 15:19:31 -0700585 wait: timeout for ARP/ND in milliseconds
You Wang48381752018-05-07 13:50:57 -0700586 dstIp: destination address used by IPv4 hosts
587 dstIp6: destination address used by IPv6 hosts
588 Returns:
You Wang32833172018-10-23 15:19:31 -0700589 main.TRUE if all packets were successfully sent. Otherwise main.FALSE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700590 '''
591 try:
You Wang32833172018-10-23 15:19:31 -0700592 hosts = self.getHosts()
You Wang48381752018-05-07 13:50:57 -0700593 if not hostList:
You Wang48381752018-05-07 13:50:57 -0700594 hostList = hosts.keys()
595 discoveryResult = main.TRUE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700596 for host in hostList:
You Wang0b82aa52018-06-06 14:33:58 -0700597 flushCmd = ""
You Wang48381752018-05-07 13:50:57 -0700598 cmd = ""
599 if self.getIPAddress( host ):
You Wang0b82aa52018-06-06 14:33:58 -0700600 flushCmd = "{} ip neigh flush all".format( host )
You Wang32833172018-10-23 15:19:31 -0700601 cmd = "{} arping -c 1 -w {} {}".format( host, wait, dstIp )
602 main.log.debug( "Sending IPv4 arping from host {}".format( host ) )
You Wang48381752018-05-07 13:50:57 -0700603 elif self.getIPAddress( host, proto='IPV6' ):
You Wang0b82aa52018-06-06 14:33:58 -0700604 flushCmd = "{} ip -6 neigh flush all".format( host )
You Wang32833172018-10-23 15:19:31 -0700605 intf = hosts[host]['interfaces'][0]['name']
606 cmd = "{} ndisc6 -r 1 -w {} {} {}".format( host, wait, dstIp6, intf )
607 main.log.debug( "Sending IPv6 ND from host {}".format( host ) )
You Wang48381752018-05-07 13:50:57 -0700608 else:
609 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
610 discoveryResult = main.FALSE
611 if cmd:
You Wang0b82aa52018-06-06 14:33:58 -0700612 self.handle.sendline( flushCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700613 self.handle.expect( "mininet>" )
You Wang48381752018-05-07 13:50:57 -0700614 self.handle.sendline( cmd )
Jon Halla604fd42018-05-04 14:27:27 -0700615 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700616 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700617 except pexpect.TIMEOUT:
618 main.log.exception( self.name + ": TIMEOUT exception" )
619 response = self.handle.before
620 # NOTE: Send ctrl-c to make sure command is stopped
621 self.handle.send( "\x03" )
622 self.handle.expect( "Interrupt" )
623 response += self.handle.before + self.handle.after
624 self.handle.expect( "mininet>" )
625 response += self.handle.before + self.handle.after
626 main.log.debug( response )
627 return main.FALSE
628 except pexpect.EOF:
629 main.log.error( self.name + ": EOF exception found" )
630 main.log.error( self.name + ": " + self.handle.before )
631 main.cleanAndExit()
632 except Exception:
633 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800634 main.cleanAndExit()
635
636 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
637 """
638 Verify ping from each host in srcList to each host in dstList
639
640 acceptableFailed: max number of acceptable failed pings
641
642 Returns main.TRUE if all src hosts can reach all dst hosts
643 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
644 """
645 try:
646 main.log.info( "Verifying ping from each src host to each dst host" )
647 isReachable = main.TRUE
648 wait = int( wait )
649 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
650 pingResponse = "Ping output:\n"
651 failedPingsTotal = 0
652 for host in srcList:
653 pingResponse += str( str( host ) + " -> " )
654 for temp in dstList:
655 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700656 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
657 assert dstIP, "Not able to get IP address of host {}".format( temp )
658 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800659 while failedPings <= acceptableFailed:
660 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
661 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700662 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800663 response = self.handle.before
664 if re.search( ',\s0\%\spacket\sloss', response ):
665 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800666 break
667 else:
668 failedPings += 1
669 time.sleep(1)
670 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700671 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800672 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700673 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800674 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700675 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800676 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700677 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700678 except AssertionError:
679 main.log.exception( "" )
680 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700681 except pexpect.TIMEOUT:
682 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800683 response = self.handle.before
684 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700685 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800686 self.handle.expect( "Interrupt" )
687 response += self.handle.before + self.handle.after
688 self.handle.expect( "mininet>" )
689 response += self.handle.before + self.handle.after
690 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700691 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700692 except pexpect.EOF:
693 main.log.error( self.name + ": EOF exception found" )
694 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700695 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700696 except Exception:
697 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700698 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700699
Jon Hall7eb38402015-01-08 17:19:54 -0800700 def pingHost( self, **pingParams ):
701 """
Jon Hall3b489db2015-10-05 14:38:37 -0700702 Ping from one mininet host to another
703 Currently the only supported Params: SRC, TARGET, and WAIT
704 """
705 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700706 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700707 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800708 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700709 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700710 try:
Jon Hall61282e32015-03-19 11:34:11 -0700711 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800712 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700713 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700714 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700715 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800716 main.log.error(
717 self.name +
718 ": timeout when waiting for response from mininet" )
719 main.log.error( "response: " + str( self.handle.before ) )
720 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700721 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800722 main.log.error(
723 self.name +
724 ": timeout when waiting for response from mininet" )
725 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700726 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700727 if re.search( ',\s0\%\spacket\sloss', response ):
728 main.log.info( self.name + ": no packets lost, host is reachable" )
729 return main.TRUE
730 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800731 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700732 self.name +
733 ": PACKET LOST, HOST IS NOT REACHABLE" )
734 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800735 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800736 main.log.error( self.name + ": EOF exception found" )
737 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700738 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700739 except Exception:
740 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700741 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700742
743 def ping6pair( self, **pingParams ):
744 """
GlennRC2cf7d952015-09-11 16:32:13 -0700745 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700746 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000747 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700748 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
749 """
Jon Hall3b489db2015-10-05 14:38:37 -0700750 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700751 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700752 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530753 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700754 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700755 try:
756 main.log.info( "Sending: " + command )
757 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700758 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700759 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700760 if i == 1:
761 main.log.error(
762 self.name +
763 ": timeout when waiting for response from mininet" )
764 main.log.error( "response: " + str( self.handle.before ) )
765 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
766 if i == 1:
767 main.log.error(
768 self.name +
769 ": timeout when waiting for response from mininet" )
770 main.log.error( "response: " + str( self.handle.before ) )
771 response = self.handle.before
772 main.log.info( self.name + ": Ping Response: " + response )
773 if re.search( ',\s0\%\spacket\sloss', response ):
774 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700775 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700776 else:
alisone4121a92016-11-22 16:31:36 -0800777 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700778 self.name +
779 ": PACKET LOST, HOST IS NOT REACHABLE" )
780 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700781 except pexpect.EOF:
782 main.log.error( self.name + ": EOF exception found" )
783 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700784 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700785 except Exception:
786 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700787 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800788
You Wangdb927a52016-02-26 11:03:28 -0800789 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
790 """
791 Description:
792 Ping a set of destination host from host CLI.
793 Logging into a Mininet host CLI is required before calling this funtion.
794 Params:
795 dstIPList is a list of destination ip addresses
796 Returns:
797 main.TRUE if the destination host is reachable
798 main.FALSE otherwise
799 """
800 isReachable = main.TRUE
801 wait = int( wait )
802 cmd = "ping"
803 if IPv6:
804 cmd = cmd + "6"
805 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
806 try:
807 for dstIP in dstIPList:
808 pingCmd = cmd + " " + dstIP
809 self.handle.sendline( pingCmd )
810 i = self.handle.expect( [ self.hostPrompt,
811 '\*\*\* Unknown command: ' + pingCmd,
812 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700813 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700814 # For some reason we need to send something
815 # Otherwise ping results won't be read by handle
816 self.handle.sendline( "" )
817 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800818 if i == 0:
819 response = self.handle.before
820 if not re.search( ',\s0\%\spacket\sloss', response ):
821 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
822 isReachable = main.FALSE
823 elif i == 1:
824 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700825 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800826 elif i == 2:
827 main.log.error( self.name + ": timeout when waiting for response" )
828 isReachable = main.FALSE
829 else:
830 main.log.error( self.name + ": unknown response: " + self.handle.before )
831 isReachable = main.FALSE
832 except pexpect.TIMEOUT:
833 main.log.exception( self.name + ": TIMEOUT exception" )
You Wangd4fae5c2018-08-22 13:56:49 -0700834 self.exitFromCmd( [ self.hostPrompt, self.bashPrompt ] )
You Wangdb927a52016-02-26 11:03:28 -0800835 isReachable = main.FALSE
836 except pexpect.EOF:
837 main.log.error( self.name + ": EOF exception found" )
838 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700839 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800840 except Exception:
841 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700842 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800843 return isReachable
844
Jon Hall7eb38402015-01-08 17:19:54 -0800845 def checkIP( self, host ):
846 """
847 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700848 try:
849 if self.handle:
850 try:
851 response = self.execute(
852 cmd=host +
853 " ifconfig",
854 prompt="mininet>",
855 timeout=10 )
856 except pexpect.EOF:
857 main.log.error( self.name + ": EOF exception found" )
858 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700859 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700860
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700861 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
862 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
863 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
864 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
865 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
866 "[0-9]|25[0-5]|[0-9]{1,2})"
867 # pattern = "inet addr:10.0.0.6"
868 if re.search( pattern, response ):
869 main.log.info( self.name + ": Host Ip configured properly" )
870 return main.TRUE
871 else:
872 main.log.error( self.name + ": Host IP not found" )
873 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700874 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700875 main.log.error( self.name + ": Connection failed to the host" )
876 except Exception:
877 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700878 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800879
Jon Hall7eb38402015-01-08 17:19:54 -0800880 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800881 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700882 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800883 response = self.execute(
884 cmd="h1 /usr/sbin/sshd -D&",
885 prompt="mininet>",
886 timeout=10 )
887 response = self.execute(
888 cmd="h4 /usr/sbin/sshd -D&",
889 prompt="mininet>",
890 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700891 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800892 vars( self )[ key ] = connectargs[ key ]
893 response = self.execute(
894 cmd="xterm h1 h4 ",
895 prompt="mininet>",
896 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800897 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800898 main.log.error( self.name + ": EOF exception found" )
899 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700900 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700901 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800902 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700903 if self.flag == 0:
904 self.flag = 1
905 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800906 else:
adminbae64d82013-08-01 10:50:15 -0700907 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800908
Jon Hall7eb38402015-01-08 17:19:54 -0800909 def changeIP( self, host, intf, newIP, newNetmask ):
910 """
911 Changes the ip address of a host on the fly
912 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800913 if self.handle:
914 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800915 cmd = host + " ifconfig " + intf + " " + \
916 newIP + " " + 'netmask' + " " + newNetmask
917 self.handle.sendline( cmd )
918 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800919 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800920 main.log.info( "response = " + response )
921 main.log.info(
922 "Ip of host " +
923 host +
924 " changed to new IP " +
925 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800926 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700927 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700928 main.log.error( self.name + ": TIMEOUT exception found" )
929 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700930 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800931 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800932 main.log.error( self.name + ": EOF exception found" )
933 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800934 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700935 except Exception:
936 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700937 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800938
Jon Hall7eb38402015-01-08 17:19:54 -0800939 def changeDefaultGateway( self, host, newGW ):
940 """
941 Changes the default gateway of a host
942 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800943 if self.handle:
944 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800945 cmd = host + " route add default gw " + newGW
946 self.handle.sendline( cmd )
947 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800948 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800949 main.log.info( "response = " + response )
950 main.log.info(
951 "Default gateway of host " +
952 host +
953 " changed to " +
954 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800955 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700956 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700957 main.log.error( self.name + ": TIMEOUT exception found" )
958 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700959 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800960 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800961 main.log.error( self.name + ": EOF exception found" )
962 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800963 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700964 except Exception:
965 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700966 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800967
You Wange24d6272018-03-27 21:18:50 -0700968 def addRoute( self, host, dstIP, interface, ipv6=False ):
969 """
970 Add a route to host
971 Ex: h1 route add -host 224.2.0.1 h1-eth0
972 """
973 if self.handle:
974 try:
975 cmd = str( host )
976 if ipv6:
977 cmd += " route -A inet6 add "
978 else:
979 cmd += " route add -host "
980 cmd += str( dstIP ) + " " + str( interface )
981 self.handle.sendline( cmd )
982 self.handle.expect( "mininet>" )
983 response = self.handle.before
984 main.log.debug( "response = " + response )
985 return main.TRUE
986 except pexpect.TIMEOUT:
987 main.log.error( self.name + ": TIMEOUT exception found" )
988 main.log.error( self.name + ": " + self.handle.before )
989 main.cleanAndExit()
990 except pexpect.EOF:
991 main.log.error( self.name + ": EOF exception found" )
992 main.log.error( self.name + ": " + self.handle.before )
993 return main.FALSE
994 except Exception:
995 main.log.exception( self.name + ": Uncaught exception!" )
996 main.cleanAndExit()
997
Jon Hall7eb38402015-01-08 17:19:54 -0800998 def addStaticMACAddress( self, host, GW, macaddr ):
999 """
Jon Hallefbd9792015-03-05 16:11:36 -08001000 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001001 if self.handle:
1002 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001003 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1004 cmd = host + " arp -s " + GW + " " + macaddr
1005 self.handle.sendline( cmd )
1006 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001007 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001008 main.log.info( "response = " + response )
1009 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001010 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001011 GW +
1012 " changed to " +
1013 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001014 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001015 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001016 main.log.error( self.name + ": TIMEOUT exception found" )
1017 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001018 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001019 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001020 main.log.error( self.name + ": EOF exception found" )
1021 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001022 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001023 except Exception:
1024 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001025 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001026
Jon Hall7eb38402015-01-08 17:19:54 -08001027 def verifyStaticGWandMAC( self, host ):
1028 """
1029 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001030 if self.handle:
1031 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001032 # h1 arp -an
1033 cmd = host + " arp -an "
1034 self.handle.sendline( cmd )
1035 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001036 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001037 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001038 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001039 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001040 main.log.error( self.name + ": TIMEOUT exception found" )
1041 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001042 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001043 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001044 main.log.error( self.name + ": EOF exception found" )
1045 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001046 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001047 except Exception:
1048 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001049 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001050
Jon Hall7eb38402015-01-08 17:19:54 -08001051 def getMacAddress( self, host ):
1052 """
1053 Verifies the host's ip configured or not."""
1054 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001055 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001056 response = self.execute(
1057 cmd=host +
1058 " ifconfig",
1059 prompt="mininet>",
1060 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001061 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001062 main.log.error( self.name + ": EOF exception found" )
1063 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001064 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001065 except Exception:
1066 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001067 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001068
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001069 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001070 macAddressSearch = re.search( pattern, response, re.I )
1071 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001072 main.log.info(
1073 self.name +
1074 ": Mac-Address of Host " +
1075 host +
1076 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001077 macAddress )
1078 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001079 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001080 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001081
Jon Hall7eb38402015-01-08 17:19:54 -08001082 def getInterfaceMACAddress( self, host, interface ):
1083 """
1084 Return the IP address of the interface on the given host"""
1085 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001086 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001087 response = self.execute( cmd=host + " ifconfig " + interface,
1088 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001089 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001090 main.log.error( self.name + ": EOF exception found" )
1091 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001092 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001093 except Exception:
1094 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001095 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001096
1097 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001098 macAddressSearch = re.search( pattern, response, re.I )
1099 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001100 main.log.info( "No mac address found in %s" % response )
1101 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001102 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001103 main.log.info(
1104 "Mac-Address of " +
1105 host +
1106 ":" +
1107 interface +
1108 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001109 macAddress )
1110 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001111 else:
1112 main.log.error( "Connection failed to the host" )
1113
You Wang5da39c82018-04-26 22:55:08 -07001114 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001115 """
1116 Verifies the host's ip configured or not."""
1117 if self.handle:
1118 try:
1119 response = self.execute(
1120 cmd=host +
1121 " ifconfig",
1122 prompt="mininet>",
1123 timeout=10 )
1124 except pexpect.EOF:
1125 main.log.error( self.name + ": EOF exception found" )
1126 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001127 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001128 except Exception:
1129 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001130 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001131
sathishmad953462015-12-03 17:42:07 +05301132 pattern = ''
1133 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001134 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301135 else:
Jon Hall439c8912016-04-15 02:22:03 -07001136 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001137 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001138 if not ipAddressSearch:
1139 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001140 main.log.info(
1141 self.name +
1142 ": IP-Address of Host " +
1143 host +
1144 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001145 ipAddressSearch.group( 1 ) )
1146 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001147 else:
1148 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001149
Jon Hall7eb38402015-01-08 17:19:54 -08001150 def getSwitchDPID( self, switch ):
1151 """
1152 return the datapath ID of the switch"""
1153 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001154 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001155 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001156 response = self.execute(
1157 cmd=cmd,
1158 prompt="mininet>",
1159 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001160 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001161 main.log.error( self.name + ": EOF exception found" )
1162 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001163 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001164 except Exception:
1165 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001166 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001167 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001168 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001169 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001170 main.log.info(
1171 "Couldn't find DPID for switch %s, found: %s" %
1172 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001173 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001174 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001175 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001176 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001177
Jon Hall7eb38402015-01-08 17:19:54 -08001178 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001179 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001180 self.handle.sendline( "" )
1181 self.expect( "mininet>" )
1182 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001183 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001184 response = self.execute(
1185 cmd=cmd,
1186 prompt="mininet>",
1187 timeout=10 )
1188 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001189 response = self.handle.before
1190 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001191 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001192 main.log.error( self.name + ": TIMEOUT exception found" )
1193 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001194 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001195 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001196 main.log.error( self.name + ": EOF exception found" )
1197 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001198 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001199 except Exception:
1200 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001201 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001202
Jon Hall7eb38402015-01-08 17:19:54 -08001203 def getInterfaces( self, node ):
1204 """
1205 return information dict about interfaces connected to the node"""
1206 if self.handle:
1207 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001208 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001209 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001210 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001211 response = self.execute(
1212 cmd=cmd,
1213 prompt="mininet>",
You Wang9fc5ce42019-01-23 15:10:08 -08001214 timeout=10,
1215 logCmd=False )
Jon Hallfbc828e2015-01-06 17:30:19 -08001216 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001217 main.log.error( self.name + ": EOF exception found" )
1218 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001219 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001220 except Exception:
1221 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001222 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001223 return response
1224 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001225 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001226
Jon Hall7eb38402015-01-08 17:19:54 -08001227 def dump( self ):
1228 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001229 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001230 response = self.execute(
1231 cmd='dump',
1232 prompt='mininet>',
1233 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001234 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001235 main.log.error( self.name + ": EOF exception found" )
1236 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001237 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001238 except Exception:
1239 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001240 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001241 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001242
Jon Hall7eb38402015-01-08 17:19:54 -08001243 def intfs( self ):
1244 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001245 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001246 response = self.execute(
1247 cmd='intfs',
1248 prompt='mininet>',
1249 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001250 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001251 main.log.error( self.name + ": EOF exception found" )
1252 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001253 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001254 except Exception:
1255 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001256 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001257 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001258
Jon Hall7eb38402015-01-08 17:19:54 -08001259 def net( self ):
1260 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001261 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001262 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001263 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001264 main.log.error( self.name + ": EOF exception found" )
1265 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001266 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001267 except Exception:
1268 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001269 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001270 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001271
Devin Lima7cfdbd2017-09-29 15:02:22 -07001272 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001273 main.log.info( self.name + ": List network links" )
1274 try:
1275 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001276 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001277 except pexpect.EOF:
1278 main.log.error( self.name + ": EOF exception found" )
1279 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001280 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001281 except Exception:
1282 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001283 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001284 return response
1285
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001286 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001287 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001288 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001289
kelvin-onlab7cce9382015-07-17 10:21:03 -07001290 @parm:
1291 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1292 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001293 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001294 try:
1295 for host1 in hosts:
1296 for host2 in hosts:
1297 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001298 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1299 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001300 except Exception:
1301 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001302 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001303
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001304 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001305 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001306 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1307 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001308
kelvin-onlab7cce9382015-07-17 10:21:03 -07001309 @parm:
1310 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1311 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001312 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001313 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1314 try:
1315 # Setup the mininet command
1316 cmd1 = 'iperf ' + host1 + " " + host2
1317 self.handle.sendline( cmd1 )
1318 outcome = self.handle.expect( "mininet>", timeout )
1319 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001320
kelvin-onlab7cce9382015-07-17 10:21:03 -07001321 # checks if there are results in the mininet response
1322 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001323 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001324 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001325 response = response.split( "\r\n" )
1326 response = response[ len( response )-2 ]
1327 response = response.split( ": " )
1328 response = response[ len( response )-1 ]
1329 response = response.replace( "[", "" )
1330 response = response.replace( "]", "" )
1331 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001332
kelvin-onlab7cce9382015-07-17 10:21:03 -07001333 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001334 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001335
kelvin-onlab7cce9382015-07-17 10:21:03 -07001336 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001337 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001338 if len( bandwidth ) == 2:
1339 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001340 return main.TRUE
1341 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001342 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001343 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001344 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001345 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001346 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001347 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001348 main.log.error( self.name + ": TIMEOUT exception found" )
1349 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001350 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001351 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001352 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001353 self.handle.expect( "Interrupt" )
1354 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001355 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001356 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001357 main.log.error( self.name + ": EOF exception found" )
1358 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001359 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001360 except Exception:
1361 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001362 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001363
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001364 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001365 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1366 try:
1367 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001368 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001369 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001370 outcome1 = self.handle.expect( "mininet>" )
1371 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001372 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001373 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001374 response1 = self.handle.before
1375 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001376 print response1, response2
1377 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001378 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001379 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001380 return main.TRUE
1381 else:
1382 main.log.error( self.name + ": iperf test failed" )
1383 return main.FALSE
1384 except pexpect.TIMEOUT:
1385 main.log.error( self.name + ": TIMEOUT exception found" )
1386 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001387 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001388 self.handle.expect( "Interrupt" )
1389 self.handle.expect( "mininet>" )
1390 return main.FALSE
1391 except pexpect.EOF:
1392 main.log.error( self.name + ": EOF exception found" )
1393 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001394 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001395 except Exception:
1396 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001397 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001398
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001399 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001400 '''
GlennRC61321f22015-07-16 13:36:54 -07001401 Runs the iperfudp function with a given set of hosts and specified
1402 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001403
GlennRC61321f22015-07-16 13:36:54 -07001404 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001405 bandwidth: the targeted bandwidth, in megabits ('M')
1406 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001407 try:
1408 for host1 in hosts:
1409 for host2 in hosts:
1410 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001411 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1412 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001413 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001414 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001415 return main.FALSE
1416 except Exception:
1417 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001418 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001419
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001420 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001421 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001422 Creates an iperf UDP test with a specific bandwidth.
1423 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001424
kelvin-onlab7cce9382015-07-17 10:21:03 -07001425 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001426 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1427 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001428 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001429 try:
1430 # setup the mininet command
1431 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001432 self.handle.sendline( cmd )
1433 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001434 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001435
kelvin-onlab7cce9382015-07-17 10:21:03 -07001436 # check if there are in results in the mininet response
1437 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001438 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001439 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001440 response = response.split( "\r\n" )
1441 response = response[ len( response )-2 ]
1442 response = response.split( ": " )
1443 response = response[ len( response )-1 ]
1444 response = response.replace( "[", "" )
1445 response = response.replace( "]", "" )
1446 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001447
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001448 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001449
kelvin-onlab7cce9382015-07-17 10:21:03 -07001450 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001451 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001452 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001453 # if one entry is blank then something is wrong
1454 for item in mnBandwidth:
1455 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001456 main.log.error( self.name + ": Could not parse iperf output" )
1457 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001458 return main.FALSE
1459 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001460 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001461 return main.TRUE
1462 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001463 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001464 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001465
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001466 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001467 main.log.error( self.name + ": TIMEOUT exception found" )
1468 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001469 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001470 except pexpect.EOF:
1471 main.log.error( self.name + ": EOF exception found" )
1472 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001473 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001474 except Exception:
1475 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001476 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001477
Jon Hall7eb38402015-01-08 17:19:54 -08001478 def nodes( self ):
1479 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001480 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001481 response = self.execute(
1482 cmd='nodes',
1483 prompt='mininet>',
1484 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001485 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001486 main.log.error( self.name + ": EOF exception found" )
1487 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001488 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001489 except Exception:
1490 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001491 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001492 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001493
Jon Hall7eb38402015-01-08 17:19:54 -08001494 def pingpair( self ):
1495 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001496 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001497 response = self.execute(
1498 cmd='pingpair',
1499 prompt='mininet>',
1500 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001501 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001502 main.log.error( self.name + ": EOF exception found" )
1503 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001504 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001505 except Exception:
1506 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001507 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001508
Jon Hall7eb38402015-01-08 17:19:54 -08001509 if re.search( ',\s0\%\spacket\sloss', response ):
1510 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001511 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001512 else:
alisone4121a92016-11-22 16:31:36 -08001513 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001514 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001515
Jon Hall7eb38402015-01-08 17:19:54 -08001516 def link( self, **linkargs ):
1517 """
GlennRCed771242016-01-13 17:02:47 -08001518 Bring link( s ) between two nodes up or down
1519 """
Jon Hall6094a362014-04-11 14:46:56 -07001520 try:
GlennRCed771242016-01-13 17:02:47 -08001521 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1522 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1523 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1524 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1525
1526 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1527 cmd = "link {} {} {}".format( end1, end2, option )
1528 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001529 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001530 response = self.handle.before
1531 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001532 if "not in network" in response:
1533 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1534 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001535 return main.TRUE
1536 except pexpect.TIMEOUT:
1537 main.log.exception( self.name + ": Command timed out" )
1538 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001539 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001540 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001541 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001542 except Exception:
1543 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001544 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001545
pingping-lin8244a3b2015-09-16 13:36:56 -07001546 def switch( self, **switchargs ):
1547 """
1548 start/stop a switch
1549 """
1550 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1551 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1552 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1553 command = "switch " + str( sw ) + " " + str( option )
1554 main.log.info( command )
1555 try:
1556 self.handle.sendline( command )
1557 self.handle.expect( "mininet>" )
1558 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001559 main.log.error( self.name + ": TIMEOUT exception found" )
1560 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001561 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001562 except pexpect.EOF:
1563 main.log.error( self.name + ": EOF exception found" )
1564 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001565 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001566 return main.TRUE
1567
pingping-lin5bb663b2015-09-24 11:47:50 -07001568 def node( self, nodeName, commandStr ):
1569 """
1570 Carry out a command line on a given node
1571 @parm:
1572 nodeName: the node name in Mininet testbed
1573 commandStr: the command line will be carried out on the node
1574 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1575 """
1576 command = str( nodeName ) + " " + str( commandStr )
1577 main.log.info( command )
1578
1579 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001580 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001581 if re.search( "Unknown command", response ):
1582 main.log.warn( response )
1583 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001584 if re.search( "Permission denied", response ):
1585 main.log.warn( response )
1586 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001587 except pexpect.EOF:
1588 main.log.error( self.name + ": EOF exception found" )
1589 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001590 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001591 main.log.info( " response is :" )
1592 main.log.info( response )
1593 return response
1594
Jon Hall7eb38402015-01-08 17:19:54 -08001595 def yank( self, **yankargs ):
1596 """
1597 yank a mininet switch interface to a host"""
1598 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001599 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001600 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1601 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001602 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001603 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001604 response = self.execute(
1605 cmd=command,
1606 prompt="mininet>",
1607 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001608 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001609 main.log.error( self.name + ": EOF exception found" )
1610 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001611 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001612 except Exception:
1613 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001614 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001615 return main.TRUE
1616
Jon Hall7eb38402015-01-08 17:19:54 -08001617 def plug( self, **plugargs ):
1618 """
1619 plug the yanked mininet switch interface to a switch"""
1620 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001621 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001622 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1623 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001624 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001625 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001626 response = self.execute(
1627 cmd=command,
1628 prompt="mininet>",
1629 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001630 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001631 main.log.error( self.name + ": EOF exception found" )
1632 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001633 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001634 except Exception:
1635 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001636 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001637 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001638
Jon Hall7eb38402015-01-08 17:19:54 -08001639 def dpctl( self, **dpctlargs ):
1640 """
1641 Run dpctl command on all switches."""
1642 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001643 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001644 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1645 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1646 command = "dpctl " + cmd + " " + str( cmdargs )
1647 try:
1648 response = self.execute(
1649 cmd=command,
1650 prompt="mininet>",
1651 timeout=10 )
1652 except pexpect.EOF:
1653 main.log.error( self.name + ": EOF exception found" )
1654 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001655 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001656 except Exception:
1657 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001658 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001659 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001660
kelvin-onlabd3b64892015-01-20 13:26:24 -08001661 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001662 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001663 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001664 try:
1665 fileInput = path + '/lib/Mininet/INSTALL'
1666 version = super( Mininet, self ).getVersion()
1667 pattern = 'Mininet\s\w\.\w\.\w\w*'
1668 for line in open( fileInput, 'r' ).readlines():
1669 result = re.match( pattern, line )
1670 if result:
1671 version = result.group( 0 )
1672 return version
1673 except Exception:
1674 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001675 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001676
kelvin-onlabd3b64892015-01-20 13:26:24 -08001677 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001678 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001679 Parameters:
1680 sw: The name of an OVS switch. Example "s1"
1681 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001682 The output of the command from the mininet cli
1683 or main.FALSE on timeout"""
1684 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001685 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001686 response = self.execute(
1687 cmd=command,
1688 prompt="mininet>",
1689 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001690 if response:
Jon Hallab611372018-02-21 15:26:05 -08001691 if "no bridge named" in response:
1692 main.log.error( self.name + ": Error in getSwController: " +
1693 self.handle.before )
1694 return main.FALSE
1695 else:
1696 return response
admin2a9548d2014-06-17 14:08:07 -07001697 else:
1698 return main.FALSE
1699 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001700 main.log.error( self.name + ": EOF exception found" )
1701 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001702 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001703 except Exception:
1704 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001705 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001706
Charles Chan029be652015-08-24 01:46:10 +08001707 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001708 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001709 Description:
1710 Assign switches to the controllers ( for ovs use only )
1711 Required:
1712 sw - Name of the switch. This can be a list or a string.
1713 ip - Ip addresses of controllers. This can be a list or a string.
1714 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001715 port - ONOS use port 6653, if no list of ports is passed, then
1716 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001717 ptcp - ptcp number, This can be a string or a list that has
1718 the same length as switch. This is optional and not required
1719 when using ovs switches.
1720 NOTE: If switches and ptcp are given in a list type they should have the
1721 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1722 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001723
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001724 Return:
1725 Returns main.TRUE if mininet correctly assigned switches to
1726 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001727 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001728 """
1729 assignResult = main.TRUE
1730 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001731 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001732 command = "sh ovs-vsctl set-controller "
1733 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001734 try:
1735 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001736 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001737 if isinstance( port, types.StringType ) or \
1738 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001739 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001740 elif isinstance( port, types.ListType ):
1741 main.log.error( self.name + ": Only one controller " +
1742 "assigned and a list of ports has" +
1743 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001744 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001745 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001746 main.log.error( self.name + ": Invalid controller port " +
1747 "number. Please specify correct " +
1748 "controller port" )
1749 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001750
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001751 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001752 if isinstance( port, types.StringType ) or \
1753 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001754 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001755 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1756 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001757 elif isinstance( port, types.ListType ):
1758 if ( len( ip ) != len( port ) ):
1759 main.log.error( self.name + ": Port list = " +
1760 str( len( port ) ) +
1761 "should be the same as controller" +
1762 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001763 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001764 else:
1765 onosIp = ""
1766 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001767 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1768 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001769 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001770 main.log.error( self.name + ": Invalid controller port " +
1771 "number. Please specify correct " +
1772 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001773 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001774 else:
1775 main.log.error( self.name + ": Invalid ip address" )
1776 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001777
1778 if isinstance( sw, types.StringType ):
1779 command += sw + " "
1780 if ptcp:
1781 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001782 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001783 elif isinstance( ptcp, types.ListType ):
1784 main.log.error( self.name + ": Only one switch is " +
1785 "being set and multiple PTCP is " +
1786 "being passed " )
1787 else:
1788 main.log.error( self.name + ": Invalid PTCP" )
1789 ptcp = ""
1790 command += onosIp
1791 commandList.append( command )
1792
1793 elif isinstance( sw, types.ListType ):
1794 if ptcp:
1795 if isinstance( ptcp, types.ListType ):
1796 if len( ptcp ) != len( sw ):
1797 main.log.error( self.name + ": PTCP length = " +
1798 str( len( ptcp ) ) +
1799 " is not the same as switch" +
1800 " length = " +
1801 str( len( sw ) ) )
1802 return main.FALSE
1803 else:
1804 for switch, ptcpNum in zip( sw, ptcp ):
1805 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001806 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001807 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001808 tempCmd += onosIp
1809 commandList.append( tempCmd )
1810 else:
1811 main.log.error( self.name + ": Invalid PTCP" )
1812 return main.FALSE
1813 else:
1814 for switch in sw:
1815 tempCmd = "sh ovs-vsctl set-controller "
1816 tempCmd += switch + " " + onosIp
1817 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001818 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001819 main.log.error( self.name + ": Invalid switch type " )
1820 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001821
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001822 for cmd in commandList:
1823 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001824 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08001825 if "no bridge named" in self.handle.before:
1826 main.log.error( self.name + ": Error in assignSwController: " +
1827 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001828 except pexpect.TIMEOUT:
1829 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1830 return main.FALSE
1831 except pexpect.EOF:
1832 main.log.error( self.name + ": EOF exception found" )
1833 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001834 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001835 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001836 except pexpect.EOF:
1837 main.log.error( self.name + ": EOF exception found" )
1838 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001839 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001840 except Exception:
1841 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001842 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001843
kelvin-onlabd3b64892015-01-20 13:26:24 -08001844 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001845 """
1846 Removes the controller target from sw"""
1847 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001848 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001849 response = self.execute(
1850 cmd=command,
1851 prompt="mininet>",
1852 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001853 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001854 main.log.error( self.name + ": EOF exception found" )
1855 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001856 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001857 except Exception:
1858 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001859 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001860 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001861 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001862
kelvin-onlabd3b64892015-01-20 13:26:24 -08001863 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001864 """
Jon Hallb1290e82014-11-18 16:17:48 -05001865 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001866 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001867 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001868 NOTE: cannot currently specify what type of switch
1869 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001870 sw = name of the new switch as a string
1871 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001872 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001873 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001874 """
1875 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001876 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001877 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001878 response = self.execute(
1879 cmd=command,
1880 prompt="mininet>",
1881 timeout=10 )
1882 if re.search( "already exists!", response ):
1883 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001884 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001885 elif re.search( "Error", response ):
1886 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001887 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001888 elif re.search( "usage:", response ):
1889 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001890 return main.FALSE
1891 else:
1892 return main.TRUE
1893 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001894 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001895 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001896 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001897 except Exception:
1898 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001899 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001900
kelvin-onlabd3b64892015-01-20 13:26:24 -08001901 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001902 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001903 delete a switch from the mininet topology
1904 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001905 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001906 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001907 sw = name of the switch as a string
1908 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001909 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001910 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001911 response = self.execute(
1912 cmd=command,
1913 prompt="mininet>",
1914 timeout=10 )
1915 if re.search( "no switch named", response ):
1916 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001917 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001918 elif re.search( "Error", response ):
1919 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001920 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001921 elif re.search( "usage:", response ):
1922 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001923 return main.FALSE
1924 else:
1925 return main.TRUE
1926 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001927 main.log.error( self.name + ": EOF exception found" )
1928 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001929 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001930 except Exception:
1931 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001932 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001933
You Wangc61aaa22019-02-01 15:49:48 -08001934 def getSwitchRandom( self, timeout=60, nonCut=True, excludeNodes=[], skipSwitches=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07001935 """
1936 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001937 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001938 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001939 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07001940 it just randomly returns one switch from all current switches in
1941 Mininet.
You Wang9fc5ce42019-01-23 15:10:08 -08001942 excludeNodes will be pased to getGraphDict method
You Wangc61aaa22019-02-01 15:49:48 -08001943 Switches specified in skipSwitches will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07001944 Returns the name of the chosen switch.
1945 """
1946 import random
1947 candidateSwitches = []
1948 try:
1949 if not nonCut:
You Wangc61aaa22019-02-01 15:49:48 -08001950 switches = self.getSwitches( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07001951 assert len( switches ) != 0
1952 for switchName in switches.keys():
1953 candidateSwitches.append( switchName )
1954 else:
You Wang9fc5ce42019-01-23 15:10:08 -08001955 graphDict = self.getGraphDict( timeout=timeout, useId=False,
You Wang9fc5ce42019-01-23 15:10:08 -08001956 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001957 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001958 return None
1959 self.graph.update( graphDict )
1960 candidateSwitches = self.graph.getNonCutVertices()
You Wangc61aaa22019-02-01 15:49:48 -08001961 candidateSwitches = [ switch for switch in candidateSwitches if switch not in skipSwitches ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001962 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001963 return None
1964 elif len( candidateSwitches ) == 0:
1965 main.log.info( self.name + ": No candidate switch for deletion" )
1966 return None
1967 else:
1968 switch = random.sample( candidateSwitches, 1 )
1969 return switch[ 0 ]
1970 except KeyError:
1971 main.log.exception( self.name + ": KeyError exception found" )
1972 return None
1973 except AssertionError:
1974 main.log.exception( self.name + ": AssertionError exception found" )
1975 return None
1976 except Exception:
1977 main.log.exception( self.name + ": Uncaught exception" )
1978 return None
1979
1980 def delSwitchRandom( self, timeout=60, nonCut=True ):
1981 """
1982 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001983 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001984 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001985 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07001986 otherwise it just randomly delete one switch from all current
1987 switches in Mininet.
1988 Returns the name of the deleted switch
1989 """
1990 try:
1991 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001992 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001993 return None
1994 else:
1995 deletionResult = self.delSwitch( switch )
1996 if deletionResult:
1997 return switch
1998 else:
1999 return None
2000 except Exception:
2001 main.log.exception( self.name + ": Uncaught exception" )
2002 return None
2003
kelvin-onlabd3b64892015-01-20 13:26:24 -08002004 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002005 """
2006 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002007 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002008 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002009 NOTE: cannot currently specify what type of link
2010 required params:
2011 node1 = the string node name of the first endpoint of the link
2012 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002013 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002014 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002015 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002016 response = self.execute(
2017 cmd=command,
2018 prompt="mininet>",
2019 timeout=10 )
2020 if re.search( "doesnt exist!", response ):
2021 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002022 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002023 elif re.search( "Error", response ):
2024 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002025 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002026 elif re.search( "usage:", response ):
2027 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002028 return main.FALSE
2029 else:
2030 return main.TRUE
2031 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002032 main.log.error( self.name + ": EOF exception found" )
2033 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002034 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002035 except Exception:
2036 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002037 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002038
kelvin-onlabd3b64892015-01-20 13:26:24 -08002039 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002040 """
2041 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002042 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002043 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002044 required params:
2045 node1 = the string node name of the first endpoint of the link
2046 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002047 returns: main.FALSE on an error, else main.TRUE
2048 """
Jon Hallffb386d2014-11-21 13:43:38 -08002049 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002050 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002051 response = self.execute(
2052 cmd=command,
2053 prompt="mininet>",
2054 timeout=10 )
2055 if re.search( "no node named", response ):
2056 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002057 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002058 elif re.search( "Error", response ):
2059 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002060 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002061 elif re.search( "usage:", response ):
2062 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002063 return main.FALSE
2064 else:
2065 return main.TRUE
2066 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002067 main.log.error( self.name + ": EOF exception found" )
2068 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002069 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002070 except Exception:
2071 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002072 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002073
You Wangc61aaa22019-02-01 15:49:48 -08002074 def getLinkRandom( self, timeout=60, nonCut=True, excludeNodes=[], skipLinks=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07002075 """
2076 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002077 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002078 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002079 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002080 it just randomly returns one link from all current links in
2081 Mininet.
You Wang9fc5ce42019-01-23 15:10:08 -08002082 excludeNodes will be passed to getLinks method to exclude unexpected links.
You Wangc61aaa22019-02-01 15:49:48 -08002083 Any link that has either end included in skipLinks will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07002084 Returns the link as a list, e.g. [ 's1', 's2' ]
2085 """
2086 import random
2087 candidateLinks = []
2088 try:
2089 if not nonCut:
You Wang9fc5ce42019-01-23 15:10:08 -08002090 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07002091 assert len( links ) != 0
2092 for link in links:
2093 # Exclude host-switch link
2094 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2095 continue
2096 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2097 else:
You Wang9fc5ce42019-01-23 15:10:08 -08002098 graphDict = self.getGraphDict( timeout=timeout, useId=False,
You Wang9fc5ce42019-01-23 15:10:08 -08002099 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002100 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002101 return None
2102 self.graph.update( graphDict )
2103 candidateLinks = self.graph.getNonCutEdges()
You Wangc61aaa22019-02-01 15:49:48 -08002104 candidateLinks = [ link for link in candidateLinks
2105 if link[0] not in skipLinks and link[1] not in skipLinks ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002106 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002107 return None
2108 elif len( candidateLinks ) == 0:
2109 main.log.info( self.name + ": No candidate link for deletion" )
2110 return None
2111 else:
2112 link = random.sample( candidateLinks, 1 )
2113 return link[ 0 ]
2114 except KeyError:
2115 main.log.exception( self.name + ": KeyError exception found" )
2116 return None
2117 except AssertionError:
2118 main.log.exception( self.name + ": AssertionError exception found" )
2119 return None
2120 except Exception:
2121 main.log.exception( self.name + ": Uncaught exception" )
2122 return None
2123
2124 def delLinkRandom( self, timeout=60, nonCut=True ):
2125 """
2126 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002127 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002128 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002129 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002130 otherwise it just randomly delete one link from all current links
2131 in Mininet.
2132 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2133 """
2134 try:
2135 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002136 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002137 return None
2138 else:
2139 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2140 if deletionResult:
2141 return link
2142 else:
2143 return None
2144 except Exception:
2145 main.log.exception( self.name + ": Uncaught exception" )
2146 return None
2147
kelvin-onlabd3b64892015-01-20 13:26:24 -08002148 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002149 """
Jon Hallb1290e82014-11-18 16:17:48 -05002150 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002151 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002152 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002153 NOTE: cannot currently specify what type of host
2154 required params:
2155 hostname = the string hostname
2156 optional key-value params
2157 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002158 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002159 """
2160 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002161 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002162 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002163 response = self.execute(
2164 cmd=command,
2165 prompt="mininet>",
2166 timeout=10 )
2167 if re.search( "already exists!", response ):
2168 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002169 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002170 elif re.search( "doesnt exists!", response ):
2171 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002172 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002173 elif re.search( "Error", response ):
2174 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002175 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002176 elif re.search( "usage:", response ):
2177 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002178 return main.FALSE
2179 else:
2180 return main.TRUE
2181 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002182 main.log.error( self.name + ": EOF exception found" )
2183 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002184 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002185 except Exception:
2186 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002187 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002188
kelvin-onlabd3b64892015-01-20 13:26:24 -08002189 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002190 """
2191 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002192 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002193 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002194 NOTE: this uses a custom mn function
2195 required params:
2196 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002197 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002198 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002199 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002200 response = self.execute(
2201 cmd=command,
2202 prompt="mininet>",
2203 timeout=10 )
2204 if re.search( "no host named", response ):
2205 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002206 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002207 elif re.search( "Error", response ):
2208 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002209 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002210 elif re.search( "usage:", response ):
2211 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002212 return main.FALSE
2213 else:
2214 return main.TRUE
2215 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002216 main.log.error( self.name + ": EOF exception found" )
2217 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002218 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002219 except Exception:
2220 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002221 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002222
Jon Hall7eb38402015-01-08 17:19:54 -08002223 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002224 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002225 Called at the end of the test to stop the mininet and
2226 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002227 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002228 try:
2229 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002230 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002231 timeout=2 )
2232 response = main.TRUE
2233 if i == 0:
2234 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002235 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002236 return main.TRUE
2237 # print "Disconnecting Mininet"
2238 if self.handle:
2239 self.handle.sendline( "exit" )
2240 self.handle.expect( "exit" )
2241 self.handle.expect( "(.*)" )
2242 else:
2243 main.log.error( "Connection failed to the host" )
2244 return response
2245 except pexpect.EOF:
2246 main.log.error( self.name + ": EOF exception found" )
2247 main.log.error( self.name + ": " + self.handle.before )
You Wangd4fae5c2018-08-22 13:56:49 -07002248 # Do not exit the entire test when pexpect.EOF is caught
2249 # FIXME: We might need to do something else here
2250 return main.ERROR
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002251 except Exception:
2252 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002253 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002254
Devin Lima7cfdbd2017-09-29 15:02:22 -07002255 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002256 """
Jon Hall21270ac2015-02-16 17:59:55 -08002257 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002258 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002259 main.FALSE if the pexpect handle does not exist.
2260
Jon Halld61331b2015-02-17 16:35:47 -08002261 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002262 """
Jon Halld61331b2015-02-17 16:35:47 -08002263 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002264 response = ''
2265 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002266 try:
Jon Halld80cc142015-07-06 13:36:05 -07002267 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002268 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002269 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002270 pexpect.EOF,
2271 pexpect.TIMEOUT ],
2272 timeout )
2273 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002274 main.log.info( "Exiting mininet.." )
2275 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002276 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002277 prompt=self.prompt,
2278 timeout=exitTimeout )
2279 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002280 self.handle.sendline( "sudo mn -c" )
2281 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002282
Jeremyd9e4eb12016-04-13 12:09:06 -07002283 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002284 main.log.info( " Mininet trying to exit while not " +
2285 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002286 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002287 elif i == 2:
2288 main.log.error( "Something went wrong exiting mininet" )
2289 elif i == 3: # timeout
2290 main.log.error( "Something went wrong exiting mininet " +
2291 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002292
You Wang18db8592018-04-02 13:52:03 -07002293 self.handle.sendline( "" )
2294 self.handle.expect( self.prompt )
2295 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2296
Hari Krishnab35c6d02015-03-18 11:13:51 -07002297 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002298 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002299 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002300 self.handle.sendline(
2301 "sudo kill -9 \`ps -ef | grep \"" +
2302 fileName +
2303 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002304 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002305 main.log.error( self.name + ": TIMEOUT exception found" )
2306 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002307 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002308 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002309 main.log.error( self.name + ": EOF exception found" )
2310 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002311 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002312 except Exception:
2313 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002314 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002315 else:
2316 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002317 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002318 return response
2319
YPZhang26a139e2016-04-25 14:01:55 -07002320 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002321 """
2322 Description:
2323 Sends arp message from mininet host for hosts discovery
2324 Required:
2325 host - hosts name
2326 Optional:
2327 ip - ip address that does not exist in the network so there would
2328 be no reply.
2329 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002330 if ethDevice:
2331 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002332 cmd = srcHost + " arping -c1 "
2333 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002334 cmd += "-w10 " # If we don't want the actural arping result, set -w10, arping will exit after 10 ms.
YPZhang26a139e2016-04-25 14:01:55 -07002335 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002336 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002337 if output:
2338 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002339 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002340 i = self.handle.expect( [ "mininet>", "arping: " ] )
2341 if i == 0:
2342 return main.TRUE
2343 elif i == 1:
2344 response = self.handle.before + self.handle.after
2345 self.handle.expect( "mininet>" )
2346 response += self.handle.before + self.handle.after
2347 main.log.warn( "Error sending arping, output was: " +
2348 response )
2349 return main.FALSE
2350 except pexpect.TIMEOUT:
2351 main.log.error( self.name + ": TIMEOUT exception found" )
2352 main.log.warn( self.handle.before )
2353 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002354 except pexpect.EOF:
2355 main.log.error( self.name + ": EOF exception found" )
2356 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002357 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002358 except Exception:
2359 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002360 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002361
Jon Hall7eb38402015-01-08 17:19:54 -08002362 def decToHex( self, num ):
2363 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002364
Jon Hall7eb38402015-01-08 17:19:54 -08002365 def getSwitchFlowCount( self, switch ):
2366 """
2367 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002368 if self.handle:
2369 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2370 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002371 response = self.execute(
2372 cmd=cmd,
2373 prompt="mininet>",
2374 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002375 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002376 main.log.error( self.name + ": EOF exception found" )
2377 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002378 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002379 except Exception:
2380 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002381 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002382 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002383 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002384 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002385 main.log.info(
2386 "Couldn't find flows on switch %s, found: %s" %
2387 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002388 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002389 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002390 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002391 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002392
Jon Hall9ed8f372016-02-24 17:34:07 -08002393 def checkFlows( self, sw, dumpFormat=None ):
2394 if dumpFormat:
2395 command = "sh ovs-ofctl -F " + \
2396 dumpFormat + " dump-flows " + str( sw )
2397 else:
2398 command = "sh ovs-ofctl dump-flows " + str( sw )
2399 try:
2400 response = self.execute(
2401 cmd=command,
2402 prompt="mininet>",
2403 timeout=10 )
2404 return response
2405 except pexpect.EOF:
2406 main.log.error( self.name + ": EOF exception found" )
2407 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002408 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002409 except Exception:
2410 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002411 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002412
GlennRC68467eb2015-11-16 18:01:01 -08002413 def flowTableComp( self, flowTable1, flowTable2 ):
2414 # This function compares the selctors and treatments of each flow
2415 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002416 assert flowTable1, "flowTable1 is empty or None"
2417 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002418 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002419 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002420 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002421 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002422 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2423 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002424 for field in dFields:
2425 try:
2426 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002427 except KeyError:
2428 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002429 try:
2430 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002431 except KeyError:
2432 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002433 for i in range( len( flowTable1 ) ):
2434 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002435 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002436 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002437 returnValue = main.FALSE
2438 break
2439 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002440 except AssertionError:
2441 main.log.exception( "Nothing to compare" )
2442 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002443 except Exception:
2444 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002445 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002446
GlennRC528ad292015-11-12 10:38:18 -08002447 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002448 '''
GlennRC956ea742015-11-05 16:14:15 -08002449 Discription: Parses flows into json format.
2450 NOTE: this can parse any string thats separated with commas
2451 Arguments:
2452 Required:
2453 flows: a list of strings that represnt flows
2454 Optional:
2455 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2456 debug: prints out the final result
2457 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002458 '''
GlennRC528ad292015-11-12 10:38:18 -08002459 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002460 try:
2461 for flow in flowTable:
2462 jsonFlow = {}
2463 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002464 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002465 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002466 for i in range( len( parsedFlow ) ):
2467 item = parsedFlow[ i ]
2468 if item[ 0 ] == " ":
2469 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002470 # grab the selector and treatment from the parsed flow
2471 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002472 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002473 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002474 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002475 index = 0
2476 # parse the flags
2477 # NOTE: This only parses one flag
2478 flag = {}
2479 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002480 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002481 index += 1
2482 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002483 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002484 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002485 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002486 # the priority is stuck in the selecter so put it back
2487 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002488 if 'priority' in sel[0]:
2489 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002490 # parse selector
2491 criteria = []
2492 for item in sel:
2493 # this is the type of the packet e.g. "arp"
2494 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002495 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002496 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002497 field = item.split( "=" )
2498 criteria.append( { field[ 0 ]: field[ 1 ] } )
2499 selector = { "selector": { "criteria": sorted( criteria ) } }
2500 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002501 # get rid of the action part e.g. "action=output:2"
2502 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002503 treat = treat.split( "=" )
2504 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002505 # parse treatment
2506 action = []
2507 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002508 if ":" in item:
2509 field = item.split( ":" )
2510 action.append( { field[ 0 ]: field[ 1 ] } )
2511 else:
2512 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2513 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002514 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002515 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002516 # parse the rest of the flow
2517 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002518 field = item.split( "=" )
2519 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002520 # add the treatment and the selector to the json flow
2521 jsonFlow.update( selector )
2522 jsonFlow.update( treatment )
2523 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002524
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002525 if debug:
2526 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002527
You Wang91c37cf2016-05-23 09:39:42 -07002528 # add the json flow to the json flow table
2529 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002530
You Wang91c37cf2016-05-23 09:39:42 -07002531 return jsonFlowTable
2532
2533 except IndexError:
2534 main.log.exception( self.name + ": IndexError found" )
2535 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002536 except pexpect.EOF:
2537 main.log.error( self.name + ": EOF exception found" )
2538 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002539 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002540 except Exception:
2541 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002542 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002543
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002544 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002545 '''
2546 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002547 Each element is a flow.
2548 Arguments:
2549 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002550 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002551 a list of switches.
2552 Optional:
2553 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2554 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002555 '''
GlennRC956ea742015-11-05 16:14:15 -08002556 try:
2557 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002558 if isinstance( sw, list ):
2559 switches.extend( sw )
2560 else:
2561 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002562
2563 flows = []
2564 for s in switches:
2565 cmd = "sh ovs-ofctl dump-flows " + s
2566
GlennRC528ad292015-11-12 10:38:18 -08002567 if "1.0" == version:
2568 cmd += " -F OpenFlow10-table_id"
2569 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002570 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002571
2572 main.log.info( "Sending: " + cmd )
2573 self.handle.sendline( cmd )
2574 self.handle.expect( "mininet>" )
2575 response = self.handle.before
2576 response = response.split( "\r\n" )
2577 # dump the first two elements and the last
2578 # the first element is the command that was sent
2579 # the second is the table header
2580 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002581 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002582 flows.extend( response )
2583
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002584 if debug:
2585 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002586
GlennRC528ad292015-11-12 10:38:18 -08002587 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002588
GlennRC956ea742015-11-05 16:14:15 -08002589 except pexpect.EOF:
2590 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002591 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002592 except Exception:
2593 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002594 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002595
2596 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002597 '''
GlennRC956ea742015-11-05 16:14:15 -08002598 Discription: Checks whether the ID provided matches a flow ID in Mininet
2599 Arguments:
2600 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002601 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002602 a list of switches.
2603 flowId: the flow ID in hex format. Can also be a list of IDs
2604 Optional:
2605 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2606 debug: prints out the final result
2607 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2608 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002609 '''
GlennRC956ea742015-11-05 16:14:15 -08002610 try:
2611 main.log.info( "Getting flows from Mininet" )
2612 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002613 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002614 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002615
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002616 if debug:
2617 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002618
2619 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002620 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002621 result = False
2622 for f in flows:
2623 if flowId in f.get( 'cookie' ):
2624 result = True
2625 break
2626 # flowId is a list
2627 else:
2628 result = True
2629 # Get flow IDs from Mininet
2630 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2631 # Save the IDs that are not in Mininet
2632 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2633
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002634 if debug:
2635 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002636
2637 # Print out the IDs that are not in Mininet
2638 if absentIds:
2639 main.log.warn( "Absent ids: {}".format( absentIds ) )
2640 result = False
2641
2642 return main.TRUE if result else main.FALSE
2643
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002644 except pexpect.EOF:
2645 main.log.error( self.name + ": EOF exception found" )
2646 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002647 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002648 except Exception:
2649 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002650 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002651
Charles Chan029be652015-08-24 01:46:10 +08002652 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002653 """
Jon Hallefbd9792015-03-05 16:11:36 -08002654 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002655 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002656 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002657 self.handle.sendline( "" )
2658 self.handle.expect( "mininet>" )
2659 self.handle.sendline(
2660 "sh sudo tcpdump -n -i " +
2661 intf +
2662 " " +
2663 port +
2664 " -w " +
2665 filename.strip() +
2666 " &" )
2667 self.handle.sendline( "" )
2668 i = self.handle.expect( [ 'No\ssuch\device',
2669 'listening\son',
2670 pexpect.TIMEOUT,
2671 "mininet>" ],
2672 timeout=10 )
2673 main.log.warn( self.handle.before + self.handle.after )
2674 self.handle.sendline( "" )
2675 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002676 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002677 main.log.error(
2678 self.name +
2679 ": tcpdump - No such device exists. " +
2680 "tcpdump attempted on: " +
2681 intf )
admin2a9548d2014-06-17 14:08:07 -07002682 return main.FALSE
2683 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002684 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002685 return main.TRUE
2686 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002687 main.log.error(
2688 self.name +
2689 ": tcpdump command timed out! Check interface name," +
2690 " given interface was: " +
2691 intf )
admin2a9548d2014-06-17 14:08:07 -07002692 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002693 elif i == 3:
2694 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002695 return main.TRUE
2696 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002697 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002698 return main.FALSE
2699 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002700 main.log.error( self.name + ": EOF exception found" )
2701 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002702 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002703 except Exception:
2704 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002705 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002706
kelvin-onlabd3b64892015-01-20 13:26:24 -08002707 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002708 """
2709 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002710 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002711 self.handle.sendline( "sh sudo pkill tcpdump" )
2712 self.handle.expect( "mininet>" )
2713 self.handle.sendline( "" )
2714 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002715 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002716 main.log.error( self.name + ": TIMEOUT exception found" )
2717 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002718 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002719 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002720 main.log.error( self.name + ": EOF exception found" )
2721 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002722 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002723 except Exception:
2724 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002725 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002726
Jon Halld80cc142015-07-06 13:36:05 -07002727 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002728 """
2729 Read ports from a Mininet switch.
2730
2731 Returns a json structure containing information about the
2732 ports of the given switch.
2733 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002734 try:
2735 response = self.getInterfaces( nodeName )
2736 # TODO: Sanity check on response. log if no such switch exists
2737 ports = []
2738 for line in response.split( "\n" ):
2739 if not line.startswith( "name=" ):
2740 continue
2741 portVars = {}
2742 for var in line.split( "," ):
2743 key, value = var.split( "=" )
2744 portVars[ key ] = value
2745 isUp = portVars.pop( 'enabled', "True" )
2746 isUp = "True" in isUp
2747 if verbose:
2748 main.log.info( "Reading switch port %s(%s)" %
2749 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2750 mac = portVars[ 'mac' ]
2751 if mac == 'None':
2752 mac = None
2753 ips = []
2754 ip = portVars[ 'ip' ]
2755 if ip == 'None':
2756 ip = None
2757 ips.append( ip )
2758 name = portVars[ 'name' ]
2759 if name == 'None':
2760 name = None
2761 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2762 if name == 'lo':
2763 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2764 else:
2765 portNo = re.search( portRe, name ).group( 'port' )
2766 ports.append( { 'of_port': portNo,
2767 'mac': str( mac ).replace( '\'', '' ),
2768 'name': name,
2769 'ips': ips,
2770 'enabled': isUp } )
2771 return ports
2772 except pexpect.EOF:
2773 main.log.error( self.name + ": EOF exception found" )
2774 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002775 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002776 except Exception:
2777 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002778 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002779
You Wangdb8cd0a2016-05-26 15:19:45 -07002780 def getOVSPorts( self, nodeName ):
2781 """
2782 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2783
2784 Returns a list of dictionaries containing information about each
2785 port of the given switch.
2786 """
2787 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2788 try:
2789 response = self.execute(
2790 cmd=command,
2791 prompt="mininet>",
You Wang9fc5ce42019-01-23 15:10:08 -08002792 timeout=10,
2793 logCmd=False )
You Wangdb8cd0a2016-05-26 15:19:45 -07002794 ports = []
2795 if response:
2796 for line in response.split( "\n" ):
2797 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2798 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002799 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002800 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2801 result = re.search( pattern, line )
2802 if result:
2803 index = result.group( 'index' )
2804 name = result.group( 'name' )
2805 # This port number is extracted from port name
2806 port = result.group( 'port' )
2807 mac = result.group( 'mac' )
2808 ports.append( { 'index': index,
2809 'name': name,
2810 'port': port,
2811 'mac': mac } )
2812 return ports
2813 except pexpect.EOF:
2814 main.log.error( self.name + ": EOF exception found" )
2815 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002816 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002817 except Exception:
2818 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002819 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002820
You Wangc61aaa22019-02-01 15:49:48 -08002821 def getSwitches( self, verbose=False, updateTimeout=1000, excludeNodes=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002822 """
2823 Read switches from Mininet.
2824
2825 Returns a dictionary whose keys are the switch names and the value is
2826 a dictionary containing information about the switch.
You Wangc61aaa22019-02-01 15:49:48 -08002827 If excludeNodes is specified, switches with names included in excludeNodes
2828 will be ingored.
Jon Hallafa8a472015-06-12 14:02:42 -07002829 """
Jon Halla22481b2015-07-28 17:46:01 -07002830 # NOTE: To support new Mininet switch classes, just append the new
2831 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002832
Jon Halla22481b2015-07-28 17:46:01 -07002833 # Regex patterns to parse 'dump' output
2834 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002835 # <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 -07002836 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002837 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2838 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2839 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
You Wangc61aaa22019-02-01 15:49:48 -08002840 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
You Wang9fc5ce42019-01-23 15:10:08 -08002841 try:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002842 swRE = r"<(?P<class>" + switchClasses + r")" +\
2843 r"(?P<options>\{.*\})?\s" +\
2844 r"(?P<name>[^:]+)\:\s" +\
2845 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2846 r"\spid=(?P<pid>(\d)+)"
2847 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002848 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002849 output = {}
2850 dump = self.dump().split( "\n" )
2851 for line in dump:
2852 result = re.search( swRE, line, re.I )
2853 if result:
2854 name = result.group( 'name' )
You Wangc61aaa22019-02-01 15:49:48 -08002855 if name in excludeNodes:
2856 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002857 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2858 pid = result.group( 'pid' )
2859 swClass = result.group( 'class' )
2860 options = result.group( 'options' )
2861 if verbose:
2862 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2863 ports = self.getPorts( name )
2864 output[ name ] = { "dpid": dpid,
2865 "ports": ports,
2866 "swClass": swClass,
2867 "pid": pid,
2868 "options": options }
2869 return output
2870 except pexpect.EOF:
2871 main.log.error( self.name + ": EOF exception found" )
2872 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002873 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002874 except Exception:
2875 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002876 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002877
You Wangd66de192018-04-30 17:30:12 -07002878 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002879 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2880 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002881 """
2882 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002883 Optional:
2884 hostClass: it is used to match the class of the mininet host. It
2885 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002886 Returns a dictionary whose keys are the host names and the value is
2887 a dictionary containing information about the host.
2888 """
2889 # Regex patterns to parse dump output
2890 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002891 # <Host h1: pid=12725>
2892 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2893 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2894 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002895 # NOTE: Does not correctly match hosts with multi-links
2896 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2897 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002898 try:
You Wang53dba1e2018-02-02 17:45:44 -08002899 if not isinstance( hostClass, types.ListType ):
2900 hostClass = [ str( hostClass ) ]
2901 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002902 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2903 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2904 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002905 if update:
2906 # update mn port info
2907 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002908 # Get mininet dump
2909 dump = self.dump().split( "\n" )
2910 hosts = {}
2911 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002912 result = re.search( hostRE, line )
2913 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002914 name = result.group( 'name' )
2915 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002916 if getInterfaces:
2917 response = self.getInterfaces( name )
2918 # Populate interface info
2919 for line in response.split( "\n" ):
2920 if line.startswith( "name=" ):
2921 portVars = {}
2922 for var in line.split( "," ):
2923 key, value = var.split( "=" )
2924 portVars[ key ] = value
2925 isUp = portVars.pop( 'enabled', "True" )
2926 isUp = "True" in isUp
2927 if verbose:
2928 main.log.info( "Reading host port %s(%s)" %
2929 ( portVars[ 'name' ],
2930 portVars[ 'mac' ] ) )
2931 mac = portVars[ 'mac' ]
2932 if mac == 'None':
2933 mac = None
2934 ips = []
2935 ip = portVars[ 'ip' ]
2936 if ip == 'None':
2937 ip = None
2938 ips.append( ip )
2939 intfName = portVars[ 'name' ]
2940 if name == 'None':
2941 name = None
2942 interfaces.append( {
2943 "name": intfName,
2944 "ips": ips,
2945 "mac": str( mac ),
2946 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002947 hosts[ name ] = { "interfaces": interfaces }
2948 return hosts
2949 except pexpect.EOF:
2950 main.log.error( self.name + ": EOF exception found" )
2951 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002952 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002953 except Exception:
2954 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002955 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002956
You Wang9fc5ce42019-01-23 15:10:08 -08002957 def getLinks( self, timeout=20, updateTimeout=1000, excludeNodes=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002958 """
2959 Gathers information about current Mininet links. These links may not
2960 be up if one of the ports is down.
2961
2962 Returns a list of dictionaries with link endpoints.
2963
2964 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002965 { 'node1': str( node1 name )
2966 'node2': str( node2 name )
2967 'port1': str( port1 of_port )
2968 'port2': str( port2 of_port ) }
You Wang9fc5ce42019-01-23 15:10:08 -08002969
You Wangc61aaa22019-02-01 15:49:48 -08002970 If either node1 or node2 name matches any of the names sepcified in
2971 excludeNodes, the link will be excluded from the returned value
You Wang9fc5ce42019-01-23 15:10:08 -08002972
Jon Hallafa8a472015-06-12 14:02:42 -07002973 Note: The port number returned is the eth#, not necessarily the of_port
2974 number. In Mininet, for OVS switch, these should be the same. For
2975 hosts, this is just the eth#.
2976 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002977 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002978 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002979 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002980
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002981 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002982 # s1-eth3<->s2-eth1 (OK OK)
2983 # s13-eth3<->h27-eth0 (OK OK)
You Wang9fc5ce42019-01-23 15:10:08 -08002984 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d\.]+)\<\-\>" +\
2985 "(?P<node2>[\w]+)\-eth(?P<port2>[\d\.]+)"
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002986 links = []
2987 for line in response:
2988 match = re.search( linkRE, line )
2989 if match:
2990 node1 = match.group( 'node1' )
2991 node2 = match.group( 'node2' )
You Wangc61aaa22019-02-01 15:49:48 -08002992 if any( node1 == node or node2 == node for node in excludeNodes ):
You Wang9fc5ce42019-01-23 15:10:08 -08002993 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002994 port1 = match.group( 'port1' )
2995 port2 = match.group( 'port2' )
2996 links.append( { 'node1': node1,
2997 'node2': node2,
2998 'port1': port1,
2999 'port2': port2 } )
3000 return links
3001
3002 except pexpect.EOF:
3003 main.log.error( self.name + ": EOF exception found" )
3004 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003005 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003006 except Exception:
3007 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003008 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003009
3010 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003011 """
3012 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003013 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003014
Jon Hallafa8a472015-06-12 14:02:42 -07003015 Dependencies:
3016 1. numpy - "sudo pip install numpy"
3017 """
3018 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003019 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003020 try:
3021 mnDPIDs = []
3022 for swName, switch in switches.iteritems():
3023 mnDPIDs.append( switch[ 'dpid' ].lower() )
3024 mnDPIDs.sort()
3025 if switchesJson == "": # if rest call fails
3026 main.log.error(
3027 self.name +
3028 ".compareSwitches(): Empty JSON object given from ONOS" )
3029 return main.FALSE
3030 onos = switchesJson
3031 onosDPIDs = []
3032 for switch in onos:
3033 if switch[ 'available' ]:
3034 onosDPIDs.append(
3035 switch[ 'id' ].replace(
3036 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003037 '' ).replace(
3038 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003039 '' ).lower() )
3040 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003041
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003042 if mnDPIDs != onosDPIDs:
3043 switchResults = main.FALSE
3044 main.log.error( "Switches in MN but not in ONOS:" )
3045 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3046 main.log.error( str( list1 ) )
3047 main.log.error( "Switches in ONOS but not in MN:" )
3048 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3049 main.log.error( str( list2 ) )
3050 else: # list of dpid's match in onos and mn
3051 switchResults = main.TRUE
3052 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003053
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003054 # FIXME: this does not look for extra ports in ONOS, only checks that
3055 # ONOS has what is in MN
3056 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003057
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003058 # PORTS
3059 for name, mnSwitch in switches.iteritems():
3060 mnPorts = []
3061 onosPorts = []
3062 switchResult = main.TRUE
3063 for port in mnSwitch[ 'ports' ]:
3064 if port[ 'enabled' ]:
3065 mnPorts.append( int( port[ 'of_port' ] ) )
3066 for onosSwitch in portsJson:
3067 if onosSwitch[ 'device' ][ 'available' ]:
3068 if onosSwitch[ 'device' ][ 'id' ].replace(
3069 ':',
3070 '' ).replace(
3071 "of",
3072 '' ) == mnSwitch[ 'dpid' ]:
3073 for port in onosSwitch[ 'ports' ]:
3074 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003075 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003076 # onosPorts.append( 'local' )
3077 onosPorts.append( long( uint64( -2 ) ) )
3078 else:
3079 onosPorts.append( int( port[ 'port' ] ) )
3080 break
3081 mnPorts.sort( key=float )
3082 onosPorts.sort( key=float )
3083
3084 mnPortsLog = mnPorts
3085 onosPortsLog = onosPorts
3086 mnPorts = [ x for x in mnPorts ]
3087 onosPorts = [ x for x in onosPorts ]
3088
3089 # TODO: handle other reserved port numbers besides LOCAL
3090 # NOTE: Reserved ports
3091 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3092 # long( uint64( -2 ) )
3093 for mnPort in mnPortsLog:
3094 if mnPort in onosPorts:
3095 # don't set results to true here as this is just one of
3096 # many checks and it might override a failure
3097 mnPorts.remove( mnPort )
3098 onosPorts.remove( mnPort )
3099
3100 # NOTE: OVS reports this as down since there is no link
3101 # So ignoring these for now
3102 # TODO: Come up with a better way of handling these
3103 if 65534 in mnPorts:
3104 mnPorts.remove( 65534 )
3105 if long( uint64( -2 ) ) in onosPorts:
3106 onosPorts.remove( long( uint64( -2 ) ) )
3107 if len( mnPorts ): # the ports of this switch don't match
3108 switchResult = main.FALSE
3109 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3110 if len( onosPorts ): # the ports of this switch don't match
3111 switchResult = main.FALSE
3112 main.log.warn(
3113 "Ports in ONOS but not MN: " +
3114 str( onosPorts ) )
3115 if switchResult == main.FALSE:
3116 main.log.error(
3117 "The list of ports for switch %s(%s) does not match:" %
3118 ( name, mnSwitch[ 'dpid' ] ) )
3119 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3120 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3121 portsResults = portsResults and switchResult
3122 finalResults = finalResults and portsResults
3123 return finalResults
3124 except pexpect.EOF:
3125 main.log.error( self.name + ": EOF exception found" )
3126 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003127 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003128 except Exception:
3129 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003130 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003131
Jon Hallafa8a472015-06-12 14:02:42 -07003132 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003133 """
3134 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003135 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003136
Jon Hallafa8a472015-06-12 14:02:42 -07003137 """
Jon Hall7eb38402015-01-08 17:19:54 -08003138 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003139 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003140 try:
3141 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003142
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003143 mnLinks = []
3144 for l in links:
3145 try:
3146 node1 = switches[ l[ 'node1' ] ]
3147 node2 = switches[ l[ 'node2' ] ]
3148 enabled = True
3149 for port in node1[ 'ports' ]:
3150 if port[ 'of_port' ] == l[ 'port1' ]:
3151 enabled = enabled and port[ 'enabled' ]
3152 for port in node2[ 'ports' ]:
3153 if port[ 'of_port' ] == l[ 'port2' ]:
3154 enabled = enabled and port[ 'enabled' ]
3155 if enabled:
3156 mnLinks.append( l )
3157 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003158 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003159 if 2 * len( mnLinks ) == len( onos ):
3160 linkResults = main.TRUE
3161 else:
3162 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003163 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003164 "Mininet has " + str( len( mnLinks ) ) +
3165 " bidirectional links and ONOS has " +
3166 str( len( onos ) ) + " unidirectional links" )
3167
3168 # iterate through MN links and check if an ONOS link exists in
3169 # both directions
3170 for link in mnLinks:
3171 # TODO: Find a more efficient search method
3172 node1 = None
3173 port1 = None
3174 node2 = None
3175 port2 = None
3176 firstDir = main.FALSE
3177 secondDir = main.FALSE
3178 for swName, switch in switches.iteritems():
3179 if swName == link[ 'node1' ]:
3180 node1 = switch[ 'dpid' ]
3181 for port in switch[ 'ports' ]:
3182 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3183 port1 = port[ 'of_port' ]
3184 if node1 is not None and node2 is not None:
3185 break
3186 if swName == link[ 'node2' ]:
3187 node2 = switch[ 'dpid' ]
3188 for port in switch[ 'ports' ]:
3189 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3190 port2 = port[ 'of_port' ]
3191 if node1 is not None and node2 is not None:
3192 break
3193
3194 for onosLink in onos:
3195 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3196 ":", '' ).replace( "of", '' )
3197 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3198 ":", '' ).replace( "of", '' )
3199 onosPort1 = onosLink[ 'src' ][ 'port' ]
3200 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3201
3202 # check onos link from node1 to node2
3203 if str( onosNode1 ) == str( node1 ) and str(
3204 onosNode2 ) == str( node2 ):
3205 if int( onosPort1 ) == int( port1 ) and int(
3206 onosPort2 ) == int( port2 ):
3207 firstDir = main.TRUE
3208 else:
Jon Hallab611372018-02-21 15:26:05 -08003209 # The right switches, but wrong ports, could be
3210 # another link between these devices, or onos
3211 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003212 main.log.warn(
3213 'The port numbers do not match for ' +
3214 str( link ) +
3215 ' between ONOS and MN. When checking ONOS for ' +
3216 'link %s/%s -> %s/%s' %
3217 ( node1, port1, node2, port2 ) +
3218 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003219 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3220 '. This could be another link between these devices' +
3221 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003222
3223 # check onos link from node2 to node1
3224 elif ( str( onosNode1 ) == str( node2 ) and
3225 str( onosNode2 ) == str( node1 ) ):
3226 if ( int( onosPort1 ) == int( port2 )
3227 and int( onosPort2 ) == int( port1 ) ):
3228 secondDir = main.TRUE
3229 else:
Jon Hallab611372018-02-21 15:26:05 -08003230 # The right switches, but wrong ports, could be
3231 # another link between these devices, or onos
3232 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003233 main.log.warn(
3234 'The port numbers do not match for ' +
3235 str( link ) +
3236 ' between ONOS and MN. When checking ONOS for ' +
3237 'link %s/%s -> %s/%s' %
3238 ( node1, port1, node2, port2 ) +
3239 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003240 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3241 '. This could be another link between these devices' +
3242 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003243 else: # this is not the link you're looking for
3244 pass
3245 if not firstDir:
3246 main.log.error(
3247 'ONOS does not have the link %s/%s -> %s/%s' %
3248 ( node1, port1, node2, port2 ) )
3249 if not secondDir:
3250 main.log.error(
3251 'ONOS does not have the link %s/%s -> %s/%s' %
3252 ( node2, port2, node1, port1 ) )
3253 linkResults = linkResults and firstDir and secondDir
3254 return linkResults
3255 except pexpect.EOF:
3256 main.log.error( self.name + ": EOF exception found" )
3257 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003258 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003259 except Exception:
3260 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003261 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003262
Jon Hallafa8a472015-06-12 14:02:42 -07003263 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003264 """
Jon Hallafa8a472015-06-12 14:02:42 -07003265 Compare mn and onos Hosts.
3266 Since Mininet hosts are quiet, ONOS will only know of them when they
3267 speak. For this reason, we will only check that the hosts in ONOS
3268 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003269
Jon Hallafa8a472015-06-12 14:02:42 -07003270 Arguments:
3271 hostsJson: parsed json object from the onos hosts api
3272 Returns:
3273 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003274 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003275 try:
3276 hostResults = main.TRUE
3277 for onosHost in hostsJson:
3278 onosMAC = onosHost[ 'mac' ].lower()
3279 match = False
3280 for mnHost, info in hosts.iteritems():
3281 for mnIntf in info[ 'interfaces' ]:
3282 if onosMAC == mnIntf[ 'mac' ].lower():
3283 match = True
3284 for ip in mnIntf[ 'ips' ]:
3285 if ip in onosHost[ 'ipAddresses' ]:
3286 pass # all is well
3287 else:
3288 # misssing ip
3289 main.log.error( "ONOS host " +
3290 onosHost[ 'id' ] +
3291 " has a different IP(" +
3292 str( onosHost[ 'ipAddresses' ] ) +
3293 ") than the Mininet host(" +
3294 str( ip ) +
3295 ")." )
3296 output = json.dumps(
3297 onosHost,
3298 sort_keys=True,
3299 indent=4,
3300 separators=( ',', ': ' ) )
3301 main.log.info( output )
3302 hostResults = main.FALSE
3303 if not match:
3304 hostResults = main.FALSE
3305 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3306 "corresponding Mininet host." )
3307 output = json.dumps( onosHost,
3308 sort_keys=True,
3309 indent=4,
3310 separators=( ',', ': ' ) )
3311 main.log.info( output )
3312 return hostResults
3313 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003314 main.log.error( self.name + ": EOF exception found" )
3315 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003316 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003317 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003318 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003319 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003320
You Wangd66de192018-04-30 17:30:12 -07003321 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003322 """
3323 Description:
3324 Verify that all hosts have IP address assigned to them
3325 Optional:
3326 hostList: If specified, verifications only happen to the hosts
3327 in hostList
3328 prefix: at least one of the ip address assigned to the host
3329 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003330 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003331 Returns:
3332 main.TRUE if all hosts have specific IP address assigned;
3333 main.FALSE otherwise
3334 """
3335 try:
You Wangd66de192018-04-30 17:30:12 -07003336 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003337 if not hostList:
3338 hostList = hosts.keys()
3339 for hostName in hosts.keys():
3340 if hostName not in hostList:
3341 continue
3342 ipList = []
3343 self.handle.sendline( str( hostName ) + " ip a" )
3344 self.handle.expect( "mininet>" )
3345 ipa = self.handle.before
3346 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3347 ipList += re.findall( ipv4Pattern, ipa )
3348 # It's tricky to make regex for IPv6 addresses and this one is simplified
3349 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})/'
3350 ipList += re.findall( ipv6Pattern, ipa )
3351 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3352 if not ipList:
3353 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3354 else:
3355 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3356 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3357 else:
3358 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3359 hostList.remove( hostName )
3360 return main.FALSE if hostList else main.TRUE
3361 except KeyError:
3362 main.log.exception( self.name + ": host data not as expected: " + hosts )
3363 return None
3364 except pexpect.EOF:
3365 main.log.error( self.name + ": EOF exception found" )
3366 main.log.error( self.name + ": " + self.handle.before )
3367 main.cleanAndExit()
3368 except Exception:
3369 main.log.exception( self.name + ": Uncaught exception" )
3370 return None
3371
Jon Hallafa8a472015-06-12 14:02:42 -07003372 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003373 """
3374 Returns a list of all hosts
3375 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003376 try:
3377 self.handle.sendline( "" )
3378 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003379
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003380 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3381 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003382
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003383 handlePy = self.handle.before
3384 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3385 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003386
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003387 self.handle.sendline( "" )
3388 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003389
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003390 hostStr = handlePy.replace( "]", "" )
3391 hostStr = hostStr.replace( "'", "" )
3392 hostStr = hostStr.replace( "[", "" )
3393 hostStr = hostStr.replace( " ", "" )
3394 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003395
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003396 return hostList
3397 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003398 main.log.error( self.name + ": TIMEOUT exception found" )
3399 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003400 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003401 except pexpect.EOF:
3402 main.log.error( self.name + ": EOF exception found" )
3403 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003404 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003405 except Exception:
3406 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003407 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003408
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003409 def getSwitch( self ):
3410 """
3411 Returns a list of all switches
3412 Again, don't ask question just use it...
3413 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003414 try:
3415 # get host list...
3416 hostList = self.getHosts()
3417 # Make host set
3418 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003419
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003420 # Getting all the nodes in mininet
3421 self.handle.sendline( "" )
3422 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003423
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003424 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3425 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003426
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003427 handlePy = self.handle.before
3428 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3429 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003430
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003431 self.handle.sendline( "" )
3432 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003433
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003434 nodesStr = handlePy.replace( "]", "" )
3435 nodesStr = nodesStr.replace( "'", "" )
3436 nodesStr = nodesStr.replace( "[", "" )
3437 nodesStr = nodesStr.replace( " ", "" )
3438 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003439
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003440 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003441 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003442 nodesSet.discard( 'c0' )
3443 nodesSet.discard( 'c1' )
3444 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003445
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003446 switchSet = nodesSet - hostSet
3447 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003448
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003449 return switchList
3450 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003451 main.log.error( self.name + ": TIMEOUT exception found" )
3452 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003453 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003454 except pexpect.EOF:
3455 main.log.error( self.name + ": EOF exception found" )
3456 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003457 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003458 except Exception:
3459 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003460 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003461
You Wang9fc5ce42019-01-23 15:10:08 -08003462 def getGraphDict( self, timeout=60, useId=True, includeHost=False,
You Wangc61aaa22019-02-01 15:49:48 -08003463 excludeNodes=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07003464 """
3465 Return a dictionary which describes the latest Mininet topology data as a
3466 graph.
3467 An example of the dictionary:
3468 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3469 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3470 Each vertex should at least have an 'edges' attribute which describes the
3471 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003472 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003473 list of attributes.
3474 An example of the edges dictionary:
3475 'edges': { vertex2: { 'port': ..., 'weight': ... },
3476 vertex3: { 'port': ..., 'weight': ... } }
3477 If useId == True, dpid/mac will be used instead of names to identify
3478 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3479 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003480 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003481 in topology data.
You Wangc61aaa22019-02-01 15:49:48 -08003482 excludeNodes will be passed to getSwitches and getLinks methods to exclude
3483 unexpected switches and links.
You Wangdb8cd0a2016-05-26 15:19:45 -07003484 Note that link or switch that are brought down by 'link x x down' or 'switch
3485 x down' commands still show in the output of Mininet CLI commands such as
3486 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3487 recommended to use delLink() or delSwitch functions to simulate link/switch
3488 down, and addLink() or addSwitch to add them back.
3489 """
3490 graphDict = {}
3491 try:
You Wang9fc5ce42019-01-23 15:10:08 -08003492 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003493 portDict = {}
You Wangc61aaa22019-02-01 15:49:48 -08003494 switches = self.getSwitches( excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003495 if includeHost:
3496 hosts = self.getHosts()
3497 for link in links:
You Wangc61aaa22019-02-01 15:49:48 -08003498 # TODO: support 'includeHost' argument
You Wangdb8cd0a2016-05-26 15:19:45 -07003499 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3500 continue
3501 nodeName1 = link[ 'node1' ]
3502 nodeName2 = link[ 'node2' ]
You Wang9fc5ce42019-01-23 15:10:08 -08003503 if not self.getOVSPorts( nodeName1 ) or not self.getOVSPorts( nodeName2 ):
3504 # The device is probably offline
3505 continue
You Wangdb8cd0a2016-05-26 15:19:45 -07003506 port1 = link[ 'port1' ]
3507 port2 = link[ 'port2' ]
3508 # Loop for two nodes
3509 for i in range( 2 ):
3510 # Get port index from OVS
3511 # The index extracted from port name may be inconsistent with ONOS
3512 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003513 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003514 portList = self.getOVSPorts( nodeName1 )
3515 if len( portList ) == 0:
3516 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3517 return None
3518 portDict[ nodeName1 ] = portList
3519 for port in portDict[ nodeName1 ]:
3520 if port[ 'port' ] == port1:
3521 portIndex = port[ 'index' ]
3522 break
3523 if portIndex == -1:
3524 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3525 return None
3526 if useId:
3527 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3528 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3529 else:
3530 node1 = nodeName1
3531 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003532 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003533 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003534 graphDict[ node1 ] = { 'edges': {},
3535 'dpid': switches[ nodeName1 ][ 'dpid' ],
3536 'name': nodeName1,
3537 'ports': switches[ nodeName1 ][ 'ports' ],
3538 'swClass': switches[ nodeName1 ][ 'swClass' ],
3539 'pid': switches[ nodeName1 ][ 'pid' ],
3540 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003541 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003542 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003543 else:
3544 # Assert node2 is not connected to any current links of node1
You Wang9fc5ce42019-01-23 15:10:08 -08003545 # assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
3546 pass
3547 for port in switches[ nodeName1 ][ 'ports' ]:
3548 if port[ 'of_port' ] == str( portIndex ):
3549 # Use -1 as index for disabled port
You Wangc61aaa22019-02-01 15:49:48 -08003550 if port[ 'enabled' ]:
You Wang9fc5ce42019-01-23 15:10:08 -08003551 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
3552 else:
3553 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': -1 }
You Wangdb8cd0a2016-05-26 15:19:45 -07003554 # Swap two nodes/ports
3555 nodeName1, nodeName2 = nodeName2, nodeName1
3556 port1, port2 = port2, port1
You Wang9fc5ce42019-01-23 15:10:08 -08003557 # Remove links with disabled ports
3558 linksToRemove = []
3559 for node, edges in graphDict.items():
3560 for neighbor, port in edges[ 'edges' ].items():
3561 if port[ 'port' ] == -1:
3562 linksToRemove.append( ( node, neighbor ) )
3563 for node1, node2 in linksToRemove:
3564 for i in range( 2 ):
3565 if graphDict.get( node1 )[ 'edges' ].get( node2 ):
3566 graphDict[ node1 ][ 'edges' ].pop( node2 )
3567 node1, node2 = node2, node1
You Wangdb8cd0a2016-05-26 15:19:45 -07003568 return graphDict
3569 except KeyError:
3570 main.log.exception( self.name + ": KeyError exception found" )
3571 return None
3572 except AssertionError:
3573 main.log.exception( self.name + ": AssertionError exception found" )
3574 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003575 except pexpect.EOF:
3576 main.log.error( self.name + ": EOF exception found" )
3577 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003578 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003579 except Exception:
3580 main.log.exception( self.name + ": Uncaught exception" )
3581 return None
3582
Devin Lima7cfdbd2017-09-29 15:02:22 -07003583 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003584 """
3585 updates the port address and status information for
3586 each port in mn"""
3587 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003588 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003589 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003590 self.handle.sendline( "" )
3591 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003592
Jon Hall7eb38402015-01-08 17:19:54 -08003593 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003594 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003595
Jon Hall7eb38402015-01-08 17:19:54 -08003596 self.handle.sendline( "" )
3597 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003598
Jon Hallb1290e82014-11-18 16:17:48 -05003599 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003600 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003601 main.log.error( self.name + ": TIMEOUT exception found" )
3602 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003603 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003604 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003605 main.log.error( self.name + ": EOF exception found" )
3606 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003607 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003608 except Exception:
3609 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003610 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003611
Jon Halld80cc142015-07-06 13:36:05 -07003612 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003613 """
3614 Add vlan tag to a host.
3615 Dependencies:
3616 This class depends on the "vlan" package
3617 $ sudo apt-get install vlan
3618 Configuration:
3619 Load the 8021q module into the kernel
3620 $sudo modprobe 8021q
3621
3622 To make this setup permanent:
3623 $ sudo su -c 'echo "8021q" >> /etc/modules'
3624 """
3625 if self.handle:
3626 try:
Jon Halld80cc142015-07-06 13:36:05 -07003627 # get the ip address of the host
3628 main.log.info( "Get the ip address of the host" )
3629 ipaddr = self.getIPAddress( host )
3630 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003631
Jon Halld80cc142015-07-06 13:36:05 -07003632 # remove IP from interface intf
3633 # Ex: h1 ifconfig h1-eth0 inet 0
3634 main.log.info( "Remove IP from interface " )
3635 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3636 self.handle.sendline( cmd2 )
3637 self.handle.expect( "mininet>" )
3638 response = self.handle.before
3639 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003640
Jon Halld80cc142015-07-06 13:36:05 -07003641 # create VLAN interface
3642 # Ex: h1 vconfig add h1-eth0 100
3643 main.log.info( "Create Vlan" )
3644 cmd3 = host + " vconfig add " + intf + " " + vlan
3645 self.handle.sendline( cmd3 )
3646 self.handle.expect( "mininet>" )
3647 response = self.handle.before
3648 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003649
Jon Halld80cc142015-07-06 13:36:05 -07003650 # assign the host's IP to the VLAN interface
3651 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3652 main.log.info( "Assign the host IP to the vlan interface" )
3653 vintf = intf + "." + vlan
3654 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3655 self.handle.sendline( cmd4 )
3656 self.handle.expect( "mininet>" )
3657 response = self.handle.before
3658 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003659
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003660 # update Mininet node variables
3661 main.log.info( "Update Mininet node variables" )
3662 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3663 self.handle.sendline( cmd5 )
3664 self.handle.expect( "mininet>" )
3665 response = self.handle.before
3666 main.log.info( "====> %s ", response )
3667
3668 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3669 self.handle.sendline( cmd6 )
3670 self.handle.expect( "mininet>" )
3671 response = self.handle.before
3672 main.log.info( "====> %s ", response )
3673
3674 return main.TRUE
3675 except pexpect.TIMEOUT:
3676 main.log.error( self.name + ": TIMEOUT exception found" )
3677 main.log.error( self.name + ": " + self.handle.before )
3678 main.cleanAndExit()
3679 except pexpect.EOF:
3680 main.log.error( self.name + ": EOF exception found" )
3681 main.log.error( self.name + ": " + self.handle.before )
3682 return main.FALSE
3683 except Exception:
3684 main.log.exception( self.name + ": Uncaught exception!" )
3685 return main.FALSE
3686
3687 def removeVLAN( self, host, intf ):
3688 """
3689 Remove vlan tag from a host.
3690 Dependencies:
3691 This class depends on the "vlan" package
3692 $ sudo apt-get install vlan
3693 Configuration:
3694 Load the 8021q module into the kernel
3695 $sudo modprobe 8021q
3696
3697 To make this setup permanent:
3698 $ sudo su -c 'echo "8021q" >> /etc/modules'
3699 """
3700 if self.handle:
3701 try:
3702 # get the ip address of the host
3703 main.log.info( "Get the ip address of the host" )
3704 ipaddr = self.getIPAddress( host )
3705
3706 # remove VLAN interface
3707 # Ex: h1 vconfig rem h1-eth0.100
3708 main.log.info( "Remove Vlan interface" )
3709 cmd2 = host + " vconfig rem " + intf
3710 self.handle.sendline( cmd2 )
3711 self.handle.expect( "mininet>" )
3712 response = self.handle.before
3713 main.log.info( "====> %s ", response )
3714
3715 # assign the host's IP to the original interface
3716 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3717 main.log.info( "Assign the host IP to the original interface" )
3718 original_intf = intf.split(".")[0]
3719 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3720 self.handle.sendline( cmd3 )
3721 self.handle.expect( "mininet>" )
3722 response = self.handle.before
3723 main.log.info( "====> %s ", response )
3724
3725 # update Mininet node variables
3726 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3727 self.handle.sendline( cmd4 )
3728 self.handle.expect( "mininet>" )
3729 response = self.handle.before
3730 main.log.info( "====> %s ", response )
3731
3732 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3733 self.handle.sendline( cmd5 )
3734 self.handle.expect( "mininet>" )
3735 response = self.handle.before
3736 main.log.info( "====> %s ", response )
3737
kaouthera3f13ca22015-05-05 15:01:41 -07003738 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003739 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003740 main.log.error( self.name + ": TIMEOUT exception found" )
3741 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003742 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003743 except pexpect.EOF:
3744 main.log.error( self.name + ": EOF exception found" )
3745 main.log.error( self.name + ": " + self.handle.before )
3746 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003747 except Exception:
3748 main.log.exception( self.name + ": Uncaught exception!" )
3749 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003750
Jon Hall892818c2015-10-20 17:58:34 -07003751 def createHostComponent( self, name ):
3752 """
3753 Creates a new mininet cli component with the same parameters as self.
3754 This new component is intended to be used to login to the hosts created
3755 by mininet.
3756
3757 Arguments:
3758 name - The string of the name of this component. The new component
3759 will be assigned to main.<name> .
3760 In addition, main.<name>.name = str( name )
3761 """
3762 try:
3763 # look to see if this component already exists
3764 getattr( main, name )
3765 except AttributeError:
3766 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003767 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3768 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003769 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003770 except pexpect.EOF:
3771 main.log.error( self.name + ": EOF exception found" )
3772 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003773 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003774 except Exception:
3775 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003776 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003777 else:
3778 # namespace is not clear!
3779 main.log.error( name + " component already exists!" )
3780 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003781 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003782
3783 def removeHostComponent( self, name ):
3784 """
3785 Remove host component
3786 Arguments:
3787 name - The string of the name of the component to delete.
3788 """
3789 try:
3790 # Get host component
3791 component = getattr( main, name )
3792 except AttributeError:
3793 main.log.error( "Component " + name + " does not exist." )
3794 return
3795 try:
3796 # Disconnect from component
3797 component.disconnect()
You Wangf32c6ed2018-08-23 17:10:22 -07003798 component.close_log_handles()
Jon Hall892818c2015-10-20 17:58:34 -07003799 # Delete component
3800 delattr( main, name )
3801 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003802 del( main.componentDictionary[ name ] )
You Wangf32c6ed2018-08-23 17:10:22 -07003803 except StandardError:
3804 self.log.exception( "Exception while closing log files for " + name )
3805 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003806 except pexpect.EOF:
3807 main.log.error( self.name + ": EOF exception found" )
3808 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003809 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003810 except Exception:
3811 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003812 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003813
3814 def startHostCli( self, host=None ):
3815 """
3816 Use the mininet m utility to connect to the host's cli
3817 """
3818 # These are fields that can be used by scapy packets. Initialized to None
3819 self.hostIp = None
3820 self.hostMac = None
3821 try:
3822 if not host:
3823 host = self.name
3824 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003825 self.handle.sendline( "cd" )
3826 self.handle.expect( self.hostPrompt )
3827 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003828 self.handle.expect( self.hostPrompt )
3829 return main.TRUE
3830 except pexpect.TIMEOUT:
3831 main.log.exception( self.name + ": Command timed out" )
3832 return main.FALSE
3833 except pexpect.EOF:
3834 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003835 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003836 except Exception:
3837 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003838 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003839
YPZhang801d46d2016-08-08 13:26:28 -07003840 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003841 '''
3842
YPZhang801d46d2016-08-08 13:26:28 -07003843 Args:
3844 devicename: switch name
3845 intf: port name on switch
3846 status: up or down
3847
3848 Returns: boolean to show success change status
3849
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003850 '''
YPZhang801d46d2016-08-08 13:26:28 -07003851 if status == "down" or status == "up":
3852 try:
3853 cmd = devicename + " ifconfig " + intf + " " + status
3854 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003855 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003856 return main.TRUE
3857 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003858 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003859 return main.FALSE
3860 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003861 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003862 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003863 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003864 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003865 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003866 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003867 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003868 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003869 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003870 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003871 return main.FALSE
3872
You Wang6e5b48e2018-07-23 16:17:38 -07003873 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003874 """
You Wang6e5b48e2018-07-23 16:17:38 -07003875 Moves a host from one switch to another on the fly
3876 Optional:
3877 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3878 prefixLen: length of the host IP prefix
3879 ipv6: move an IPv6 host if True
3880 intfSuffix: suffix of the new interface after host movement
3881 vlan: vlan ID of the host. Use None for non-vlan host
3882 Note: The intf between host and oldSw when detached
3883 using detach(), will still show up in the 'net'
3884 cmd, because switch.detach() doesn't affect switch.intfs[]
3885 ( which is correct behavior since the interfaces
3886 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003887 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003888 if self.handle:
3889 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003890 newIntf = "%s-%s" % ( host, intfSuffix )
3891 commands = [
3892 # Bring link between oldSw-host down
3893 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3894 # Determine hostintf and Oldswitchintf
3895 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
3896 ]
3897 # Determine ip address of the host-oldSw interface
3898 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3899 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3900 commands += [
3901 # Determine mac address of the host-oldSw interface
3902 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3903 # Detach interface between oldSw-host
3904 "px " + oldSw + ".detach( sintf )",
3905 # Add link between host-newSw
3906 "py net.addLink(" + host + "," + newSw + ")",
3907 # Determine hostintf and Newswitchintf
3908 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3909 # Attach interface between newSw-host
3910 "px " + newSw + ".attach( sintf )",
3911 ]
3912 if vlan:
3913 vlanIntf = "%s.%s" % ( newIntf, vlan )
3914 commands += [
3915 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
3916 host + " ip link set up %s" % vlanIntf,
3917 "px hintf.name = '" + vlanIntf + "'",
3918 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
3919 ]
3920 newIntf = vlanIntf
3921 commands += [
3922 # Set mac address of the host-newSw interface
3923 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
3924 # Set IP address of the host-newSw interface
3925 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
3926 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
3927 ]
3928 if ipv6:
3929 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
3930 commands += [
3931 "net",
3932 host + " ifconfig"
3933 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003934 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003935 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003936 self.handle.sendline( cmd )
3937 self.handle.expect( "mininet>" )
3938 main.log.info( "====> %s ", self.handle.before )
3939 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003940 except pexpect.TIMEOUT:
3941 main.log.error( self.name + ": TIMEOUT exception found" )
3942 main.log.error( self.name + ": " + self.handle.before )
3943 main.cleanAndExit()
3944 except pexpect.EOF:
3945 main.log.error( self.name + ": EOF exception found" )
3946 main.log.error( self.name + ": " + self.handle.before )
3947 return main.FALSE
3948 except Exception:
3949 main.log.exception( self.name + ": Uncaught exception!" )
3950 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07003951
You Wang6e5b48e2018-07-23 16:17:38 -07003952 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
3953 macAddr=None, prefixLen=None, ipv6=False,
3954 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07003955 """
You Wang6e5b48e2018-07-23 16:17:38 -07003956 Moves a dual-homed host from one switch-pair to another pair on the fly
3957 Optional:
3958 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3959 prefixLen: length of the host IP prefix
3960 ipv6: move an IPv6 host if True
3961 intfSuffix1: suffix of the first new interface
3962 intfSuffix2: suffix of the second new interface
3963 bondSuffix: suffix of the new bond interface
3964 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07003965 """
You Wang7ea90582018-07-19 15:27:58 -07003966 if self.handle:
3967 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003968 bondIntf = "%s-%s" % ( host, bondSuffix )
3969 newIntf = "%s-%s" % ( host, intfSuffix1 )
3970 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07003971 commands = [
3972 # Bring link between oldSw-host down
3973 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3974 # Bring link between oldPairSw-host down
3975 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
3976 # Determine hostintf and Oldswitchintf
3977 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07003978 ]
3979 # Determine ip address of the host-oldSw interface
3980 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3981 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3982 commands += [
3983 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07003984 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3985 # Detach interface between oldSw-host
3986 "px " + oldSw + ".detach( sintf )",
3987 # Determine hostintf and Oldpairswitchintf
3988 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
3989 # Detach interface between oldPairSw-host
3990 "px " + oldPairSw + ".detach( sintfpair )",
3991 # Add link between host-newSw
3992 "py net.addLink(" + host + "," + newSw + ", 2)",
3993 # Add link between host-newPairSw
3994 "py net.addLink(" + host + "," + newPairSw + ")",
3995 # Determine hostintf and Newswitchintf
3996 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3997 # Determine hostintf and NewPairswitchintf
3998 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
3999 # Attach interface between newSw-host
4000 "px " + newSw + ".attach( sintf )",
4001 # Attach interface between newPairSw-host
4002 "px " + newPairSw + ".attach( sintfpair )",
4003 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07004004 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004005 host + ' ip link set %s down' % newIntf,
4006 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004007 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
4008 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07004009 host + ' ip addr flush dev %s' % newIntf,
4010 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004011 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004012 "px lowestIntf = min( [ hintf, hintfpair ] )",
4013 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07004014 "px lowestIntf.name = '" + bondIntf + "'",
4015 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07004016 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
4017 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07004018 ]
4019 if vlan:
4020 vlanIntf = "%s.%s" % ( bondIntf, vlan )
4021 commands += [
4022 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
4023 host + " ip link set up %s" % vlanIntf,
4024 "px lowestIntf.name = '" + vlanIntf + "'",
4025 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
4026 ]
4027 bondIntf = vlanIntf
4028 commands += [
4029 # Set macaddress of the host-newSw interface
4030 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07004031 # Set ipaddress of the host-newSw interface
4032 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
4033 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07004034 ]
You Wang6e5b48e2018-07-23 16:17:38 -07004035 if ipv6:
4036 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
4037 commands += [
4038 "net",
4039 host + " ifconfig"
4040 ]
You Wang7ea90582018-07-19 15:27:58 -07004041 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004042 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07004043 self.handle.sendline( cmd )
4044 self.handle.expect( "mininet>" )
4045 main.log.info( "====> %s ", self.handle.before )
4046 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07004047 except pexpect.TIMEOUT:
4048 main.log.error( self.name + ": TIMEOUT exception found" )
4049 main.log.error( self.name + ": " + self.handle.before )
4050 main.cleanAndExit()
4051 except pexpect.EOF:
4052 main.log.error( self.name + ": EOF exception found" )
4053 main.log.error( self.name + ": " + self.handle.before )
4054 return main.FALSE
4055 except Exception:
4056 main.log.exception( self.name + ": Uncaught exception!" )
4057 return main.FALSE
4058
adminbae64d82013-08-01 10:50:15 -07004059if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004060 sys.modules[ __name__ ] = MininetCliDriver()