blob: 39821e78b6c2fea8764f9e47717194ff20d4f563 [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 Wang6f373972019-02-20 16:13:47 -0800605 for intf in hosts[ host ][ 'interfaces' ]:
606 intfName = intf[ 'name' ]
607 cmd = "{} ndisc6 -r 1 -w {} {} {}".format( host, wait, dstIp6, intfName )
608 main.log.debug( "Sending IPv6 ND from interface {} on host {}".format( intfName, host ) )
You Wang48381752018-05-07 13:50:57 -0700609 else:
610 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
611 discoveryResult = main.FALSE
612 if cmd:
You Wang0b82aa52018-06-06 14:33:58 -0700613 self.handle.sendline( flushCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700614 self.handle.expect( "mininet>" )
You Wang48381752018-05-07 13:50:57 -0700615 self.handle.sendline( cmd )
Jon Halla604fd42018-05-04 14:27:27 -0700616 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700617 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700618 except pexpect.TIMEOUT:
619 main.log.exception( self.name + ": TIMEOUT exception" )
620 response = self.handle.before
621 # NOTE: Send ctrl-c to make sure command is stopped
622 self.handle.send( "\x03" )
623 self.handle.expect( "Interrupt" )
624 response += self.handle.before + self.handle.after
625 self.handle.expect( "mininet>" )
626 response += self.handle.before + self.handle.after
627 main.log.debug( response )
628 return main.FALSE
629 except pexpect.EOF:
630 main.log.error( self.name + ": EOF exception found" )
631 main.log.error( self.name + ": " + self.handle.before )
632 main.cleanAndExit()
633 except Exception:
634 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800635 main.cleanAndExit()
636
637 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
638 """
639 Verify ping from each host in srcList to each host in dstList
640
641 acceptableFailed: max number of acceptable failed pings
642
643 Returns main.TRUE if all src hosts can reach all dst hosts
644 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
645 """
646 try:
647 main.log.info( "Verifying ping from each src host to each dst host" )
648 isReachable = main.TRUE
649 wait = int( wait )
650 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
651 pingResponse = "Ping output:\n"
652 failedPingsTotal = 0
653 for host in srcList:
654 pingResponse += str( str( host ) + " -> " )
655 for temp in dstList:
656 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700657 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
658 assert dstIP, "Not able to get IP address of host {}".format( temp )
659 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800660 while failedPings <= acceptableFailed:
661 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
662 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700663 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800664 response = self.handle.before
665 if re.search( ',\s0\%\spacket\sloss', response ):
666 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800667 break
668 else:
669 failedPings += 1
670 time.sleep(1)
671 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700672 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800673 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700674 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800675 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700676 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800677 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700678 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700679 except AssertionError:
680 main.log.exception( "" )
681 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700682 except pexpect.TIMEOUT:
683 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800684 response = self.handle.before
685 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700686 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800687 self.handle.expect( "Interrupt" )
688 response += self.handle.before + self.handle.after
689 self.handle.expect( "mininet>" )
690 response += self.handle.before + self.handle.after
691 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700692 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700693 except pexpect.EOF:
694 main.log.error( self.name + ": EOF exception found" )
695 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700696 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700697 except Exception:
698 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700699 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700700
Jon Hall7eb38402015-01-08 17:19:54 -0800701 def pingHost( self, **pingParams ):
702 """
Jon Hall3b489db2015-10-05 14:38:37 -0700703 Ping from one mininet host to another
704 Currently the only supported Params: SRC, TARGET, and WAIT
705 """
706 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700707 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700708 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800709 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700710 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700711 try:
Jon Hall61282e32015-03-19 11:34:11 -0700712 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800713 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700714 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700715 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700716 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800717 main.log.error(
718 self.name +
719 ": timeout when waiting for response from mininet" )
720 main.log.error( "response: " + str( self.handle.before ) )
721 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700722 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800723 main.log.error(
724 self.name +
725 ": timeout when waiting for response from mininet" )
726 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700727 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700728 if re.search( ',\s0\%\spacket\sloss', response ):
729 main.log.info( self.name + ": no packets lost, host is reachable" )
730 return main.TRUE
731 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800732 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700733 self.name +
734 ": PACKET LOST, HOST IS NOT REACHABLE" )
735 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800736 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800737 main.log.error( self.name + ": EOF exception found" )
738 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700739 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700740 except Exception:
741 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700742 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700743
744 def ping6pair( self, **pingParams ):
745 """
GlennRC2cf7d952015-09-11 16:32:13 -0700746 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700747 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000748 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700749 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
750 """
Jon Hall3b489db2015-10-05 14:38:37 -0700751 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700752 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700753 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530754 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700755 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700756 try:
757 main.log.info( "Sending: " + command )
758 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700759 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700760 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700761 if i == 1:
762 main.log.error(
763 self.name +
764 ": timeout when waiting for response from mininet" )
765 main.log.error( "response: " + str( self.handle.before ) )
766 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
767 if i == 1:
768 main.log.error(
769 self.name +
770 ": timeout when waiting for response from mininet" )
771 main.log.error( "response: " + str( self.handle.before ) )
772 response = self.handle.before
773 main.log.info( self.name + ": Ping Response: " + response )
774 if re.search( ',\s0\%\spacket\sloss', response ):
775 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700776 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700777 else:
alisone4121a92016-11-22 16:31:36 -0800778 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700779 self.name +
780 ": PACKET LOST, HOST IS NOT REACHABLE" )
781 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700782 except pexpect.EOF:
783 main.log.error( self.name + ": EOF exception found" )
784 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700785 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700786 except Exception:
787 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700788 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800789
You Wangdb927a52016-02-26 11:03:28 -0800790 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
791 """
792 Description:
793 Ping a set of destination host from host CLI.
794 Logging into a Mininet host CLI is required before calling this funtion.
795 Params:
796 dstIPList is a list of destination ip addresses
797 Returns:
798 main.TRUE if the destination host is reachable
799 main.FALSE otherwise
800 """
801 isReachable = main.TRUE
802 wait = int( wait )
803 cmd = "ping"
804 if IPv6:
805 cmd = cmd + "6"
806 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
807 try:
808 for dstIP in dstIPList:
809 pingCmd = cmd + " " + dstIP
810 self.handle.sendline( pingCmd )
811 i = self.handle.expect( [ self.hostPrompt,
812 '\*\*\* Unknown command: ' + pingCmd,
813 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700814 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700815 # For some reason we need to send something
816 # Otherwise ping results won't be read by handle
817 self.handle.sendline( "" )
818 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800819 if i == 0:
820 response = self.handle.before
821 if not re.search( ',\s0\%\spacket\sloss', response ):
822 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
823 isReachable = main.FALSE
824 elif i == 1:
825 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700826 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800827 elif i == 2:
828 main.log.error( self.name + ": timeout when waiting for response" )
829 isReachable = main.FALSE
830 else:
831 main.log.error( self.name + ": unknown response: " + self.handle.before )
832 isReachable = main.FALSE
833 except pexpect.TIMEOUT:
834 main.log.exception( self.name + ": TIMEOUT exception" )
You Wangd4fae5c2018-08-22 13:56:49 -0700835 self.exitFromCmd( [ self.hostPrompt, self.bashPrompt ] )
You Wangdb927a52016-02-26 11:03:28 -0800836 isReachable = main.FALSE
837 except pexpect.EOF:
838 main.log.error( self.name + ": EOF exception found" )
839 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700840 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800841 except Exception:
842 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700843 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800844 return isReachable
845
Jon Hall7eb38402015-01-08 17:19:54 -0800846 def checkIP( self, host ):
847 """
848 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700849 try:
850 if self.handle:
851 try:
852 response = self.execute(
853 cmd=host +
854 " ifconfig",
855 prompt="mininet>",
856 timeout=10 )
857 except pexpect.EOF:
858 main.log.error( self.name + ": EOF exception found" )
859 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700860 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700861
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700862 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
863 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
864 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
865 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
866 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
867 "[0-9]|25[0-5]|[0-9]{1,2})"
868 # pattern = "inet addr:10.0.0.6"
869 if re.search( pattern, response ):
870 main.log.info( self.name + ": Host Ip configured properly" )
871 return main.TRUE
872 else:
873 main.log.error( self.name + ": Host IP not found" )
874 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700875 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700876 main.log.error( self.name + ": Connection failed to the host" )
877 except Exception:
878 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700879 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800880
Jon Hall7eb38402015-01-08 17:19:54 -0800881 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800882 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700883 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800884 response = self.execute(
885 cmd="h1 /usr/sbin/sshd -D&",
886 prompt="mininet>",
887 timeout=10 )
888 response = self.execute(
889 cmd="h4 /usr/sbin/sshd -D&",
890 prompt="mininet>",
891 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700892 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800893 vars( self )[ key ] = connectargs[ key ]
894 response = self.execute(
895 cmd="xterm h1 h4 ",
896 prompt="mininet>",
897 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800898 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800899 main.log.error( self.name + ": EOF exception found" )
900 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700901 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700902 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800903 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700904 if self.flag == 0:
905 self.flag = 1
906 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800907 else:
adminbae64d82013-08-01 10:50:15 -0700908 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800909
Jon Hall7eb38402015-01-08 17:19:54 -0800910 def changeIP( self, host, intf, newIP, newNetmask ):
911 """
912 Changes the ip address of a host on the fly
913 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800914 if self.handle:
915 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800916 cmd = host + " ifconfig " + intf + " " + \
917 newIP + " " + 'netmask' + " " + newNetmask
918 self.handle.sendline( cmd )
919 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800920 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800921 main.log.info( "response = " + response )
922 main.log.info(
923 "Ip of host " +
924 host +
925 " changed to new IP " +
926 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800927 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700928 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700929 main.log.error( self.name + ": TIMEOUT exception found" )
930 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700931 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800932 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800933 main.log.error( self.name + ": EOF exception found" )
934 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800935 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700936 except Exception:
937 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700938 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800939
Jon Hall7eb38402015-01-08 17:19:54 -0800940 def changeDefaultGateway( self, host, newGW ):
941 """
942 Changes the default gateway of a host
943 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800944 if self.handle:
945 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800946 cmd = host + " route add default gw " + newGW
947 self.handle.sendline( cmd )
948 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800949 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800950 main.log.info( "response = " + response )
951 main.log.info(
952 "Default gateway of host " +
953 host +
954 " changed to " +
955 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800956 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700957 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700958 main.log.error( self.name + ": TIMEOUT exception found" )
959 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700960 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800961 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800962 main.log.error( self.name + ": EOF exception found" )
963 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800964 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700965 except Exception:
966 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700967 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800968
You Wange24d6272018-03-27 21:18:50 -0700969 def addRoute( self, host, dstIP, interface, ipv6=False ):
970 """
971 Add a route to host
972 Ex: h1 route add -host 224.2.0.1 h1-eth0
973 """
974 if self.handle:
975 try:
976 cmd = str( host )
977 if ipv6:
978 cmd += " route -A inet6 add "
979 else:
980 cmd += " route add -host "
981 cmd += str( dstIP ) + " " + str( interface )
982 self.handle.sendline( cmd )
983 self.handle.expect( "mininet>" )
984 response = self.handle.before
985 main.log.debug( "response = " + response )
986 return main.TRUE
987 except pexpect.TIMEOUT:
988 main.log.error( self.name + ": TIMEOUT exception found" )
989 main.log.error( self.name + ": " + self.handle.before )
990 main.cleanAndExit()
991 except pexpect.EOF:
992 main.log.error( self.name + ": EOF exception found" )
993 main.log.error( self.name + ": " + self.handle.before )
994 return main.FALSE
995 except Exception:
996 main.log.exception( self.name + ": Uncaught exception!" )
997 main.cleanAndExit()
998
Jon Hall7eb38402015-01-08 17:19:54 -0800999 def addStaticMACAddress( self, host, GW, macaddr ):
1000 """
Jon Hallefbd9792015-03-05 16:11:36 -08001001 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001002 if self.handle:
1003 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001004 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1005 cmd = host + " arp -s " + GW + " " + macaddr
1006 self.handle.sendline( cmd )
1007 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001008 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001009 main.log.info( "response = " + response )
1010 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001011 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001012 GW +
1013 " changed to " +
1014 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001015 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001016 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001017 main.log.error( self.name + ": TIMEOUT exception found" )
1018 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001019 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001020 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001021 main.log.error( self.name + ": EOF exception found" )
1022 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001023 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001024 except Exception:
1025 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001026 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001027
Jon Hall7eb38402015-01-08 17:19:54 -08001028 def verifyStaticGWandMAC( self, host ):
1029 """
1030 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001031 if self.handle:
1032 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001033 # h1 arp -an
1034 cmd = host + " arp -an "
1035 self.handle.sendline( cmd )
1036 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001037 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001038 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001039 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001040 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001041 main.log.error( self.name + ": TIMEOUT exception found" )
1042 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001043 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001044 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001045 main.log.error( self.name + ": EOF exception found" )
1046 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001047 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001048 except Exception:
1049 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001050 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001051
Jon Hall7eb38402015-01-08 17:19:54 -08001052 def getMacAddress( self, host ):
1053 """
1054 Verifies the host's ip configured or not."""
1055 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001056 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001057 response = self.execute(
1058 cmd=host +
1059 " ifconfig",
1060 prompt="mininet>",
1061 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001062 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001063 main.log.error( self.name + ": EOF exception found" )
1064 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001065 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001066 except Exception:
1067 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001068 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001069
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001070 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001071 macAddressSearch = re.search( pattern, response, re.I )
1072 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001073 main.log.info(
1074 self.name +
1075 ": Mac-Address of Host " +
1076 host +
1077 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001078 macAddress )
1079 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001080 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001081 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001082
Jon Hall7eb38402015-01-08 17:19:54 -08001083 def getInterfaceMACAddress( self, host, interface ):
1084 """
1085 Return the IP address of the interface on the given host"""
1086 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001087 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001088 response = self.execute( cmd=host + " ifconfig " + interface,
1089 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001090 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001091 main.log.error( self.name + ": EOF exception found" )
1092 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001093 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001094 except Exception:
1095 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001096 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001097
1098 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001099 macAddressSearch = re.search( pattern, response, re.I )
1100 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001101 main.log.info( "No mac address found in %s" % response )
1102 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001103 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001104 main.log.info(
1105 "Mac-Address of " +
1106 host +
1107 ":" +
1108 interface +
1109 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001110 macAddress )
1111 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001112 else:
1113 main.log.error( "Connection failed to the host" )
1114
You Wang5da39c82018-04-26 22:55:08 -07001115 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001116 """
1117 Verifies the host's ip configured or not."""
1118 if self.handle:
1119 try:
1120 response = self.execute(
1121 cmd=host +
1122 " ifconfig",
1123 prompt="mininet>",
1124 timeout=10 )
1125 except pexpect.EOF:
1126 main.log.error( self.name + ": EOF exception found" )
1127 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001128 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001129 except Exception:
1130 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001131 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001132
sathishmad953462015-12-03 17:42:07 +05301133 pattern = ''
1134 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001135 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301136 else:
Jon Hall439c8912016-04-15 02:22:03 -07001137 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001138 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001139 if not ipAddressSearch:
1140 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001141 main.log.info(
1142 self.name +
1143 ": IP-Address of Host " +
1144 host +
1145 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001146 ipAddressSearch.group( 1 ) )
1147 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001148 else:
1149 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001150
Jon Hall7eb38402015-01-08 17:19:54 -08001151 def getSwitchDPID( self, switch ):
1152 """
1153 return the datapath ID of the switch"""
1154 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001155 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001156 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001157 response = self.execute(
1158 cmd=cmd,
1159 prompt="mininet>",
1160 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001161 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001162 main.log.error( self.name + ": EOF exception found" )
1163 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001164 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001165 except Exception:
1166 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001167 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001168 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001169 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001170 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001171 main.log.info(
1172 "Couldn't find DPID for switch %s, found: %s" %
1173 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001174 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001175 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001176 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001177 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001178
Jon Hall7eb38402015-01-08 17:19:54 -08001179 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001180 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001181 self.handle.sendline( "" )
1182 self.expect( "mininet>" )
1183 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001184 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001185 response = self.execute(
1186 cmd=cmd,
1187 prompt="mininet>",
1188 timeout=10 )
1189 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001190 response = self.handle.before
1191 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001192 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001193 main.log.error( self.name + ": TIMEOUT exception found" )
1194 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001195 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001196 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001197 main.log.error( self.name + ": EOF exception found" )
1198 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001199 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001200 except Exception:
1201 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001202 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001203
Jon Hall7eb38402015-01-08 17:19:54 -08001204 def getInterfaces( self, node ):
1205 """
1206 return information dict about interfaces connected to the node"""
1207 if self.handle:
1208 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001209 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001210 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001211 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001212 response = self.execute(
1213 cmd=cmd,
1214 prompt="mininet>",
You Wang9fc5ce42019-01-23 15:10:08 -08001215 timeout=10,
1216 logCmd=False )
Jon Hallfbc828e2015-01-06 17:30:19 -08001217 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001218 main.log.error( self.name + ": EOF exception found" )
1219 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001220 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001221 except Exception:
1222 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001223 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001224 return response
1225 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001226 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001227
Jon Hall7eb38402015-01-08 17:19:54 -08001228 def dump( self ):
1229 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001230 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001231 response = self.execute(
1232 cmd='dump',
1233 prompt='mininet>',
1234 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001235 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001236 main.log.error( self.name + ": EOF exception found" )
1237 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001238 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001239 except Exception:
1240 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001241 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001242 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001243
Jon Hall7eb38402015-01-08 17:19:54 -08001244 def intfs( self ):
1245 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001246 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001247 response = self.execute(
1248 cmd='intfs',
1249 prompt='mininet>',
1250 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001251 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001252 main.log.error( self.name + ": EOF exception found" )
1253 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001254 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001255 except Exception:
1256 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001257 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001258 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001259
Jon Hall7eb38402015-01-08 17:19:54 -08001260 def net( self ):
1261 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001262 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001263 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001264 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001265 main.log.error( self.name + ": EOF exception found" )
1266 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001267 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001268 except Exception:
1269 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001270 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001271 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001272
Devin Lima7cfdbd2017-09-29 15:02:22 -07001273 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001274 main.log.info( self.name + ": List network links" )
1275 try:
1276 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001277 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001278 except pexpect.EOF:
1279 main.log.error( self.name + ": EOF exception found" )
1280 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001281 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001282 except Exception:
1283 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001284 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001285 return response
1286
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001287 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001288 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001289 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001290
kelvin-onlab7cce9382015-07-17 10:21:03 -07001291 @parm:
1292 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1293 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001294 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001295 try:
1296 for host1 in hosts:
1297 for host2 in hosts:
1298 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001299 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1300 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001301 except Exception:
1302 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001303 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001304
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001305 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001306 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001307 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1308 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001309
kelvin-onlab7cce9382015-07-17 10:21:03 -07001310 @parm:
1311 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1312 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001313 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001314 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1315 try:
1316 # Setup the mininet command
1317 cmd1 = 'iperf ' + host1 + " " + host2
1318 self.handle.sendline( cmd1 )
1319 outcome = self.handle.expect( "mininet>", timeout )
1320 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001321
kelvin-onlab7cce9382015-07-17 10:21:03 -07001322 # checks if there are results in the mininet response
1323 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001324 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001325 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001326 response = response.split( "\r\n" )
1327 response = response[ len( response )-2 ]
1328 response = response.split( ": " )
1329 response = response[ len( response )-1 ]
1330 response = response.replace( "[", "" )
1331 response = response.replace( "]", "" )
1332 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001333
kelvin-onlab7cce9382015-07-17 10:21:03 -07001334 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001335 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001336
kelvin-onlab7cce9382015-07-17 10:21:03 -07001337 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001338 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001339 if len( bandwidth ) == 2:
1340 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001341 return main.TRUE
1342 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001343 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001344 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001345 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001346 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001347 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001348 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001349 main.log.error( self.name + ": TIMEOUT exception found" )
1350 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001351 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001352 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001353 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001354 self.handle.expect( "Interrupt" )
1355 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001356 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001357 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001358 main.log.error( self.name + ": EOF exception found" )
1359 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001360 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001361 except Exception:
1362 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001363 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001364
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001365 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001366 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1367 try:
1368 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001369 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001370 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001371 outcome1 = self.handle.expect( "mininet>" )
1372 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001373 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001374 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001375 response1 = self.handle.before
1376 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001377 print response1, response2
1378 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001379 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001380 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001381 return main.TRUE
1382 else:
1383 main.log.error( self.name + ": iperf test failed" )
1384 return main.FALSE
1385 except pexpect.TIMEOUT:
1386 main.log.error( self.name + ": TIMEOUT exception found" )
1387 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001388 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001389 self.handle.expect( "Interrupt" )
1390 self.handle.expect( "mininet>" )
1391 return main.FALSE
1392 except pexpect.EOF:
1393 main.log.error( self.name + ": EOF exception found" )
1394 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001395 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001396 except Exception:
1397 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001398 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001399
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001400 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001401 '''
GlennRC61321f22015-07-16 13:36:54 -07001402 Runs the iperfudp function with a given set of hosts and specified
1403 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001404
GlennRC61321f22015-07-16 13:36:54 -07001405 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001406 bandwidth: the targeted bandwidth, in megabits ('M')
1407 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001408 try:
1409 for host1 in hosts:
1410 for host2 in hosts:
1411 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001412 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1413 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001414 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001415 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001416 return main.FALSE
1417 except Exception:
1418 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001419 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001420
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001421 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001422 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001423 Creates an iperf UDP test with a specific bandwidth.
1424 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001425
kelvin-onlab7cce9382015-07-17 10:21:03 -07001426 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001427 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1428 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001429 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001430 try:
1431 # setup the mininet command
1432 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001433 self.handle.sendline( cmd )
1434 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001435 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001436
kelvin-onlab7cce9382015-07-17 10:21:03 -07001437 # check if there are in results in the mininet response
1438 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001439 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001440 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001441 response = response.split( "\r\n" )
1442 response = response[ len( response )-2 ]
1443 response = response.split( ": " )
1444 response = response[ len( response )-1 ]
1445 response = response.replace( "[", "" )
1446 response = response.replace( "]", "" )
1447 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001448
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001449 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001450
kelvin-onlab7cce9382015-07-17 10:21:03 -07001451 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001452 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001453 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001454 # if one entry is blank then something is wrong
1455 for item in mnBandwidth:
1456 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001457 main.log.error( self.name + ": Could not parse iperf output" )
1458 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001459 return main.FALSE
1460 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001461 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001462 return main.TRUE
1463 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001464 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001465 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001466
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001467 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001468 main.log.error( self.name + ": TIMEOUT exception found" )
1469 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001470 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001471 except pexpect.EOF:
1472 main.log.error( self.name + ": EOF exception found" )
1473 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001474 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001475 except Exception:
1476 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001477 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001478
Jon Hall7eb38402015-01-08 17:19:54 -08001479 def nodes( self ):
1480 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001481 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001482 response = self.execute(
1483 cmd='nodes',
1484 prompt='mininet>',
1485 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001486 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001487 main.log.error( self.name + ": EOF exception found" )
1488 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001489 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001490 except Exception:
1491 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001492 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001493 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001494
Jon Hall7eb38402015-01-08 17:19:54 -08001495 def pingpair( self ):
1496 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001497 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001498 response = self.execute(
1499 cmd='pingpair',
1500 prompt='mininet>',
1501 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001502 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001503 main.log.error( self.name + ": EOF exception found" )
1504 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001505 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001506 except Exception:
1507 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001508 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001509
Jon Hall7eb38402015-01-08 17:19:54 -08001510 if re.search( ',\s0\%\spacket\sloss', response ):
1511 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001512 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001513 else:
alisone4121a92016-11-22 16:31:36 -08001514 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001515 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001516
Jon Hall7eb38402015-01-08 17:19:54 -08001517 def link( self, **linkargs ):
1518 """
GlennRCed771242016-01-13 17:02:47 -08001519 Bring link( s ) between two nodes up or down
1520 """
Jon Hall6094a362014-04-11 14:46:56 -07001521 try:
GlennRCed771242016-01-13 17:02:47 -08001522 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1523 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1524 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1525 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1526
1527 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1528 cmd = "link {} {} {}".format( end1, end2, option )
1529 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001530 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001531 response = self.handle.before
1532 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001533 if "not in network" in response:
1534 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1535 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001536 return main.TRUE
1537 except pexpect.TIMEOUT:
1538 main.log.exception( self.name + ": Command timed out" )
1539 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001540 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001541 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001542 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001543 except Exception:
1544 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001545 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001546
pingping-lin8244a3b2015-09-16 13:36:56 -07001547 def switch( self, **switchargs ):
1548 """
1549 start/stop a switch
1550 """
1551 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1552 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1553 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1554 command = "switch " + str( sw ) + " " + str( option )
1555 main.log.info( command )
1556 try:
1557 self.handle.sendline( command )
1558 self.handle.expect( "mininet>" )
1559 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001560 main.log.error( self.name + ": TIMEOUT exception found" )
1561 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001562 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001563 except pexpect.EOF:
1564 main.log.error( self.name + ": EOF exception found" )
1565 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001566 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001567 return main.TRUE
1568
pingping-lin5bb663b2015-09-24 11:47:50 -07001569 def node( self, nodeName, commandStr ):
1570 """
1571 Carry out a command line on a given node
1572 @parm:
1573 nodeName: the node name in Mininet testbed
1574 commandStr: the command line will be carried out on the node
1575 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1576 """
1577 command = str( nodeName ) + " " + str( commandStr )
1578 main.log.info( command )
1579
1580 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001581 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001582 if re.search( "Unknown command", response ):
1583 main.log.warn( response )
1584 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001585 if re.search( "Permission denied", response ):
1586 main.log.warn( response )
1587 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001588 except pexpect.EOF:
1589 main.log.error( self.name + ": EOF exception found" )
1590 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001591 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001592 main.log.info( " response is :" )
1593 main.log.info( response )
1594 return response
1595
Jon Hall7eb38402015-01-08 17:19:54 -08001596 def yank( self, **yankargs ):
1597 """
1598 yank a mininet switch interface to a host"""
1599 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001600 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001601 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1602 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001603 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001604 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001605 response = self.execute(
1606 cmd=command,
1607 prompt="mininet>",
1608 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001609 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001610 main.log.error( self.name + ": EOF exception found" )
1611 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001612 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001613 except Exception:
1614 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001615 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001616 return main.TRUE
1617
Jon Hall7eb38402015-01-08 17:19:54 -08001618 def plug( self, **plugargs ):
1619 """
1620 plug the yanked mininet switch interface to a switch"""
1621 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001622 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001623 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1624 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001625 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001626 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001627 response = self.execute(
1628 cmd=command,
1629 prompt="mininet>",
1630 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001631 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001632 main.log.error( self.name + ": EOF exception found" )
1633 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001634 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001635 except Exception:
1636 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001637 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001638 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001639
Jon Hall7eb38402015-01-08 17:19:54 -08001640 def dpctl( self, **dpctlargs ):
1641 """
1642 Run dpctl command on all switches."""
1643 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001644 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001645 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1646 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1647 command = "dpctl " + cmd + " " + str( cmdargs )
1648 try:
1649 response = self.execute(
1650 cmd=command,
1651 prompt="mininet>",
1652 timeout=10 )
1653 except pexpect.EOF:
1654 main.log.error( self.name + ": EOF exception found" )
1655 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001656 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001657 except Exception:
1658 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001659 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001660 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001661
kelvin-onlabd3b64892015-01-20 13:26:24 -08001662 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001663 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001664 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001665 try:
1666 fileInput = path + '/lib/Mininet/INSTALL'
1667 version = super( Mininet, self ).getVersion()
1668 pattern = 'Mininet\s\w\.\w\.\w\w*'
1669 for line in open( fileInput, 'r' ).readlines():
1670 result = re.match( pattern, line )
1671 if result:
1672 version = result.group( 0 )
1673 return version
1674 except Exception:
1675 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001676 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001677
kelvin-onlabd3b64892015-01-20 13:26:24 -08001678 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001679 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001680 Parameters:
1681 sw: The name of an OVS switch. Example "s1"
1682 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001683 The output of the command from the mininet cli
1684 or main.FALSE on timeout"""
1685 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001686 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001687 response = self.execute(
1688 cmd=command,
1689 prompt="mininet>",
1690 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001691 if response:
Jon Hallab611372018-02-21 15:26:05 -08001692 if "no bridge named" in response:
1693 main.log.error( self.name + ": Error in getSwController: " +
1694 self.handle.before )
1695 return main.FALSE
1696 else:
1697 return response
admin2a9548d2014-06-17 14:08:07 -07001698 else:
1699 return main.FALSE
1700 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001701 main.log.error( self.name + ": EOF exception found" )
1702 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001703 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001704 except Exception:
1705 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001706 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001707
Charles Chan029be652015-08-24 01:46:10 +08001708 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001709 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001710 Description:
1711 Assign switches to the controllers ( for ovs use only )
1712 Required:
1713 sw - Name of the switch. This can be a list or a string.
1714 ip - Ip addresses of controllers. This can be a list or a string.
1715 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001716 port - ONOS use port 6653, if no list of ports is passed, then
1717 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001718 ptcp - ptcp number, This can be a string or a list that has
1719 the same length as switch. This is optional and not required
1720 when using ovs switches.
1721 NOTE: If switches and ptcp are given in a list type they should have the
1722 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1723 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001724
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001725 Return:
1726 Returns main.TRUE if mininet correctly assigned switches to
1727 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001728 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001729 """
1730 assignResult = main.TRUE
1731 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001732 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001733 command = "sh ovs-vsctl set-controller "
1734 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001735 try:
1736 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001737 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001738 if isinstance( port, types.StringType ) or \
1739 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001740 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001741 elif isinstance( port, types.ListType ):
1742 main.log.error( self.name + ": Only one controller " +
1743 "assigned and a list of ports has" +
1744 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001745 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001746 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001747 main.log.error( self.name + ": Invalid controller port " +
1748 "number. Please specify correct " +
1749 "controller port" )
1750 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001751
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001752 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001753 if isinstance( port, types.StringType ) or \
1754 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001755 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001756 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1757 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001758 elif isinstance( port, types.ListType ):
1759 if ( len( ip ) != len( port ) ):
1760 main.log.error( self.name + ": Port list = " +
1761 str( len( port ) ) +
1762 "should be the same as controller" +
1763 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001764 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001765 else:
1766 onosIp = ""
1767 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001768 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1769 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001770 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001771 main.log.error( self.name + ": Invalid controller port " +
1772 "number. Please specify correct " +
1773 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001774 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001775 else:
1776 main.log.error( self.name + ": Invalid ip address" )
1777 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001778
1779 if isinstance( sw, types.StringType ):
1780 command += sw + " "
1781 if ptcp:
1782 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001783 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001784 elif isinstance( ptcp, types.ListType ):
1785 main.log.error( self.name + ": Only one switch is " +
1786 "being set and multiple PTCP is " +
1787 "being passed " )
1788 else:
1789 main.log.error( self.name + ": Invalid PTCP" )
1790 ptcp = ""
1791 command += onosIp
1792 commandList.append( command )
1793
1794 elif isinstance( sw, types.ListType ):
1795 if ptcp:
1796 if isinstance( ptcp, types.ListType ):
1797 if len( ptcp ) != len( sw ):
1798 main.log.error( self.name + ": PTCP length = " +
1799 str( len( ptcp ) ) +
1800 " is not the same as switch" +
1801 " length = " +
1802 str( len( sw ) ) )
1803 return main.FALSE
1804 else:
1805 for switch, ptcpNum in zip( sw, ptcp ):
1806 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001807 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001808 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001809 tempCmd += onosIp
1810 commandList.append( tempCmd )
1811 else:
1812 main.log.error( self.name + ": Invalid PTCP" )
1813 return main.FALSE
1814 else:
1815 for switch in sw:
1816 tempCmd = "sh ovs-vsctl set-controller "
1817 tempCmd += switch + " " + onosIp
1818 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001819 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001820 main.log.error( self.name + ": Invalid switch type " )
1821 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001822
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001823 for cmd in commandList:
1824 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001825 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08001826 if "no bridge named" in self.handle.before:
1827 main.log.error( self.name + ": Error in assignSwController: " +
1828 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001829 except pexpect.TIMEOUT:
1830 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1831 return main.FALSE
1832 except pexpect.EOF:
1833 main.log.error( self.name + ": EOF exception found" )
1834 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001835 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001836 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001837 except pexpect.EOF:
1838 main.log.error( self.name + ": EOF exception found" )
1839 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001840 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001841 except Exception:
1842 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001843 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001844
kelvin-onlabd3b64892015-01-20 13:26:24 -08001845 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001846 """
1847 Removes the controller target from sw"""
1848 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001849 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001850 response = self.execute(
1851 cmd=command,
1852 prompt="mininet>",
1853 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001854 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001855 main.log.error( self.name + ": EOF exception found" )
1856 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001857 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001858 except Exception:
1859 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001860 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001861 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001862 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001863
kelvin-onlabd3b64892015-01-20 13:26:24 -08001864 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001865 """
Jon Hallb1290e82014-11-18 16:17:48 -05001866 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001867 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001868 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001869 NOTE: cannot currently specify what type of switch
1870 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001871 sw = name of the new switch as a string
1872 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001873 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001874 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001875 """
1876 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001877 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001878 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001879 response = self.execute(
1880 cmd=command,
1881 prompt="mininet>",
1882 timeout=10 )
1883 if re.search( "already exists!", response ):
1884 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001885 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001886 elif re.search( "Error", response ):
1887 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001888 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001889 elif re.search( "usage:", response ):
1890 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001891 return main.FALSE
1892 else:
1893 return main.TRUE
1894 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001895 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001896 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001897 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001898 except Exception:
1899 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001900 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001901
kelvin-onlabd3b64892015-01-20 13:26:24 -08001902 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001903 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001904 delete a switch from the mininet topology
1905 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001906 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001907 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001908 sw = name of the switch as a string
1909 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001910 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001911 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001912 response = self.execute(
1913 cmd=command,
1914 prompt="mininet>",
1915 timeout=10 )
1916 if re.search( "no switch named", response ):
1917 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001918 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001919 elif re.search( "Error", response ):
1920 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001921 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001922 elif re.search( "usage:", response ):
1923 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001924 return main.FALSE
1925 else:
1926 return main.TRUE
1927 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001928 main.log.error( self.name + ": EOF exception found" )
1929 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001930 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001931 except Exception:
1932 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001933 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001934
You Wangc61aaa22019-02-01 15:49:48 -08001935 def getSwitchRandom( self, timeout=60, nonCut=True, excludeNodes=[], skipSwitches=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07001936 """
1937 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001938 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001939 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001940 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07001941 it just randomly returns one switch from all current switches in
1942 Mininet.
You Wang9fc5ce42019-01-23 15:10:08 -08001943 excludeNodes will be pased to getGraphDict method
You Wangc61aaa22019-02-01 15:49:48 -08001944 Switches specified in skipSwitches will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07001945 Returns the name of the chosen switch.
1946 """
1947 import random
1948 candidateSwitches = []
1949 try:
1950 if not nonCut:
You Wangc61aaa22019-02-01 15:49:48 -08001951 switches = self.getSwitches( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07001952 assert len( switches ) != 0
1953 for switchName in switches.keys():
1954 candidateSwitches.append( switchName )
1955 else:
You Wang9fc5ce42019-01-23 15:10:08 -08001956 graphDict = self.getGraphDict( timeout=timeout, useId=False,
You Wang9fc5ce42019-01-23 15:10:08 -08001957 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001958 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001959 return None
1960 self.graph.update( graphDict )
1961 candidateSwitches = self.graph.getNonCutVertices()
You Wangc61aaa22019-02-01 15:49:48 -08001962 candidateSwitches = [ switch for switch in candidateSwitches if switch not in skipSwitches ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001963 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001964 return None
1965 elif len( candidateSwitches ) == 0:
1966 main.log.info( self.name + ": No candidate switch for deletion" )
1967 return None
1968 else:
1969 switch = random.sample( candidateSwitches, 1 )
1970 return switch[ 0 ]
1971 except KeyError:
1972 main.log.exception( self.name + ": KeyError exception found" )
1973 return None
1974 except AssertionError:
1975 main.log.exception( self.name + ": AssertionError exception found" )
1976 return None
1977 except Exception:
1978 main.log.exception( self.name + ": Uncaught exception" )
1979 return None
1980
1981 def delSwitchRandom( self, timeout=60, nonCut=True ):
1982 """
1983 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001984 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001985 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001986 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07001987 otherwise it just randomly delete one switch from all current
1988 switches in Mininet.
1989 Returns the name of the deleted switch
1990 """
1991 try:
1992 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001993 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001994 return None
1995 else:
1996 deletionResult = self.delSwitch( switch )
1997 if deletionResult:
1998 return switch
1999 else:
2000 return None
2001 except Exception:
2002 main.log.exception( self.name + ": Uncaught exception" )
2003 return None
2004
kelvin-onlabd3b64892015-01-20 13:26:24 -08002005 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002006 """
2007 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002008 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002009 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002010 NOTE: cannot currently specify what type of link
2011 required params:
2012 node1 = the string node name of the first endpoint of the link
2013 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002014 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002015 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002016 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002017 response = self.execute(
2018 cmd=command,
2019 prompt="mininet>",
2020 timeout=10 )
2021 if re.search( "doesnt exist!", response ):
2022 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002023 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002024 elif re.search( "Error", response ):
2025 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002026 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002027 elif re.search( "usage:", response ):
2028 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002029 return main.FALSE
2030 else:
2031 return main.TRUE
2032 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002033 main.log.error( self.name + ": EOF exception found" )
2034 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002035 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002036 except Exception:
2037 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002038 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002039
kelvin-onlabd3b64892015-01-20 13:26:24 -08002040 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002041 """
2042 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002043 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002044 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002045 required params:
2046 node1 = the string node name of the first endpoint of the link
2047 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002048 returns: main.FALSE on an error, else main.TRUE
2049 """
Jon Hallffb386d2014-11-21 13:43:38 -08002050 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002051 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002052 response = self.execute(
2053 cmd=command,
2054 prompt="mininet>",
2055 timeout=10 )
2056 if re.search( "no node named", response ):
2057 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002058 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002059 elif re.search( "Error", response ):
2060 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002061 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002062 elif re.search( "usage:", response ):
2063 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002064 return main.FALSE
2065 else:
2066 return main.TRUE
2067 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002068 main.log.error( self.name + ": EOF exception found" )
2069 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002070 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002071 except Exception:
2072 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002073 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002074
You Wangc61aaa22019-02-01 15:49:48 -08002075 def getLinkRandom( self, timeout=60, nonCut=True, excludeNodes=[], skipLinks=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07002076 """
2077 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002078 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002079 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002080 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002081 it just randomly returns one link from all current links in
2082 Mininet.
You Wang9fc5ce42019-01-23 15:10:08 -08002083 excludeNodes will be passed to getLinks method to exclude unexpected links.
You Wangc61aaa22019-02-01 15:49:48 -08002084 Any link that has either end included in skipLinks will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07002085 Returns the link as a list, e.g. [ 's1', 's2' ]
2086 """
2087 import random
2088 candidateLinks = []
2089 try:
2090 if not nonCut:
You Wang9fc5ce42019-01-23 15:10:08 -08002091 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07002092 assert len( links ) != 0
2093 for link in links:
2094 # Exclude host-switch link
2095 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2096 continue
2097 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2098 else:
You Wang9fc5ce42019-01-23 15:10:08 -08002099 graphDict = self.getGraphDict( timeout=timeout, useId=False,
You Wang9fc5ce42019-01-23 15:10:08 -08002100 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002101 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002102 return None
2103 self.graph.update( graphDict )
2104 candidateLinks = self.graph.getNonCutEdges()
You Wangc61aaa22019-02-01 15:49:48 -08002105 candidateLinks = [ link for link in candidateLinks
2106 if link[0] not in skipLinks and link[1] not in skipLinks ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002107 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002108 return None
2109 elif len( candidateLinks ) == 0:
2110 main.log.info( self.name + ": No candidate link for deletion" )
2111 return None
2112 else:
2113 link = random.sample( candidateLinks, 1 )
2114 return link[ 0 ]
2115 except KeyError:
2116 main.log.exception( self.name + ": KeyError exception found" )
2117 return None
2118 except AssertionError:
2119 main.log.exception( self.name + ": AssertionError exception found" )
2120 return None
2121 except Exception:
2122 main.log.exception( self.name + ": Uncaught exception" )
2123 return None
2124
2125 def delLinkRandom( self, timeout=60, nonCut=True ):
2126 """
2127 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002128 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002129 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002130 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002131 otherwise it just randomly delete one link from all current links
2132 in Mininet.
2133 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2134 """
2135 try:
2136 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002137 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002138 return None
2139 else:
2140 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2141 if deletionResult:
2142 return link
2143 else:
2144 return None
2145 except Exception:
2146 main.log.exception( self.name + ": Uncaught exception" )
2147 return None
2148
kelvin-onlabd3b64892015-01-20 13:26:24 -08002149 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002150 """
Jon Hallb1290e82014-11-18 16:17:48 -05002151 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002152 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002153 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002154 NOTE: cannot currently specify what type of host
2155 required params:
2156 hostname = the string hostname
2157 optional key-value params
2158 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002159 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002160 """
2161 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002162 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002163 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002164 response = self.execute(
2165 cmd=command,
2166 prompt="mininet>",
2167 timeout=10 )
2168 if re.search( "already exists!", response ):
2169 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002170 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002171 elif re.search( "doesnt exists!", response ):
2172 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002173 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002174 elif re.search( "Error", response ):
2175 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002176 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002177 elif re.search( "usage:", response ):
2178 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002179 return main.FALSE
2180 else:
2181 return main.TRUE
2182 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002183 main.log.error( self.name + ": EOF exception found" )
2184 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002185 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002186 except Exception:
2187 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002188 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002189
kelvin-onlabd3b64892015-01-20 13:26:24 -08002190 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002191 """
2192 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002193 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002194 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002195 NOTE: this uses a custom mn function
2196 required params:
2197 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002198 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002199 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002200 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002201 response = self.execute(
2202 cmd=command,
2203 prompt="mininet>",
2204 timeout=10 )
2205 if re.search( "no host named", response ):
2206 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002207 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002208 elif re.search( "Error", response ):
2209 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002210 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002211 elif re.search( "usage:", response ):
2212 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002213 return main.FALSE
2214 else:
2215 return main.TRUE
2216 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002217 main.log.error( self.name + ": EOF exception found" )
2218 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002219 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002220 except Exception:
2221 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002222 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002223
Jon Hall7eb38402015-01-08 17:19:54 -08002224 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002225 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002226 Called at the end of the test to stop the mininet and
2227 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002228 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002229 try:
2230 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002231 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002232 timeout=2 )
2233 response = main.TRUE
2234 if i == 0:
2235 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002236 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002237 return main.TRUE
2238 # print "Disconnecting Mininet"
2239 if self.handle:
2240 self.handle.sendline( "exit" )
2241 self.handle.expect( "exit" )
2242 self.handle.expect( "(.*)" )
2243 else:
2244 main.log.error( "Connection failed to the host" )
2245 return response
2246 except pexpect.EOF:
2247 main.log.error( self.name + ": EOF exception found" )
2248 main.log.error( self.name + ": " + self.handle.before )
You Wangd4fae5c2018-08-22 13:56:49 -07002249 # Do not exit the entire test when pexpect.EOF is caught
2250 # FIXME: We might need to do something else here
2251 return main.ERROR
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002252 except Exception:
2253 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002254 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002255
Devin Lima7cfdbd2017-09-29 15:02:22 -07002256 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002257 """
Jon Hall21270ac2015-02-16 17:59:55 -08002258 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002259 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002260 main.FALSE if the pexpect handle does not exist.
2261
Jon Halld61331b2015-02-17 16:35:47 -08002262 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002263 """
Jon Halld61331b2015-02-17 16:35:47 -08002264 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002265 response = ''
2266 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002267 try:
Jon Halld80cc142015-07-06 13:36:05 -07002268 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002269 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002270 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002271 pexpect.EOF,
2272 pexpect.TIMEOUT ],
2273 timeout )
2274 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002275 main.log.info( "Exiting mininet.." )
2276 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002277 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002278 prompt=self.prompt,
2279 timeout=exitTimeout )
2280 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002281 self.handle.sendline( "sudo mn -c" )
2282 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002283
Jeremyd9e4eb12016-04-13 12:09:06 -07002284 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002285 main.log.info( " Mininet trying to exit while not " +
2286 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002287 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002288 elif i == 2:
2289 main.log.error( "Something went wrong exiting mininet" )
2290 elif i == 3: # timeout
2291 main.log.error( "Something went wrong exiting mininet " +
2292 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002293
You Wang18db8592018-04-02 13:52:03 -07002294 self.handle.sendline( "" )
2295 self.handle.expect( self.prompt )
2296 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2297
Hari Krishnab35c6d02015-03-18 11:13:51 -07002298 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002299 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002300 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002301 self.handle.sendline(
2302 "sudo kill -9 \`ps -ef | grep \"" +
2303 fileName +
2304 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002305 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002306 main.log.error( self.name + ": TIMEOUT exception found" )
2307 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002308 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002309 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002310 main.log.error( self.name + ": EOF exception found" )
2311 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002312 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002313 except Exception:
2314 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002315 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002316 else:
2317 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002318 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002319 return response
2320
YPZhang26a139e2016-04-25 14:01:55 -07002321 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002322 """
2323 Description:
2324 Sends arp message from mininet host for hosts discovery
2325 Required:
2326 host - hosts name
2327 Optional:
2328 ip - ip address that does not exist in the network so there would
2329 be no reply.
2330 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002331 if ethDevice:
2332 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002333 cmd = srcHost + " arping -c1 "
2334 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002335 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 -07002336 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002337 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002338 if output:
2339 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002340 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002341 i = self.handle.expect( [ "mininet>", "arping: " ] )
2342 if i == 0:
2343 return main.TRUE
2344 elif i == 1:
2345 response = self.handle.before + self.handle.after
2346 self.handle.expect( "mininet>" )
2347 response += self.handle.before + self.handle.after
2348 main.log.warn( "Error sending arping, output was: " +
2349 response )
2350 return main.FALSE
2351 except pexpect.TIMEOUT:
2352 main.log.error( self.name + ": TIMEOUT exception found" )
2353 main.log.warn( self.handle.before )
2354 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002355 except pexpect.EOF:
2356 main.log.error( self.name + ": EOF exception found" )
2357 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002358 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002359 except Exception:
2360 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002361 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002362
Jon Hall7eb38402015-01-08 17:19:54 -08002363 def decToHex( self, num ):
2364 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002365
Jon Hall7eb38402015-01-08 17:19:54 -08002366 def getSwitchFlowCount( self, switch ):
2367 """
2368 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002369 if self.handle:
2370 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2371 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002372 response = self.execute(
2373 cmd=cmd,
2374 prompt="mininet>",
2375 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002376 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002377 main.log.error( self.name + ": EOF exception found" )
2378 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002379 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002380 except Exception:
2381 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002382 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002383 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002384 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002385 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002386 main.log.info(
2387 "Couldn't find flows on switch %s, found: %s" %
2388 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002389 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002390 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002391 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002392 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002393
Jon Hall9ed8f372016-02-24 17:34:07 -08002394 def checkFlows( self, sw, dumpFormat=None ):
2395 if dumpFormat:
2396 command = "sh ovs-ofctl -F " + \
2397 dumpFormat + " dump-flows " + str( sw )
2398 else:
2399 command = "sh ovs-ofctl dump-flows " + str( sw )
2400 try:
2401 response = self.execute(
2402 cmd=command,
2403 prompt="mininet>",
2404 timeout=10 )
2405 return response
2406 except pexpect.EOF:
2407 main.log.error( self.name + ": EOF exception found" )
2408 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002409 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002410 except Exception:
2411 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002412 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002413
GlennRC68467eb2015-11-16 18:01:01 -08002414 def flowTableComp( self, flowTable1, flowTable2 ):
2415 # This function compares the selctors and treatments of each flow
2416 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002417 assert flowTable1, "flowTable1 is empty or None"
2418 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002419 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002420 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002421 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002422 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002423 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2424 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002425 for field in dFields:
2426 try:
2427 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002428 except KeyError:
2429 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002430 try:
2431 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002432 except KeyError:
2433 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002434 for i in range( len( flowTable1 ) ):
2435 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002436 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002437 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002438 returnValue = main.FALSE
2439 break
2440 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002441 except AssertionError:
2442 main.log.exception( "Nothing to compare" )
2443 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002444 except Exception:
2445 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002446 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002447
GlennRC528ad292015-11-12 10:38:18 -08002448 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002449 '''
GlennRC956ea742015-11-05 16:14:15 -08002450 Discription: Parses flows into json format.
2451 NOTE: this can parse any string thats separated with commas
2452 Arguments:
2453 Required:
2454 flows: a list of strings that represnt flows
2455 Optional:
2456 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2457 debug: prints out the final result
2458 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002459 '''
GlennRC528ad292015-11-12 10:38:18 -08002460 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002461 try:
2462 for flow in flowTable:
2463 jsonFlow = {}
2464 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002465 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002466 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002467 for i in range( len( parsedFlow ) ):
2468 item = parsedFlow[ i ]
2469 if item[ 0 ] == " ":
2470 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002471 # grab the selector and treatment from the parsed flow
2472 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002473 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002474 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002475 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002476 index = 0
2477 # parse the flags
2478 # NOTE: This only parses one flag
2479 flag = {}
2480 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002481 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002482 index += 1
2483 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002484 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002485 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002486 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002487 # the priority is stuck in the selecter so put it back
2488 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002489 if 'priority' in sel[0]:
2490 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002491 # parse selector
2492 criteria = []
2493 for item in sel:
2494 # this is the type of the packet e.g. "arp"
2495 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002496 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002497 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002498 field = item.split( "=" )
2499 criteria.append( { field[ 0 ]: field[ 1 ] } )
2500 selector = { "selector": { "criteria": sorted( criteria ) } }
2501 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002502 # get rid of the action part e.g. "action=output:2"
2503 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002504 treat = treat.split( "=" )
2505 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002506 # parse treatment
2507 action = []
2508 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002509 if ":" in item:
2510 field = item.split( ":" )
2511 action.append( { field[ 0 ]: field[ 1 ] } )
2512 else:
2513 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2514 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002515 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002516 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002517 # parse the rest of the flow
2518 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002519 field = item.split( "=" )
2520 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002521 # add the treatment and the selector to the json flow
2522 jsonFlow.update( selector )
2523 jsonFlow.update( treatment )
2524 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002525
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002526 if debug:
2527 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002528
You Wang91c37cf2016-05-23 09:39:42 -07002529 # add the json flow to the json flow table
2530 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002531
You Wang91c37cf2016-05-23 09:39:42 -07002532 return jsonFlowTable
2533
2534 except IndexError:
2535 main.log.exception( self.name + ": IndexError found" )
2536 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002537 except pexpect.EOF:
2538 main.log.error( self.name + ": EOF exception found" )
2539 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002540 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002541 except Exception:
2542 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002543 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002544
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002545 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002546 '''
2547 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002548 Each element is a flow.
2549 Arguments:
2550 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002551 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002552 a list of switches.
2553 Optional:
2554 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2555 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002556 '''
GlennRC956ea742015-11-05 16:14:15 -08002557 try:
2558 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002559 if isinstance( sw, list ):
2560 switches.extend( sw )
2561 else:
2562 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002563
2564 flows = []
2565 for s in switches:
2566 cmd = "sh ovs-ofctl dump-flows " + s
2567
GlennRC528ad292015-11-12 10:38:18 -08002568 if "1.0" == version:
2569 cmd += " -F OpenFlow10-table_id"
2570 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002571 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002572
2573 main.log.info( "Sending: " + cmd )
2574 self.handle.sendline( cmd )
2575 self.handle.expect( "mininet>" )
2576 response = self.handle.before
2577 response = response.split( "\r\n" )
2578 # dump the first two elements and the last
2579 # the first element is the command that was sent
2580 # the second is the table header
2581 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002582 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002583 flows.extend( response )
2584
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002585 if debug:
2586 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002587
GlennRC528ad292015-11-12 10:38:18 -08002588 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002589
GlennRC956ea742015-11-05 16:14:15 -08002590 except pexpect.EOF:
2591 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002592 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002593 except Exception:
2594 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002595 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002596
2597 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002598 '''
GlennRC956ea742015-11-05 16:14:15 -08002599 Discription: Checks whether the ID provided matches a flow ID in Mininet
2600 Arguments:
2601 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002602 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002603 a list of switches.
2604 flowId: the flow ID in hex format. Can also be a list of IDs
2605 Optional:
2606 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2607 debug: prints out the final result
2608 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2609 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002610 '''
GlennRC956ea742015-11-05 16:14:15 -08002611 try:
2612 main.log.info( "Getting flows from Mininet" )
2613 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002614 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002615 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002616
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002617 if debug:
2618 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002619
2620 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002621 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002622 result = False
2623 for f in flows:
2624 if flowId in f.get( 'cookie' ):
2625 result = True
2626 break
2627 # flowId is a list
2628 else:
2629 result = True
2630 # Get flow IDs from Mininet
2631 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2632 # Save the IDs that are not in Mininet
2633 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2634
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002635 if debug:
2636 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002637
2638 # Print out the IDs that are not in Mininet
2639 if absentIds:
2640 main.log.warn( "Absent ids: {}".format( absentIds ) )
2641 result = False
2642
2643 return main.TRUE if result else main.FALSE
2644
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002645 except pexpect.EOF:
2646 main.log.error( self.name + ": EOF exception found" )
2647 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002648 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002649 except Exception:
2650 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002651 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002652
Charles Chan029be652015-08-24 01:46:10 +08002653 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002654 """
Jon Hallefbd9792015-03-05 16:11:36 -08002655 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002656 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002657 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002658 self.handle.sendline( "" )
2659 self.handle.expect( "mininet>" )
2660 self.handle.sendline(
2661 "sh sudo tcpdump -n -i " +
2662 intf +
2663 " " +
2664 port +
2665 " -w " +
2666 filename.strip() +
2667 " &" )
2668 self.handle.sendline( "" )
2669 i = self.handle.expect( [ 'No\ssuch\device',
2670 'listening\son',
2671 pexpect.TIMEOUT,
2672 "mininet>" ],
2673 timeout=10 )
2674 main.log.warn( self.handle.before + self.handle.after )
2675 self.handle.sendline( "" )
2676 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002677 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002678 main.log.error(
2679 self.name +
2680 ": tcpdump - No such device exists. " +
2681 "tcpdump attempted on: " +
2682 intf )
admin2a9548d2014-06-17 14:08:07 -07002683 return main.FALSE
2684 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002685 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002686 return main.TRUE
2687 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002688 main.log.error(
2689 self.name +
2690 ": tcpdump command timed out! Check interface name," +
2691 " given interface was: " +
2692 intf )
admin2a9548d2014-06-17 14:08:07 -07002693 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002694 elif i == 3:
2695 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002696 return main.TRUE
2697 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002698 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002699 return main.FALSE
2700 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002701 main.log.error( self.name + ": EOF exception found" )
2702 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002703 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002704 except Exception:
2705 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002706 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002707
kelvin-onlabd3b64892015-01-20 13:26:24 -08002708 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002709 """
2710 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002711 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002712 self.handle.sendline( "sh sudo pkill tcpdump" )
2713 self.handle.expect( "mininet>" )
2714 self.handle.sendline( "" )
2715 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002716 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002717 main.log.error( self.name + ": TIMEOUT exception found" )
2718 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002719 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002720 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002721 main.log.error( self.name + ": EOF exception found" )
2722 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002723 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002724 except Exception:
2725 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002726 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002727
Jon Halld80cc142015-07-06 13:36:05 -07002728 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002729 """
2730 Read ports from a Mininet switch.
2731
2732 Returns a json structure containing information about the
2733 ports of the given switch.
2734 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002735 try:
2736 response = self.getInterfaces( nodeName )
2737 # TODO: Sanity check on response. log if no such switch exists
2738 ports = []
2739 for line in response.split( "\n" ):
2740 if not line.startswith( "name=" ):
2741 continue
2742 portVars = {}
2743 for var in line.split( "," ):
2744 key, value = var.split( "=" )
2745 portVars[ key ] = value
2746 isUp = portVars.pop( 'enabled', "True" )
2747 isUp = "True" in isUp
2748 if verbose:
2749 main.log.info( "Reading switch port %s(%s)" %
2750 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2751 mac = portVars[ 'mac' ]
2752 if mac == 'None':
2753 mac = None
2754 ips = []
2755 ip = portVars[ 'ip' ]
2756 if ip == 'None':
2757 ip = None
2758 ips.append( ip )
2759 name = portVars[ 'name' ]
2760 if name == 'None':
2761 name = None
2762 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2763 if name == 'lo':
2764 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2765 else:
2766 portNo = re.search( portRe, name ).group( 'port' )
2767 ports.append( { 'of_port': portNo,
2768 'mac': str( mac ).replace( '\'', '' ),
2769 'name': name,
2770 'ips': ips,
2771 'enabled': isUp } )
2772 return ports
2773 except pexpect.EOF:
2774 main.log.error( self.name + ": EOF exception found" )
2775 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002776 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002777 except Exception:
2778 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002779 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002780
You Wangdb8cd0a2016-05-26 15:19:45 -07002781 def getOVSPorts( self, nodeName ):
2782 """
2783 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2784
2785 Returns a list of dictionaries containing information about each
2786 port of the given switch.
2787 """
2788 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2789 try:
2790 response = self.execute(
2791 cmd=command,
2792 prompt="mininet>",
You Wang9fc5ce42019-01-23 15:10:08 -08002793 timeout=10,
2794 logCmd=False )
You Wangdb8cd0a2016-05-26 15:19:45 -07002795 ports = []
2796 if response:
2797 for line in response.split( "\n" ):
2798 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2799 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002800 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002801 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2802 result = re.search( pattern, line )
2803 if result:
2804 index = result.group( 'index' )
2805 name = result.group( 'name' )
2806 # This port number is extracted from port name
2807 port = result.group( 'port' )
2808 mac = result.group( 'mac' )
2809 ports.append( { 'index': index,
2810 'name': name,
2811 'port': port,
2812 'mac': mac } )
2813 return ports
2814 except pexpect.EOF:
2815 main.log.error( self.name + ": EOF exception found" )
2816 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002817 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002818 except Exception:
2819 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002820 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002821
You Wangc61aaa22019-02-01 15:49:48 -08002822 def getSwitches( self, verbose=False, updateTimeout=1000, excludeNodes=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002823 """
2824 Read switches from Mininet.
2825
2826 Returns a dictionary whose keys are the switch names and the value is
2827 a dictionary containing information about the switch.
You Wangc61aaa22019-02-01 15:49:48 -08002828 If excludeNodes is specified, switches with names included in excludeNodes
2829 will be ingored.
Jon Hallafa8a472015-06-12 14:02:42 -07002830 """
Jon Halla22481b2015-07-28 17:46:01 -07002831 # NOTE: To support new Mininet switch classes, just append the new
2832 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002833
Jon Halla22481b2015-07-28 17:46:01 -07002834 # Regex patterns to parse 'dump' output
2835 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002836 # <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 -07002837 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002838 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2839 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2840 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
You Wangc61aaa22019-02-01 15:49:48 -08002841 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
You Wang9fc5ce42019-01-23 15:10:08 -08002842 try:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002843 swRE = r"<(?P<class>" + switchClasses + r")" +\
2844 r"(?P<options>\{.*\})?\s" +\
2845 r"(?P<name>[^:]+)\:\s" +\
2846 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2847 r"\spid=(?P<pid>(\d)+)"
2848 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002849 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002850 output = {}
2851 dump = self.dump().split( "\n" )
2852 for line in dump:
2853 result = re.search( swRE, line, re.I )
2854 if result:
2855 name = result.group( 'name' )
You Wangc61aaa22019-02-01 15:49:48 -08002856 if name in excludeNodes:
2857 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002858 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2859 pid = result.group( 'pid' )
2860 swClass = result.group( 'class' )
2861 options = result.group( 'options' )
2862 if verbose:
2863 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2864 ports = self.getPorts( name )
2865 output[ name ] = { "dpid": dpid,
2866 "ports": ports,
2867 "swClass": swClass,
2868 "pid": pid,
2869 "options": options }
2870 return output
2871 except pexpect.EOF:
2872 main.log.error( self.name + ": EOF exception found" )
2873 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002874 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002875 except Exception:
2876 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002877 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002878
You Wangd66de192018-04-30 17:30:12 -07002879 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002880 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2881 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002882 """
2883 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002884 Optional:
2885 hostClass: it is used to match the class of the mininet host. It
2886 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002887 Returns a dictionary whose keys are the host names and the value is
2888 a dictionary containing information about the host.
2889 """
2890 # Regex patterns to parse dump output
2891 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002892 # <Host h1: pid=12725>
2893 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2894 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2895 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002896 # NOTE: Does not correctly match hosts with multi-links
2897 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2898 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002899 try:
You Wang53dba1e2018-02-02 17:45:44 -08002900 if not isinstance( hostClass, types.ListType ):
2901 hostClass = [ str( hostClass ) ]
2902 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002903 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2904 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2905 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002906 if update:
2907 # update mn port info
2908 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002909 # Get mininet dump
2910 dump = self.dump().split( "\n" )
2911 hosts = {}
2912 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002913 result = re.search( hostRE, line )
2914 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002915 name = result.group( 'name' )
2916 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002917 if getInterfaces:
2918 response = self.getInterfaces( name )
2919 # Populate interface info
2920 for line in response.split( "\n" ):
2921 if line.startswith( "name=" ):
2922 portVars = {}
2923 for var in line.split( "," ):
2924 key, value = var.split( "=" )
2925 portVars[ key ] = value
2926 isUp = portVars.pop( 'enabled', "True" )
2927 isUp = "True" in isUp
2928 if verbose:
2929 main.log.info( "Reading host port %s(%s)" %
2930 ( portVars[ 'name' ],
2931 portVars[ 'mac' ] ) )
2932 mac = portVars[ 'mac' ]
2933 if mac == 'None':
2934 mac = None
2935 ips = []
2936 ip = portVars[ 'ip' ]
2937 if ip == 'None':
2938 ip = None
2939 ips.append( ip )
2940 intfName = portVars[ 'name' ]
2941 if name == 'None':
2942 name = None
2943 interfaces.append( {
2944 "name": intfName,
2945 "ips": ips,
2946 "mac": str( mac ),
2947 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002948 hosts[ name ] = { "interfaces": interfaces }
2949 return hosts
2950 except pexpect.EOF:
2951 main.log.error( self.name + ": EOF exception found" )
2952 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002953 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002954 except Exception:
2955 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002956 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002957
You Wang9fc5ce42019-01-23 15:10:08 -08002958 def getLinks( self, timeout=20, updateTimeout=1000, excludeNodes=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002959 """
2960 Gathers information about current Mininet links. These links may not
2961 be up if one of the ports is down.
2962
2963 Returns a list of dictionaries with link endpoints.
2964
2965 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002966 { 'node1': str( node1 name )
2967 'node2': str( node2 name )
2968 'port1': str( port1 of_port )
2969 'port2': str( port2 of_port ) }
You Wang9fc5ce42019-01-23 15:10:08 -08002970
You Wangc61aaa22019-02-01 15:49:48 -08002971 If either node1 or node2 name matches any of the names sepcified in
2972 excludeNodes, the link will be excluded from the returned value
You Wang9fc5ce42019-01-23 15:10:08 -08002973
Jon Hallafa8a472015-06-12 14:02:42 -07002974 Note: The port number returned is the eth#, not necessarily the of_port
2975 number. In Mininet, for OVS switch, these should be the same. For
2976 hosts, this is just the eth#.
2977 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002978 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002979 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002980 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002981
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002982 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002983 # s1-eth3<->s2-eth1 (OK OK)
2984 # s13-eth3<->h27-eth0 (OK OK)
You Wang9fc5ce42019-01-23 15:10:08 -08002985 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d\.]+)\<\-\>" +\
2986 "(?P<node2>[\w]+)\-eth(?P<port2>[\d\.]+)"
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002987 links = []
2988 for line in response:
2989 match = re.search( linkRE, line )
2990 if match:
2991 node1 = match.group( 'node1' )
2992 node2 = match.group( 'node2' )
You Wangc61aaa22019-02-01 15:49:48 -08002993 if any( node1 == node or node2 == node for node in excludeNodes ):
You Wang9fc5ce42019-01-23 15:10:08 -08002994 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002995 port1 = match.group( 'port1' )
2996 port2 = match.group( 'port2' )
2997 links.append( { 'node1': node1,
2998 'node2': node2,
2999 'port1': port1,
3000 'port2': port2 } )
3001 return links
3002
3003 except pexpect.EOF:
3004 main.log.error( self.name + ": EOF exception found" )
3005 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003006 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003007 except Exception:
3008 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003009 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003010
3011 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003012 """
3013 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003014 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003015
Jon Hallafa8a472015-06-12 14:02:42 -07003016 Dependencies:
3017 1. numpy - "sudo pip install numpy"
3018 """
3019 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003020 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003021 try:
3022 mnDPIDs = []
3023 for swName, switch in switches.iteritems():
3024 mnDPIDs.append( switch[ 'dpid' ].lower() )
3025 mnDPIDs.sort()
3026 if switchesJson == "": # if rest call fails
3027 main.log.error(
3028 self.name +
3029 ".compareSwitches(): Empty JSON object given from ONOS" )
3030 return main.FALSE
3031 onos = switchesJson
3032 onosDPIDs = []
3033 for switch in onos:
3034 if switch[ 'available' ]:
3035 onosDPIDs.append(
3036 switch[ 'id' ].replace(
3037 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003038 '' ).replace(
3039 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003040 '' ).lower() )
3041 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003042
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003043 if mnDPIDs != onosDPIDs:
3044 switchResults = main.FALSE
3045 main.log.error( "Switches in MN but not in ONOS:" )
3046 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3047 main.log.error( str( list1 ) )
3048 main.log.error( "Switches in ONOS but not in MN:" )
3049 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3050 main.log.error( str( list2 ) )
3051 else: # list of dpid's match in onos and mn
3052 switchResults = main.TRUE
3053 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003054
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003055 # FIXME: this does not look for extra ports in ONOS, only checks that
3056 # ONOS has what is in MN
3057 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003058
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003059 # PORTS
3060 for name, mnSwitch in switches.iteritems():
3061 mnPorts = []
3062 onosPorts = []
3063 switchResult = main.TRUE
3064 for port in mnSwitch[ 'ports' ]:
3065 if port[ 'enabled' ]:
3066 mnPorts.append( int( port[ 'of_port' ] ) )
3067 for onosSwitch in portsJson:
3068 if onosSwitch[ 'device' ][ 'available' ]:
3069 if onosSwitch[ 'device' ][ 'id' ].replace(
3070 ':',
3071 '' ).replace(
3072 "of",
3073 '' ) == mnSwitch[ 'dpid' ]:
3074 for port in onosSwitch[ 'ports' ]:
3075 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003076 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003077 # onosPorts.append( 'local' )
3078 onosPorts.append( long( uint64( -2 ) ) )
3079 else:
3080 onosPorts.append( int( port[ 'port' ] ) )
3081 break
3082 mnPorts.sort( key=float )
3083 onosPorts.sort( key=float )
3084
3085 mnPortsLog = mnPorts
3086 onosPortsLog = onosPorts
3087 mnPorts = [ x for x in mnPorts ]
3088 onosPorts = [ x for x in onosPorts ]
3089
3090 # TODO: handle other reserved port numbers besides LOCAL
3091 # NOTE: Reserved ports
3092 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3093 # long( uint64( -2 ) )
3094 for mnPort in mnPortsLog:
3095 if mnPort in onosPorts:
3096 # don't set results to true here as this is just one of
3097 # many checks and it might override a failure
3098 mnPorts.remove( mnPort )
3099 onosPorts.remove( mnPort )
3100
3101 # NOTE: OVS reports this as down since there is no link
3102 # So ignoring these for now
3103 # TODO: Come up with a better way of handling these
3104 if 65534 in mnPorts:
3105 mnPorts.remove( 65534 )
3106 if long( uint64( -2 ) ) in onosPorts:
3107 onosPorts.remove( long( uint64( -2 ) ) )
3108 if len( mnPorts ): # the ports of this switch don't match
3109 switchResult = main.FALSE
3110 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3111 if len( onosPorts ): # the ports of this switch don't match
3112 switchResult = main.FALSE
3113 main.log.warn(
3114 "Ports in ONOS but not MN: " +
3115 str( onosPorts ) )
3116 if switchResult == main.FALSE:
3117 main.log.error(
3118 "The list of ports for switch %s(%s) does not match:" %
3119 ( name, mnSwitch[ 'dpid' ] ) )
3120 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3121 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3122 portsResults = portsResults and switchResult
3123 finalResults = finalResults and portsResults
3124 return finalResults
3125 except pexpect.EOF:
3126 main.log.error( self.name + ": EOF exception found" )
3127 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003128 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003129 except Exception:
3130 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003131 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003132
Jon Hallafa8a472015-06-12 14:02:42 -07003133 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003134 """
3135 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003136 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003137
Jon Hallafa8a472015-06-12 14:02:42 -07003138 """
Jon Hall7eb38402015-01-08 17:19:54 -08003139 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003140 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003141 try:
3142 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003143
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003144 mnLinks = []
3145 for l in links:
3146 try:
3147 node1 = switches[ l[ 'node1' ] ]
3148 node2 = switches[ l[ 'node2' ] ]
3149 enabled = True
3150 for port in node1[ 'ports' ]:
3151 if port[ 'of_port' ] == l[ 'port1' ]:
3152 enabled = enabled and port[ 'enabled' ]
3153 for port in node2[ 'ports' ]:
3154 if port[ 'of_port' ] == l[ 'port2' ]:
3155 enabled = enabled and port[ 'enabled' ]
3156 if enabled:
3157 mnLinks.append( l )
3158 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003159 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003160 if 2 * len( mnLinks ) == len( onos ):
3161 linkResults = main.TRUE
3162 else:
3163 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003164 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003165 "Mininet has " + str( len( mnLinks ) ) +
3166 " bidirectional links and ONOS has " +
3167 str( len( onos ) ) + " unidirectional links" )
3168
3169 # iterate through MN links and check if an ONOS link exists in
3170 # both directions
3171 for link in mnLinks:
3172 # TODO: Find a more efficient search method
3173 node1 = None
3174 port1 = None
3175 node2 = None
3176 port2 = None
3177 firstDir = main.FALSE
3178 secondDir = main.FALSE
3179 for swName, switch in switches.iteritems():
3180 if swName == link[ 'node1' ]:
3181 node1 = switch[ 'dpid' ]
3182 for port in switch[ 'ports' ]:
3183 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3184 port1 = port[ 'of_port' ]
3185 if node1 is not None and node2 is not None:
3186 break
3187 if swName == link[ 'node2' ]:
3188 node2 = switch[ 'dpid' ]
3189 for port in switch[ 'ports' ]:
3190 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3191 port2 = port[ 'of_port' ]
3192 if node1 is not None and node2 is not None:
3193 break
3194
3195 for onosLink in onos:
3196 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3197 ":", '' ).replace( "of", '' )
3198 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3199 ":", '' ).replace( "of", '' )
3200 onosPort1 = onosLink[ 'src' ][ 'port' ]
3201 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3202
3203 # check onos link from node1 to node2
3204 if str( onosNode1 ) == str( node1 ) and str(
3205 onosNode2 ) == str( node2 ):
3206 if int( onosPort1 ) == int( port1 ) and int(
3207 onosPort2 ) == int( port2 ):
3208 firstDir = main.TRUE
3209 else:
Jon Hallab611372018-02-21 15:26:05 -08003210 # The right switches, but wrong ports, could be
3211 # another link between these devices, or onos
3212 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003213 main.log.warn(
3214 'The port numbers do not match for ' +
3215 str( link ) +
3216 ' between ONOS and MN. When checking ONOS for ' +
3217 'link %s/%s -> %s/%s' %
3218 ( node1, port1, node2, port2 ) +
3219 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003220 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3221 '. This could be another link between these devices' +
3222 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003223
3224 # check onos link from node2 to node1
3225 elif ( str( onosNode1 ) == str( node2 ) and
3226 str( onosNode2 ) == str( node1 ) ):
3227 if ( int( onosPort1 ) == int( port2 )
3228 and int( onosPort2 ) == int( port1 ) ):
3229 secondDir = main.TRUE
3230 else:
Jon Hallab611372018-02-21 15:26:05 -08003231 # The right switches, but wrong ports, could be
3232 # another link between these devices, or onos
3233 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003234 main.log.warn(
3235 'The port numbers do not match for ' +
3236 str( link ) +
3237 ' between ONOS and MN. When checking ONOS for ' +
3238 'link %s/%s -> %s/%s' %
3239 ( node1, port1, node2, port2 ) +
3240 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003241 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3242 '. This could be another link between these devices' +
3243 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003244 else: # this is not the link you're looking for
3245 pass
3246 if not firstDir:
3247 main.log.error(
3248 'ONOS does not have the link %s/%s -> %s/%s' %
3249 ( node1, port1, node2, port2 ) )
3250 if not secondDir:
3251 main.log.error(
3252 'ONOS does not have the link %s/%s -> %s/%s' %
3253 ( node2, port2, node1, port1 ) )
3254 linkResults = linkResults and firstDir and secondDir
3255 return linkResults
3256 except pexpect.EOF:
3257 main.log.error( self.name + ": EOF exception found" )
3258 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003259 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003260 except Exception:
3261 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003262 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003263
Jon Hallafa8a472015-06-12 14:02:42 -07003264 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003265 """
Jon Hallafa8a472015-06-12 14:02:42 -07003266 Compare mn and onos Hosts.
3267 Since Mininet hosts are quiet, ONOS will only know of them when they
3268 speak. For this reason, we will only check that the hosts in ONOS
3269 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003270
Jon Hallafa8a472015-06-12 14:02:42 -07003271 Arguments:
3272 hostsJson: parsed json object from the onos hosts api
3273 Returns:
3274 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003275 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003276 try:
3277 hostResults = main.TRUE
3278 for onosHost in hostsJson:
3279 onosMAC = onosHost[ 'mac' ].lower()
3280 match = False
3281 for mnHost, info in hosts.iteritems():
3282 for mnIntf in info[ 'interfaces' ]:
3283 if onosMAC == mnIntf[ 'mac' ].lower():
3284 match = True
3285 for ip in mnIntf[ 'ips' ]:
3286 if ip in onosHost[ 'ipAddresses' ]:
3287 pass # all is well
3288 else:
3289 # misssing ip
3290 main.log.error( "ONOS host " +
3291 onosHost[ 'id' ] +
3292 " has a different IP(" +
3293 str( onosHost[ 'ipAddresses' ] ) +
3294 ") than the Mininet host(" +
3295 str( ip ) +
3296 ")." )
3297 output = json.dumps(
3298 onosHost,
3299 sort_keys=True,
3300 indent=4,
3301 separators=( ',', ': ' ) )
3302 main.log.info( output )
3303 hostResults = main.FALSE
3304 if not match:
3305 hostResults = main.FALSE
3306 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3307 "corresponding Mininet host." )
3308 output = json.dumps( onosHost,
3309 sort_keys=True,
3310 indent=4,
3311 separators=( ',', ': ' ) )
3312 main.log.info( output )
3313 return hostResults
3314 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003315 main.log.error( self.name + ": EOF exception found" )
3316 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003317 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003318 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003319 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003320 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003321
You Wangd66de192018-04-30 17:30:12 -07003322 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003323 """
3324 Description:
3325 Verify that all hosts have IP address assigned to them
3326 Optional:
3327 hostList: If specified, verifications only happen to the hosts
3328 in hostList
3329 prefix: at least one of the ip address assigned to the host
3330 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003331 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003332 Returns:
3333 main.TRUE if all hosts have specific IP address assigned;
3334 main.FALSE otherwise
3335 """
3336 try:
You Wangd66de192018-04-30 17:30:12 -07003337 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003338 if not hostList:
3339 hostList = hosts.keys()
3340 for hostName in hosts.keys():
3341 if hostName not in hostList:
3342 continue
3343 ipList = []
3344 self.handle.sendline( str( hostName ) + " ip a" )
3345 self.handle.expect( "mininet>" )
3346 ipa = self.handle.before
3347 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3348 ipList += re.findall( ipv4Pattern, ipa )
3349 # It's tricky to make regex for IPv6 addresses and this one is simplified
3350 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})/'
3351 ipList += re.findall( ipv6Pattern, ipa )
3352 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3353 if not ipList:
3354 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3355 else:
3356 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3357 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3358 else:
3359 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3360 hostList.remove( hostName )
3361 return main.FALSE if hostList else main.TRUE
3362 except KeyError:
3363 main.log.exception( self.name + ": host data not as expected: " + hosts )
3364 return None
3365 except pexpect.EOF:
3366 main.log.error( self.name + ": EOF exception found" )
3367 main.log.error( self.name + ": " + self.handle.before )
3368 main.cleanAndExit()
3369 except Exception:
3370 main.log.exception( self.name + ": Uncaught exception" )
3371 return None
3372
Jon Hallafa8a472015-06-12 14:02:42 -07003373 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003374 """
3375 Returns a list of all hosts
3376 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003377 try:
3378 self.handle.sendline( "" )
3379 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003380
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003381 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3382 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003383
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003384 handlePy = self.handle.before
3385 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3386 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003387
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003388 self.handle.sendline( "" )
3389 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003390
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003391 hostStr = handlePy.replace( "]", "" )
3392 hostStr = hostStr.replace( "'", "" )
3393 hostStr = hostStr.replace( "[", "" )
3394 hostStr = hostStr.replace( " ", "" )
3395 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003396
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003397 return hostList
3398 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003399 main.log.error( self.name + ": TIMEOUT exception found" )
3400 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003401 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003402 except pexpect.EOF:
3403 main.log.error( self.name + ": EOF exception found" )
3404 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003405 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003406 except Exception:
3407 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003408 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003409
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003410 def getSwitch( self ):
3411 """
3412 Returns a list of all switches
3413 Again, don't ask question just use it...
3414 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003415 try:
3416 # get host list...
3417 hostList = self.getHosts()
3418 # Make host set
3419 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003420
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003421 # Getting all the nodes in mininet
3422 self.handle.sendline( "" )
3423 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003424
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003425 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3426 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003427
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003428 handlePy = self.handle.before
3429 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3430 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003431
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003432 self.handle.sendline( "" )
3433 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003434
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003435 nodesStr = handlePy.replace( "]", "" )
3436 nodesStr = nodesStr.replace( "'", "" )
3437 nodesStr = nodesStr.replace( "[", "" )
3438 nodesStr = nodesStr.replace( " ", "" )
3439 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003440
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003441 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003442 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003443 nodesSet.discard( 'c0' )
3444 nodesSet.discard( 'c1' )
3445 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003446
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003447 switchSet = nodesSet - hostSet
3448 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003449
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003450 return switchList
3451 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003452 main.log.error( self.name + ": TIMEOUT exception found" )
3453 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003454 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003455 except pexpect.EOF:
3456 main.log.error( self.name + ": EOF exception found" )
3457 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003458 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003459 except Exception:
3460 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003461 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003462
You Wang9fc5ce42019-01-23 15:10:08 -08003463 def getGraphDict( self, timeout=60, useId=True, includeHost=False,
You Wangc61aaa22019-02-01 15:49:48 -08003464 excludeNodes=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07003465 """
3466 Return a dictionary which describes the latest Mininet topology data as a
3467 graph.
3468 An example of the dictionary:
3469 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3470 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3471 Each vertex should at least have an 'edges' attribute which describes the
3472 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003473 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003474 list of attributes.
3475 An example of the edges dictionary:
3476 'edges': { vertex2: { 'port': ..., 'weight': ... },
3477 vertex3: { 'port': ..., 'weight': ... } }
3478 If useId == True, dpid/mac will be used instead of names to identify
3479 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3480 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003481 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003482 in topology data.
You Wangc61aaa22019-02-01 15:49:48 -08003483 excludeNodes will be passed to getSwitches and getLinks methods to exclude
3484 unexpected switches and links.
You Wangdb8cd0a2016-05-26 15:19:45 -07003485 Note that link or switch that are brought down by 'link x x down' or 'switch
3486 x down' commands still show in the output of Mininet CLI commands such as
3487 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3488 recommended to use delLink() or delSwitch functions to simulate link/switch
3489 down, and addLink() or addSwitch to add them back.
3490 """
3491 graphDict = {}
3492 try:
You Wang9fc5ce42019-01-23 15:10:08 -08003493 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003494 portDict = {}
You Wangc61aaa22019-02-01 15:49:48 -08003495 switches = self.getSwitches( excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003496 if includeHost:
3497 hosts = self.getHosts()
3498 for link in links:
You Wangc61aaa22019-02-01 15:49:48 -08003499 # TODO: support 'includeHost' argument
You Wangdb8cd0a2016-05-26 15:19:45 -07003500 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3501 continue
3502 nodeName1 = link[ 'node1' ]
3503 nodeName2 = link[ 'node2' ]
You Wang9fc5ce42019-01-23 15:10:08 -08003504 if not self.getOVSPorts( nodeName1 ) or not self.getOVSPorts( nodeName2 ):
3505 # The device is probably offline
3506 continue
You Wangdb8cd0a2016-05-26 15:19:45 -07003507 port1 = link[ 'port1' ]
3508 port2 = link[ 'port2' ]
3509 # Loop for two nodes
3510 for i in range( 2 ):
3511 # Get port index from OVS
3512 # The index extracted from port name may be inconsistent with ONOS
3513 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003514 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003515 portList = self.getOVSPorts( nodeName1 )
3516 if len( portList ) == 0:
3517 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3518 return None
3519 portDict[ nodeName1 ] = portList
3520 for port in portDict[ nodeName1 ]:
3521 if port[ 'port' ] == port1:
3522 portIndex = port[ 'index' ]
3523 break
3524 if portIndex == -1:
3525 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3526 return None
3527 if useId:
3528 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3529 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3530 else:
3531 node1 = nodeName1
3532 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003533 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003534 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003535 graphDict[ node1 ] = { 'edges': {},
3536 'dpid': switches[ nodeName1 ][ 'dpid' ],
3537 'name': nodeName1,
3538 'ports': switches[ nodeName1 ][ 'ports' ],
3539 'swClass': switches[ nodeName1 ][ 'swClass' ],
3540 'pid': switches[ nodeName1 ][ 'pid' ],
3541 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003542 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003543 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003544 else:
3545 # Assert node2 is not connected to any current links of node1
You Wang9fc5ce42019-01-23 15:10:08 -08003546 # assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
3547 pass
3548 for port in switches[ nodeName1 ][ 'ports' ]:
3549 if port[ 'of_port' ] == str( portIndex ):
3550 # Use -1 as index for disabled port
You Wangc61aaa22019-02-01 15:49:48 -08003551 if port[ 'enabled' ]:
You Wang9fc5ce42019-01-23 15:10:08 -08003552 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
3553 else:
3554 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': -1 }
You Wangdb8cd0a2016-05-26 15:19:45 -07003555 # Swap two nodes/ports
3556 nodeName1, nodeName2 = nodeName2, nodeName1
3557 port1, port2 = port2, port1
You Wang9fc5ce42019-01-23 15:10:08 -08003558 # Remove links with disabled ports
3559 linksToRemove = []
3560 for node, edges in graphDict.items():
3561 for neighbor, port in edges[ 'edges' ].items():
3562 if port[ 'port' ] == -1:
3563 linksToRemove.append( ( node, neighbor ) )
3564 for node1, node2 in linksToRemove:
3565 for i in range( 2 ):
3566 if graphDict.get( node1 )[ 'edges' ].get( node2 ):
3567 graphDict[ node1 ][ 'edges' ].pop( node2 )
3568 node1, node2 = node2, node1
You Wangdb8cd0a2016-05-26 15:19:45 -07003569 return graphDict
3570 except KeyError:
3571 main.log.exception( self.name + ": KeyError exception found" )
3572 return None
3573 except AssertionError:
3574 main.log.exception( self.name + ": AssertionError exception found" )
3575 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003576 except pexpect.EOF:
3577 main.log.error( self.name + ": EOF exception found" )
3578 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003579 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003580 except Exception:
3581 main.log.exception( self.name + ": Uncaught exception" )
3582 return None
3583
Devin Lima7cfdbd2017-09-29 15:02:22 -07003584 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003585 """
3586 updates the port address and status information for
3587 each port in mn"""
3588 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003589 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003590 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003591 self.handle.sendline( "" )
3592 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003593
Jon Hall7eb38402015-01-08 17:19:54 -08003594 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003595 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003596
Jon Hall7eb38402015-01-08 17:19:54 -08003597 self.handle.sendline( "" )
3598 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003599
Jon Hallb1290e82014-11-18 16:17:48 -05003600 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003601 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003602 main.log.error( self.name + ": TIMEOUT exception found" )
3603 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003604 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003605 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003606 main.log.error( self.name + ": EOF exception found" )
3607 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003608 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003609 except Exception:
3610 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003611 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003612
Jon Halld80cc142015-07-06 13:36:05 -07003613 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003614 """
3615 Add vlan tag to a host.
3616 Dependencies:
3617 This class depends on the "vlan" package
3618 $ sudo apt-get install vlan
3619 Configuration:
3620 Load the 8021q module into the kernel
3621 $sudo modprobe 8021q
3622
3623 To make this setup permanent:
3624 $ sudo su -c 'echo "8021q" >> /etc/modules'
3625 """
3626 if self.handle:
3627 try:
Jon Halld80cc142015-07-06 13:36:05 -07003628 # get the ip address of the host
3629 main.log.info( "Get the ip address of the host" )
3630 ipaddr = self.getIPAddress( host )
3631 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003632
Jon Halld80cc142015-07-06 13:36:05 -07003633 # remove IP from interface intf
3634 # Ex: h1 ifconfig h1-eth0 inet 0
3635 main.log.info( "Remove IP from interface " )
3636 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3637 self.handle.sendline( cmd2 )
3638 self.handle.expect( "mininet>" )
3639 response = self.handle.before
3640 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003641
Jon Halld80cc142015-07-06 13:36:05 -07003642 # create VLAN interface
3643 # Ex: h1 vconfig add h1-eth0 100
3644 main.log.info( "Create Vlan" )
3645 cmd3 = host + " vconfig add " + intf + " " + vlan
3646 self.handle.sendline( cmd3 )
3647 self.handle.expect( "mininet>" )
3648 response = self.handle.before
3649 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003650
Jon Halld80cc142015-07-06 13:36:05 -07003651 # assign the host's IP to the VLAN interface
3652 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3653 main.log.info( "Assign the host IP to the vlan interface" )
3654 vintf = intf + "." + vlan
3655 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3656 self.handle.sendline( cmd4 )
3657 self.handle.expect( "mininet>" )
3658 response = self.handle.before
3659 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003660
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003661 # update Mininet node variables
3662 main.log.info( "Update Mininet node variables" )
3663 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3664 self.handle.sendline( cmd5 )
3665 self.handle.expect( "mininet>" )
3666 response = self.handle.before
3667 main.log.info( "====> %s ", response )
3668
3669 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3670 self.handle.sendline( cmd6 )
3671 self.handle.expect( "mininet>" )
3672 response = self.handle.before
3673 main.log.info( "====> %s ", response )
3674
3675 return main.TRUE
3676 except pexpect.TIMEOUT:
3677 main.log.error( self.name + ": TIMEOUT exception found" )
3678 main.log.error( self.name + ": " + self.handle.before )
3679 main.cleanAndExit()
3680 except pexpect.EOF:
3681 main.log.error( self.name + ": EOF exception found" )
3682 main.log.error( self.name + ": " + self.handle.before )
3683 return main.FALSE
3684 except Exception:
3685 main.log.exception( self.name + ": Uncaught exception!" )
3686 return main.FALSE
3687
3688 def removeVLAN( self, host, intf ):
3689 """
3690 Remove vlan tag from a host.
3691 Dependencies:
3692 This class depends on the "vlan" package
3693 $ sudo apt-get install vlan
3694 Configuration:
3695 Load the 8021q module into the kernel
3696 $sudo modprobe 8021q
3697
3698 To make this setup permanent:
3699 $ sudo su -c 'echo "8021q" >> /etc/modules'
3700 """
3701 if self.handle:
3702 try:
3703 # get the ip address of the host
3704 main.log.info( "Get the ip address of the host" )
3705 ipaddr = self.getIPAddress( host )
3706
3707 # remove VLAN interface
3708 # Ex: h1 vconfig rem h1-eth0.100
3709 main.log.info( "Remove Vlan interface" )
3710 cmd2 = host + " vconfig rem " + intf
3711 self.handle.sendline( cmd2 )
3712 self.handle.expect( "mininet>" )
3713 response = self.handle.before
3714 main.log.info( "====> %s ", response )
3715
3716 # assign the host's IP to the original interface
3717 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3718 main.log.info( "Assign the host IP to the original interface" )
3719 original_intf = intf.split(".")[0]
3720 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3721 self.handle.sendline( cmd3 )
3722 self.handle.expect( "mininet>" )
3723 response = self.handle.before
3724 main.log.info( "====> %s ", response )
3725
3726 # update Mininet node variables
3727 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3728 self.handle.sendline( cmd4 )
3729 self.handle.expect( "mininet>" )
3730 response = self.handle.before
3731 main.log.info( "====> %s ", response )
3732
3733 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3734 self.handle.sendline( cmd5 )
3735 self.handle.expect( "mininet>" )
3736 response = self.handle.before
3737 main.log.info( "====> %s ", response )
3738
kaouthera3f13ca22015-05-05 15:01:41 -07003739 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003740 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003741 main.log.error( self.name + ": TIMEOUT exception found" )
3742 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003743 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003744 except pexpect.EOF:
3745 main.log.error( self.name + ": EOF exception found" )
3746 main.log.error( self.name + ": " + self.handle.before )
3747 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003748 except Exception:
3749 main.log.exception( self.name + ": Uncaught exception!" )
3750 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003751
Jon Hall892818c2015-10-20 17:58:34 -07003752 def createHostComponent( self, name ):
3753 """
3754 Creates a new mininet cli component with the same parameters as self.
3755 This new component is intended to be used to login to the hosts created
3756 by mininet.
3757
3758 Arguments:
3759 name - The string of the name of this component. The new component
3760 will be assigned to main.<name> .
3761 In addition, main.<name>.name = str( name )
3762 """
3763 try:
3764 # look to see if this component already exists
3765 getattr( main, name )
3766 except AttributeError:
3767 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003768 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3769 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003770 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003771 except pexpect.EOF:
3772 main.log.error( self.name + ": EOF exception found" )
3773 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003774 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003775 except Exception:
3776 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003777 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003778 else:
3779 # namespace is not clear!
3780 main.log.error( name + " component already exists!" )
3781 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003782 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003783
3784 def removeHostComponent( self, name ):
3785 """
3786 Remove host component
3787 Arguments:
3788 name - The string of the name of the component to delete.
3789 """
3790 try:
3791 # Get host component
3792 component = getattr( main, name )
3793 except AttributeError:
3794 main.log.error( "Component " + name + " does not exist." )
3795 return
3796 try:
3797 # Disconnect from component
3798 component.disconnect()
You Wangf32c6ed2018-08-23 17:10:22 -07003799 component.close_log_handles()
Jon Hall892818c2015-10-20 17:58:34 -07003800 # Delete component
3801 delattr( main, name )
3802 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003803 del( main.componentDictionary[ name ] )
You Wangf32c6ed2018-08-23 17:10:22 -07003804 except StandardError:
3805 self.log.exception( "Exception while closing log files for " + name )
3806 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003807 except pexpect.EOF:
3808 main.log.error( self.name + ": EOF exception found" )
3809 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003810 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003811 except Exception:
3812 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003813 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003814
3815 def startHostCli( self, host=None ):
3816 """
3817 Use the mininet m utility to connect to the host's cli
3818 """
3819 # These are fields that can be used by scapy packets. Initialized to None
3820 self.hostIp = None
3821 self.hostMac = None
3822 try:
3823 if not host:
3824 host = self.name
3825 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003826 self.handle.sendline( "cd" )
3827 self.handle.expect( self.hostPrompt )
3828 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003829 self.handle.expect( self.hostPrompt )
3830 return main.TRUE
3831 except pexpect.TIMEOUT:
3832 main.log.exception( self.name + ": Command timed out" )
3833 return main.FALSE
3834 except pexpect.EOF:
3835 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003836 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003837 except Exception:
3838 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003839 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003840
YPZhang801d46d2016-08-08 13:26:28 -07003841 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003842 '''
3843
YPZhang801d46d2016-08-08 13:26:28 -07003844 Args:
3845 devicename: switch name
3846 intf: port name on switch
3847 status: up or down
3848
3849 Returns: boolean to show success change status
3850
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003851 '''
YPZhang801d46d2016-08-08 13:26:28 -07003852 if status == "down" or status == "up":
3853 try:
3854 cmd = devicename + " ifconfig " + intf + " " + status
3855 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003856 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003857 return main.TRUE
3858 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003859 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003860 return main.FALSE
3861 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003862 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003863 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003864 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003865 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003866 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003867 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003868 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003869 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003870 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003871 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003872 return main.FALSE
3873
You Wang6e5b48e2018-07-23 16:17:38 -07003874 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003875 """
You Wang6e5b48e2018-07-23 16:17:38 -07003876 Moves a host from one switch to another on the fly
3877 Optional:
3878 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3879 prefixLen: length of the host IP prefix
3880 ipv6: move an IPv6 host if True
3881 intfSuffix: suffix of the new interface after host movement
3882 vlan: vlan ID of the host. Use None for non-vlan host
3883 Note: The intf between host and oldSw when detached
3884 using detach(), will still show up in the 'net'
3885 cmd, because switch.detach() doesn't affect switch.intfs[]
3886 ( which is correct behavior since the interfaces
3887 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003888 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003889 if self.handle:
3890 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003891 newIntf = "%s-%s" % ( host, intfSuffix )
3892 commands = [
3893 # Bring link between oldSw-host down
3894 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3895 # Determine hostintf and Oldswitchintf
3896 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
3897 ]
3898 # Determine ip address of the host-oldSw interface
3899 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3900 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3901 commands += [
3902 # Determine mac address of the host-oldSw interface
3903 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3904 # Detach interface between oldSw-host
3905 "px " + oldSw + ".detach( sintf )",
3906 # Add link between host-newSw
3907 "py net.addLink(" + host + "," + newSw + ")",
3908 # Determine hostintf and Newswitchintf
3909 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3910 # Attach interface between newSw-host
3911 "px " + newSw + ".attach( sintf )",
3912 ]
3913 if vlan:
3914 vlanIntf = "%s.%s" % ( newIntf, vlan )
3915 commands += [
3916 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
3917 host + " ip link set up %s" % vlanIntf,
3918 "px hintf.name = '" + vlanIntf + "'",
3919 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
3920 ]
3921 newIntf = vlanIntf
3922 commands += [
3923 # Set mac address of the host-newSw interface
3924 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
3925 # Set IP address of the host-newSw interface
3926 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
3927 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
3928 ]
3929 if ipv6:
3930 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
3931 commands += [
3932 "net",
3933 host + " ifconfig"
3934 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003935 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003936 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003937 self.handle.sendline( cmd )
3938 self.handle.expect( "mininet>" )
3939 main.log.info( "====> %s ", self.handle.before )
3940 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003941 except pexpect.TIMEOUT:
3942 main.log.error( self.name + ": TIMEOUT exception found" )
3943 main.log.error( self.name + ": " + self.handle.before )
3944 main.cleanAndExit()
3945 except pexpect.EOF:
3946 main.log.error( self.name + ": EOF exception found" )
3947 main.log.error( self.name + ": " + self.handle.before )
3948 return main.FALSE
3949 except Exception:
3950 main.log.exception( self.name + ": Uncaught exception!" )
3951 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07003952
You Wang6e5b48e2018-07-23 16:17:38 -07003953 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
3954 macAddr=None, prefixLen=None, ipv6=False,
3955 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07003956 """
You Wang6e5b48e2018-07-23 16:17:38 -07003957 Moves a dual-homed host from one switch-pair to another pair on the fly
3958 Optional:
3959 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3960 prefixLen: length of the host IP prefix
3961 ipv6: move an IPv6 host if True
3962 intfSuffix1: suffix of the first new interface
3963 intfSuffix2: suffix of the second new interface
3964 bondSuffix: suffix of the new bond interface
3965 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07003966 """
You Wang7ea90582018-07-19 15:27:58 -07003967 if self.handle:
3968 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003969 bondIntf = "%s-%s" % ( host, bondSuffix )
3970 newIntf = "%s-%s" % ( host, intfSuffix1 )
3971 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07003972 commands = [
3973 # Bring link between oldSw-host down
3974 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3975 # Bring link between oldPairSw-host down
3976 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
3977 # Determine hostintf and Oldswitchintf
3978 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07003979 ]
3980 # Determine ip address of the host-oldSw interface
3981 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3982 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3983 commands += [
3984 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07003985 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3986 # Detach interface between oldSw-host
3987 "px " + oldSw + ".detach( sintf )",
3988 # Determine hostintf and Oldpairswitchintf
3989 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
3990 # Detach interface between oldPairSw-host
3991 "px " + oldPairSw + ".detach( sintfpair )",
3992 # Add link between host-newSw
3993 "py net.addLink(" + host + "," + newSw + ", 2)",
3994 # Add link between host-newPairSw
3995 "py net.addLink(" + host + "," + newPairSw + ")",
3996 # Determine hostintf and Newswitchintf
3997 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3998 # Determine hostintf and NewPairswitchintf
3999 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
4000 # Attach interface between newSw-host
4001 "px " + newSw + ".attach( sintf )",
4002 # Attach interface between newPairSw-host
4003 "px " + newPairSw + ".attach( sintfpair )",
4004 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07004005 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004006 host + ' ip link set %s down' % newIntf,
4007 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004008 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
4009 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07004010 host + ' ip addr flush dev %s' % newIntf,
4011 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004012 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004013 "px lowestIntf = min( [ hintf, hintfpair ] )",
4014 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07004015 "px lowestIntf.name = '" + bondIntf + "'",
4016 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07004017 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
4018 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07004019 ]
4020 if vlan:
4021 vlanIntf = "%s.%s" % ( bondIntf, vlan )
4022 commands += [
4023 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
4024 host + " ip link set up %s" % vlanIntf,
4025 "px lowestIntf.name = '" + vlanIntf + "'",
4026 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
4027 ]
4028 bondIntf = vlanIntf
4029 commands += [
4030 # Set macaddress of the host-newSw interface
4031 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07004032 # Set ipaddress of the host-newSw interface
4033 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
4034 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07004035 ]
You Wang6e5b48e2018-07-23 16:17:38 -07004036 if ipv6:
4037 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
4038 commands += [
4039 "net",
4040 host + " ifconfig"
4041 ]
You Wang7ea90582018-07-19 15:27:58 -07004042 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004043 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07004044 self.handle.sendline( cmd )
4045 self.handle.expect( "mininet>" )
4046 main.log.info( "====> %s ", self.handle.before )
4047 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07004048 except pexpect.TIMEOUT:
4049 main.log.error( self.name + ": TIMEOUT exception found" )
4050 main.log.error( self.name + ": " + self.handle.before )
4051 main.cleanAndExit()
4052 except pexpect.EOF:
4053 main.log.error( self.name + ": EOF exception found" )
4054 main.log.error( self.name + ": " + self.handle.before )
4055 return main.FALSE
4056 except Exception:
4057 main.log.exception( self.name + ": Uncaught exception!" )
4058 return main.FALSE
4059
adminbae64d82013-08-01 10:50:15 -07004060if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004061 sys.modules[ __name__ ] = MininetCliDriver()