blob: 826fc8ce129ca6079f224fd82800ae44cc7ff6b6 [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 Wang036ec2c2019-02-27 15:44:15 -0800598 cmds = []
You Wang48381752018-05-07 13:50:57 -0700599 if self.getIPAddress( host ):
You Wang0b82aa52018-06-06 14:33:58 -0700600 flushCmd = "{} ip neigh flush all".format( host )
You Wang036ec2c2019-02-27 15:44:15 -0800601 cmds.append( "{} arping -c 1 -w {} {}".format( host, wait, dstIp ) )
You Wang32833172018-10-23 15:19:31 -0700602 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 Wang036ec2c2019-02-27 15:44:15 -0800605 # FIXME: we are using the same ipv6Addr for all interfaces
606 ipv6Addr = self.getIPAddress( host, proto='IPV6' )
You Wangad347c92019-02-20 16:13:47 -0800607 for intf in hosts[ host ][ 'interfaces' ]:
608 intfName = intf[ 'name' ]
You Wang036ec2c2019-02-27 15:44:15 -0800609 cmds.append( "{} ndsend {} {}".format( host, ipv6Addr, intfName ) )
You Wangad347c92019-02-20 16:13:47 -0800610 main.log.debug( "Sending IPv6 ND from interface {} on host {}".format( intfName, host ) )
You Wang48381752018-05-07 13:50:57 -0700611 else:
612 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
613 discoveryResult = main.FALSE
You Wang036ec2c2019-02-27 15:44:15 -0800614 if flushCmd:
You Wang0b82aa52018-06-06 14:33:58 -0700615 self.handle.sendline( flushCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700616 self.handle.expect( "mininet>" )
You Wang036ec2c2019-02-27 15:44:15 -0800617 for cmd in cmds:
You Wang48381752018-05-07 13:50:57 -0700618 self.handle.sendline( cmd )
Jon Halla604fd42018-05-04 14:27:27 -0700619 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700620 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700621 except pexpect.TIMEOUT:
622 main.log.exception( self.name + ": TIMEOUT exception" )
623 response = self.handle.before
624 # NOTE: Send ctrl-c to make sure command is stopped
625 self.handle.send( "\x03" )
626 self.handle.expect( "Interrupt" )
627 response += self.handle.before + self.handle.after
628 self.handle.expect( "mininet>" )
629 response += self.handle.before + self.handle.after
630 main.log.debug( response )
631 return main.FALSE
632 except pexpect.EOF:
633 main.log.error( self.name + ": EOF exception found" )
634 main.log.error( self.name + ": " + self.handle.before )
635 main.cleanAndExit()
636 except Exception:
637 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800638 main.cleanAndExit()
639
640 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
641 """
642 Verify ping from each host in srcList to each host in dstList
643
644 acceptableFailed: max number of acceptable failed pings
645
646 Returns main.TRUE if all src hosts can reach all dst hosts
647 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
648 """
649 try:
650 main.log.info( "Verifying ping from each src host to each dst host" )
651 isReachable = main.TRUE
652 wait = int( wait )
653 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
654 pingResponse = "Ping output:\n"
655 failedPingsTotal = 0
656 for host in srcList:
657 pingResponse += str( str( host ) + " -> " )
658 for temp in dstList:
659 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700660 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
661 assert dstIP, "Not able to get IP address of host {}".format( temp )
662 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800663 while failedPings <= acceptableFailed:
664 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
665 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700666 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800667 response = self.handle.before
668 if re.search( ',\s0\%\spacket\sloss', response ):
669 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800670 break
671 else:
672 failedPings += 1
673 time.sleep(1)
674 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700675 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800676 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700677 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800678 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700679 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800680 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700681 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700682 except AssertionError:
683 main.log.exception( "" )
684 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700685 except pexpect.TIMEOUT:
686 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800687 response = self.handle.before
688 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700689 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800690 self.handle.expect( "Interrupt" )
691 response += self.handle.before + self.handle.after
692 self.handle.expect( "mininet>" )
693 response += self.handle.before + self.handle.after
694 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700695 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700696 except pexpect.EOF:
697 main.log.error( self.name + ": EOF exception found" )
698 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700699 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700700 except Exception:
701 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700702 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700703
Jon Hall7eb38402015-01-08 17:19:54 -0800704 def pingHost( self, **pingParams ):
705 """
Jon Hall3b489db2015-10-05 14:38:37 -0700706 Ping from one mininet host to another
707 Currently the only supported Params: SRC, TARGET, and WAIT
708 """
709 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700710 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700711 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800712 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700713 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700714 try:
Jon Hall61282e32015-03-19 11:34:11 -0700715 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800716 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700717 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700718 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700719 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800720 main.log.error(
721 self.name +
722 ": timeout when waiting for response from mininet" )
723 main.log.error( "response: " + str( self.handle.before ) )
724 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700725 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800726 main.log.error(
727 self.name +
728 ": timeout when waiting for response from mininet" )
729 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700730 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700731 if re.search( ',\s0\%\spacket\sloss', response ):
732 main.log.info( self.name + ": no packets lost, host is reachable" )
733 return main.TRUE
734 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800735 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700736 self.name +
737 ": PACKET LOST, HOST IS NOT REACHABLE" )
738 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800739 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800740 main.log.error( self.name + ": EOF exception found" )
741 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700742 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700743 except Exception:
744 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700745 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700746
747 def ping6pair( self, **pingParams ):
748 """
GlennRC2cf7d952015-09-11 16:32:13 -0700749 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700750 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000751 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700752 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
753 """
Jon Hall3b489db2015-10-05 14:38:37 -0700754 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700755 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700756 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530757 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700758 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700759 try:
760 main.log.info( "Sending: " + command )
761 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700762 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700763 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700764 if i == 1:
765 main.log.error(
766 self.name +
767 ": timeout when waiting for response from mininet" )
768 main.log.error( "response: " + str( self.handle.before ) )
769 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
770 if i == 1:
771 main.log.error(
772 self.name +
773 ": timeout when waiting for response from mininet" )
774 main.log.error( "response: " + str( self.handle.before ) )
775 response = self.handle.before
776 main.log.info( self.name + ": Ping Response: " + response )
777 if re.search( ',\s0\%\spacket\sloss', response ):
778 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700779 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700780 else:
alisone4121a92016-11-22 16:31:36 -0800781 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700782 self.name +
783 ": PACKET LOST, HOST IS NOT REACHABLE" )
784 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700785 except pexpect.EOF:
786 main.log.error( self.name + ": EOF exception found" )
787 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700788 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700789 except Exception:
790 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700791 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800792
You Wangdb927a52016-02-26 11:03:28 -0800793 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
794 """
795 Description:
796 Ping a set of destination host from host CLI.
797 Logging into a Mininet host CLI is required before calling this funtion.
798 Params:
799 dstIPList is a list of destination ip addresses
800 Returns:
801 main.TRUE if the destination host is reachable
802 main.FALSE otherwise
803 """
804 isReachable = main.TRUE
805 wait = int( wait )
806 cmd = "ping"
807 if IPv6:
808 cmd = cmd + "6"
809 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
810 try:
811 for dstIP in dstIPList:
812 pingCmd = cmd + " " + dstIP
813 self.handle.sendline( pingCmd )
814 i = self.handle.expect( [ self.hostPrompt,
815 '\*\*\* Unknown command: ' + pingCmd,
816 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700817 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700818 # For some reason we need to send something
819 # Otherwise ping results won't be read by handle
820 self.handle.sendline( "" )
821 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800822 if i == 0:
823 response = self.handle.before
824 if not re.search( ',\s0\%\spacket\sloss', response ):
825 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
826 isReachable = main.FALSE
827 elif i == 1:
828 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700829 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800830 elif i == 2:
831 main.log.error( self.name + ": timeout when waiting for response" )
832 isReachable = main.FALSE
833 else:
834 main.log.error( self.name + ": unknown response: " + self.handle.before )
835 isReachable = main.FALSE
836 except pexpect.TIMEOUT:
837 main.log.exception( self.name + ": TIMEOUT exception" )
You Wangd4fae5c2018-08-22 13:56:49 -0700838 self.exitFromCmd( [ self.hostPrompt, self.bashPrompt ] )
You Wangdb927a52016-02-26 11:03:28 -0800839 isReachable = main.FALSE
840 except pexpect.EOF:
841 main.log.error( self.name + ": EOF exception found" )
842 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700843 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800844 except Exception:
845 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700846 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800847 return isReachable
848
Jon Hall7eb38402015-01-08 17:19:54 -0800849 def checkIP( self, host ):
850 """
851 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700852 try:
853 if self.handle:
854 try:
855 response = self.execute(
856 cmd=host +
857 " ifconfig",
858 prompt="mininet>",
859 timeout=10 )
860 except pexpect.EOF:
861 main.log.error( self.name + ": EOF exception found" )
862 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700863 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700864
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700865 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
866 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
867 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
868 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
869 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
870 "[0-9]|25[0-5]|[0-9]{1,2})"
871 # pattern = "inet addr:10.0.0.6"
872 if re.search( pattern, response ):
873 main.log.info( self.name + ": Host Ip configured properly" )
874 return main.TRUE
875 else:
876 main.log.error( self.name + ": Host IP not found" )
877 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700878 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700879 main.log.error( self.name + ": Connection failed to the host" )
880 except Exception:
881 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700882 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800883
Jon Hall7eb38402015-01-08 17:19:54 -0800884 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800885 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700886 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800887 response = self.execute(
888 cmd="h1 /usr/sbin/sshd -D&",
889 prompt="mininet>",
890 timeout=10 )
891 response = self.execute(
892 cmd="h4 /usr/sbin/sshd -D&",
893 prompt="mininet>",
894 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700895 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800896 vars( self )[ key ] = connectargs[ key ]
897 response = self.execute(
898 cmd="xterm h1 h4 ",
899 prompt="mininet>",
900 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800901 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800902 main.log.error( self.name + ": EOF exception found" )
903 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700904 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700905 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800906 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700907 if self.flag == 0:
908 self.flag = 1
909 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800910 else:
adminbae64d82013-08-01 10:50:15 -0700911 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800912
Jon Hall7eb38402015-01-08 17:19:54 -0800913 def changeIP( self, host, intf, newIP, newNetmask ):
914 """
915 Changes the ip address of a host on the fly
916 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800917 if self.handle:
918 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800919 cmd = host + " ifconfig " + intf + " " + \
920 newIP + " " + 'netmask' + " " + newNetmask
921 self.handle.sendline( cmd )
922 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800923 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800924 main.log.info( "response = " + response )
925 main.log.info(
926 "Ip of host " +
927 host +
928 " changed to new IP " +
929 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800930 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700931 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700932 main.log.error( self.name + ": TIMEOUT exception found" )
933 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700934 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800935 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800936 main.log.error( self.name + ": EOF exception found" )
937 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800938 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700939 except Exception:
940 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700941 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800942
Jon Hall7eb38402015-01-08 17:19:54 -0800943 def changeDefaultGateway( self, host, newGW ):
944 """
945 Changes the default gateway of a host
946 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800947 if self.handle:
948 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800949 cmd = host + " route add default gw " + newGW
950 self.handle.sendline( cmd )
951 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800952 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800953 main.log.info( "response = " + response )
954 main.log.info(
955 "Default gateway of host " +
956 host +
957 " changed to " +
958 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800959 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700960 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700961 main.log.error( self.name + ": TIMEOUT exception found" )
962 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700963 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800964 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800965 main.log.error( self.name + ": EOF exception found" )
966 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800967 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700968 except Exception:
969 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700970 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800971
You Wange24d6272018-03-27 21:18:50 -0700972 def addRoute( self, host, dstIP, interface, ipv6=False ):
973 """
974 Add a route to host
975 Ex: h1 route add -host 224.2.0.1 h1-eth0
976 """
977 if self.handle:
978 try:
979 cmd = str( host )
980 if ipv6:
981 cmd += " route -A inet6 add "
982 else:
983 cmd += " route add -host "
984 cmd += str( dstIP ) + " " + str( interface )
985 self.handle.sendline( cmd )
986 self.handle.expect( "mininet>" )
987 response = self.handle.before
988 main.log.debug( "response = " + response )
989 return main.TRUE
990 except pexpect.TIMEOUT:
991 main.log.error( self.name + ": TIMEOUT exception found" )
992 main.log.error( self.name + ": " + self.handle.before )
993 main.cleanAndExit()
994 except pexpect.EOF:
995 main.log.error( self.name + ": EOF exception found" )
996 main.log.error( self.name + ": " + self.handle.before )
997 return main.FALSE
998 except Exception:
999 main.log.exception( self.name + ": Uncaught exception!" )
1000 main.cleanAndExit()
1001
Jon Hall7eb38402015-01-08 17:19:54 -08001002 def addStaticMACAddress( self, host, GW, macaddr ):
1003 """
Jon Hallefbd9792015-03-05 16:11:36 -08001004 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001005 if self.handle:
1006 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001007 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1008 cmd = host + " arp -s " + GW + " " + macaddr
1009 self.handle.sendline( cmd )
1010 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001011 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001012 main.log.info( "response = " + response )
1013 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001014 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001015 GW +
1016 " changed to " +
1017 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001018 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001019 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001020 main.log.error( self.name + ": TIMEOUT exception found" )
1021 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001022 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001023 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001024 main.log.error( self.name + ": EOF exception found" )
1025 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001026 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001027 except Exception:
1028 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001029 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001030
Jon Hall7eb38402015-01-08 17:19:54 -08001031 def verifyStaticGWandMAC( self, host ):
1032 """
1033 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001034 if self.handle:
1035 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001036 # h1 arp -an
1037 cmd = host + " arp -an "
1038 self.handle.sendline( cmd )
1039 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001040 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001041 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001042 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001043 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001044 main.log.error( self.name + ": TIMEOUT exception found" )
1045 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001046 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001047 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001048 main.log.error( self.name + ": EOF exception found" )
1049 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001050 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001051 except Exception:
1052 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001053 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001054
Jon Hall7eb38402015-01-08 17:19:54 -08001055 def getMacAddress( self, host ):
1056 """
1057 Verifies the host's ip configured or not."""
1058 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001059 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001060 response = self.execute(
1061 cmd=host +
1062 " ifconfig",
1063 prompt="mininet>",
1064 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001065 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001066 main.log.error( self.name + ": EOF exception found" )
1067 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001068 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001069 except Exception:
1070 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001071 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001072
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001073 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001074 macAddressSearch = re.search( pattern, response, re.I )
1075 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001076 main.log.info(
1077 self.name +
1078 ": Mac-Address of Host " +
1079 host +
1080 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001081 macAddress )
1082 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001083 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001084 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001085
Jon Hall7eb38402015-01-08 17:19:54 -08001086 def getInterfaceMACAddress( self, host, interface ):
1087 """
1088 Return the IP address of the interface on the given host"""
1089 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001090 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001091 response = self.execute( cmd=host + " ifconfig " + interface,
1092 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001093 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001094 main.log.error( self.name + ": EOF exception found" )
1095 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001096 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001097 except Exception:
1098 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001099 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001100
1101 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001102 macAddressSearch = re.search( pattern, response, re.I )
1103 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001104 main.log.info( "No mac address found in %s" % response )
1105 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001106 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001107 main.log.info(
1108 "Mac-Address of " +
1109 host +
1110 ":" +
1111 interface +
1112 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001113 macAddress )
1114 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001115 else:
1116 main.log.error( "Connection failed to the host" )
1117
You Wang5da39c82018-04-26 22:55:08 -07001118 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001119 """
1120 Verifies the host's ip configured or not."""
1121 if self.handle:
1122 try:
1123 response = self.execute(
1124 cmd=host +
1125 " ifconfig",
1126 prompt="mininet>",
1127 timeout=10 )
1128 except pexpect.EOF:
1129 main.log.error( self.name + ": EOF exception found" )
1130 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001131 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001132 except Exception:
1133 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001134 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001135
sathishmad953462015-12-03 17:42:07 +05301136 pattern = ''
1137 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001138 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301139 else:
Jon Hall439c8912016-04-15 02:22:03 -07001140 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001141 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001142 if not ipAddressSearch:
1143 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001144 main.log.info(
1145 self.name +
1146 ": IP-Address of Host " +
1147 host +
1148 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001149 ipAddressSearch.group( 1 ) )
1150 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001151 else:
1152 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001153
Jon Hall7eb38402015-01-08 17:19:54 -08001154 def getSwitchDPID( self, switch ):
1155 """
1156 return the datapath ID of the switch"""
1157 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001158 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001159 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001160 response = self.execute(
1161 cmd=cmd,
1162 prompt="mininet>",
1163 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001164 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001165 main.log.error( self.name + ": EOF exception found" )
1166 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001167 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001168 except Exception:
1169 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001170 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001171 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001172 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001173 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001174 main.log.info(
1175 "Couldn't find DPID for switch %s, found: %s" %
1176 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001177 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001178 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001179 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001180 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001181
Jon Hall7eb38402015-01-08 17:19:54 -08001182 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001183 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001184 self.handle.sendline( "" )
1185 self.expect( "mininet>" )
1186 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001187 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001188 response = self.execute(
1189 cmd=cmd,
1190 prompt="mininet>",
1191 timeout=10 )
1192 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001193 response = self.handle.before
1194 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001195 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001196 main.log.error( self.name + ": TIMEOUT exception found" )
1197 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001198 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001199 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001200 main.log.error( self.name + ": EOF exception found" )
1201 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001202 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001203 except Exception:
1204 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001205 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001206
Jon Hall7eb38402015-01-08 17:19:54 -08001207 def getInterfaces( self, node ):
1208 """
1209 return information dict about interfaces connected to the node"""
1210 if self.handle:
1211 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001212 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001213 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001214 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001215 response = self.execute(
1216 cmd=cmd,
1217 prompt="mininet>",
You Wang7d14d642019-01-23 15:10:08 -08001218 timeout=10,
1219 logCmd=False )
Jon Hallfbc828e2015-01-06 17:30:19 -08001220 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001221 main.log.error( self.name + ": EOF exception found" )
1222 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001223 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001224 except Exception:
1225 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001226 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001227 return response
1228 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001229 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001230
Jon Hall7eb38402015-01-08 17:19:54 -08001231 def dump( self ):
1232 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001233 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001234 response = self.execute(
1235 cmd='dump',
1236 prompt='mininet>',
1237 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001238 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001239 main.log.error( self.name + ": EOF exception found" )
1240 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001241 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001242 except Exception:
1243 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001244 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001245 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001246
Jon Hall7eb38402015-01-08 17:19:54 -08001247 def intfs( self ):
1248 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001249 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001250 response = self.execute(
1251 cmd='intfs',
1252 prompt='mininet>',
1253 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001254 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001255 main.log.error( self.name + ": EOF exception found" )
1256 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001257 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001258 except Exception:
1259 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001260 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001261 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001262
Jon Hall7eb38402015-01-08 17:19:54 -08001263 def net( self ):
1264 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001265 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001266 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001267 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001268 main.log.error( self.name + ": EOF exception found" )
1269 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001270 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001271 except Exception:
1272 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001273 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001274 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001275
Devin Lima7cfdbd2017-09-29 15:02:22 -07001276 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001277 main.log.info( self.name + ": List network links" )
1278 try:
1279 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001280 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001281 except pexpect.EOF:
1282 main.log.error( self.name + ": EOF exception found" )
1283 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001284 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001285 except Exception:
1286 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001287 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001288 return response
1289
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001290 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001291 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001292 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001293
kelvin-onlab7cce9382015-07-17 10:21:03 -07001294 @parm:
1295 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1296 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001297 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001298 try:
1299 for host1 in hosts:
1300 for host2 in hosts:
1301 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001302 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1303 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001304 except Exception:
1305 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001306 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001307
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001308 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001309 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001310 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1311 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001312
kelvin-onlab7cce9382015-07-17 10:21:03 -07001313 @parm:
1314 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1315 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001316 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001317 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1318 try:
1319 # Setup the mininet command
1320 cmd1 = 'iperf ' + host1 + " " + host2
1321 self.handle.sendline( cmd1 )
1322 outcome = self.handle.expect( "mininet>", timeout )
1323 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001324
kelvin-onlab7cce9382015-07-17 10:21:03 -07001325 # checks if there are results in the mininet response
1326 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001327 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001328 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001329 response = response.split( "\r\n" )
1330 response = response[ len( response )-2 ]
1331 response = response.split( ": " )
1332 response = response[ len( response )-1 ]
1333 response = response.replace( "[", "" )
1334 response = response.replace( "]", "" )
1335 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001336
kelvin-onlab7cce9382015-07-17 10:21:03 -07001337 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001338 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001339
kelvin-onlab7cce9382015-07-17 10:21:03 -07001340 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001341 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001342 if len( bandwidth ) == 2:
1343 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001344 return main.TRUE
1345 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001346 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001347 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001348 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001349 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001350 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001351 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001352 main.log.error( self.name + ": TIMEOUT exception found" )
1353 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001354 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001355 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001356 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001357 self.handle.expect( "Interrupt" )
1358 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001359 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001360 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001361 main.log.error( self.name + ": EOF exception found" )
1362 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001363 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001364 except Exception:
1365 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001366 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001367
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001368 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001369 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1370 try:
1371 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001372 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001373 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001374 outcome1 = self.handle.expect( "mininet>" )
1375 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001376 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001377 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001378 response1 = self.handle.before
1379 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001380 print response1, response2
1381 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001382 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001383 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001384 return main.TRUE
1385 else:
1386 main.log.error( self.name + ": iperf test failed" )
1387 return main.FALSE
1388 except pexpect.TIMEOUT:
1389 main.log.error( self.name + ": TIMEOUT exception found" )
1390 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001391 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001392 self.handle.expect( "Interrupt" )
1393 self.handle.expect( "mininet>" )
1394 return main.FALSE
1395 except pexpect.EOF:
1396 main.log.error( self.name + ": EOF exception found" )
1397 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001398 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001399 except Exception:
1400 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001401 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001402
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001403 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001404 '''
GlennRC61321f22015-07-16 13:36:54 -07001405 Runs the iperfudp function with a given set of hosts and specified
1406 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001407
GlennRC61321f22015-07-16 13:36:54 -07001408 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001409 bandwidth: the targeted bandwidth, in megabits ('M')
1410 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001411 try:
1412 for host1 in hosts:
1413 for host2 in hosts:
1414 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001415 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1416 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001417 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001418 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001419 return main.FALSE
1420 except Exception:
1421 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001422 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001423
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001424 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001425 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001426 Creates an iperf UDP test with a specific bandwidth.
1427 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001428
kelvin-onlab7cce9382015-07-17 10:21:03 -07001429 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001430 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1431 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001432 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001433 try:
1434 # setup the mininet command
1435 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001436 self.handle.sendline( cmd )
1437 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001438 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001439
kelvin-onlab7cce9382015-07-17 10:21:03 -07001440 # check if there are in results in the mininet response
1441 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001442 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001443 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001444 response = response.split( "\r\n" )
1445 response = response[ len( response )-2 ]
1446 response = response.split( ": " )
1447 response = response[ len( response )-1 ]
1448 response = response.replace( "[", "" )
1449 response = response.replace( "]", "" )
1450 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001451
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001452 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001453
kelvin-onlab7cce9382015-07-17 10:21:03 -07001454 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001455 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001456 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001457 # if one entry is blank then something is wrong
1458 for item in mnBandwidth:
1459 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001460 main.log.error( self.name + ": Could not parse iperf output" )
1461 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001462 return main.FALSE
1463 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001464 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001465 return main.TRUE
1466 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001467 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001468 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001469
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001470 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001471 main.log.error( self.name + ": TIMEOUT exception found" )
1472 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001473 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001474 except pexpect.EOF:
1475 main.log.error( self.name + ": EOF exception found" )
1476 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001477 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001478 except Exception:
1479 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001480 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001481
Jon Hall7eb38402015-01-08 17:19:54 -08001482 def nodes( self ):
1483 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001484 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001485 response = self.execute(
1486 cmd='nodes',
1487 prompt='mininet>',
1488 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001489 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001490 main.log.error( self.name + ": EOF exception found" )
1491 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001492 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001493 except Exception:
1494 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001495 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001496 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001497
Jon Hall7eb38402015-01-08 17:19:54 -08001498 def pingpair( self ):
1499 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001500 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001501 response = self.execute(
1502 cmd='pingpair',
1503 prompt='mininet>',
1504 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001505 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001506 main.log.error( self.name + ": EOF exception found" )
1507 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001508 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001509 except Exception:
1510 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001511 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001512
Jon Hall7eb38402015-01-08 17:19:54 -08001513 if re.search( ',\s0\%\spacket\sloss', response ):
1514 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001515 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001516 else:
alisone4121a92016-11-22 16:31:36 -08001517 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001518 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001519
Jon Hall7eb38402015-01-08 17:19:54 -08001520 def link( self, **linkargs ):
1521 """
GlennRCed771242016-01-13 17:02:47 -08001522 Bring link( s ) between two nodes up or down
1523 """
Jon Hall6094a362014-04-11 14:46:56 -07001524 try:
GlennRCed771242016-01-13 17:02:47 -08001525 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1526 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1527 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1528 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1529
1530 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1531 cmd = "link {} {} {}".format( end1, end2, option )
1532 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001533 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001534 response = self.handle.before
1535 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001536 if "not in network" in response:
1537 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1538 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001539 return main.TRUE
1540 except pexpect.TIMEOUT:
1541 main.log.exception( self.name + ": Command timed out" )
1542 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001543 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001544 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001545 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001546 except Exception:
1547 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001548 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001549
pingping-lin8244a3b2015-09-16 13:36:56 -07001550 def switch( self, **switchargs ):
1551 """
1552 start/stop a switch
1553 """
1554 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1555 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1556 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1557 command = "switch " + str( sw ) + " " + str( option )
1558 main.log.info( command )
1559 try:
1560 self.handle.sendline( command )
1561 self.handle.expect( "mininet>" )
1562 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001563 main.log.error( self.name + ": TIMEOUT exception found" )
1564 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001565 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001566 except pexpect.EOF:
1567 main.log.error( self.name + ": EOF exception found" )
1568 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001569 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001570 return main.TRUE
1571
pingping-lin5bb663b2015-09-24 11:47:50 -07001572 def node( self, nodeName, commandStr ):
1573 """
1574 Carry out a command line on a given node
1575 @parm:
1576 nodeName: the node name in Mininet testbed
1577 commandStr: the command line will be carried out on the node
1578 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1579 """
1580 command = str( nodeName ) + " " + str( commandStr )
1581 main.log.info( command )
1582
1583 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001584 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001585 if re.search( "Unknown command", response ):
1586 main.log.warn( response )
1587 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001588 if re.search( "Permission denied", response ):
1589 main.log.warn( response )
1590 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001591 except pexpect.EOF:
1592 main.log.error( self.name + ": EOF exception found" )
1593 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001594 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001595 main.log.info( " response is :" )
1596 main.log.info( response )
1597 return response
1598
Jon Hall7eb38402015-01-08 17:19:54 -08001599 def yank( self, **yankargs ):
1600 """
1601 yank a mininet switch interface to a host"""
1602 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001603 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001604 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1605 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001606 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001607 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001608 response = self.execute(
1609 cmd=command,
1610 prompt="mininet>",
1611 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001612 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001613 main.log.error( self.name + ": EOF exception found" )
1614 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001615 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001616 except Exception:
1617 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001618 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001619 return main.TRUE
1620
Jon Hall7eb38402015-01-08 17:19:54 -08001621 def plug( self, **plugargs ):
1622 """
1623 plug the yanked mininet switch interface to a switch"""
1624 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001625 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001626 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1627 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001628 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001629 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001630 response = self.execute(
1631 cmd=command,
1632 prompt="mininet>",
1633 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001634 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001635 main.log.error( self.name + ": EOF exception found" )
1636 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001637 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001638 except Exception:
1639 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001640 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001641 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001642
Jon Hall7eb38402015-01-08 17:19:54 -08001643 def dpctl( self, **dpctlargs ):
1644 """
1645 Run dpctl command on all switches."""
1646 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001647 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001648 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1649 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1650 command = "dpctl " + cmd + " " + str( cmdargs )
1651 try:
1652 response = self.execute(
1653 cmd=command,
1654 prompt="mininet>",
1655 timeout=10 )
1656 except pexpect.EOF:
1657 main.log.error( self.name + ": EOF exception found" )
1658 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001659 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001660 except Exception:
1661 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001662 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001663 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001664
kelvin-onlabd3b64892015-01-20 13:26:24 -08001665 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001666 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001667 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001668 try:
1669 fileInput = path + '/lib/Mininet/INSTALL'
1670 version = super( Mininet, self ).getVersion()
1671 pattern = 'Mininet\s\w\.\w\.\w\w*'
1672 for line in open( fileInput, 'r' ).readlines():
1673 result = re.match( pattern, line )
1674 if result:
1675 version = result.group( 0 )
1676 return version
1677 except Exception:
1678 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001679 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001680
kelvin-onlabd3b64892015-01-20 13:26:24 -08001681 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001682 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001683 Parameters:
1684 sw: The name of an OVS switch. Example "s1"
1685 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001686 The output of the command from the mininet cli
1687 or main.FALSE on timeout"""
1688 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001689 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001690 response = self.execute(
1691 cmd=command,
1692 prompt="mininet>",
1693 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001694 if response:
Jon Hallab611372018-02-21 15:26:05 -08001695 if "no bridge named" in response:
1696 main.log.error( self.name + ": Error in getSwController: " +
1697 self.handle.before )
1698 return main.FALSE
1699 else:
1700 return response
admin2a9548d2014-06-17 14:08:07 -07001701 else:
1702 return main.FALSE
1703 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001704 main.log.error( self.name + ": EOF exception found" )
1705 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001706 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001707 except Exception:
1708 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001709 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001710
Charles Chan029be652015-08-24 01:46:10 +08001711 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001712 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001713 Description:
1714 Assign switches to the controllers ( for ovs use only )
1715 Required:
1716 sw - Name of the switch. This can be a list or a string.
1717 ip - Ip addresses of controllers. This can be a list or a string.
1718 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001719 port - ONOS use port 6653, if no list of ports is passed, then
1720 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001721 ptcp - ptcp number, This can be a string or a list that has
1722 the same length as switch. This is optional and not required
1723 when using ovs switches.
1724 NOTE: If switches and ptcp are given in a list type they should have the
1725 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1726 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001727
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001728 Return:
1729 Returns main.TRUE if mininet correctly assigned switches to
1730 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001731 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001732 """
1733 assignResult = main.TRUE
1734 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001735 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001736 command = "sh ovs-vsctl set-controller "
1737 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001738 try:
1739 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001740 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001741 if isinstance( port, types.StringType ) or \
1742 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001743 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001744 elif isinstance( port, types.ListType ):
1745 main.log.error( self.name + ": Only one controller " +
1746 "assigned and a list of ports has" +
1747 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001748 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001749 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001750 main.log.error( self.name + ": Invalid controller port " +
1751 "number. Please specify correct " +
1752 "controller port" )
1753 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001754
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001755 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001756 if isinstance( port, types.StringType ) or \
1757 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001758 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001759 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1760 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001761 elif isinstance( port, types.ListType ):
1762 if ( len( ip ) != len( port ) ):
1763 main.log.error( self.name + ": Port list = " +
1764 str( len( port ) ) +
1765 "should be the same as controller" +
1766 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001767 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001768 else:
1769 onosIp = ""
1770 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001771 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1772 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001773 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001774 main.log.error( self.name + ": Invalid controller port " +
1775 "number. Please specify correct " +
1776 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001777 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001778 else:
1779 main.log.error( self.name + ": Invalid ip address" )
1780 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001781
1782 if isinstance( sw, types.StringType ):
1783 command += sw + " "
1784 if ptcp:
1785 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001786 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001787 elif isinstance( ptcp, types.ListType ):
1788 main.log.error( self.name + ": Only one switch is " +
1789 "being set and multiple PTCP is " +
1790 "being passed " )
1791 else:
1792 main.log.error( self.name + ": Invalid PTCP" )
1793 ptcp = ""
1794 command += onosIp
1795 commandList.append( command )
1796
1797 elif isinstance( sw, types.ListType ):
1798 if ptcp:
1799 if isinstance( ptcp, types.ListType ):
1800 if len( ptcp ) != len( sw ):
1801 main.log.error( self.name + ": PTCP length = " +
1802 str( len( ptcp ) ) +
1803 " is not the same as switch" +
1804 " length = " +
1805 str( len( sw ) ) )
1806 return main.FALSE
1807 else:
1808 for switch, ptcpNum in zip( sw, ptcp ):
1809 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001810 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001811 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001812 tempCmd += onosIp
1813 commandList.append( tempCmd )
1814 else:
1815 main.log.error( self.name + ": Invalid PTCP" )
1816 return main.FALSE
1817 else:
1818 for switch in sw:
1819 tempCmd = "sh ovs-vsctl set-controller "
1820 tempCmd += switch + " " + onosIp
1821 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001822 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001823 main.log.error( self.name + ": Invalid switch type " )
1824 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001825
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001826 for cmd in commandList:
1827 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001828 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08001829 if "no bridge named" in self.handle.before:
1830 main.log.error( self.name + ": Error in assignSwController: " +
1831 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001832 except pexpect.TIMEOUT:
1833 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1834 return main.FALSE
1835 except pexpect.EOF:
1836 main.log.error( self.name + ": EOF exception found" )
1837 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001838 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001839 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001840 except pexpect.EOF:
1841 main.log.error( self.name + ": EOF exception found" )
1842 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001843 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001844 except Exception:
1845 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001846 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001847
kelvin-onlabd3b64892015-01-20 13:26:24 -08001848 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001849 """
1850 Removes the controller target from sw"""
1851 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001852 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001853 response = self.execute(
1854 cmd=command,
1855 prompt="mininet>",
1856 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001857 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001858 main.log.error( self.name + ": EOF exception found" )
1859 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001860 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001861 except Exception:
1862 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001863 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001864 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001865 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001866
kelvin-onlabd3b64892015-01-20 13:26:24 -08001867 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001868 """
Jon Hallb1290e82014-11-18 16:17:48 -05001869 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001870 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001871 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001872 NOTE: cannot currently specify what type of switch
1873 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001874 sw = name of the new switch as a string
1875 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001876 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001877 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001878 """
1879 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001880 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001881 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001882 response = self.execute(
1883 cmd=command,
1884 prompt="mininet>",
1885 timeout=10 )
1886 if re.search( "already exists!", 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( "Error", response ):
1890 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001891 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001892 elif re.search( "usage:", response ):
1893 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001894 return main.FALSE
1895 else:
1896 return main.TRUE
1897 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001898 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001899 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001900 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001901 except Exception:
1902 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001903 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001904
kelvin-onlabd3b64892015-01-20 13:26:24 -08001905 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001906 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001907 delete a switch from the mininet topology
1908 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001909 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001910 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001911 sw = name of the switch as a string
1912 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001913 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001914 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001915 response = self.execute(
1916 cmd=command,
1917 prompt="mininet>",
1918 timeout=10 )
1919 if re.search( "no switch named", 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( "Error", response ):
1923 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001924 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001925 elif re.search( "usage:", response ):
1926 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001927 return main.FALSE
1928 else:
1929 return main.TRUE
1930 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001931 main.log.error( self.name + ": EOF exception found" )
1932 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001933 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001934 except Exception:
1935 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001936 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001937
You Wanga9a5e002019-01-31 12:33:26 -08001938 def getSwitchRandom( self, timeout=60, nonCut=True, switchClasses=None, excludeNodes=[], excludeSwitches=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07001939 """
1940 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001941 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001942 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001943 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07001944 it just randomly returns one switch from all current switches in
1945 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08001946 excludeNodes will be pased to getGraphDict method
You Wanga9a5e002019-01-31 12:33:26 -08001947 Switches specified in excludeSwitches will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07001948 Returns the name of the chosen switch.
1949 """
1950 import random
1951 candidateSwitches = []
1952 try:
1953 if not nonCut:
You Wang7d14d642019-01-23 15:10:08 -08001954 switches = self.getSwitches( timeout=timeout, switchClasses=switchClasses )
You Wangdb8cd0a2016-05-26 15:19:45 -07001955 assert len( switches ) != 0
1956 for switchName in switches.keys():
1957 candidateSwitches.append( switchName )
1958 else:
You Wang7d14d642019-01-23 15:10:08 -08001959 graphDict = self.getGraphDict( timeout=timeout, useId=False,
1960 switchClasses=switchClasses,
1961 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001962 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001963 return None
1964 self.graph.update( graphDict )
1965 candidateSwitches = self.graph.getNonCutVertices()
You Wanga9a5e002019-01-31 12:33:26 -08001966 candidateSwitches = [ switch for switch in candidateSwitches if switch not in excludeSwitches ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001967 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001968 return None
1969 elif len( candidateSwitches ) == 0:
1970 main.log.info( self.name + ": No candidate switch for deletion" )
1971 return None
1972 else:
1973 switch = random.sample( candidateSwitches, 1 )
1974 return switch[ 0 ]
1975 except KeyError:
1976 main.log.exception( self.name + ": KeyError exception found" )
1977 return None
1978 except AssertionError:
1979 main.log.exception( self.name + ": AssertionError exception found" )
1980 return None
1981 except Exception:
1982 main.log.exception( self.name + ": Uncaught exception" )
1983 return None
1984
1985 def delSwitchRandom( self, timeout=60, nonCut=True ):
1986 """
1987 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001988 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001989 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001990 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07001991 otherwise it just randomly delete one switch from all current
1992 switches in Mininet.
1993 Returns the name of the deleted switch
1994 """
1995 try:
1996 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001997 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001998 return None
1999 else:
2000 deletionResult = self.delSwitch( switch )
2001 if deletionResult:
2002 return switch
2003 else:
2004 return None
2005 except Exception:
2006 main.log.exception( self.name + ": Uncaught exception" )
2007 return None
2008
kelvin-onlabd3b64892015-01-20 13:26:24 -08002009 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002010 """
2011 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002012 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002013 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002014 NOTE: cannot currently specify what type of link
2015 required params:
2016 node1 = the string node name of the first endpoint of the link
2017 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002018 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002019 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002020 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002021 response = self.execute(
2022 cmd=command,
2023 prompt="mininet>",
2024 timeout=10 )
2025 if re.search( "doesnt exist!", response ):
2026 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002027 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002028 elif re.search( "Error", response ):
2029 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002030 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002031 elif re.search( "usage:", response ):
2032 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002033 return main.FALSE
2034 else:
2035 return main.TRUE
2036 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002037 main.log.error( self.name + ": EOF exception found" )
2038 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002039 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002040 except Exception:
2041 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002042 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002043
kelvin-onlabd3b64892015-01-20 13:26:24 -08002044 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002045 """
2046 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002047 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002048 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002049 required params:
2050 node1 = the string node name of the first endpoint of the link
2051 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002052 returns: main.FALSE on an error, else main.TRUE
2053 """
Jon Hallffb386d2014-11-21 13:43:38 -08002054 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002055 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002056 response = self.execute(
2057 cmd=command,
2058 prompt="mininet>",
2059 timeout=10 )
2060 if re.search( "no node named", response ):
2061 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002062 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002063 elif re.search( "Error", response ):
2064 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002065 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002066 elif re.search( "usage:", response ):
2067 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002068 return main.FALSE
2069 else:
2070 return main.TRUE
2071 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002072 main.log.error( self.name + ": EOF exception found" )
2073 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002074 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002075 except Exception:
2076 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002077 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002078
You Wang7d14d642019-01-23 15:10:08 -08002079 def getLinkRandom( self, timeout=60, nonCut=True, switchClasses=None, excludeNodes=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07002080 """
2081 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002082 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002083 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002084 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002085 it just randomly returns one link from all current links in
2086 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08002087 excludeNodes will be passed to getLinks method to exclude unexpected links.
You Wangdb8cd0a2016-05-26 15:19:45 -07002088 Returns the link as a list, e.g. [ 's1', 's2' ]
2089 """
2090 import random
2091 candidateLinks = []
2092 try:
2093 if not nonCut:
You Wang7d14d642019-01-23 15:10:08 -08002094 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07002095 assert len( links ) != 0
2096 for link in links:
2097 # Exclude host-switch link
2098 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2099 continue
2100 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2101 else:
You Wang7d14d642019-01-23 15:10:08 -08002102 graphDict = self.getGraphDict( timeout=timeout, useId=False,
2103 switchClasses=switchClasses,
2104 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002105 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002106 return None
2107 self.graph.update( graphDict )
2108 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002109 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002110 return None
2111 elif len( candidateLinks ) == 0:
2112 main.log.info( self.name + ": No candidate link for deletion" )
2113 return None
2114 else:
2115 link = random.sample( candidateLinks, 1 )
2116 return link[ 0 ]
2117 except KeyError:
2118 main.log.exception( self.name + ": KeyError exception found" )
2119 return None
2120 except AssertionError:
2121 main.log.exception( self.name + ": AssertionError exception found" )
2122 return None
2123 except Exception:
2124 main.log.exception( self.name + ": Uncaught exception" )
2125 return None
2126
2127 def delLinkRandom( self, timeout=60, nonCut=True ):
2128 """
2129 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002130 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002131 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002132 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002133 otherwise it just randomly delete one link from all current links
2134 in Mininet.
2135 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2136 """
2137 try:
2138 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002139 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002140 return None
2141 else:
2142 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2143 if deletionResult:
2144 return link
2145 else:
2146 return None
2147 except Exception:
2148 main.log.exception( self.name + ": Uncaught exception" )
2149 return None
2150
kelvin-onlabd3b64892015-01-20 13:26:24 -08002151 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002152 """
Jon Hallb1290e82014-11-18 16:17:48 -05002153 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002154 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002155 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002156 NOTE: cannot currently specify what type of host
2157 required params:
2158 hostname = the string hostname
2159 optional key-value params
2160 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002161 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002162 """
2163 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002164 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002165 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002166 response = self.execute(
2167 cmd=command,
2168 prompt="mininet>",
2169 timeout=10 )
2170 if re.search( "already exists!", response ):
2171 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002172 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002173 elif re.search( "doesnt exists!", response ):
2174 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002175 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002176 elif re.search( "Error", response ):
2177 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002178 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002179 elif re.search( "usage:", response ):
2180 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002181 return main.FALSE
2182 else:
2183 return main.TRUE
2184 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002185 main.log.error( self.name + ": EOF exception found" )
2186 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002187 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002188 except Exception:
2189 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002190 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002191
kelvin-onlabd3b64892015-01-20 13:26:24 -08002192 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002193 """
2194 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002195 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002196 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002197 NOTE: this uses a custom mn function
2198 required params:
2199 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002200 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002201 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002202 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002203 response = self.execute(
2204 cmd=command,
2205 prompt="mininet>",
2206 timeout=10 )
2207 if re.search( "no host named", response ):
2208 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002209 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002210 elif re.search( "Error", response ):
2211 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002212 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002213 elif re.search( "usage:", response ):
2214 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002215 return main.FALSE
2216 else:
2217 return main.TRUE
2218 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002219 main.log.error( self.name + ": EOF exception found" )
2220 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002221 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002222 except Exception:
2223 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002224 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002225
Jon Hall7eb38402015-01-08 17:19:54 -08002226 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002227 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002228 Called at the end of the test to stop the mininet and
2229 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002230 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002231 try:
2232 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002233 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002234 timeout=2 )
2235 response = main.TRUE
2236 if i == 0:
2237 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002238 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002239 return main.TRUE
2240 # print "Disconnecting Mininet"
2241 if self.handle:
2242 self.handle.sendline( "exit" )
2243 self.handle.expect( "exit" )
2244 self.handle.expect( "(.*)" )
2245 else:
2246 main.log.error( "Connection failed to the host" )
2247 return response
2248 except pexpect.EOF:
2249 main.log.error( self.name + ": EOF exception found" )
2250 main.log.error( self.name + ": " + self.handle.before )
You Wangd4fae5c2018-08-22 13:56:49 -07002251 # Do not exit the entire test when pexpect.EOF is caught
2252 # FIXME: We might need to do something else here
2253 return main.ERROR
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002254 except Exception:
2255 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002256 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002257
Devin Lima7cfdbd2017-09-29 15:02:22 -07002258 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002259 """
Jon Hall21270ac2015-02-16 17:59:55 -08002260 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002261 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002262 main.FALSE if the pexpect handle does not exist.
2263
Jon Halld61331b2015-02-17 16:35:47 -08002264 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002265 """
Jon Halld61331b2015-02-17 16:35:47 -08002266 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002267 response = ''
2268 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002269 try:
Jon Halld80cc142015-07-06 13:36:05 -07002270 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002271 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002272 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002273 pexpect.EOF,
2274 pexpect.TIMEOUT ],
2275 timeout )
2276 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002277 main.log.info( "Exiting mininet.." )
2278 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002279 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002280 prompt=self.prompt,
2281 timeout=exitTimeout )
2282 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002283 self.handle.sendline( "sudo mn -c" )
2284 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002285
Jeremyd9e4eb12016-04-13 12:09:06 -07002286 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002287 main.log.info( " Mininet trying to exit while not " +
2288 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002289 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002290 elif i == 2:
2291 main.log.error( "Something went wrong exiting mininet" )
2292 elif i == 3: # timeout
2293 main.log.error( "Something went wrong exiting mininet " +
2294 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002295
You Wang18db8592018-04-02 13:52:03 -07002296 self.handle.sendline( "" )
2297 self.handle.expect( self.prompt )
2298 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2299
Hari Krishnab35c6d02015-03-18 11:13:51 -07002300 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002301 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002302 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002303 self.handle.sendline(
2304 "sudo kill -9 \`ps -ef | grep \"" +
2305 fileName +
2306 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002307 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002308 main.log.error( self.name + ": TIMEOUT exception found" )
2309 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002310 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002311 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002312 main.log.error( self.name + ": EOF exception found" )
2313 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002314 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002315 except Exception:
2316 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002317 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002318 else:
2319 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002320 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002321 return response
2322
YPZhang26a139e2016-04-25 14:01:55 -07002323 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002324 """
2325 Description:
2326 Sends arp message from mininet host for hosts discovery
2327 Required:
2328 host - hosts name
2329 Optional:
2330 ip - ip address that does not exist in the network so there would
2331 be no reply.
2332 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002333 if ethDevice:
2334 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002335 cmd = srcHost + " arping -c1 "
2336 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002337 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 -07002338 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002339 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002340 if output:
2341 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002342 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002343 i = self.handle.expect( [ "mininet>", "arping: " ] )
2344 if i == 0:
2345 return main.TRUE
2346 elif i == 1:
2347 response = self.handle.before + self.handle.after
2348 self.handle.expect( "mininet>" )
2349 response += self.handle.before + self.handle.after
2350 main.log.warn( "Error sending arping, output was: " +
2351 response )
2352 return main.FALSE
2353 except pexpect.TIMEOUT:
2354 main.log.error( self.name + ": TIMEOUT exception found" )
2355 main.log.warn( self.handle.before )
2356 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002357 except pexpect.EOF:
2358 main.log.error( self.name + ": EOF exception found" )
2359 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002360 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002361 except Exception:
2362 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002363 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002364
Jon Hall7eb38402015-01-08 17:19:54 -08002365 def decToHex( self, num ):
2366 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002367
Jon Hall7eb38402015-01-08 17:19:54 -08002368 def getSwitchFlowCount( self, switch ):
2369 """
2370 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002371 if self.handle:
2372 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2373 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002374 response = self.execute(
2375 cmd=cmd,
2376 prompt="mininet>",
2377 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002378 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002379 main.log.error( self.name + ": EOF exception found" )
2380 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002381 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002382 except Exception:
2383 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002384 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002385 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002386 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002387 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002388 main.log.info(
2389 "Couldn't find flows on switch %s, found: %s" %
2390 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002391 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002392 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002393 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002394 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002395
Jon Hall9ed8f372016-02-24 17:34:07 -08002396 def checkFlows( self, sw, dumpFormat=None ):
2397 if dumpFormat:
2398 command = "sh ovs-ofctl -F " + \
2399 dumpFormat + " dump-flows " + str( sw )
2400 else:
2401 command = "sh ovs-ofctl dump-flows " + str( sw )
2402 try:
2403 response = self.execute(
2404 cmd=command,
2405 prompt="mininet>",
2406 timeout=10 )
2407 return response
2408 except pexpect.EOF:
2409 main.log.error( self.name + ": EOF exception found" )
2410 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002411 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002412 except Exception:
2413 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002414 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002415
GlennRC68467eb2015-11-16 18:01:01 -08002416 def flowTableComp( self, flowTable1, flowTable2 ):
2417 # This function compares the selctors and treatments of each flow
2418 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002419 assert flowTable1, "flowTable1 is empty or None"
2420 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002421 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002422 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002423 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002424 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002425 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2426 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002427 for field in dFields:
2428 try:
2429 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002430 except KeyError:
2431 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002432 try:
2433 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002434 except KeyError:
2435 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002436 for i in range( len( flowTable1 ) ):
2437 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002438 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002439 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002440 returnValue = main.FALSE
2441 break
2442 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002443 except AssertionError:
2444 main.log.exception( "Nothing to compare" )
2445 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002446 except Exception:
2447 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002448 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002449
GlennRC528ad292015-11-12 10:38:18 -08002450 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002451 '''
GlennRC956ea742015-11-05 16:14:15 -08002452 Discription: Parses flows into json format.
2453 NOTE: this can parse any string thats separated with commas
2454 Arguments:
2455 Required:
2456 flows: a list of strings that represnt flows
2457 Optional:
2458 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2459 debug: prints out the final result
2460 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002461 '''
GlennRC528ad292015-11-12 10:38:18 -08002462 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002463 try:
2464 for flow in flowTable:
2465 jsonFlow = {}
2466 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002467 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002468 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002469 for i in range( len( parsedFlow ) ):
2470 item = parsedFlow[ i ]
2471 if item[ 0 ] == " ":
2472 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002473 # grab the selector and treatment from the parsed flow
2474 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002475 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002476 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002477 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002478 index = 0
2479 # parse the flags
2480 # NOTE: This only parses one flag
2481 flag = {}
2482 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002483 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002484 index += 1
2485 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002486 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002487 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002488 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002489 # the priority is stuck in the selecter so put it back
2490 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002491 if 'priority' in sel[0]:
2492 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002493 # parse selector
2494 criteria = []
2495 for item in sel:
2496 # this is the type of the packet e.g. "arp"
2497 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002498 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002499 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002500 field = item.split( "=" )
2501 criteria.append( { field[ 0 ]: field[ 1 ] } )
2502 selector = { "selector": { "criteria": sorted( criteria ) } }
2503 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002504 # get rid of the action part e.g. "action=output:2"
2505 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002506 treat = treat.split( "=" )
2507 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002508 # parse treatment
2509 action = []
2510 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002511 if ":" in item:
2512 field = item.split( ":" )
2513 action.append( { field[ 0 ]: field[ 1 ] } )
2514 else:
2515 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2516 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002517 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002518 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002519 # parse the rest of the flow
2520 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002521 field = item.split( "=" )
2522 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002523 # add the treatment and the selector to the json flow
2524 jsonFlow.update( selector )
2525 jsonFlow.update( treatment )
2526 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002527
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002528 if debug:
2529 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002530
You Wang91c37cf2016-05-23 09:39:42 -07002531 # add the json flow to the json flow table
2532 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002533
You Wang91c37cf2016-05-23 09:39:42 -07002534 return jsonFlowTable
2535
2536 except IndexError:
2537 main.log.exception( self.name + ": IndexError found" )
2538 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002539 except pexpect.EOF:
2540 main.log.error( self.name + ": EOF exception found" )
2541 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002542 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002543 except Exception:
2544 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002545 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002546
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002547 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002548 '''
2549 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002550 Each element is a flow.
2551 Arguments:
2552 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002553 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002554 a list of switches.
2555 Optional:
2556 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2557 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002558 '''
GlennRC956ea742015-11-05 16:14:15 -08002559 try:
2560 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002561 if isinstance( sw, list ):
2562 switches.extend( sw )
2563 else:
2564 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002565
2566 flows = []
2567 for s in switches:
2568 cmd = "sh ovs-ofctl dump-flows " + s
2569
GlennRC528ad292015-11-12 10:38:18 -08002570 if "1.0" == version:
2571 cmd += " -F OpenFlow10-table_id"
2572 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002573 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002574
2575 main.log.info( "Sending: " + cmd )
2576 self.handle.sendline( cmd )
2577 self.handle.expect( "mininet>" )
2578 response = self.handle.before
2579 response = response.split( "\r\n" )
2580 # dump the first two elements and the last
2581 # the first element is the command that was sent
2582 # the second is the table header
2583 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002584 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002585 flows.extend( response )
2586
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002587 if debug:
2588 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002589
GlennRC528ad292015-11-12 10:38:18 -08002590 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002591
GlennRC956ea742015-11-05 16:14:15 -08002592 except pexpect.EOF:
2593 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002594 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002595 except Exception:
2596 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002597 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002598
2599 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002600 '''
GlennRC956ea742015-11-05 16:14:15 -08002601 Discription: Checks whether the ID provided matches a flow ID in Mininet
2602 Arguments:
2603 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002604 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002605 a list of switches.
2606 flowId: the flow ID in hex format. Can also be a list of IDs
2607 Optional:
2608 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2609 debug: prints out the final result
2610 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2611 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002612 '''
GlennRC956ea742015-11-05 16:14:15 -08002613 try:
2614 main.log.info( "Getting flows from Mininet" )
2615 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002616 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002617 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002618
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002619 if debug:
2620 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002621
2622 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002623 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002624 result = False
2625 for f in flows:
2626 if flowId in f.get( 'cookie' ):
2627 result = True
2628 break
2629 # flowId is a list
2630 else:
2631 result = True
2632 # Get flow IDs from Mininet
2633 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2634 # Save the IDs that are not in Mininet
2635 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2636
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002637 if debug:
2638 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002639
2640 # Print out the IDs that are not in Mininet
2641 if absentIds:
2642 main.log.warn( "Absent ids: {}".format( absentIds ) )
2643 result = False
2644
2645 return main.TRUE if result else main.FALSE
2646
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002647 except pexpect.EOF:
2648 main.log.error( self.name + ": EOF exception found" )
2649 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002650 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002651 except Exception:
2652 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002653 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002654
Charles Chan029be652015-08-24 01:46:10 +08002655 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002656 """
Jon Hallefbd9792015-03-05 16:11:36 -08002657 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002658 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002659 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002660 self.handle.sendline( "" )
2661 self.handle.expect( "mininet>" )
2662 self.handle.sendline(
2663 "sh sudo tcpdump -n -i " +
2664 intf +
2665 " " +
2666 port +
2667 " -w " +
2668 filename.strip() +
2669 " &" )
2670 self.handle.sendline( "" )
2671 i = self.handle.expect( [ 'No\ssuch\device',
2672 'listening\son',
2673 pexpect.TIMEOUT,
2674 "mininet>" ],
2675 timeout=10 )
2676 main.log.warn( self.handle.before + self.handle.after )
2677 self.handle.sendline( "" )
2678 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002679 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002680 main.log.error(
2681 self.name +
2682 ": tcpdump - No such device exists. " +
2683 "tcpdump attempted on: " +
2684 intf )
admin2a9548d2014-06-17 14:08:07 -07002685 return main.FALSE
2686 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002687 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002688 return main.TRUE
2689 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002690 main.log.error(
2691 self.name +
2692 ": tcpdump command timed out! Check interface name," +
2693 " given interface was: " +
2694 intf )
admin2a9548d2014-06-17 14:08:07 -07002695 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002696 elif i == 3:
2697 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002698 return main.TRUE
2699 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002700 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002701 return main.FALSE
2702 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002703 main.log.error( self.name + ": EOF exception found" )
2704 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002705 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002706 except Exception:
2707 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002708 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002709
kelvin-onlabd3b64892015-01-20 13:26:24 -08002710 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002711 """
2712 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002713 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002714 self.handle.sendline( "sh sudo pkill tcpdump" )
2715 self.handle.expect( "mininet>" )
2716 self.handle.sendline( "" )
2717 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002718 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002719 main.log.error( self.name + ": TIMEOUT exception found" )
2720 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002721 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002722 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002723 main.log.error( self.name + ": EOF exception found" )
2724 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002725 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002726 except Exception:
2727 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002728 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002729
Jon Halld80cc142015-07-06 13:36:05 -07002730 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002731 """
2732 Read ports from a Mininet switch.
2733
2734 Returns a json structure containing information about the
2735 ports of the given switch.
2736 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002737 try:
2738 response = self.getInterfaces( nodeName )
2739 # TODO: Sanity check on response. log if no such switch exists
2740 ports = []
2741 for line in response.split( "\n" ):
2742 if not line.startswith( "name=" ):
2743 continue
2744 portVars = {}
2745 for var in line.split( "," ):
2746 key, value = var.split( "=" )
2747 portVars[ key ] = value
2748 isUp = portVars.pop( 'enabled', "True" )
2749 isUp = "True" in isUp
2750 if verbose:
2751 main.log.info( "Reading switch port %s(%s)" %
2752 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2753 mac = portVars[ 'mac' ]
2754 if mac == 'None':
2755 mac = None
2756 ips = []
2757 ip = portVars[ 'ip' ]
2758 if ip == 'None':
2759 ip = None
2760 ips.append( ip )
2761 name = portVars[ 'name' ]
2762 if name == 'None':
2763 name = None
2764 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2765 if name == 'lo':
2766 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2767 else:
2768 portNo = re.search( portRe, name ).group( 'port' )
2769 ports.append( { 'of_port': portNo,
2770 'mac': str( mac ).replace( '\'', '' ),
2771 'name': name,
2772 'ips': ips,
2773 'enabled': isUp } )
2774 return ports
2775 except pexpect.EOF:
2776 main.log.error( self.name + ": EOF exception found" )
2777 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002778 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002779 except Exception:
2780 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002781 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002782
You Wangdb8cd0a2016-05-26 15:19:45 -07002783 def getOVSPorts( self, nodeName ):
2784 """
2785 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2786
2787 Returns a list of dictionaries containing information about each
2788 port of the given switch.
2789 """
2790 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2791 try:
2792 response = self.execute(
2793 cmd=command,
2794 prompt="mininet>",
You Wang7d14d642019-01-23 15:10:08 -08002795 timeout=10,
2796 logCmd=False )
You Wangdb8cd0a2016-05-26 15:19:45 -07002797 ports = []
2798 if response:
2799 for line in response.split( "\n" ):
2800 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2801 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002802 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002803 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2804 result = re.search( pattern, line )
2805 if result:
2806 index = result.group( 'index' )
2807 name = result.group( 'name' )
2808 # This port number is extracted from port name
2809 port = result.group( 'port' )
2810 mac = result.group( 'mac' )
2811 ports.append( { 'index': index,
2812 'name': name,
2813 'port': port,
2814 'mac': mac } )
2815 return ports
2816 except pexpect.EOF:
2817 main.log.error( self.name + ": EOF exception found" )
2818 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002819 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002820 except Exception:
2821 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002822 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002823
You Wang7d14d642019-01-23 15:10:08 -08002824 def getSwitches( self, verbose=False, updateTimeout=1000, switchClasses=None ):
Jon Hallafa8a472015-06-12 14:02:42 -07002825 """
2826 Read switches from Mininet.
2827
2828 Returns a dictionary whose keys are the switch names and the value is
2829 a dictionary containing information about the switch.
2830 """
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 Wang7d14d642019-01-23 15:10:08 -08002841 if not switchClasses:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002842 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
You Wang7d14d642019-01-23 15:10:08 -08002843 try:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002844 swRE = r"<(?P<class>" + switchClasses + r")" +\
2845 r"(?P<options>\{.*\})?\s" +\
2846 r"(?P<name>[^:]+)\:\s" +\
2847 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2848 r"\spid=(?P<pid>(\d)+)"
2849 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002850 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002851 output = {}
2852 dump = self.dump().split( "\n" )
2853 for line in dump:
2854 result = re.search( swRE, line, re.I )
2855 if result:
2856 name = result.group( 'name' )
2857 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2858 pid = result.group( 'pid' )
2859 swClass = result.group( 'class' )
2860 options = result.group( 'options' )
2861 if verbose:
2862 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2863 ports = self.getPorts( name )
2864 output[ name ] = { "dpid": dpid,
2865 "ports": ports,
2866 "swClass": swClass,
2867 "pid": pid,
2868 "options": options }
2869 return output
2870 except pexpect.EOF:
2871 main.log.error( self.name + ": EOF exception found" )
2872 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002873 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002874 except Exception:
2875 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002876 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002877
You Wangd66de192018-04-30 17:30:12 -07002878 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002879 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2880 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002881 """
2882 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002883 Optional:
2884 hostClass: it is used to match the class of the mininet host. It
2885 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002886 Returns a dictionary whose keys are the host names and the value is
2887 a dictionary containing information about the host.
2888 """
2889 # Regex patterns to parse dump output
2890 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002891 # <Host h1: pid=12725>
2892 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2893 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2894 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002895 # NOTE: Does not correctly match hosts with multi-links
2896 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2897 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002898 try:
You Wang53dba1e2018-02-02 17:45:44 -08002899 if not isinstance( hostClass, types.ListType ):
2900 hostClass = [ str( hostClass ) ]
2901 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002902 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2903 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2904 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002905 if update:
2906 # update mn port info
2907 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002908 # Get mininet dump
2909 dump = self.dump().split( "\n" )
2910 hosts = {}
2911 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002912 result = re.search( hostRE, line )
2913 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002914 name = result.group( 'name' )
2915 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002916 if getInterfaces:
2917 response = self.getInterfaces( name )
2918 # Populate interface info
2919 for line in response.split( "\n" ):
2920 if line.startswith( "name=" ):
2921 portVars = {}
2922 for var in line.split( "," ):
2923 key, value = var.split( "=" )
2924 portVars[ key ] = value
2925 isUp = portVars.pop( 'enabled', "True" )
2926 isUp = "True" in isUp
2927 if verbose:
2928 main.log.info( "Reading host port %s(%s)" %
2929 ( portVars[ 'name' ],
2930 portVars[ 'mac' ] ) )
2931 mac = portVars[ 'mac' ]
2932 if mac == 'None':
2933 mac = None
2934 ips = []
2935 ip = portVars[ 'ip' ]
2936 if ip == 'None':
2937 ip = None
2938 ips.append( ip )
2939 intfName = portVars[ 'name' ]
2940 if name == 'None':
2941 name = None
2942 interfaces.append( {
2943 "name": intfName,
2944 "ips": ips,
2945 "mac": str( mac ),
2946 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002947 hosts[ name ] = { "interfaces": interfaces }
2948 return hosts
2949 except pexpect.EOF:
2950 main.log.error( self.name + ": EOF exception found" )
2951 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002952 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002953 except Exception:
2954 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002955 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002956
You Wang7d14d642019-01-23 15:10:08 -08002957 def getLinks( self, timeout=20, updateTimeout=1000, excludeNodes=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002958 """
2959 Gathers information about current Mininet links. These links may not
2960 be up if one of the ports is down.
2961
2962 Returns a list of dictionaries with link endpoints.
2963
2964 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002965 { 'node1': str( node1 name )
2966 'node2': str( node2 name )
2967 'port1': str( port1 of_port )
2968 'port2': str( port2 of_port ) }
You Wang7d14d642019-01-23 15:10:08 -08002969
2970 If either node1 or node2 name starts with any of the strings sepcified
2971 in excludeNodes, the link will be excluded from the returned value
2972
Jon Hallafa8a472015-06-12 14:02:42 -07002973 Note: The port number returned is the eth#, not necessarily the of_port
2974 number. In Mininet, for OVS switch, these should be the same. For
2975 hosts, this is just the eth#.
2976 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002977 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002978 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002979 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002980
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002981 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002982 # s1-eth3<->s2-eth1 (OK OK)
2983 # s13-eth3<->h27-eth0 (OK OK)
You Wang7d14d642019-01-23 15:10:08 -08002984 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d\.]+)\<\-\>" +\
2985 "(?P<node2>[\w]+)\-eth(?P<port2>[\d\.]+)"
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002986 links = []
2987 for line in response:
2988 match = re.search( linkRE, line )
2989 if match:
2990 node1 = match.group( 'node1' )
2991 node2 = match.group( 'node2' )
You Wang7d14d642019-01-23 15:10:08 -08002992 if any( node1.startswith( node ) for node in excludeNodes ) or \
2993 any( node2.startswith( node ) for node in excludeNodes ):
2994 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 Wang7d14d642019-01-23 15:10:08 -08003463 def getGraphDict( self, timeout=60, useId=True, includeHost=False,
3464 switchClasses=None, 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 Wang7d14d642019-01-23 15:10:08 -08003483 if switchClasses == None, default switchClasses will be used when calling
3484 getSwitches method.
3485 excludeNodes will be passed to getLinks method to exclude unexpected links.
You Wangdb8cd0a2016-05-26 15:19:45 -07003486 Note that link or switch that are brought down by 'link x x down' or 'switch
3487 x down' commands still show in the output of Mininet CLI commands such as
3488 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3489 recommended to use delLink() or delSwitch functions to simulate link/switch
3490 down, and addLink() or addSwitch to add them back.
3491 """
3492 graphDict = {}
3493 try:
You Wang7d14d642019-01-23 15:10:08 -08003494 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003495 portDict = {}
You Wang7d14d642019-01-23 15:10:08 -08003496 switches = self.getSwitches( switchClasses=switchClasses )
You Wangdb8cd0a2016-05-26 15:19:45 -07003497 if includeHost:
3498 hosts = self.getHosts()
3499 for link in links:
3500 # FIXME: support 'includeHost' argument
3501 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3502 continue
3503 nodeName1 = link[ 'node1' ]
3504 nodeName2 = link[ 'node2' ]
You Wang7d14d642019-01-23 15:10:08 -08003505 if not self.getOVSPorts( nodeName1 ) or not self.getOVSPorts( nodeName2 ):
3506 # The device is probably offline
3507 continue
You Wangdb8cd0a2016-05-26 15:19:45 -07003508 port1 = link[ 'port1' ]
3509 port2 = link[ 'port2' ]
3510 # Loop for two nodes
3511 for i in range( 2 ):
3512 # Get port index from OVS
3513 # The index extracted from port name may be inconsistent with ONOS
3514 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003515 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003516 portList = self.getOVSPorts( nodeName1 )
3517 if len( portList ) == 0:
3518 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3519 return None
3520 portDict[ nodeName1 ] = portList
3521 for port in portDict[ nodeName1 ]:
3522 if port[ 'port' ] == port1:
3523 portIndex = port[ 'index' ]
3524 break
3525 if portIndex == -1:
3526 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3527 return None
3528 if useId:
3529 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3530 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3531 else:
3532 node1 = nodeName1
3533 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003534 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003535 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003536 graphDict[ node1 ] = { 'edges': {},
3537 'dpid': switches[ nodeName1 ][ 'dpid' ],
3538 'name': nodeName1,
3539 'ports': switches[ nodeName1 ][ 'ports' ],
3540 'swClass': switches[ nodeName1 ][ 'swClass' ],
3541 'pid': switches[ nodeName1 ][ 'pid' ],
3542 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003543 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003544 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003545 else:
3546 # Assert node2 is not connected to any current links of node1
You Wang7d14d642019-01-23 15:10:08 -08003547 # assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
3548 pass
3549 for port in switches[ nodeName1 ][ 'ports' ]:
3550 if port[ 'of_port' ] == str( portIndex ):
3551 # Use -1 as index for disabled port
3552 if port[ 'enabled' ] == True:
3553 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
3554 else:
3555 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': -1 }
You Wangdb8cd0a2016-05-26 15:19:45 -07003556 # Swap two nodes/ports
3557 nodeName1, nodeName2 = nodeName2, nodeName1
3558 port1, port2 = port2, port1
You Wang7d14d642019-01-23 15:10:08 -08003559 # Remove links with disabled ports
3560 linksToRemove = []
3561 for node, edges in graphDict.items():
3562 for neighbor, port in edges[ 'edges' ].items():
3563 if port[ 'port' ] == -1:
3564 linksToRemove.append( ( node, neighbor ) )
3565 for node1, node2 in linksToRemove:
3566 for i in range( 2 ):
3567 if graphDict.get( node1 )[ 'edges' ].get( node2 ):
3568 graphDict[ node1 ][ 'edges' ].pop( node2 )
3569 node1, node2 = node2, node1
You Wangdb8cd0a2016-05-26 15:19:45 -07003570 return graphDict
3571 except KeyError:
3572 main.log.exception( self.name + ": KeyError exception found" )
3573 return None
3574 except AssertionError:
3575 main.log.exception( self.name + ": AssertionError exception found" )
3576 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003577 except pexpect.EOF:
3578 main.log.error( self.name + ": EOF exception found" )
3579 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003580 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003581 except Exception:
3582 main.log.exception( self.name + ": Uncaught exception" )
3583 return None
3584
Devin Lima7cfdbd2017-09-29 15:02:22 -07003585 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003586 """
3587 updates the port address and status information for
3588 each port in mn"""
3589 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003590 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003591 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003592 self.handle.sendline( "" )
3593 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003594
Jon Hall7eb38402015-01-08 17:19:54 -08003595 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003596 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003597
Jon Hall7eb38402015-01-08 17:19:54 -08003598 self.handle.sendline( "" )
3599 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003600
Jon Hallb1290e82014-11-18 16:17:48 -05003601 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003602 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003603 main.log.error( self.name + ": TIMEOUT exception found" )
3604 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003605 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003606 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003607 main.log.error( self.name + ": EOF exception found" )
3608 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003609 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003610 except Exception:
3611 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003612 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003613
Jon Halld80cc142015-07-06 13:36:05 -07003614 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003615 """
3616 Add vlan tag to a host.
3617 Dependencies:
3618 This class depends on the "vlan" package
3619 $ sudo apt-get install vlan
3620 Configuration:
3621 Load the 8021q module into the kernel
3622 $sudo modprobe 8021q
3623
3624 To make this setup permanent:
3625 $ sudo su -c 'echo "8021q" >> /etc/modules'
3626 """
3627 if self.handle:
3628 try:
Jon Halld80cc142015-07-06 13:36:05 -07003629 # get the ip address of the host
3630 main.log.info( "Get the ip address of the host" )
3631 ipaddr = self.getIPAddress( host )
3632 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003633
Jon Halld80cc142015-07-06 13:36:05 -07003634 # remove IP from interface intf
3635 # Ex: h1 ifconfig h1-eth0 inet 0
3636 main.log.info( "Remove IP from interface " )
3637 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3638 self.handle.sendline( cmd2 )
3639 self.handle.expect( "mininet>" )
3640 response = self.handle.before
3641 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003642
Jon Halld80cc142015-07-06 13:36:05 -07003643 # create VLAN interface
3644 # Ex: h1 vconfig add h1-eth0 100
3645 main.log.info( "Create Vlan" )
3646 cmd3 = host + " vconfig add " + intf + " " + vlan
3647 self.handle.sendline( cmd3 )
3648 self.handle.expect( "mininet>" )
3649 response = self.handle.before
3650 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003651
Jon Halld80cc142015-07-06 13:36:05 -07003652 # assign the host's IP to the VLAN interface
3653 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3654 main.log.info( "Assign the host IP to the vlan interface" )
3655 vintf = intf + "." + vlan
3656 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3657 self.handle.sendline( cmd4 )
3658 self.handle.expect( "mininet>" )
3659 response = self.handle.before
3660 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003661
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003662 # update Mininet node variables
3663 main.log.info( "Update Mininet node variables" )
3664 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3665 self.handle.sendline( cmd5 )
3666 self.handle.expect( "mininet>" )
3667 response = self.handle.before
3668 main.log.info( "====> %s ", response )
3669
3670 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3671 self.handle.sendline( cmd6 )
3672 self.handle.expect( "mininet>" )
3673 response = self.handle.before
3674 main.log.info( "====> %s ", response )
3675
3676 return main.TRUE
3677 except pexpect.TIMEOUT:
3678 main.log.error( self.name + ": TIMEOUT exception found" )
3679 main.log.error( self.name + ": " + self.handle.before )
3680 main.cleanAndExit()
3681 except pexpect.EOF:
3682 main.log.error( self.name + ": EOF exception found" )
3683 main.log.error( self.name + ": " + self.handle.before )
3684 return main.FALSE
3685 except Exception:
3686 main.log.exception( self.name + ": Uncaught exception!" )
3687 return main.FALSE
3688
3689 def removeVLAN( self, host, intf ):
3690 """
3691 Remove vlan tag from a host.
3692 Dependencies:
3693 This class depends on the "vlan" package
3694 $ sudo apt-get install vlan
3695 Configuration:
3696 Load the 8021q module into the kernel
3697 $sudo modprobe 8021q
3698
3699 To make this setup permanent:
3700 $ sudo su -c 'echo "8021q" >> /etc/modules'
3701 """
3702 if self.handle:
3703 try:
3704 # get the ip address of the host
3705 main.log.info( "Get the ip address of the host" )
3706 ipaddr = self.getIPAddress( host )
3707
3708 # remove VLAN interface
3709 # Ex: h1 vconfig rem h1-eth0.100
3710 main.log.info( "Remove Vlan interface" )
3711 cmd2 = host + " vconfig rem " + intf
3712 self.handle.sendline( cmd2 )
3713 self.handle.expect( "mininet>" )
3714 response = self.handle.before
3715 main.log.info( "====> %s ", response )
3716
3717 # assign the host's IP to the original interface
3718 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3719 main.log.info( "Assign the host IP to the original interface" )
3720 original_intf = intf.split(".")[0]
3721 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3722 self.handle.sendline( cmd3 )
3723 self.handle.expect( "mininet>" )
3724 response = self.handle.before
3725 main.log.info( "====> %s ", response )
3726
3727 # update Mininet node variables
3728 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3729 self.handle.sendline( cmd4 )
3730 self.handle.expect( "mininet>" )
3731 response = self.handle.before
3732 main.log.info( "====> %s ", response )
3733
3734 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3735 self.handle.sendline( cmd5 )
3736 self.handle.expect( "mininet>" )
3737 response = self.handle.before
3738 main.log.info( "====> %s ", response )
3739
kaouthera3f13ca22015-05-05 15:01:41 -07003740 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003741 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003742 main.log.error( self.name + ": TIMEOUT exception found" )
3743 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003744 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003745 except pexpect.EOF:
3746 main.log.error( self.name + ": EOF exception found" )
3747 main.log.error( self.name + ": " + self.handle.before )
3748 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003749 except Exception:
3750 main.log.exception( self.name + ": Uncaught exception!" )
3751 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003752
Jon Hall892818c2015-10-20 17:58:34 -07003753 def createHostComponent( self, name ):
3754 """
3755 Creates a new mininet cli component with the same parameters as self.
3756 This new component is intended to be used to login to the hosts created
3757 by mininet.
3758
3759 Arguments:
3760 name - The string of the name of this component. The new component
3761 will be assigned to main.<name> .
3762 In addition, main.<name>.name = str( name )
3763 """
3764 try:
3765 # look to see if this component already exists
3766 getattr( main, name )
3767 except AttributeError:
3768 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003769 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3770 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003771 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003772 except pexpect.EOF:
3773 main.log.error( self.name + ": EOF exception found" )
3774 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003775 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003776 except Exception:
3777 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003778 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003779 else:
3780 # namespace is not clear!
3781 main.log.error( name + " component already exists!" )
3782 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003783 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003784
3785 def removeHostComponent( self, name ):
3786 """
3787 Remove host component
3788 Arguments:
3789 name - The string of the name of the component to delete.
3790 """
3791 try:
3792 # Get host component
3793 component = getattr( main, name )
3794 except AttributeError:
3795 main.log.error( "Component " + name + " does not exist." )
3796 return
3797 try:
3798 # Disconnect from component
3799 component.disconnect()
You Wangf32c6ed2018-08-23 17:10:22 -07003800 component.close_log_handles()
Jon Hall892818c2015-10-20 17:58:34 -07003801 # Delete component
3802 delattr( main, name )
3803 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003804 del( main.componentDictionary[ name ] )
You Wangf32c6ed2018-08-23 17:10:22 -07003805 except StandardError:
3806 self.log.exception( "Exception while closing log files for " + name )
3807 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003808 except pexpect.EOF:
3809 main.log.error( self.name + ": EOF exception found" )
3810 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003811 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003812 except Exception:
3813 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003814 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003815
3816 def startHostCli( self, host=None ):
3817 """
3818 Use the mininet m utility to connect to the host's cli
3819 """
3820 # These are fields that can be used by scapy packets. Initialized to None
3821 self.hostIp = None
3822 self.hostMac = None
3823 try:
3824 if not host:
3825 host = self.name
3826 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003827 self.handle.sendline( "cd" )
3828 self.handle.expect( self.hostPrompt )
3829 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003830 self.handle.expect( self.hostPrompt )
3831 return main.TRUE
3832 except pexpect.TIMEOUT:
3833 main.log.exception( self.name + ": Command timed out" )
3834 return main.FALSE
3835 except pexpect.EOF:
3836 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003837 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003838 except Exception:
3839 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003840 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003841
YPZhang801d46d2016-08-08 13:26:28 -07003842 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003843 '''
3844
YPZhang801d46d2016-08-08 13:26:28 -07003845 Args:
3846 devicename: switch name
3847 intf: port name on switch
3848 status: up or down
3849
3850 Returns: boolean to show success change status
3851
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003852 '''
YPZhang801d46d2016-08-08 13:26:28 -07003853 if status == "down" or status == "up":
3854 try:
3855 cmd = devicename + " ifconfig " + intf + " " + status
3856 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003857 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003858 return main.TRUE
3859 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003860 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003861 return main.FALSE
3862 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003863 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003864 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003865 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003866 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003867 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003868 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003869 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003870 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003871 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003872 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003873 return main.FALSE
3874
You Wang6e5b48e2018-07-23 16:17:38 -07003875 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003876 """
You Wang6e5b48e2018-07-23 16:17:38 -07003877 Moves a host from one switch to another on the fly
3878 Optional:
3879 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3880 prefixLen: length of the host IP prefix
3881 ipv6: move an IPv6 host if True
3882 intfSuffix: suffix of the new interface after host movement
3883 vlan: vlan ID of the host. Use None for non-vlan host
3884 Note: The intf between host and oldSw when detached
3885 using detach(), will still show up in the 'net'
3886 cmd, because switch.detach() doesn't affect switch.intfs[]
3887 ( which is correct behavior since the interfaces
3888 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003889 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003890 if self.handle:
3891 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003892 newIntf = "%s-%s" % ( host, intfSuffix )
3893 commands = [
3894 # Bring link between oldSw-host down
3895 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3896 # Determine hostintf and Oldswitchintf
3897 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
3898 ]
3899 # Determine ip address of the host-oldSw interface
3900 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3901 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3902 commands += [
3903 # Determine mac address of the host-oldSw interface
3904 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3905 # Detach interface between oldSw-host
3906 "px " + oldSw + ".detach( sintf )",
3907 # Add link between host-newSw
3908 "py net.addLink(" + host + "," + newSw + ")",
3909 # Determine hostintf and Newswitchintf
3910 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3911 # Attach interface between newSw-host
3912 "px " + newSw + ".attach( sintf )",
3913 ]
3914 if vlan:
3915 vlanIntf = "%s.%s" % ( newIntf, vlan )
3916 commands += [
3917 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
3918 host + " ip link set up %s" % vlanIntf,
3919 "px hintf.name = '" + vlanIntf + "'",
3920 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
3921 ]
3922 newIntf = vlanIntf
3923 commands += [
3924 # Set mac address of the host-newSw interface
3925 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
3926 # Set IP address of the host-newSw interface
3927 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
3928 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
3929 ]
3930 if ipv6:
3931 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
3932 commands += [
3933 "net",
3934 host + " ifconfig"
3935 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003936 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003937 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003938 self.handle.sendline( cmd )
3939 self.handle.expect( "mininet>" )
3940 main.log.info( "====> %s ", self.handle.before )
3941 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003942 except pexpect.TIMEOUT:
3943 main.log.error( self.name + ": TIMEOUT exception found" )
3944 main.log.error( self.name + ": " + self.handle.before )
3945 main.cleanAndExit()
3946 except pexpect.EOF:
3947 main.log.error( self.name + ": EOF exception found" )
3948 main.log.error( self.name + ": " + self.handle.before )
3949 return main.FALSE
3950 except Exception:
3951 main.log.exception( self.name + ": Uncaught exception!" )
3952 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07003953
You Wang6e5b48e2018-07-23 16:17:38 -07003954 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
3955 macAddr=None, prefixLen=None, ipv6=False,
3956 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07003957 """
You Wang6e5b48e2018-07-23 16:17:38 -07003958 Moves a dual-homed host from one switch-pair to another pair on the fly
3959 Optional:
3960 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3961 prefixLen: length of the host IP prefix
3962 ipv6: move an IPv6 host if True
3963 intfSuffix1: suffix of the first new interface
3964 intfSuffix2: suffix of the second new interface
3965 bondSuffix: suffix of the new bond interface
3966 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07003967 """
You Wang7ea90582018-07-19 15:27:58 -07003968 if self.handle:
3969 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003970 bondIntf = "%s-%s" % ( host, bondSuffix )
3971 newIntf = "%s-%s" % ( host, intfSuffix1 )
3972 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07003973 commands = [
3974 # Bring link between oldSw-host down
3975 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3976 # Bring link between oldPairSw-host down
3977 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
3978 # Determine hostintf and Oldswitchintf
3979 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07003980 ]
3981 # Determine ip address of the host-oldSw interface
3982 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3983 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3984 commands += [
3985 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07003986 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3987 # Detach interface between oldSw-host
3988 "px " + oldSw + ".detach( sintf )",
3989 # Determine hostintf and Oldpairswitchintf
3990 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
3991 # Detach interface between oldPairSw-host
3992 "px " + oldPairSw + ".detach( sintfpair )",
3993 # Add link between host-newSw
3994 "py net.addLink(" + host + "," + newSw + ", 2)",
3995 # Add link between host-newPairSw
3996 "py net.addLink(" + host + "," + newPairSw + ")",
3997 # Determine hostintf and Newswitchintf
3998 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3999 # Determine hostintf and NewPairswitchintf
4000 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
4001 # Attach interface between newSw-host
4002 "px " + newSw + ".attach( sintf )",
4003 # Attach interface between newPairSw-host
4004 "px " + newPairSw + ".attach( sintfpair )",
4005 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07004006 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004007 host + ' ip link set %s down' % newIntf,
4008 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004009 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
4010 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07004011 host + ' ip addr flush dev %s' % newIntf,
4012 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004013 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004014 "px lowestIntf = min( [ hintf, hintfpair ] )",
4015 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07004016 "px lowestIntf.name = '" + bondIntf + "'",
4017 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07004018 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
4019 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07004020 ]
4021 if vlan:
4022 vlanIntf = "%s.%s" % ( bondIntf, vlan )
4023 commands += [
4024 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
4025 host + " ip link set up %s" % vlanIntf,
4026 "px lowestIntf.name = '" + vlanIntf + "'",
4027 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
4028 ]
4029 bondIntf = vlanIntf
4030 commands += [
4031 # Set macaddress of the host-newSw interface
4032 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07004033 # Set ipaddress of the host-newSw interface
4034 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
4035 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07004036 ]
You Wang6e5b48e2018-07-23 16:17:38 -07004037 if ipv6:
4038 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
4039 commands += [
4040 "net",
4041 host + " ifconfig"
4042 ]
You Wang7ea90582018-07-19 15:27:58 -07004043 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004044 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07004045 self.handle.sendline( cmd )
4046 self.handle.expect( "mininet>" )
4047 main.log.info( "====> %s ", self.handle.before )
4048 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07004049 except pexpect.TIMEOUT:
4050 main.log.error( self.name + ": TIMEOUT exception found" )
4051 main.log.error( self.name + ": " + self.handle.before )
4052 main.cleanAndExit()
4053 except pexpect.EOF:
4054 main.log.error( self.name + ": EOF exception found" )
4055 main.log.error( self.name + ": " + self.handle.before )
4056 return main.FALSE
4057 except Exception:
4058 main.log.exception( self.name + ": Uncaught exception!" )
4059 return main.FALSE
4060
adminbae64d82013-08-01 10:50:15 -07004061if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004062 sys.modules[ __name__ ] = MininetCliDriver()