blob: 120d8c99d97de33a7ce7c744e232f4c26e2b06c2 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
Jon Hall7eb38402015-01-08 17:19:54 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004Copyright 2012 Open Networking Foundation (ONF)
adminbae64d82013-08-01 10:50:15 -07005
Jeremy Songsterae01bba2016-07-11 15:39:17 -07006Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
7the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
8or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
adminbae64d82013-08-01 10:50:15 -07009
Jon Hall7eb38402015-01-08 17:19:54 -080010TestON is free software: you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation, either version 2 of the License, or
13( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070014
Jon Hall7eb38402015-01-08 17:19:54 -080015TestON is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070019
Jon Hall7eb38402015-01-08 17:19:54 -080020You should have received a copy of the GNU General Public License
21along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070022
Jon Hallbe6dfc42015-01-12 17:37:25 -080023MininetCliDriver is the basic driver which will handle the Mininet functions
24
25Some functions rely on a modified version of Mininet. These functions
26should all be noted in the comments. To get this MN version run these commands
27from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080028 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080029 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080030 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080031 git pull
32
Jon Hall272a4db2015-01-12 17:43:48 -080033
34 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080035changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070036import pexpect
adminbae64d82013-08-01 10:50:15 -070037import re
38import sys
kelvin-onlabfa6ada82015-06-11 13:06:24 -070039import types
kelvin-onlaba4074292015-07-09 15:19:49 -070040import os
Devin Lima7cfdbd2017-09-29 15:02:22 -070041import time
Jon Hall1ccf82c2014-10-15 14:55:16 -040042from math import pow
adminbae64d82013-08-01 10:50:15 -070043from drivers.common.cli.emulatordriver import Emulator
You Wangdb8cd0a2016-05-26 15:19:45 -070044from core.graph import Graph
adminbae64d82013-08-01 10:50:15 -070045
Jon Hall7eb38402015-01-08 17:19:54 -080046
kelvin-onlab50907142015-04-01 13:37:45 -070047class MininetCliDriver( Emulator ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -070048
Jon Hall7eb38402015-01-08 17:19:54 -080049 """
50 MininetCliDriver is the basic driver which will handle
51 the Mininet functions"""
52 def __init__( self ):
Devin Limdc78e202017-06-09 18:30:07 -070053 super( MininetCliDriver, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070054 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080055 self.name = None
kelvin-onlabd9e23de2015-08-06 10:34:44 -070056 self.home = None
Jon Hall7eb38402015-01-08 17:19:54 -080057 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070058 self.flag = 0
Jon Hall892818c2015-10-20 17:58:34 -070059 # TODO: Refactor driver to use these everywhere
60 self.mnPrompt = "mininet>"
61 self.hostPrompt = "~#"
62 self.bashPrompt = "\$"
63 self.scapyPrompt = ">>>"
You Wangdb8cd0a2016-05-26 15:19:45 -070064 self.graph = Graph()
adminbae64d82013-08-01 10:50:15 -070065
Jon Hall7eb38402015-01-08 17:19:54 -080066 def connect( self, **connectargs ):
67 """
68 Here the main is the TestON instance after creating
69 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080070 try:
71 for key in connectargs:
72 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070073 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080074 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070075 for key in self.options:
76 if key == "home":
77 self.home = self.options[ 'home' ]
78 break
79 if self.home is None or self.home == "":
80 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070081
82 try:
Jon Hall892818c2015-10-20 17:58:34 -070083 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070084 self.ip_address = os.getenv( str( self.ip_address ) )
85 else:
86 main.log.info( self.name +
87 ": Trying to connect to " +
88 self.ip_address )
89
90 except KeyError:
91 main.log.info( "Invalid host name," +
92 " connecting to local host instead" )
93 self.ip_address = 'localhost'
94 except Exception as inst:
95 main.log.error( "Uncaught exception: " + str( inst ) )
96
kelvin-onlaba1484582015-02-02 15:46:20 -080097 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070098 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080099 self ).connect(
100 user_name=self.user_name,
101 ip_address=self.ip_address,
102 port=None,
103 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -0800104
kelvin-onlaba1484582015-02-02 15:46:20 -0800105 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -0800106 main.log.info( "Connection successful to the host " +
107 self.user_name +
108 "@" +
109 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800110 return main.TRUE
111 else:
112 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800113 self.user_name +
114 "@" +
115 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800116 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800117 return main.FALSE
118 except pexpect.EOF:
119 main.log.error( self.name + ": EOF exception found" )
120 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700121 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800122 except Exception:
123 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700124 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -0800125
kelvin-onlab10e8d392015-06-03 13:53:45 -0700126 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800127 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700128 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000129 Starts Mininet accepts a topology(.py) file and/or an optional
kelvin-onlabf512e942015-06-08 19:42:59 -0700130 argument, to start the mininet, as a parameter.
131 Can also send regular mininet command to load up desired topology.
alison12f34c32016-06-10 14:39:21 -0700132 Eg. Pass in a string 'mn --topo=tree,3,3' to mnCmd
kelvin-onlabf512e942015-06-08 19:42:59 -0700133 Options:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000134 topoFile = file path for topology file (.py)
kelvin-onlabf512e942015-06-08 19:42:59 -0700135 args = extra option added when starting the topology from the file
136 mnCmd = Mininet command use to start topology
137 Returns:
138 main.TRUE if the mininet starts successfully, main.FALSE
139 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800140 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700141 try:
142 if self.handle:
143 # make sure old networks are cleaned up
144 main.log.info( self.name +
145 ": Clearing any residual state or processes" )
146 self.handle.sendline( "sudo mn -c" )
147 i = self.handle.expect( [ 'password\sfor\s',
148 'Cleanup\scomplete',
Jon Hallefbd9792015-03-05 16:11:36 -0800149 pexpect.EOF,
150 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700151 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800152 if i == 0:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700153 # Sudo asking for password
154 main.log.info( self.name + ": Sending sudo password" )
155 self.handle.sendline( self.pwd )
Jon Hall173f2a02018-01-11 13:56:37 -0800156 i = self.handle.expect( [ '%s:' % self.user_name,
Devin Limdc78e202017-06-09 18:30:07 -0700157 self.prompt,
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700158 pexpect.EOF,
159 pexpect.TIMEOUT ],
160 timeout )
161 if i == 1:
162 main.log.info( self.name + ": Clean" )
Jon Hall689d8e42015-04-03 13:59:24 -0700163 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700164 main.log.error( self.name + ": Connection terminated" )
165 elif i == 3: # timeout
166 main.log.error( self.name + ": Something while cleaning " +
167 "Mininet took too long... " )
168 # Craft the string to start mininet
169 cmdString = "sudo "
170 if not mnCmd:
171 if topoFile is None or topoFile == '': # If no file is given
172 main.log.info( self.name + ": building fresh Mininet" )
173 cmdString += "mn "
174 if args is None or args == '':
175 # If no args given, use args from .topo file
176 args = self.options[ 'arg1' ] +\
177 " " + self.options[ 'arg2' ] +\
178 " --mac --controller " +\
179 self.options[ 'controller' ] + " " +\
180 self.options[ 'arg3' ]
181 else: # else only use given args
182 pass
183 # TODO: allow use of topo args and method args?
184 else: # Use given topology file
185 main.log.info(
186 "Starting Mininet from topo file " +
187 topoFile )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700188 cmdString += "-E python " + topoFile + " "
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700189 if args is None:
190 args = ''
191 # TODO: allow use of args from .topo file?
192 cmdString += args
193 else:
194 main.log.info( "Starting Mininet topology using '" + mnCmd +
195 "' command" )
196 cmdString += mnCmd
197 # Send the command and check if network started
198 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -0700199 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700200 main.log.info( "Sending '" + cmdString + "' to " + self.name )
201 self.handle.sendline( cmdString )
Devin Lima7cfdbd2017-09-29 15:02:22 -0700202 startTime = time.time()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700203 while True:
204 i = self.handle.expect( [ 'mininet>',
Jon Hallbc743112018-04-18 11:09:01 -0700205 'Exception|Error',
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700206 '\*\*\*',
207 pexpect.EOF,
Jon Hallab611372018-02-21 15:26:05 -0800208 pexpect.TIMEOUT,
209 "No such file or directory"],
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700210 timeout )
211 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -0700212 main.log.info( self.name + ": Mininet built\nTime Took : " + str( time.time() - startTime ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700213 return main.TRUE
214 elif i == 1:
215 response = str( self.handle.before +
216 self.handle.after )
Devin Limdc78e202017-06-09 18:30:07 -0700217 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700218 response += str( self.handle.before +
219 self.handle.after )
220 main.log.error(
221 self.name +
222 ": Launching Mininet failed: " + response )
223 return main.FALSE
224 elif i == 2:
225 self.handle.expect( [ "\n",
226 pexpect.EOF,
227 pexpect.TIMEOUT ],
228 timeout )
229 main.log.info( self.handle.before )
230 elif i == 3:
231 main.log.error( self.name + ": Connection timeout" )
232 return main.FALSE
233 elif i == 4: # timeout
234 main.log.error(
235 self.name +
236 ": Something took too long... " )
Jon Hallbc743112018-04-18 11:09:01 -0700237 main.log.debug( self.handle.before + self.handle.after )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700238 return main.FALSE
Jon Hallab611372018-02-21 15:26:05 -0800239 elif i == 5:
240 main.log.error( self.name + ": " + self.handle.before + self.handle.after )
241 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700242 # Why did we hit this part?
243 main.log.error( "startNet did not return correctly" )
244 return main.FASLE
245 else: # if no handle
246 main.log.error( self.name + ": Connection failed to the host " +
247 self.user_name + "@" + self.ip_address )
248 main.log.error( self.name + ": Failed to connect to the Mininet" )
249 return main.FALSE
250 except pexpect.TIMEOUT:
251 main.log.exception( self.name + ": TIMEOUT exception found while starting Mininet" )
252 main.log.error( self.name + ": " + self.handle.before )
adminbae64d82013-08-01 10:50:15 -0700253 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700254 except pexpect.EOF:
255 main.log.error( self.name + ": EOF exception found" )
256 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700257 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700258 except Exception:
259 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700260 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800261
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800262 def numSwitchesNlinks( self, topoType, depth, fanout ):
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700263 try:
264 if topoType == 'tree':
265 # In tree topology, if fanout arg is not given, by default it is 2
266 if fanout is None:
267 fanout = 2
268 k = 0
269 count = 0
270 while( k <= depth - 1 ):
271 count = count + pow( fanout, k )
272 k = k + 1
273 numSwitches = count
274 while( k <= depth - 2 ):
275 # depth-2 gives you only core links and not considering
276 # edge links as seen by ONOS. If all the links including
277 # edge links are required, do depth-1
278 count = count + pow( fanout, k )
279 k = k + 1
280 numLinks = count * fanout
281 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
282 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800283
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700284 elif topoType == 'linear':
285 # In linear topology, if fanout or numHostsPerSw is not given,
286 # by default it is 1
287 if fanout is None:
288 fanout = 1
289 numSwitches = depth
290 numHostsPerSw = fanout
291 totalNumHosts = numSwitches * numHostsPerSw
292 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hallab611372018-02-21 15:26:05 -0800293 main.log.debug( "num_switches for %s(%d,%d) = %d and links=%d" %
294 ( topoType, depth, fanout, numSwitches, numLinks ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700295 topoDict = { "num_switches": int( numSwitches ),
296 "num_corelinks": int( numLinks ) }
297 return topoDict
298 except Exception:
299 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700300 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400301
kelvin-onlabd3b64892015-01-20 13:26:24 -0800302 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700303 """
304 Calculate the number of switches and links in a topo."""
305 # TODO: combine this function and numSwitchesNlinks
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700306 try:
307 argList = self.options[ 'arg1' ].split( "," )
308 topoArgList = argList[ 0 ].split( " " )
309 argList = map( int, argList[ 1: ] )
310 topoArgList = topoArgList[ 1: ] + argList
Jon Hall689d8e42015-04-03 13:59:24 -0700311
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700312 topoDict = self.numSwitchesNlinks( *topoArgList )
313 return topoDict
314 except Exception:
315 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700316 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400317
GlennRCf07c44a2015-09-18 13:33:46 -0700318 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800319 """
320 Verifies the reachability of the hosts using pingall command.
321 Optional parameter timeout allows you to specify how long to
322 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700323 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700324 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700325 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700326 ping
327 acceptableFailed - Set the number of acceptable failed pings for the
328 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800329 Returns:
330 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700331 otherwise main.FALSE
332 """
333 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700334 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700335 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700336 if self.handle:
337 main.log.info(
338 self.name +
339 ": Checking reachabilty to the hosts using pingall" )
340 response = ""
341 failedPings = 0
342 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700343 cmd = "pingall"
344 if protocol == "IPv6":
345 cmd = "py net.pingAll6()"
346 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700347 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700348 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700349 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700350 pexpect.EOF,
351 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700352 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700353 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700354 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700355 response += self.handle.before
356 break
357 elif i == 1:
358 response += self.handle.before + self.handle.after
359 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700360 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700361 returnValue = main.FALSE
362 if shortCircuit:
363 main.log.error( self.name +
364 ": Aborting pingall - "
365 + str( failedPings ) +
366 " pings failed" )
367 break
Jon Hall390696c2015-05-05 17:13:41 -0700368 if ( time.time() - startTime ) > timeout:
369 returnValue = main.FALSE
370 main.log.error( self.name +
371 ": Aborting pingall - " +
372 "Function took too long " )
373 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700374 elif i == 2:
375 main.log.error( self.name +
376 ": EOF exception found" )
377 main.log.error( self.name + ": " +
378 self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700379 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700380 elif i == 3:
381 response += self.handle.before
382 main.log.error( self.name +
383 ": TIMEOUT exception found" )
384 main.log.error( self.name +
385 ": " +
386 str( response ) )
387 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800388 self.handle.send( "\x03" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700389 self.handle.expect( "Interrupt" )
390 self.handle.expect( "mininet>" )
391 break
392 pattern = "Results\:"
393 main.log.info( "Pingall output: " + str( response ) )
394 if re.search( pattern, response ):
395 main.log.info( self.name + ": Pingall finished with "
396 + str( failedPings ) + " failed pings" )
397 return returnValue
398 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700399 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800400 self.handle.send( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700401 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700402 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700403 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700404 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700405 main.log.error( self.name + ": Connection failed to the host" )
Devin Lim44075962017-08-11 10:56:37 -0700406 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700407 except pexpect.TIMEOUT:
408 if response:
409 main.log.info( "Pingall output: " + str( response ) )
410 main.log.error( self.name + ": pexpect.TIMEOUT found" )
411 return main.FALSE
412 except pexpect.EOF:
413 main.log.error( self.name + ": EOF exception found" )
414 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700415 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -0700416
Jon Hall7eb38402015-01-08 17:19:54 -0800417 def fpingHost( self, **pingParams ):
418 """
419 Uses the fping package for faster pinging...
420 *requires fping to be installed on machine running mininet"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700421 try:
422 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
423 command = args[ "SRC" ] + \
424 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
425 self.handle.sendline( command )
426 self.handle.expect(
427 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
428 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
429 response = self.handle.before
430 if re.search( ":\s-", response ):
431 main.log.info( self.name + ": Ping fail" )
432 return main.FALSE
433 elif re.search( ":\s\d{1,2}\.\d\d", response ):
434 main.log.info( self.name + ": Ping good!" )
435 return main.TRUE
436 main.log.info( self.name + ": Install fping on mininet machine... " )
437 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700438 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700439 except Exception:
440 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700441 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700442
Jon Hall3b489db2015-10-05 14:38:37 -0700443 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400444 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700445 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700446
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400447 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700448 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700449
450 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400451 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700452
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400453 Returns main.FALSE if one or more of hosts specified
454 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700455 wait = int( wait )
456 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400457
458 try:
459 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700460
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400461 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700462 pingResponse = "IPv4 ping across specified hosts\n"
463 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400464 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700465 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400466 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700467 pingList = hostList[ :listIndex ] + \
468 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700469
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700470 pingResponse += str( str( host ) + " -> " )
GlennRCd10d3cc2015-09-24 12:47:16 -0700471
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400472 for temp in pingList:
473 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700474 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700475 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700476 self.handle.expect( "mininet>", timeout=wait + 5 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400477 response = self.handle.before
478 if re.search( ',\s0\%\spacket\sloss', response ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700479 pingResponse += str( " h" + str( temp[ 1: ] ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400480 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700481 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400482 # One of the host to host pair is unreachable
483 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700484 failedPings += 1
You Wang11f9ead2018-03-21 14:34:59 -0700485 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
GlennRCd10d3cc2015-09-24 12:47:16 -0700486 pingResponse += "\n"
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700487 main.log.info( pingResponse + "Failed pings: " + str( failedPings ) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700488 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700489 except pexpect.TIMEOUT:
490 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800491 response = self.handle.before
492 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700493 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800494 self.handle.expect( "Interrupt" )
495 response += self.handle.before + self.handle.after
496 self.handle.expect( "mininet>" )
497 response += self.handle.before + self.handle.after
498 main.log.debug( response )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700499 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400500 except pexpect.EOF:
501 main.log.error( self.name + ": EOF exception found" )
502 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700503 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700504 except Exception:
505 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700506 main.cleanAndExit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400507
You Wangf19d9f42018-02-23 16:34:19 -0800508 def pingIpv6Hosts( self, hostList, wait=1, acceptableFailed=0 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700509 """
You Wangf19d9f42018-02-23 16:34:19 -0800510 IPv6 ping all hosts in hostList.
511
512 acceptableFailed: max number of acceptable failed pings
Hari Krishna9592fc82015-07-31 15:11:15 -0700513
Jon Hall3b489db2015-10-05 14:38:37 -0700514 Returns main.TRUE if all hosts specified can reach each other
Jon Hall3b489db2015-10-05 14:38:37 -0700515 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700516 """
517 try:
518 main.log.info( "Testing reachability between specified IPv6 hosts" )
519 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700520 wait = int( wait )
521 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700522 pingResponse = "IPv6 Pingall output:\n"
You Wangf19d9f42018-02-23 16:34:19 -0800523 failedPingsTotal = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700524 for host in hostList:
525 listIndex = hostList.index( host )
526 # List of hosts to ping other than itself
527 pingList = hostList[ :listIndex ] + \
528 hostList[ ( listIndex + 1 ): ]
529
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700530 pingResponse += str( str( host ) + " -> " )
GlennRC2cf7d952015-09-11 16:32:13 -0700531
Hari Krishna9592fc82015-07-31 15:11:15 -0700532 for temp in pingList:
533 # Current host pings all other hosts specified
You Wangf19d9f42018-02-23 16:34:19 -0800534 failedPings = 0
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700535 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
You Wangf19d9f42018-02-23 16:34:19 -0800536 while failedPings <= acceptableFailed:
537 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
538 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700539 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangf19d9f42018-02-23 16:34:19 -0800540 response = self.handle.before
541 if re.search( ',\s0\%\spacket\sloss', response ):
You Wangba231e72018-03-01 13:18:21 -0800542 pingResponse += " " + str( temp )
543 break
544 else:
545 failedPings += 1
546 time.sleep(1)
547 if failedPings > acceptableFailed:
548 # One of the host to host pair is unreachable
549 pingResponse += " X"
550 isReachable = main.FALSE
551 failedPingsTotal += 1
You Wang11f9ead2018-03-21 14:34:59 -0700552 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
You Wangba231e72018-03-01 13:18:21 -0800553 pingResponse += "\n"
554 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
555 return isReachable
556
557 except pexpect.TIMEOUT:
558 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800559 response = self.handle.before
560 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700561 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800562 self.handle.expect( "Interrupt" )
563 response += self.handle.before + self.handle.after
564 self.handle.expect( "mininet>" )
565 response += self.handle.before + self.handle.after
566 main.log.debug( response )
You Wangba231e72018-03-01 13:18:21 -0800567 return main.FALSE
568 except pexpect.EOF:
569 main.log.error( self.name + ": EOF exception found" )
570 main.log.error( self.name + ": " + self.handle.before )
571 main.cleanAndExit()
572 except Exception:
573 main.log.exception( self.name + ": Uncaught exception!" )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700574
575 main.cleanAndExit()
576
You Wang48381752018-05-07 13:50:57 -0700577 def discoverHosts( self, hostList=[], wait=1, dstIp="6.6.6.6", dstIp6="1020::3fe" ):
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700578 '''
You Wang48381752018-05-07 13:50:57 -0700579 Hosts in hostList will do a single ping to a non-existent address for ONOS to
580 discover them. A host will use ping/ping6 to send echo requests depending on if
581 it has IPv4/IPv6 addresses configured.
582 Optional:
583 hostList: a list of names of the hosts that need to be discovered. If not
584 specified mininet will send ping from all the hosts
585 wait: timeout for IPv4/IPv6 echo requests
586 dstIp: destination address used by IPv4 hosts
587 dstIp6: destination address used by IPv6 hosts
588 Returns:
589 main.TRUE if all ping packets were successfully sent. Otherwise main.FALSE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700590 '''
591 try:
You Wang48381752018-05-07 13:50:57 -0700592 if not hostList:
593 hosts = self.getHosts( getInterfaces=False )
594 hostList = hosts.keys()
595 discoveryResult = main.TRUE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700596 for host in hostList:
You Wang0b82aa52018-06-06 14:33:58 -0700597 flushCmd = ""
You Wang48381752018-05-07 13:50:57 -0700598 cmd = ""
599 if self.getIPAddress( host ):
You Wang0b82aa52018-06-06 14:33:58 -0700600 flushCmd = "{} ip neigh flush all".format( host )
You Wang48381752018-05-07 13:50:57 -0700601 cmd = "{} ping -c 1 -i 1 -W {} {}".format( host, wait, dstIp )
602 main.log.debug( "Sending IPv4 probe ping from host {}".format( host ) )
603 elif self.getIPAddress( host, proto='IPV6' ):
You Wang0b82aa52018-06-06 14:33:58 -0700604 flushCmd = "{} ip -6 neigh flush all".format( host )
You Wang48381752018-05-07 13:50:57 -0700605 cmd = "{} ping6 -c 1 -i 1 -W {} {}".format( host, wait, dstIp6 )
606 main.log.debug( "Sending IPv6 probe ping from host {}".format( host ) )
607 else:
608 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
609 discoveryResult = main.FALSE
610 if cmd:
You Wang0b82aa52018-06-06 14:33:58 -0700611 self.handle.sendline( flushCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700612 self.handle.expect( "mininet>" )
You Wang48381752018-05-07 13:50:57 -0700613 self.handle.sendline( cmd )
Jon Halla604fd42018-05-04 14:27:27 -0700614 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700615 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700616 except pexpect.TIMEOUT:
617 main.log.exception( self.name + ": TIMEOUT exception" )
618 response = self.handle.before
619 # NOTE: Send ctrl-c to make sure command is stopped
620 self.handle.send( "\x03" )
621 self.handle.expect( "Interrupt" )
622 response += self.handle.before + self.handle.after
623 self.handle.expect( "mininet>" )
624 response += self.handle.before + self.handle.after
625 main.log.debug( response )
626 return main.FALSE
627 except pexpect.EOF:
628 main.log.error( self.name + ": EOF exception found" )
629 main.log.error( self.name + ": " + self.handle.before )
630 main.cleanAndExit()
631 except Exception:
632 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800633 main.cleanAndExit()
634
635 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
636 """
637 Verify ping from each host in srcList to each host in dstList
638
639 acceptableFailed: max number of acceptable failed pings
640
641 Returns main.TRUE if all src hosts can reach all dst hosts
642 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
643 """
644 try:
645 main.log.info( "Verifying ping from each src host to each dst host" )
646 isReachable = main.TRUE
647 wait = int( wait )
648 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
649 pingResponse = "Ping output:\n"
650 failedPingsTotal = 0
651 for host in srcList:
652 pingResponse += str( str( host ) + " -> " )
653 for temp in dstList:
654 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700655 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
656 assert dstIP, "Not able to get IP address of host {}".format( temp )
657 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800658 while failedPings <= acceptableFailed:
659 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
660 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700661 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800662 response = self.handle.before
663 if re.search( ',\s0\%\spacket\sloss', response ):
664 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800665 break
666 else:
667 failedPings += 1
668 time.sleep(1)
669 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700670 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800671 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700672 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800673 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700674 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800675 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700676 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700677 except AssertionError:
678 main.log.exception( "" )
679 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700680 except pexpect.TIMEOUT:
681 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800682 response = self.handle.before
683 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700684 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800685 self.handle.expect( "Interrupt" )
686 response += self.handle.before + self.handle.after
687 self.handle.expect( "mininet>" )
688 response += self.handle.before + self.handle.after
689 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700690 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700691 except pexpect.EOF:
692 main.log.error( self.name + ": EOF exception found" )
693 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700694 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700695 except Exception:
696 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700697 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700698
Jon Hall7eb38402015-01-08 17:19:54 -0800699 def pingHost( self, **pingParams ):
700 """
Jon Hall3b489db2015-10-05 14:38:37 -0700701 Ping from one mininet host to another
702 Currently the only supported Params: SRC, TARGET, and WAIT
703 """
704 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700705 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700706 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800707 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700708 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700709 try:
Jon Hall61282e32015-03-19 11:34:11 -0700710 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800711 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700712 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700713 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700714 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800715 main.log.error(
716 self.name +
717 ": timeout when waiting for response from mininet" )
718 main.log.error( "response: " + str( self.handle.before ) )
719 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700720 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800721 main.log.error(
722 self.name +
723 ": timeout when waiting for response from mininet" )
724 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700725 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700726 if re.search( ',\s0\%\spacket\sloss', response ):
727 main.log.info( self.name + ": no packets lost, host is reachable" )
728 return main.TRUE
729 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800730 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700731 self.name +
732 ": PACKET LOST, HOST IS NOT REACHABLE" )
733 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800734 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800735 main.log.error( self.name + ": EOF exception found" )
736 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700737 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700738 except Exception:
739 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700740 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700741
742 def ping6pair( self, **pingParams ):
743 """
GlennRC2cf7d952015-09-11 16:32:13 -0700744 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700745 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000746 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700747 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
748 """
Jon Hall3b489db2015-10-05 14:38:37 -0700749 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700750 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700751 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530752 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700753 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700754 try:
755 main.log.info( "Sending: " + command )
756 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700757 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700758 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700759 if i == 1:
760 main.log.error(
761 self.name +
762 ": timeout when waiting for response from mininet" )
763 main.log.error( "response: " + str( self.handle.before ) )
764 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
765 if i == 1:
766 main.log.error(
767 self.name +
768 ": timeout when waiting for response from mininet" )
769 main.log.error( "response: " + str( self.handle.before ) )
770 response = self.handle.before
771 main.log.info( self.name + ": Ping Response: " + response )
772 if re.search( ',\s0\%\spacket\sloss', response ):
773 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700774 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700775 else:
alisone4121a92016-11-22 16:31:36 -0800776 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700777 self.name +
778 ": PACKET LOST, HOST IS NOT REACHABLE" )
779 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700780 except pexpect.EOF:
781 main.log.error( self.name + ": EOF exception found" )
782 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700783 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700784 except Exception:
785 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700786 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800787
You Wangdb927a52016-02-26 11:03:28 -0800788 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
789 """
790 Description:
791 Ping a set of destination host from host CLI.
792 Logging into a Mininet host CLI is required before calling this funtion.
793 Params:
794 dstIPList is a list of destination ip addresses
795 Returns:
796 main.TRUE if the destination host is reachable
797 main.FALSE otherwise
798 """
799 isReachable = main.TRUE
800 wait = int( wait )
801 cmd = "ping"
802 if IPv6:
803 cmd = cmd + "6"
804 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
805 try:
806 for dstIP in dstIPList:
807 pingCmd = cmd + " " + dstIP
808 self.handle.sendline( pingCmd )
809 i = self.handle.expect( [ self.hostPrompt,
810 '\*\*\* Unknown command: ' + pingCmd,
811 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700812 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700813 # For some reason we need to send something
814 # Otherwise ping results won't be read by handle
815 self.handle.sendline( "" )
816 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800817 if i == 0:
818 response = self.handle.before
819 if not re.search( ',\s0\%\spacket\sloss', response ):
820 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
821 isReachable = main.FALSE
822 elif i == 1:
823 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700824 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800825 elif i == 2:
826 main.log.error( self.name + ": timeout when waiting for response" )
827 isReachable = main.FALSE
828 else:
829 main.log.error( self.name + ": unknown response: " + self.handle.before )
830 isReachable = main.FALSE
831 except pexpect.TIMEOUT:
832 main.log.exception( self.name + ": TIMEOUT exception" )
You Wangd4fae5c2018-08-22 13:56:49 -0700833 self.exitFromCmd( [ self.hostPrompt, self.bashPrompt ] )
You Wangdb927a52016-02-26 11:03:28 -0800834 isReachable = main.FALSE
835 except pexpect.EOF:
836 main.log.error( self.name + ": EOF exception found" )
837 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700838 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800839 except Exception:
840 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700841 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800842 return isReachable
843
Jon Hall7eb38402015-01-08 17:19:54 -0800844 def checkIP( self, host ):
845 """
846 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700847 try:
848 if self.handle:
849 try:
850 response = self.execute(
851 cmd=host +
852 " ifconfig",
853 prompt="mininet>",
854 timeout=10 )
855 except pexpect.EOF:
856 main.log.error( self.name + ": EOF exception found" )
857 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700858 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700859
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700860 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
861 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
862 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
863 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
864 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
865 "[0-9]|25[0-5]|[0-9]{1,2})"
866 # pattern = "inet addr:10.0.0.6"
867 if re.search( pattern, response ):
868 main.log.info( self.name + ": Host Ip configured properly" )
869 return main.TRUE
870 else:
871 main.log.error( self.name + ": Host IP not found" )
872 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700873 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700874 main.log.error( self.name + ": Connection failed to the host" )
875 except Exception:
876 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700877 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800878
Jon Hall7eb38402015-01-08 17:19:54 -0800879 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800880 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700881 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800882 response = self.execute(
883 cmd="h1 /usr/sbin/sshd -D&",
884 prompt="mininet>",
885 timeout=10 )
886 response = self.execute(
887 cmd="h4 /usr/sbin/sshd -D&",
888 prompt="mininet>",
889 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700890 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800891 vars( self )[ key ] = connectargs[ key ]
892 response = self.execute(
893 cmd="xterm h1 h4 ",
894 prompt="mininet>",
895 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800896 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800897 main.log.error( self.name + ": EOF exception found" )
898 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700899 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700900 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800901 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700902 if self.flag == 0:
903 self.flag = 1
904 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800905 else:
adminbae64d82013-08-01 10:50:15 -0700906 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800907
Jon Hall7eb38402015-01-08 17:19:54 -0800908 def changeIP( self, host, intf, newIP, newNetmask ):
909 """
910 Changes the ip address of a host on the fly
911 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800912 if self.handle:
913 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800914 cmd = host + " ifconfig " + intf + " " + \
915 newIP + " " + 'netmask' + " " + newNetmask
916 self.handle.sendline( cmd )
917 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800918 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800919 main.log.info( "response = " + response )
920 main.log.info(
921 "Ip of host " +
922 host +
923 " changed to new IP " +
924 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800925 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700926 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700927 main.log.error( self.name + ": TIMEOUT exception found" )
928 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700929 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800930 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800931 main.log.error( self.name + ": EOF exception found" )
932 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800933 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700934 except Exception:
935 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700936 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800937
Jon Hall7eb38402015-01-08 17:19:54 -0800938 def changeDefaultGateway( self, host, newGW ):
939 """
940 Changes the default gateway of a host
941 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800942 if self.handle:
943 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800944 cmd = host + " route add default gw " + newGW
945 self.handle.sendline( cmd )
946 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800947 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800948 main.log.info( "response = " + response )
949 main.log.info(
950 "Default gateway of host " +
951 host +
952 " changed to " +
953 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800954 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700955 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700956 main.log.error( self.name + ": TIMEOUT exception found" )
957 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700958 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800959 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800960 main.log.error( self.name + ": EOF exception found" )
961 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800962 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700963 except Exception:
964 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700965 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800966
You Wange24d6272018-03-27 21:18:50 -0700967 def addRoute( self, host, dstIP, interface, ipv6=False ):
968 """
969 Add a route to host
970 Ex: h1 route add -host 224.2.0.1 h1-eth0
971 """
972 if self.handle:
973 try:
974 cmd = str( host )
975 if ipv6:
976 cmd += " route -A inet6 add "
977 else:
978 cmd += " route add -host "
979 cmd += str( dstIP ) + " " + str( interface )
980 self.handle.sendline( cmd )
981 self.handle.expect( "mininet>" )
982 response = self.handle.before
983 main.log.debug( "response = " + response )
984 return main.TRUE
985 except pexpect.TIMEOUT:
986 main.log.error( self.name + ": TIMEOUT exception found" )
987 main.log.error( self.name + ": " + self.handle.before )
988 main.cleanAndExit()
989 except pexpect.EOF:
990 main.log.error( self.name + ": EOF exception found" )
991 main.log.error( self.name + ": " + self.handle.before )
992 return main.FALSE
993 except Exception:
994 main.log.exception( self.name + ": Uncaught exception!" )
995 main.cleanAndExit()
996
Jon Hall7eb38402015-01-08 17:19:54 -0800997 def addStaticMACAddress( self, host, GW, macaddr ):
998 """
Jon Hallefbd9792015-03-05 16:11:36 -0800999 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001000 if self.handle:
1001 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001002 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1003 cmd = host + " arp -s " + GW + " " + macaddr
1004 self.handle.sendline( cmd )
1005 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001006 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001007 main.log.info( "response = " + response )
1008 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001009 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001010 GW +
1011 " changed to " +
1012 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001013 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001014 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001015 main.log.error( self.name + ": TIMEOUT exception found" )
1016 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001017 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001018 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001019 main.log.error( self.name + ": EOF exception found" )
1020 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001021 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001022 except Exception:
1023 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001024 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001025
Jon Hall7eb38402015-01-08 17:19:54 -08001026 def verifyStaticGWandMAC( self, host ):
1027 """
1028 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001029 if self.handle:
1030 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001031 # h1 arp -an
1032 cmd = host + " arp -an "
1033 self.handle.sendline( cmd )
1034 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001035 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001036 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001037 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001038 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001039 main.log.error( self.name + ": TIMEOUT exception found" )
1040 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001041 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001042 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001043 main.log.error( self.name + ": EOF exception found" )
1044 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001045 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001046 except Exception:
1047 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001048 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001049
Jon Hall7eb38402015-01-08 17:19:54 -08001050 def getMacAddress( self, host ):
1051 """
1052 Verifies the host's ip configured or not."""
1053 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001054 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001055 response = self.execute(
1056 cmd=host +
1057 " ifconfig",
1058 prompt="mininet>",
1059 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001060 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001061 main.log.error( self.name + ": EOF exception found" )
1062 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001063 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001064 except Exception:
1065 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001066 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001067
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001068 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001069 macAddressSearch = re.search( pattern, response, re.I )
1070 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001071 main.log.info(
1072 self.name +
1073 ": Mac-Address of Host " +
1074 host +
1075 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001076 macAddress )
1077 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001078 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001079 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001080
Jon Hall7eb38402015-01-08 17:19:54 -08001081 def getInterfaceMACAddress( self, host, interface ):
1082 """
1083 Return the IP address of the interface on the given host"""
1084 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001085 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001086 response = self.execute( cmd=host + " ifconfig " + interface,
1087 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001088 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001089 main.log.error( self.name + ": EOF exception found" )
1090 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001091 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001092 except Exception:
1093 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001094 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001095
1096 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001097 macAddressSearch = re.search( pattern, response, re.I )
1098 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001099 main.log.info( "No mac address found in %s" % response )
1100 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001101 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001102 main.log.info(
1103 "Mac-Address of " +
1104 host +
1105 ":" +
1106 interface +
1107 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001108 macAddress )
1109 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001110 else:
1111 main.log.error( "Connection failed to the host" )
1112
You Wang5da39c82018-04-26 22:55:08 -07001113 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001114 """
1115 Verifies the host's ip configured or not."""
1116 if self.handle:
1117 try:
1118 response = self.execute(
1119 cmd=host +
1120 " ifconfig",
1121 prompt="mininet>",
1122 timeout=10 )
1123 except pexpect.EOF:
1124 main.log.error( self.name + ": EOF exception found" )
1125 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001126 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001127 except Exception:
1128 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001129 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001130
sathishmad953462015-12-03 17:42:07 +05301131 pattern = ''
1132 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001133 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301134 else:
Jon Hall439c8912016-04-15 02:22:03 -07001135 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001136 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001137 if not ipAddressSearch:
1138 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001139 main.log.info(
1140 self.name +
1141 ": IP-Address of Host " +
1142 host +
1143 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001144 ipAddressSearch.group( 1 ) )
1145 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001146 else:
1147 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001148
Jon Hall7eb38402015-01-08 17:19:54 -08001149 def getSwitchDPID( self, switch ):
1150 """
1151 return the datapath ID of the switch"""
1152 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001153 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001154 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001155 response = self.execute(
1156 cmd=cmd,
1157 prompt="mininet>",
1158 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001159 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001160 main.log.error( self.name + ": EOF exception found" )
1161 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001162 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001163 except Exception:
1164 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001165 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001166 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001167 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001168 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001169 main.log.info(
1170 "Couldn't find DPID for switch %s, found: %s" %
1171 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001172 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001173 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001174 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001175 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001176
Jon Hall7eb38402015-01-08 17:19:54 -08001177 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001178 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001179 self.handle.sendline( "" )
1180 self.expect( "mininet>" )
1181 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001182 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001183 response = self.execute(
1184 cmd=cmd,
1185 prompt="mininet>",
1186 timeout=10 )
1187 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001188 response = self.handle.before
1189 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001190 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001191 main.log.error( self.name + ": TIMEOUT exception found" )
1192 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001193 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001194 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001195 main.log.error( self.name + ": EOF exception found" )
1196 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001197 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001198 except Exception:
1199 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001200 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001201
Jon Hall7eb38402015-01-08 17:19:54 -08001202 def getInterfaces( self, node ):
1203 """
1204 return information dict about interfaces connected to the node"""
1205 if self.handle:
1206 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001207 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001208 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001209 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001210 response = self.execute(
1211 cmd=cmd,
1212 prompt="mininet>",
1213 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001214 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001215 main.log.error( self.name + ": EOF exception found" )
1216 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001217 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001218 except Exception:
1219 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001220 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001221 return response
1222 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001223 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001224
Jon Hall7eb38402015-01-08 17:19:54 -08001225 def dump( self ):
1226 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001227 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001228 response = self.execute(
1229 cmd='dump',
1230 prompt='mininet>',
1231 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001232 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001233 main.log.error( self.name + ": EOF exception found" )
1234 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001235 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001236 except Exception:
1237 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001238 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001239 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001240
Jon Hall7eb38402015-01-08 17:19:54 -08001241 def intfs( self ):
1242 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001243 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001244 response = self.execute(
1245 cmd='intfs',
1246 prompt='mininet>',
1247 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001248 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001249 main.log.error( self.name + ": EOF exception found" )
1250 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001251 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001252 except Exception:
1253 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001254 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001255 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001256
Jon Hall7eb38402015-01-08 17:19:54 -08001257 def net( self ):
1258 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001259 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001260 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001261 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001262 main.log.error( self.name + ": EOF exception found" )
1263 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001264 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001265 except Exception:
1266 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001267 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001268 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001269
Devin Lima7cfdbd2017-09-29 15:02:22 -07001270 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001271 main.log.info( self.name + ": List network links" )
1272 try:
1273 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001274 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001275 except pexpect.EOF:
1276 main.log.error( self.name + ": EOF exception found" )
1277 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001278 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001279 except Exception:
1280 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001281 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001282 return response
1283
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001284 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001285 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001286 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001287
kelvin-onlab7cce9382015-07-17 10:21:03 -07001288 @parm:
1289 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1290 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001291 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001292 try:
1293 for host1 in hosts:
1294 for host2 in hosts:
1295 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001296 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1297 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001298 except Exception:
1299 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001300 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001301
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001302 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001303 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001304 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1305 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001306
kelvin-onlab7cce9382015-07-17 10:21:03 -07001307 @parm:
1308 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1309 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001310 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001311 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1312 try:
1313 # Setup the mininet command
1314 cmd1 = 'iperf ' + host1 + " " + host2
1315 self.handle.sendline( cmd1 )
1316 outcome = self.handle.expect( "mininet>", timeout )
1317 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001318
kelvin-onlab7cce9382015-07-17 10:21:03 -07001319 # checks if there are results in the mininet response
1320 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001321 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001322 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001323 response = response.split( "\r\n" )
1324 response = response[ len( response )-2 ]
1325 response = response.split( ": " )
1326 response = response[ len( response )-1 ]
1327 response = response.replace( "[", "" )
1328 response = response.replace( "]", "" )
1329 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001330
kelvin-onlab7cce9382015-07-17 10:21:03 -07001331 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001332 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001333
kelvin-onlab7cce9382015-07-17 10:21:03 -07001334 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001335 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001336 if len( bandwidth ) == 2:
1337 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001338 return main.TRUE
1339 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001340 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001341 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001342 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001343 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001344 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001345 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001346 main.log.error( self.name + ": TIMEOUT exception found" )
1347 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001348 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001349 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001350 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001351 self.handle.expect( "Interrupt" )
1352 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001353 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001354 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001355 main.log.error( self.name + ": EOF exception found" )
1356 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001357 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001358 except Exception:
1359 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001360 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001361
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001362 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001363 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1364 try:
1365 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001366 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001367 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001368 outcome1 = self.handle.expect( "mininet>" )
1369 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001370 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001371 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001372 response1 = self.handle.before
1373 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001374 print response1, response2
1375 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001376 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001377 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001378 return main.TRUE
1379 else:
1380 main.log.error( self.name + ": iperf test failed" )
1381 return main.FALSE
1382 except pexpect.TIMEOUT:
1383 main.log.error( self.name + ": TIMEOUT exception found" )
1384 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001385 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001386 self.handle.expect( "Interrupt" )
1387 self.handle.expect( "mininet>" )
1388 return main.FALSE
1389 except pexpect.EOF:
1390 main.log.error( self.name + ": EOF exception found" )
1391 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001392 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001393 except Exception:
1394 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001395 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001396
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001397 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001398 '''
GlennRC61321f22015-07-16 13:36:54 -07001399 Runs the iperfudp function with a given set of hosts and specified
1400 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001401
GlennRC61321f22015-07-16 13:36:54 -07001402 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001403 bandwidth: the targeted bandwidth, in megabits ('M')
1404 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001405 try:
1406 for host1 in hosts:
1407 for host2 in hosts:
1408 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001409 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1410 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001411 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001412 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001413 return main.FALSE
1414 except Exception:
1415 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001416 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001417
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001418 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001419 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001420 Creates an iperf UDP test with a specific bandwidth.
1421 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001422
kelvin-onlab7cce9382015-07-17 10:21:03 -07001423 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001424 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1425 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001426 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001427 try:
1428 # setup the mininet command
1429 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001430 self.handle.sendline( cmd )
1431 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001432 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001433
kelvin-onlab7cce9382015-07-17 10:21:03 -07001434 # check if there are in results in the mininet response
1435 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001436 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001437 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001438 response = response.split( "\r\n" )
1439 response = response[ len( response )-2 ]
1440 response = response.split( ": " )
1441 response = response[ len( response )-1 ]
1442 response = response.replace( "[", "" )
1443 response = response.replace( "]", "" )
1444 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001445
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001446 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001447
kelvin-onlab7cce9382015-07-17 10:21:03 -07001448 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001449 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001450 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001451 # if one entry is blank then something is wrong
1452 for item in mnBandwidth:
1453 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001454 main.log.error( self.name + ": Could not parse iperf output" )
1455 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001456 return main.FALSE
1457 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001458 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001459 return main.TRUE
1460 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001461 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001462 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001463
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001464 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001465 main.log.error( self.name + ": TIMEOUT exception found" )
1466 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001467 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001468 except pexpect.EOF:
1469 main.log.error( self.name + ": EOF exception found" )
1470 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001471 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001472 except Exception:
1473 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001474 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001475
Jon Hall7eb38402015-01-08 17:19:54 -08001476 def nodes( self ):
1477 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001478 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001479 response = self.execute(
1480 cmd='nodes',
1481 prompt='mininet>',
1482 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001483 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001484 main.log.error( self.name + ": EOF exception found" )
1485 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001486 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001487 except Exception:
1488 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001489 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001490 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001491
Jon Hall7eb38402015-01-08 17:19:54 -08001492 def pingpair( self ):
1493 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001494 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001495 response = self.execute(
1496 cmd='pingpair',
1497 prompt='mininet>',
1498 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001499 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001500 main.log.error( self.name + ": EOF exception found" )
1501 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001502 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001503 except Exception:
1504 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001505 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001506
Jon Hall7eb38402015-01-08 17:19:54 -08001507 if re.search( ',\s0\%\spacket\sloss', response ):
1508 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001509 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001510 else:
alisone4121a92016-11-22 16:31:36 -08001511 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001512 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001513
Jon Hall7eb38402015-01-08 17:19:54 -08001514 def link( self, **linkargs ):
1515 """
GlennRCed771242016-01-13 17:02:47 -08001516 Bring link( s ) between two nodes up or down
1517 """
Jon Hall6094a362014-04-11 14:46:56 -07001518 try:
GlennRCed771242016-01-13 17:02:47 -08001519 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1520 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1521 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1522 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1523
1524 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1525 cmd = "link {} {} {}".format( end1, end2, option )
1526 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001527 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001528 response = self.handle.before
1529 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001530 if "not in network" in response:
1531 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1532 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001533 return main.TRUE
1534 except pexpect.TIMEOUT:
1535 main.log.exception( self.name + ": Command timed out" )
1536 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001537 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001538 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001539 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001540 except Exception:
1541 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001542 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001543
pingping-lin8244a3b2015-09-16 13:36:56 -07001544 def switch( self, **switchargs ):
1545 """
1546 start/stop a switch
1547 """
1548 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1549 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1550 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1551 command = "switch " + str( sw ) + " " + str( option )
1552 main.log.info( command )
1553 try:
1554 self.handle.sendline( command )
1555 self.handle.expect( "mininet>" )
1556 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001557 main.log.error( self.name + ": TIMEOUT exception found" )
1558 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001559 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001560 except pexpect.EOF:
1561 main.log.error( self.name + ": EOF exception found" )
1562 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001563 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001564 return main.TRUE
1565
pingping-lin5bb663b2015-09-24 11:47:50 -07001566 def node( self, nodeName, commandStr ):
1567 """
1568 Carry out a command line on a given node
1569 @parm:
1570 nodeName: the node name in Mininet testbed
1571 commandStr: the command line will be carried out on the node
1572 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1573 """
1574 command = str( nodeName ) + " " + str( commandStr )
1575 main.log.info( command )
1576
1577 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001578 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001579 if re.search( "Unknown command", response ):
1580 main.log.warn( response )
1581 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001582 if re.search( "Permission denied", response ):
1583 main.log.warn( response )
1584 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001585 except pexpect.EOF:
1586 main.log.error( self.name + ": EOF exception found" )
1587 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001588 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001589 main.log.info( " response is :" )
1590 main.log.info( response )
1591 return response
1592
Jon Hall7eb38402015-01-08 17:19:54 -08001593 def yank( self, **yankargs ):
1594 """
1595 yank a mininet switch interface to a host"""
1596 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001597 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001598 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1599 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001600 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001601 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001602 response = self.execute(
1603 cmd=command,
1604 prompt="mininet>",
1605 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001606 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001607 main.log.error( self.name + ": EOF exception found" )
1608 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001609 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001610 except Exception:
1611 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001612 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001613 return main.TRUE
1614
Jon Hall7eb38402015-01-08 17:19:54 -08001615 def plug( self, **plugargs ):
1616 """
1617 plug the yanked mininet switch interface to a switch"""
1618 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001619 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001620 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1621 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001622 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001623 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001624 response = self.execute(
1625 cmd=command,
1626 prompt="mininet>",
1627 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001628 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001629 main.log.error( self.name + ": EOF exception found" )
1630 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001631 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001632 except Exception:
1633 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001634 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001635 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001636
Jon Hall7eb38402015-01-08 17:19:54 -08001637 def dpctl( self, **dpctlargs ):
1638 """
1639 Run dpctl command on all switches."""
1640 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001641 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001642 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1643 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1644 command = "dpctl " + cmd + " " + str( cmdargs )
1645 try:
1646 response = self.execute(
1647 cmd=command,
1648 prompt="mininet>",
1649 timeout=10 )
1650 except pexpect.EOF:
1651 main.log.error( self.name + ": EOF exception found" )
1652 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001653 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001654 except Exception:
1655 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001656 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001657 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001658
kelvin-onlabd3b64892015-01-20 13:26:24 -08001659 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001660 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001661 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001662 try:
1663 fileInput = path + '/lib/Mininet/INSTALL'
1664 version = super( Mininet, self ).getVersion()
1665 pattern = 'Mininet\s\w\.\w\.\w\w*'
1666 for line in open( fileInput, 'r' ).readlines():
1667 result = re.match( pattern, line )
1668 if result:
1669 version = result.group( 0 )
1670 return version
1671 except Exception:
1672 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001673 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001674
kelvin-onlabd3b64892015-01-20 13:26:24 -08001675 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001676 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001677 Parameters:
1678 sw: The name of an OVS switch. Example "s1"
1679 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001680 The output of the command from the mininet cli
1681 or main.FALSE on timeout"""
1682 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001683 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001684 response = self.execute(
1685 cmd=command,
1686 prompt="mininet>",
1687 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001688 if response:
Jon Hallab611372018-02-21 15:26:05 -08001689 if "no bridge named" in response:
1690 main.log.error( self.name + ": Error in getSwController: " +
1691 self.handle.before )
1692 return main.FALSE
1693 else:
1694 return response
admin2a9548d2014-06-17 14:08:07 -07001695 else:
1696 return main.FALSE
1697 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001698 main.log.error( self.name + ": EOF exception found" )
1699 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001700 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001701 except Exception:
1702 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001703 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001704
Charles Chan029be652015-08-24 01:46:10 +08001705 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001706 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001707 Description:
1708 Assign switches to the controllers ( for ovs use only )
1709 Required:
1710 sw - Name of the switch. This can be a list or a string.
1711 ip - Ip addresses of controllers. This can be a list or a string.
1712 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001713 port - ONOS use port 6653, if no list of ports is passed, then
1714 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001715 ptcp - ptcp number, This can be a string or a list that has
1716 the same length as switch. This is optional and not required
1717 when using ovs switches.
1718 NOTE: If switches and ptcp are given in a list type they should have the
1719 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1720 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001721
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001722 Return:
1723 Returns main.TRUE if mininet correctly assigned switches to
1724 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001725 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001726 """
1727 assignResult = main.TRUE
1728 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001729 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001730 command = "sh ovs-vsctl set-controller "
1731 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001732 try:
1733 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001734 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001735 if isinstance( port, types.StringType ) or \
1736 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001737 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001738 elif isinstance( port, types.ListType ):
1739 main.log.error( self.name + ": Only one controller " +
1740 "assigned and a list of ports has" +
1741 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001742 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001743 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001744 main.log.error( self.name + ": Invalid controller port " +
1745 "number. Please specify correct " +
1746 "controller port" )
1747 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001748
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001749 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001750 if isinstance( port, types.StringType ) or \
1751 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001752 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001753 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1754 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001755 elif isinstance( port, types.ListType ):
1756 if ( len( ip ) != len( port ) ):
1757 main.log.error( self.name + ": Port list = " +
1758 str( len( port ) ) +
1759 "should be the same as controller" +
1760 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001761 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001762 else:
1763 onosIp = ""
1764 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001765 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1766 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001767 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001768 main.log.error( self.name + ": Invalid controller port " +
1769 "number. Please specify correct " +
1770 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001771 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001772 else:
1773 main.log.error( self.name + ": Invalid ip address" )
1774 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001775
1776 if isinstance( sw, types.StringType ):
1777 command += sw + " "
1778 if ptcp:
1779 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001780 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001781 elif isinstance( ptcp, types.ListType ):
1782 main.log.error( self.name + ": Only one switch is " +
1783 "being set and multiple PTCP is " +
1784 "being passed " )
1785 else:
1786 main.log.error( self.name + ": Invalid PTCP" )
1787 ptcp = ""
1788 command += onosIp
1789 commandList.append( command )
1790
1791 elif isinstance( sw, types.ListType ):
1792 if ptcp:
1793 if isinstance( ptcp, types.ListType ):
1794 if len( ptcp ) != len( sw ):
1795 main.log.error( self.name + ": PTCP length = " +
1796 str( len( ptcp ) ) +
1797 " is not the same as switch" +
1798 " length = " +
1799 str( len( sw ) ) )
1800 return main.FALSE
1801 else:
1802 for switch, ptcpNum in zip( sw, ptcp ):
1803 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001804 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001805 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001806 tempCmd += onosIp
1807 commandList.append( tempCmd )
1808 else:
1809 main.log.error( self.name + ": Invalid PTCP" )
1810 return main.FALSE
1811 else:
1812 for switch in sw:
1813 tempCmd = "sh ovs-vsctl set-controller "
1814 tempCmd += switch + " " + onosIp
1815 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001816 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001817 main.log.error( self.name + ": Invalid switch type " )
1818 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001819
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001820 for cmd in commandList:
1821 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001822 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08001823 if "no bridge named" in self.handle.before:
1824 main.log.error( self.name + ": Error in assignSwController: " +
1825 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001826 except pexpect.TIMEOUT:
1827 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1828 return main.FALSE
1829 except pexpect.EOF:
1830 main.log.error( self.name + ": EOF exception found" )
1831 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001832 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001833 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001834 except pexpect.EOF:
1835 main.log.error( self.name + ": EOF exception found" )
1836 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001837 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001838 except Exception:
1839 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001840 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001841
kelvin-onlabd3b64892015-01-20 13:26:24 -08001842 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001843 """
1844 Removes the controller target from sw"""
1845 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001846 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001847 response = self.execute(
1848 cmd=command,
1849 prompt="mininet>",
1850 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001851 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001852 main.log.error( self.name + ": EOF exception found" )
1853 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001854 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001855 except Exception:
1856 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001857 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001858 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001859 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001860
kelvin-onlabd3b64892015-01-20 13:26:24 -08001861 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001862 """
Jon Hallb1290e82014-11-18 16:17:48 -05001863 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001864 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001865 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001866 NOTE: cannot currently specify what type of switch
1867 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001868 sw = name of the new switch as a string
1869 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001870 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001871 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001872 """
1873 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001874 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001875 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001876 response = self.execute(
1877 cmd=command,
1878 prompt="mininet>",
1879 timeout=10 )
1880 if re.search( "already exists!", response ):
1881 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001882 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001883 elif re.search( "Error", response ):
1884 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001885 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001886 elif re.search( "usage:", response ):
1887 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001888 return main.FALSE
1889 else:
1890 return main.TRUE
1891 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001892 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001893 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001894 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001895 except Exception:
1896 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001897 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001898
kelvin-onlabd3b64892015-01-20 13:26:24 -08001899 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001900 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001901 delete a switch from the mininet topology
1902 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001903 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001904 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001905 sw = name of the switch as a string
1906 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001907 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001908 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001909 response = self.execute(
1910 cmd=command,
1911 prompt="mininet>",
1912 timeout=10 )
1913 if re.search( "no switch named", response ):
1914 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001915 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001916 elif re.search( "Error", response ):
1917 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001918 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001919 elif re.search( "usage:", response ):
1920 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001921 return main.FALSE
1922 else:
1923 return main.TRUE
1924 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001925 main.log.error( self.name + ": EOF exception found" )
1926 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001927 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001928 except Exception:
1929 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001930 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001931
You Wangdb8cd0a2016-05-26 15:19:45 -07001932 def getSwitchRandom( self, timeout=60, nonCut=True ):
1933 """
1934 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001935 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001936 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001937 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07001938 it just randomly returns one switch from all current switches in
1939 Mininet.
1940 Returns the name of the chosen switch.
1941 """
1942 import random
1943 candidateSwitches = []
1944 try:
1945 if not nonCut:
1946 switches = self.getSwitches( timeout=timeout )
1947 assert len( switches ) != 0
1948 for switchName in switches.keys():
1949 candidateSwitches.append( switchName )
1950 else:
1951 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001952 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001953 return None
1954 self.graph.update( graphDict )
1955 candidateSwitches = self.graph.getNonCutVertices()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001956 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001957 return None
1958 elif len( candidateSwitches ) == 0:
1959 main.log.info( self.name + ": No candidate switch for deletion" )
1960 return None
1961 else:
1962 switch = random.sample( candidateSwitches, 1 )
1963 return switch[ 0 ]
1964 except KeyError:
1965 main.log.exception( self.name + ": KeyError exception found" )
1966 return None
1967 except AssertionError:
1968 main.log.exception( self.name + ": AssertionError exception found" )
1969 return None
1970 except Exception:
1971 main.log.exception( self.name + ": Uncaught exception" )
1972 return None
1973
1974 def delSwitchRandom( self, timeout=60, nonCut=True ):
1975 """
1976 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001977 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001978 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001979 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07001980 otherwise it just randomly delete one switch from all current
1981 switches in Mininet.
1982 Returns the name of the deleted switch
1983 """
1984 try:
1985 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001986 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001987 return None
1988 else:
1989 deletionResult = self.delSwitch( switch )
1990 if deletionResult:
1991 return switch
1992 else:
1993 return None
1994 except Exception:
1995 main.log.exception( self.name + ": Uncaught exception" )
1996 return None
1997
kelvin-onlabd3b64892015-01-20 13:26:24 -08001998 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001999 """
2000 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002001 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002002 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002003 NOTE: cannot currently specify what type of link
2004 required params:
2005 node1 = the string node name of the first endpoint of the link
2006 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002007 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002008 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002009 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002010 response = self.execute(
2011 cmd=command,
2012 prompt="mininet>",
2013 timeout=10 )
2014 if re.search( "doesnt exist!", response ):
2015 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002016 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002017 elif re.search( "Error", response ):
2018 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002019 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002020 elif re.search( "usage:", response ):
2021 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002022 return main.FALSE
2023 else:
2024 return main.TRUE
2025 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002026 main.log.error( self.name + ": EOF exception found" )
2027 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002028 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002029 except Exception:
2030 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002031 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002032
kelvin-onlabd3b64892015-01-20 13:26:24 -08002033 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002034 """
2035 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002036 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002037 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002038 required params:
2039 node1 = the string node name of the first endpoint of the link
2040 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002041 returns: main.FALSE on an error, else main.TRUE
2042 """
Jon Hallffb386d2014-11-21 13:43:38 -08002043 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002044 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002045 response = self.execute(
2046 cmd=command,
2047 prompt="mininet>",
2048 timeout=10 )
2049 if re.search( "no node named", response ):
2050 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002051 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002052 elif re.search( "Error", response ):
2053 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002054 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002055 elif re.search( "usage:", response ):
2056 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002057 return main.FALSE
2058 else:
2059 return main.TRUE
2060 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002061 main.log.error( self.name + ": EOF exception found" )
2062 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002063 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002064 except Exception:
2065 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002066 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002067
You Wangdb8cd0a2016-05-26 15:19:45 -07002068 def getLinkRandom( self, timeout=60, nonCut=True ):
2069 """
2070 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002071 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002072 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002073 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002074 it just randomly returns one link from all current links in
2075 Mininet.
2076 Returns the link as a list, e.g. [ 's1', 's2' ]
2077 """
2078 import random
2079 candidateLinks = []
2080 try:
2081 if not nonCut:
2082 links = self.getLinks( timeout=timeout )
2083 assert len( links ) != 0
2084 for link in links:
2085 # Exclude host-switch link
2086 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2087 continue
2088 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2089 else:
2090 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002091 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002092 return None
2093 self.graph.update( graphDict )
2094 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002095 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002096 return None
2097 elif len( candidateLinks ) == 0:
2098 main.log.info( self.name + ": No candidate link for deletion" )
2099 return None
2100 else:
2101 link = random.sample( candidateLinks, 1 )
2102 return link[ 0 ]
2103 except KeyError:
2104 main.log.exception( self.name + ": KeyError exception found" )
2105 return None
2106 except AssertionError:
2107 main.log.exception( self.name + ": AssertionError exception found" )
2108 return None
2109 except Exception:
2110 main.log.exception( self.name + ": Uncaught exception" )
2111 return None
2112
2113 def delLinkRandom( self, timeout=60, nonCut=True ):
2114 """
2115 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002116 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002117 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002118 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002119 otherwise it just randomly delete one link from all current links
2120 in Mininet.
2121 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2122 """
2123 try:
2124 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002125 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002126 return None
2127 else:
2128 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2129 if deletionResult:
2130 return link
2131 else:
2132 return None
2133 except Exception:
2134 main.log.exception( self.name + ": Uncaught exception" )
2135 return None
2136
kelvin-onlabd3b64892015-01-20 13:26:24 -08002137 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002138 """
Jon Hallb1290e82014-11-18 16:17:48 -05002139 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002140 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002141 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002142 NOTE: cannot currently specify what type of host
2143 required params:
2144 hostname = the string hostname
2145 optional key-value params
2146 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002147 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002148 """
2149 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002150 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002151 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002152 response = self.execute(
2153 cmd=command,
2154 prompt="mininet>",
2155 timeout=10 )
2156 if re.search( "already exists!", response ):
2157 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002158 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002159 elif re.search( "doesnt exists!", response ):
2160 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002161 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002162 elif re.search( "Error", response ):
2163 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002164 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002165 elif re.search( "usage:", response ):
2166 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002167 return main.FALSE
2168 else:
2169 return main.TRUE
2170 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002171 main.log.error( self.name + ": EOF exception found" )
2172 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002173 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002174 except Exception:
2175 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002176 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002177
kelvin-onlabd3b64892015-01-20 13:26:24 -08002178 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002179 """
2180 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002181 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002182 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002183 NOTE: this uses a custom mn function
2184 required params:
2185 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002186 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002187 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002188 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002189 response = self.execute(
2190 cmd=command,
2191 prompt="mininet>",
2192 timeout=10 )
2193 if re.search( "no host named", response ):
2194 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002195 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002196 elif re.search( "Error", response ):
2197 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002198 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002199 elif re.search( "usage:", response ):
2200 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002201 return main.FALSE
2202 else:
2203 return main.TRUE
2204 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002205 main.log.error( self.name + ": EOF exception found" )
2206 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002207 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002208 except Exception:
2209 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002210 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002211
Jon Hall7eb38402015-01-08 17:19:54 -08002212 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002213 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002214 Called at the end of the test to stop the mininet and
2215 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002216 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002217 try:
2218 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002219 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002220 timeout=2 )
2221 response = main.TRUE
2222 if i == 0:
2223 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002224 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002225 return main.TRUE
2226 # print "Disconnecting Mininet"
2227 if self.handle:
2228 self.handle.sendline( "exit" )
2229 self.handle.expect( "exit" )
2230 self.handle.expect( "(.*)" )
2231 else:
2232 main.log.error( "Connection failed to the host" )
2233 return response
2234 except pexpect.EOF:
2235 main.log.error( self.name + ": EOF exception found" )
2236 main.log.error( self.name + ": " + self.handle.before )
You Wangd4fae5c2018-08-22 13:56:49 -07002237 # Do not exit the entire test when pexpect.EOF is caught
2238 # FIXME: We might need to do something else here
2239 return main.ERROR
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002240 except Exception:
2241 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002242 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002243
Devin Lima7cfdbd2017-09-29 15:02:22 -07002244 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002245 """
Jon Hall21270ac2015-02-16 17:59:55 -08002246 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002247 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002248 main.FALSE if the pexpect handle does not exist.
2249
Jon Halld61331b2015-02-17 16:35:47 -08002250 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002251 """
Jon Halld61331b2015-02-17 16:35:47 -08002252 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002253 response = ''
2254 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002255 try:
Jon Halld80cc142015-07-06 13:36:05 -07002256 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002257 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002258 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002259 pexpect.EOF,
2260 pexpect.TIMEOUT ],
2261 timeout )
2262 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002263 main.log.info( "Exiting mininet.." )
2264 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002265 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002266 prompt=self.prompt,
2267 timeout=exitTimeout )
2268 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002269 self.handle.sendline( "sudo mn -c" )
2270 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002271
Jeremyd9e4eb12016-04-13 12:09:06 -07002272 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002273 main.log.info( " Mininet trying to exit while not " +
2274 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002275 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002276 elif i == 2:
2277 main.log.error( "Something went wrong exiting mininet" )
2278 elif i == 3: # timeout
2279 main.log.error( "Something went wrong exiting mininet " +
2280 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002281
You Wang18db8592018-04-02 13:52:03 -07002282 self.handle.sendline( "" )
2283 self.handle.expect( self.prompt )
2284 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2285
Hari Krishnab35c6d02015-03-18 11:13:51 -07002286 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002287 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002288 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002289 self.handle.sendline(
2290 "sudo kill -9 \`ps -ef | grep \"" +
2291 fileName +
2292 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002293 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002294 main.log.error( self.name + ": TIMEOUT exception found" )
2295 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002296 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002297 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002298 main.log.error( self.name + ": EOF exception found" )
2299 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002300 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002301 except Exception:
2302 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002303 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002304 else:
2305 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002306 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002307 return response
2308
YPZhang26a139e2016-04-25 14:01:55 -07002309 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002310 """
2311 Description:
2312 Sends arp message from mininet host for hosts discovery
2313 Required:
2314 host - hosts name
2315 Optional:
2316 ip - ip address that does not exist in the network so there would
2317 be no reply.
2318 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002319 if ethDevice:
2320 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002321 cmd = srcHost + " arping -c1 "
2322 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002323 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 -07002324 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002325 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002326 if output:
2327 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002328 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002329 i = self.handle.expect( [ "mininet>", "arping: " ] )
2330 if i == 0:
2331 return main.TRUE
2332 elif i == 1:
2333 response = self.handle.before + self.handle.after
2334 self.handle.expect( "mininet>" )
2335 response += self.handle.before + self.handle.after
2336 main.log.warn( "Error sending arping, output was: " +
2337 response )
2338 return main.FALSE
2339 except pexpect.TIMEOUT:
2340 main.log.error( self.name + ": TIMEOUT exception found" )
2341 main.log.warn( self.handle.before )
2342 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002343 except pexpect.EOF:
2344 main.log.error( self.name + ": EOF exception found" )
2345 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002346 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002347 except Exception:
2348 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002349 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002350
Jon Hall7eb38402015-01-08 17:19:54 -08002351 def decToHex( self, num ):
2352 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002353
Jon Hall7eb38402015-01-08 17:19:54 -08002354 def getSwitchFlowCount( self, switch ):
2355 """
2356 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002357 if self.handle:
2358 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2359 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002360 response = self.execute(
2361 cmd=cmd,
2362 prompt="mininet>",
2363 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002364 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002365 main.log.error( self.name + ": EOF exception found" )
2366 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002367 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002368 except Exception:
2369 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002370 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002371 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002372 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002373 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002374 main.log.info(
2375 "Couldn't find flows on switch %s, found: %s" %
2376 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002377 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002378 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002379 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002380 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002381
Jon Hall9ed8f372016-02-24 17:34:07 -08002382 def checkFlows( self, sw, dumpFormat=None ):
2383 if dumpFormat:
2384 command = "sh ovs-ofctl -F " + \
2385 dumpFormat + " dump-flows " + str( sw )
2386 else:
2387 command = "sh ovs-ofctl dump-flows " + str( sw )
2388 try:
2389 response = self.execute(
2390 cmd=command,
2391 prompt="mininet>",
2392 timeout=10 )
2393 return response
2394 except pexpect.EOF:
2395 main.log.error( self.name + ": EOF exception found" )
2396 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002397 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002398 except Exception:
2399 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002400 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002401
GlennRC68467eb2015-11-16 18:01:01 -08002402 def flowTableComp( self, flowTable1, flowTable2 ):
2403 # This function compares the selctors and treatments of each flow
2404 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002405 assert flowTable1, "flowTable1 is empty or None"
2406 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002407 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002408 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002409 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002410 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002411 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2412 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002413 for field in dFields:
2414 try:
2415 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002416 except KeyError:
2417 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002418 try:
2419 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002420 except KeyError:
2421 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002422 for i in range( len( flowTable1 ) ):
2423 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002424 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002425 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002426 returnValue = main.FALSE
2427 break
2428 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002429 except AssertionError:
2430 main.log.exception( "Nothing to compare" )
2431 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002432 except Exception:
2433 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002434 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002435
GlennRC528ad292015-11-12 10:38:18 -08002436 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002437 '''
GlennRC956ea742015-11-05 16:14:15 -08002438 Discription: Parses flows into json format.
2439 NOTE: this can parse any string thats separated with commas
2440 Arguments:
2441 Required:
2442 flows: a list of strings that represnt flows
2443 Optional:
2444 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2445 debug: prints out the final result
2446 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002447 '''
GlennRC528ad292015-11-12 10:38:18 -08002448 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002449 try:
2450 for flow in flowTable:
2451 jsonFlow = {}
2452 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002453 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002454 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002455 for i in range( len( parsedFlow ) ):
2456 item = parsedFlow[ i ]
2457 if item[ 0 ] == " ":
2458 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002459 # grab the selector and treatment from the parsed flow
2460 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002461 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002462 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002463 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002464 index = 0
2465 # parse the flags
2466 # NOTE: This only parses one flag
2467 flag = {}
2468 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002469 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002470 index += 1
2471 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002472 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002473 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002474 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002475 # the priority is stuck in the selecter so put it back
2476 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002477 if 'priority' in sel[0]:
2478 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002479 # parse selector
2480 criteria = []
2481 for item in sel:
2482 # this is the type of the packet e.g. "arp"
2483 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002484 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002485 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002486 field = item.split( "=" )
2487 criteria.append( { field[ 0 ]: field[ 1 ] } )
2488 selector = { "selector": { "criteria": sorted( criteria ) } }
2489 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002490 # get rid of the action part e.g. "action=output:2"
2491 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002492 treat = treat.split( "=" )
2493 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002494 # parse treatment
2495 action = []
2496 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002497 if ":" in item:
2498 field = item.split( ":" )
2499 action.append( { field[ 0 ]: field[ 1 ] } )
2500 else:
2501 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2502 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002503 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002504 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002505 # parse the rest of the flow
2506 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002507 field = item.split( "=" )
2508 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002509 # add the treatment and the selector to the json flow
2510 jsonFlow.update( selector )
2511 jsonFlow.update( treatment )
2512 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002513
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002514 if debug:
2515 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002516
You Wang91c37cf2016-05-23 09:39:42 -07002517 # add the json flow to the json flow table
2518 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002519
You Wang91c37cf2016-05-23 09:39:42 -07002520 return jsonFlowTable
2521
2522 except IndexError:
2523 main.log.exception( self.name + ": IndexError found" )
2524 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002525 except pexpect.EOF:
2526 main.log.error( self.name + ": EOF exception found" )
2527 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002528 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002529 except Exception:
2530 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002531 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002532
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002533 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002534 '''
2535 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002536 Each element is a flow.
2537 Arguments:
2538 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002539 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002540 a list of switches.
2541 Optional:
2542 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2543 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002544 '''
GlennRC956ea742015-11-05 16:14:15 -08002545 try:
2546 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002547 if isinstance( sw, list ):
2548 switches.extend( sw )
2549 else:
2550 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002551
2552 flows = []
2553 for s in switches:
2554 cmd = "sh ovs-ofctl dump-flows " + s
2555
GlennRC528ad292015-11-12 10:38:18 -08002556 if "1.0" == version:
2557 cmd += " -F OpenFlow10-table_id"
2558 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002559 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002560
2561 main.log.info( "Sending: " + cmd )
2562 self.handle.sendline( cmd )
2563 self.handle.expect( "mininet>" )
2564 response = self.handle.before
2565 response = response.split( "\r\n" )
2566 # dump the first two elements and the last
2567 # the first element is the command that was sent
2568 # the second is the table header
2569 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002570 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002571 flows.extend( response )
2572
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002573 if debug:
2574 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002575
GlennRC528ad292015-11-12 10:38:18 -08002576 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002577
GlennRC956ea742015-11-05 16:14:15 -08002578 except pexpect.EOF:
2579 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002580 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002581 except Exception:
2582 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002583 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002584
2585 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002586 '''
GlennRC956ea742015-11-05 16:14:15 -08002587 Discription: Checks whether the ID provided matches a flow ID in Mininet
2588 Arguments:
2589 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002590 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002591 a list of switches.
2592 flowId: the flow ID in hex format. Can also be a list of IDs
2593 Optional:
2594 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2595 debug: prints out the final result
2596 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2597 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002598 '''
GlennRC956ea742015-11-05 16:14:15 -08002599 try:
2600 main.log.info( "Getting flows from Mininet" )
2601 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002602 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002603 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002604
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002605 if debug:
2606 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002607
2608 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002609 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002610 result = False
2611 for f in flows:
2612 if flowId in f.get( 'cookie' ):
2613 result = True
2614 break
2615 # flowId is a list
2616 else:
2617 result = True
2618 # Get flow IDs from Mininet
2619 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2620 # Save the IDs that are not in Mininet
2621 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2622
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002623 if debug:
2624 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002625
2626 # Print out the IDs that are not in Mininet
2627 if absentIds:
2628 main.log.warn( "Absent ids: {}".format( absentIds ) )
2629 result = False
2630
2631 return main.TRUE if result else main.FALSE
2632
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002633 except pexpect.EOF:
2634 main.log.error( self.name + ": EOF exception found" )
2635 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002636 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002637 except Exception:
2638 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002639 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002640
Charles Chan029be652015-08-24 01:46:10 +08002641 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002642 """
Jon Hallefbd9792015-03-05 16:11:36 -08002643 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002644 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002645 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002646 self.handle.sendline( "" )
2647 self.handle.expect( "mininet>" )
2648 self.handle.sendline(
2649 "sh sudo tcpdump -n -i " +
2650 intf +
2651 " " +
2652 port +
2653 " -w " +
2654 filename.strip() +
2655 " &" )
2656 self.handle.sendline( "" )
2657 i = self.handle.expect( [ 'No\ssuch\device',
2658 'listening\son',
2659 pexpect.TIMEOUT,
2660 "mininet>" ],
2661 timeout=10 )
2662 main.log.warn( self.handle.before + self.handle.after )
2663 self.handle.sendline( "" )
2664 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002665 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002666 main.log.error(
2667 self.name +
2668 ": tcpdump - No such device exists. " +
2669 "tcpdump attempted on: " +
2670 intf )
admin2a9548d2014-06-17 14:08:07 -07002671 return main.FALSE
2672 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002673 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002674 return main.TRUE
2675 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002676 main.log.error(
2677 self.name +
2678 ": tcpdump command timed out! Check interface name," +
2679 " given interface was: " +
2680 intf )
admin2a9548d2014-06-17 14:08:07 -07002681 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002682 elif i == 3:
2683 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002684 return main.TRUE
2685 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002686 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002687 return main.FALSE
2688 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002689 main.log.error( self.name + ": EOF exception found" )
2690 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002691 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002692 except Exception:
2693 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002694 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002695
kelvin-onlabd3b64892015-01-20 13:26:24 -08002696 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002697 """
2698 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002699 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002700 self.handle.sendline( "sh sudo pkill tcpdump" )
2701 self.handle.expect( "mininet>" )
2702 self.handle.sendline( "" )
2703 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002704 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002705 main.log.error( self.name + ": TIMEOUT exception found" )
2706 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002707 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002708 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002709 main.log.error( self.name + ": EOF exception found" )
2710 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002711 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002712 except Exception:
2713 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002714 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002715
Jon Halld80cc142015-07-06 13:36:05 -07002716 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002717 """
2718 Read ports from a Mininet switch.
2719
2720 Returns a json structure containing information about the
2721 ports of the given switch.
2722 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002723 try:
2724 response = self.getInterfaces( nodeName )
2725 # TODO: Sanity check on response. log if no such switch exists
2726 ports = []
2727 for line in response.split( "\n" ):
2728 if not line.startswith( "name=" ):
2729 continue
2730 portVars = {}
2731 for var in line.split( "," ):
2732 key, value = var.split( "=" )
2733 portVars[ key ] = value
2734 isUp = portVars.pop( 'enabled', "True" )
2735 isUp = "True" in isUp
2736 if verbose:
2737 main.log.info( "Reading switch port %s(%s)" %
2738 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2739 mac = portVars[ 'mac' ]
2740 if mac == 'None':
2741 mac = None
2742 ips = []
2743 ip = portVars[ 'ip' ]
2744 if ip == 'None':
2745 ip = None
2746 ips.append( ip )
2747 name = portVars[ 'name' ]
2748 if name == 'None':
2749 name = None
2750 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2751 if name == 'lo':
2752 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2753 else:
2754 portNo = re.search( portRe, name ).group( 'port' )
2755 ports.append( { 'of_port': portNo,
2756 'mac': str( mac ).replace( '\'', '' ),
2757 'name': name,
2758 'ips': ips,
2759 'enabled': isUp } )
2760 return ports
2761 except pexpect.EOF:
2762 main.log.error( self.name + ": EOF exception found" )
2763 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002764 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002765 except Exception:
2766 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002767 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002768
You Wangdb8cd0a2016-05-26 15:19:45 -07002769 def getOVSPorts( self, nodeName ):
2770 """
2771 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2772
2773 Returns a list of dictionaries containing information about each
2774 port of the given switch.
2775 """
2776 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2777 try:
2778 response = self.execute(
2779 cmd=command,
2780 prompt="mininet>",
2781 timeout=10 )
2782 ports = []
2783 if response:
2784 for line in response.split( "\n" ):
2785 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2786 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002787 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002788 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2789 result = re.search( pattern, line )
2790 if result:
2791 index = result.group( 'index' )
2792 name = result.group( 'name' )
2793 # This port number is extracted from port name
2794 port = result.group( 'port' )
2795 mac = result.group( 'mac' )
2796 ports.append( { 'index': index,
2797 'name': name,
2798 'port': port,
2799 'mac': mac } )
2800 return ports
2801 except pexpect.EOF:
2802 main.log.error( self.name + ": EOF exception found" )
2803 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002804 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002805 except Exception:
2806 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002807 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002808
Devin Lima7cfdbd2017-09-29 15:02:22 -07002809 def getSwitches( self, verbose=False, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002810 """
2811 Read switches from Mininet.
2812
2813 Returns a dictionary whose keys are the switch names and the value is
2814 a dictionary containing information about the switch.
2815 """
Jon Halla22481b2015-07-28 17:46:01 -07002816 # NOTE: To support new Mininet switch classes, just append the new
2817 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002818
Jon Halla22481b2015-07-28 17:46:01 -07002819 # Regex patterns to parse 'dump' output
2820 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002821 # <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 -07002822 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002823 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2824 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2825 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002826 try:
2827 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2828 swRE = r"<(?P<class>" + switchClasses + r")" +\
2829 r"(?P<options>\{.*\})?\s" +\
2830 r"(?P<name>[^:]+)\:\s" +\
2831 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2832 r"\spid=(?P<pid>(\d)+)"
2833 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002834 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002835 output = {}
2836 dump = self.dump().split( "\n" )
2837 for line in dump:
2838 result = re.search( swRE, line, re.I )
2839 if result:
2840 name = result.group( 'name' )
2841 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2842 pid = result.group( 'pid' )
2843 swClass = result.group( 'class' )
2844 options = result.group( 'options' )
2845 if verbose:
2846 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2847 ports = self.getPorts( name )
2848 output[ name ] = { "dpid": dpid,
2849 "ports": ports,
2850 "swClass": swClass,
2851 "pid": pid,
2852 "options": options }
2853 return output
2854 except pexpect.EOF:
2855 main.log.error( self.name + ": EOF exception found" )
2856 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002857 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002858 except Exception:
2859 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002860 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002861
You Wangd66de192018-04-30 17:30:12 -07002862 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002863 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2864 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002865 """
2866 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002867 Optional:
2868 hostClass: it is used to match the class of the mininet host. It
2869 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002870 Returns a dictionary whose keys are the host names and the value is
2871 a dictionary containing information about the host.
2872 """
2873 # Regex patterns to parse dump output
2874 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002875 # <Host h1: pid=12725>
2876 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2877 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2878 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002879 # NOTE: Does not correctly match hosts with multi-links
2880 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2881 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002882 try:
You Wang53dba1e2018-02-02 17:45:44 -08002883 if not isinstance( hostClass, types.ListType ):
2884 hostClass = [ str( hostClass ) ]
2885 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002886 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2887 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2888 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002889 if update:
2890 # update mn port info
2891 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002892 # Get mininet dump
2893 dump = self.dump().split( "\n" )
2894 hosts = {}
2895 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002896 result = re.search( hostRE, line )
2897 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002898 name = result.group( 'name' )
2899 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002900 if getInterfaces:
2901 response = self.getInterfaces( name )
2902 # Populate interface info
2903 for line in response.split( "\n" ):
2904 if line.startswith( "name=" ):
2905 portVars = {}
2906 for var in line.split( "," ):
2907 key, value = var.split( "=" )
2908 portVars[ key ] = value
2909 isUp = portVars.pop( 'enabled', "True" )
2910 isUp = "True" in isUp
2911 if verbose:
2912 main.log.info( "Reading host port %s(%s)" %
2913 ( portVars[ 'name' ],
2914 portVars[ 'mac' ] ) )
2915 mac = portVars[ 'mac' ]
2916 if mac == 'None':
2917 mac = None
2918 ips = []
2919 ip = portVars[ 'ip' ]
2920 if ip == 'None':
2921 ip = None
2922 ips.append( ip )
2923 intfName = portVars[ 'name' ]
2924 if name == 'None':
2925 name = None
2926 interfaces.append( {
2927 "name": intfName,
2928 "ips": ips,
2929 "mac": str( mac ),
2930 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002931 hosts[ name ] = { "interfaces": interfaces }
2932 return hosts
2933 except pexpect.EOF:
2934 main.log.error( self.name + ": EOF exception found" )
2935 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002936 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002937 except Exception:
2938 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002939 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002940
Devin Lima7cfdbd2017-09-29 15:02:22 -07002941 def getLinks( self, timeout=20, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002942 """
2943 Gathers information about current Mininet links. These links may not
2944 be up if one of the ports is down.
2945
2946 Returns a list of dictionaries with link endpoints.
2947
2948 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002949 { 'node1': str( node1 name )
2950 'node2': str( node2 name )
2951 'port1': str( port1 of_port )
2952 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002953 Note: The port number returned is the eth#, not necessarily the of_port
2954 number. In Mininet, for OVS switch, these should be the same. For
2955 hosts, this is just the eth#.
2956 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002957 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002958 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002959 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002960
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002961 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002962 # s1-eth3<->s2-eth1 (OK OK)
2963 # s13-eth3<->h27-eth0 (OK OK)
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002964 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2965 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2966 links = []
2967 for line in response:
2968 match = re.search( linkRE, line )
2969 if match:
2970 node1 = match.group( 'node1' )
2971 node2 = match.group( 'node2' )
2972 port1 = match.group( 'port1' )
2973 port2 = match.group( 'port2' )
2974 links.append( { 'node1': node1,
2975 'node2': node2,
2976 'port1': port1,
2977 'port2': port2 } )
2978 return links
2979
2980 except pexpect.EOF:
2981 main.log.error( self.name + ": EOF exception found" )
2982 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002983 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002984 except Exception:
2985 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002986 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002987
2988 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002989 """
2990 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002991 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002992
Jon Hallafa8a472015-06-12 14:02:42 -07002993 Dependencies:
2994 1. numpy - "sudo pip install numpy"
2995 """
2996 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002997 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002998 try:
2999 mnDPIDs = []
3000 for swName, switch in switches.iteritems():
3001 mnDPIDs.append( switch[ 'dpid' ].lower() )
3002 mnDPIDs.sort()
3003 if switchesJson == "": # if rest call fails
3004 main.log.error(
3005 self.name +
3006 ".compareSwitches(): Empty JSON object given from ONOS" )
3007 return main.FALSE
3008 onos = switchesJson
3009 onosDPIDs = []
3010 for switch in onos:
3011 if switch[ 'available' ]:
3012 onosDPIDs.append(
3013 switch[ 'id' ].replace(
3014 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003015 '' ).replace(
3016 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003017 '' ).lower() )
3018 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003019
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003020 if mnDPIDs != onosDPIDs:
3021 switchResults = main.FALSE
3022 main.log.error( "Switches in MN but not in ONOS:" )
3023 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3024 main.log.error( str( list1 ) )
3025 main.log.error( "Switches in ONOS but not in MN:" )
3026 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3027 main.log.error( str( list2 ) )
3028 else: # list of dpid's match in onos and mn
3029 switchResults = main.TRUE
3030 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003031
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003032 # FIXME: this does not look for extra ports in ONOS, only checks that
3033 # ONOS has what is in MN
3034 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003035
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003036 # PORTS
3037 for name, mnSwitch in switches.iteritems():
3038 mnPorts = []
3039 onosPorts = []
3040 switchResult = main.TRUE
3041 for port in mnSwitch[ 'ports' ]:
3042 if port[ 'enabled' ]:
3043 mnPorts.append( int( port[ 'of_port' ] ) )
3044 for onosSwitch in portsJson:
3045 if onosSwitch[ 'device' ][ 'available' ]:
3046 if onosSwitch[ 'device' ][ 'id' ].replace(
3047 ':',
3048 '' ).replace(
3049 "of",
3050 '' ) == mnSwitch[ 'dpid' ]:
3051 for port in onosSwitch[ 'ports' ]:
3052 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003053 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003054 # onosPorts.append( 'local' )
3055 onosPorts.append( long( uint64( -2 ) ) )
3056 else:
3057 onosPorts.append( int( port[ 'port' ] ) )
3058 break
3059 mnPorts.sort( key=float )
3060 onosPorts.sort( key=float )
3061
3062 mnPortsLog = mnPorts
3063 onosPortsLog = onosPorts
3064 mnPorts = [ x for x in mnPorts ]
3065 onosPorts = [ x for x in onosPorts ]
3066
3067 # TODO: handle other reserved port numbers besides LOCAL
3068 # NOTE: Reserved ports
3069 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3070 # long( uint64( -2 ) )
3071 for mnPort in mnPortsLog:
3072 if mnPort in onosPorts:
3073 # don't set results to true here as this is just one of
3074 # many checks and it might override a failure
3075 mnPorts.remove( mnPort )
3076 onosPorts.remove( mnPort )
3077
3078 # NOTE: OVS reports this as down since there is no link
3079 # So ignoring these for now
3080 # TODO: Come up with a better way of handling these
3081 if 65534 in mnPorts:
3082 mnPorts.remove( 65534 )
3083 if long( uint64( -2 ) ) in onosPorts:
3084 onosPorts.remove( long( uint64( -2 ) ) )
3085 if len( mnPorts ): # the ports of this switch don't match
3086 switchResult = main.FALSE
3087 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3088 if len( onosPorts ): # the ports of this switch don't match
3089 switchResult = main.FALSE
3090 main.log.warn(
3091 "Ports in ONOS but not MN: " +
3092 str( onosPorts ) )
3093 if switchResult == main.FALSE:
3094 main.log.error(
3095 "The list of ports for switch %s(%s) does not match:" %
3096 ( name, mnSwitch[ 'dpid' ] ) )
3097 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3098 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3099 portsResults = portsResults and switchResult
3100 finalResults = finalResults and portsResults
3101 return finalResults
3102 except pexpect.EOF:
3103 main.log.error( self.name + ": EOF exception found" )
3104 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003105 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003106 except Exception:
3107 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003108 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003109
Jon Hallafa8a472015-06-12 14:02:42 -07003110 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003111 """
3112 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003113 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003114
Jon Hallafa8a472015-06-12 14:02:42 -07003115 """
Jon Hall7eb38402015-01-08 17:19:54 -08003116 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003117 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003118 try:
3119 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003120
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003121 mnLinks = []
3122 for l in links:
3123 try:
3124 node1 = switches[ l[ 'node1' ] ]
3125 node2 = switches[ l[ 'node2' ] ]
3126 enabled = True
3127 for port in node1[ 'ports' ]:
3128 if port[ 'of_port' ] == l[ 'port1' ]:
3129 enabled = enabled and port[ 'enabled' ]
3130 for port in node2[ 'ports' ]:
3131 if port[ 'of_port' ] == l[ 'port2' ]:
3132 enabled = enabled and port[ 'enabled' ]
3133 if enabled:
3134 mnLinks.append( l )
3135 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003136 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003137 if 2 * len( mnLinks ) == len( onos ):
3138 linkResults = main.TRUE
3139 else:
3140 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003141 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003142 "Mininet has " + str( len( mnLinks ) ) +
3143 " bidirectional links and ONOS has " +
3144 str( len( onos ) ) + " unidirectional links" )
3145
3146 # iterate through MN links and check if an ONOS link exists in
3147 # both directions
3148 for link in mnLinks:
3149 # TODO: Find a more efficient search method
3150 node1 = None
3151 port1 = None
3152 node2 = None
3153 port2 = None
3154 firstDir = main.FALSE
3155 secondDir = main.FALSE
3156 for swName, switch in switches.iteritems():
3157 if swName == link[ 'node1' ]:
3158 node1 = switch[ 'dpid' ]
3159 for port in switch[ 'ports' ]:
3160 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3161 port1 = port[ 'of_port' ]
3162 if node1 is not None and node2 is not None:
3163 break
3164 if swName == link[ 'node2' ]:
3165 node2 = switch[ 'dpid' ]
3166 for port in switch[ 'ports' ]:
3167 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3168 port2 = port[ 'of_port' ]
3169 if node1 is not None and node2 is not None:
3170 break
3171
3172 for onosLink in onos:
3173 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3174 ":", '' ).replace( "of", '' )
3175 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3176 ":", '' ).replace( "of", '' )
3177 onosPort1 = onosLink[ 'src' ][ 'port' ]
3178 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3179
3180 # check onos link from node1 to node2
3181 if str( onosNode1 ) == str( node1 ) and str(
3182 onosNode2 ) == str( node2 ):
3183 if int( onosPort1 ) == int( port1 ) and int(
3184 onosPort2 ) == int( port2 ):
3185 firstDir = main.TRUE
3186 else:
Jon Hallab611372018-02-21 15:26:05 -08003187 # The right switches, but wrong ports, could be
3188 # another link between these devices, or onos
3189 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003190 main.log.warn(
3191 'The port numbers do not match for ' +
3192 str( link ) +
3193 ' between ONOS and MN. When checking ONOS for ' +
3194 'link %s/%s -> %s/%s' %
3195 ( node1, port1, node2, port2 ) +
3196 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003197 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3198 '. This could be another link between these devices' +
3199 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003200
3201 # check onos link from node2 to node1
3202 elif ( str( onosNode1 ) == str( node2 ) and
3203 str( onosNode2 ) == str( node1 ) ):
3204 if ( int( onosPort1 ) == int( port2 )
3205 and int( onosPort2 ) == int( port1 ) ):
3206 secondDir = main.TRUE
3207 else:
Jon Hallab611372018-02-21 15:26:05 -08003208 # The right switches, but wrong ports, could be
3209 # another link between these devices, or onos
3210 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003211 main.log.warn(
3212 'The port numbers do not match for ' +
3213 str( link ) +
3214 ' between ONOS and MN. When checking ONOS for ' +
3215 'link %s/%s -> %s/%s' %
3216 ( node1, port1, node2, port2 ) +
3217 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003218 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3219 '. This could be another link between these devices' +
3220 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003221 else: # this is not the link you're looking for
3222 pass
3223 if not firstDir:
3224 main.log.error(
3225 'ONOS does not have the link %s/%s -> %s/%s' %
3226 ( node1, port1, node2, port2 ) )
3227 if not secondDir:
3228 main.log.error(
3229 'ONOS does not have the link %s/%s -> %s/%s' %
3230 ( node2, port2, node1, port1 ) )
3231 linkResults = linkResults and firstDir and secondDir
3232 return linkResults
3233 except pexpect.EOF:
3234 main.log.error( self.name + ": EOF exception found" )
3235 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003236 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003237 except Exception:
3238 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003239 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003240
Jon Hallafa8a472015-06-12 14:02:42 -07003241 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003242 """
Jon Hallafa8a472015-06-12 14:02:42 -07003243 Compare mn and onos Hosts.
3244 Since Mininet hosts are quiet, ONOS will only know of them when they
3245 speak. For this reason, we will only check that the hosts in ONOS
3246 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003247
Jon Hallafa8a472015-06-12 14:02:42 -07003248 Arguments:
3249 hostsJson: parsed json object from the onos hosts api
3250 Returns:
3251 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003252 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003253 try:
3254 hostResults = main.TRUE
3255 for onosHost in hostsJson:
3256 onosMAC = onosHost[ 'mac' ].lower()
3257 match = False
3258 for mnHost, info in hosts.iteritems():
3259 for mnIntf in info[ 'interfaces' ]:
3260 if onosMAC == mnIntf[ 'mac' ].lower():
3261 match = True
3262 for ip in mnIntf[ 'ips' ]:
3263 if ip in onosHost[ 'ipAddresses' ]:
3264 pass # all is well
3265 else:
3266 # misssing ip
3267 main.log.error( "ONOS host " +
3268 onosHost[ 'id' ] +
3269 " has a different IP(" +
3270 str( onosHost[ 'ipAddresses' ] ) +
3271 ") than the Mininet host(" +
3272 str( ip ) +
3273 ")." )
3274 output = json.dumps(
3275 onosHost,
3276 sort_keys=True,
3277 indent=4,
3278 separators=( ',', ': ' ) )
3279 main.log.info( output )
3280 hostResults = main.FALSE
3281 if not match:
3282 hostResults = main.FALSE
3283 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3284 "corresponding Mininet host." )
3285 output = json.dumps( onosHost,
3286 sort_keys=True,
3287 indent=4,
3288 separators=( ',', ': ' ) )
3289 main.log.info( output )
3290 return hostResults
3291 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003292 main.log.error( self.name + ": EOF exception found" )
3293 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003294 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003295 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003296 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003297 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003298
You Wangd66de192018-04-30 17:30:12 -07003299 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003300 """
3301 Description:
3302 Verify that all hosts have IP address assigned to them
3303 Optional:
3304 hostList: If specified, verifications only happen to the hosts
3305 in hostList
3306 prefix: at least one of the ip address assigned to the host
3307 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003308 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003309 Returns:
3310 main.TRUE if all hosts have specific IP address assigned;
3311 main.FALSE otherwise
3312 """
3313 try:
You Wangd66de192018-04-30 17:30:12 -07003314 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003315 if not hostList:
3316 hostList = hosts.keys()
3317 for hostName in hosts.keys():
3318 if hostName not in hostList:
3319 continue
3320 ipList = []
3321 self.handle.sendline( str( hostName ) + " ip a" )
3322 self.handle.expect( "mininet>" )
3323 ipa = self.handle.before
3324 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3325 ipList += re.findall( ipv4Pattern, ipa )
3326 # It's tricky to make regex for IPv6 addresses and this one is simplified
3327 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})/'
3328 ipList += re.findall( ipv6Pattern, ipa )
3329 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3330 if not ipList:
3331 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3332 else:
3333 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3334 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3335 else:
3336 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3337 hostList.remove( hostName )
3338 return main.FALSE if hostList else main.TRUE
3339 except KeyError:
3340 main.log.exception( self.name + ": host data not as expected: " + hosts )
3341 return None
3342 except pexpect.EOF:
3343 main.log.error( self.name + ": EOF exception found" )
3344 main.log.error( self.name + ": " + self.handle.before )
3345 main.cleanAndExit()
3346 except Exception:
3347 main.log.exception( self.name + ": Uncaught exception" )
3348 return None
3349
Jon Hallafa8a472015-06-12 14:02:42 -07003350 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003351 """
3352 Returns a list of all hosts
3353 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003354 try:
3355 self.handle.sendline( "" )
3356 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003357
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003358 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3359 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003360
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003361 handlePy = self.handle.before
3362 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3363 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003364
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003365 self.handle.sendline( "" )
3366 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003367
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003368 hostStr = handlePy.replace( "]", "" )
3369 hostStr = hostStr.replace( "'", "" )
3370 hostStr = hostStr.replace( "[", "" )
3371 hostStr = hostStr.replace( " ", "" )
3372 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003373
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003374 return hostList
3375 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003376 main.log.error( self.name + ": TIMEOUT exception found" )
3377 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003378 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003379 except pexpect.EOF:
3380 main.log.error( self.name + ": EOF exception found" )
3381 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003382 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003383 except Exception:
3384 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003385 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003386
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003387 def getSwitch( self ):
3388 """
3389 Returns a list of all switches
3390 Again, don't ask question just use it...
3391 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003392 try:
3393 # get host list...
3394 hostList = self.getHosts()
3395 # Make host set
3396 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003397
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003398 # Getting all the nodes in mininet
3399 self.handle.sendline( "" )
3400 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003401
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003402 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3403 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003404
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003405 handlePy = self.handle.before
3406 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3407 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003408
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003409 self.handle.sendline( "" )
3410 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003411
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003412 nodesStr = handlePy.replace( "]", "" )
3413 nodesStr = nodesStr.replace( "'", "" )
3414 nodesStr = nodesStr.replace( "[", "" )
3415 nodesStr = nodesStr.replace( " ", "" )
3416 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003417
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003418 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003419 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003420 nodesSet.discard( 'c0' )
3421 nodesSet.discard( 'c1' )
3422 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003423
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003424 switchSet = nodesSet - hostSet
3425 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003426
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003427 return switchList
3428 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003429 main.log.error( self.name + ": TIMEOUT exception found" )
3430 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003431 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003432 except pexpect.EOF:
3433 main.log.error( self.name + ": EOF exception found" )
3434 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003435 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003436 except Exception:
3437 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003438 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003439
You Wangdb8cd0a2016-05-26 15:19:45 -07003440 def getGraphDict( self, timeout=60, useId=True, includeHost=False ):
3441 """
3442 Return a dictionary which describes the latest Mininet topology data as a
3443 graph.
3444 An example of the dictionary:
3445 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3446 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3447 Each vertex should at least have an 'edges' attribute which describes the
3448 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003449 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003450 list of attributes.
3451 An example of the edges dictionary:
3452 'edges': { vertex2: { 'port': ..., 'weight': ... },
3453 vertex3: { 'port': ..., 'weight': ... } }
3454 If useId == True, dpid/mac will be used instead of names to identify
3455 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3456 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003457 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003458 in topology data.
3459 Note that link or switch that are brought down by 'link x x down' or 'switch
3460 x down' commands still show in the output of Mininet CLI commands such as
3461 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3462 recommended to use delLink() or delSwitch functions to simulate link/switch
3463 down, and addLink() or addSwitch to add them back.
3464 """
3465 graphDict = {}
3466 try:
3467 links = self.getLinks( timeout=timeout )
3468 portDict = {}
3469 if useId:
3470 switches = self.getSwitches()
3471 if includeHost:
3472 hosts = self.getHosts()
3473 for link in links:
3474 # FIXME: support 'includeHost' argument
3475 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3476 continue
3477 nodeName1 = link[ 'node1' ]
3478 nodeName2 = link[ 'node2' ]
3479 port1 = link[ 'port1' ]
3480 port2 = link[ 'port2' ]
3481 # Loop for two nodes
3482 for i in range( 2 ):
3483 # Get port index from OVS
3484 # The index extracted from port name may be inconsistent with ONOS
3485 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003486 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003487 portList = self.getOVSPorts( nodeName1 )
3488 if len( portList ) == 0:
3489 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3490 return None
3491 portDict[ nodeName1 ] = portList
3492 for port in portDict[ nodeName1 ]:
3493 if port[ 'port' ] == port1:
3494 portIndex = port[ 'index' ]
3495 break
3496 if portIndex == -1:
3497 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3498 return None
3499 if useId:
3500 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3501 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3502 else:
3503 node1 = nodeName1
3504 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003505 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003506 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003507 graphDict[ node1 ] = { 'edges': {},
3508 'dpid': switches[ nodeName1 ][ 'dpid' ],
3509 'name': nodeName1,
3510 'ports': switches[ nodeName1 ][ 'ports' ],
3511 'swClass': switches[ nodeName1 ][ 'swClass' ],
3512 'pid': switches[ nodeName1 ][ 'pid' ],
3513 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003514 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003515 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003516 else:
3517 # Assert node2 is not connected to any current links of node1
3518 assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003519 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
You Wangdb8cd0a2016-05-26 15:19:45 -07003520 # Swap two nodes/ports
3521 nodeName1, nodeName2 = nodeName2, nodeName1
3522 port1, port2 = port2, port1
3523 return graphDict
3524 except KeyError:
3525 main.log.exception( self.name + ": KeyError exception found" )
3526 return None
3527 except AssertionError:
3528 main.log.exception( self.name + ": AssertionError exception found" )
3529 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003530 except pexpect.EOF:
3531 main.log.error( self.name + ": EOF exception found" )
3532 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003533 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003534 except Exception:
3535 main.log.exception( self.name + ": Uncaught exception" )
3536 return None
3537
Devin Lima7cfdbd2017-09-29 15:02:22 -07003538 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003539 """
3540 updates the port address and status information for
3541 each port in mn"""
3542 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003543 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003544 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003545 self.handle.sendline( "" )
3546 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003547
Jon Hall7eb38402015-01-08 17:19:54 -08003548 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003549 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003550
Jon Hall7eb38402015-01-08 17:19:54 -08003551 self.handle.sendline( "" )
3552 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003553
Jon Hallb1290e82014-11-18 16:17:48 -05003554 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003555 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003556 main.log.error( self.name + ": TIMEOUT exception found" )
3557 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003558 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003559 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003560 main.log.error( self.name + ": EOF exception found" )
3561 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003562 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003563 except Exception:
3564 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003565 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003566
Jon Halld80cc142015-07-06 13:36:05 -07003567 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003568 """
3569 Add vlan tag to a host.
3570 Dependencies:
3571 This class depends on the "vlan" package
3572 $ sudo apt-get install vlan
3573 Configuration:
3574 Load the 8021q module into the kernel
3575 $sudo modprobe 8021q
3576
3577 To make this setup permanent:
3578 $ sudo su -c 'echo "8021q" >> /etc/modules'
3579 """
3580 if self.handle:
3581 try:
Jon Halld80cc142015-07-06 13:36:05 -07003582 # get the ip address of the host
3583 main.log.info( "Get the ip address of the host" )
3584 ipaddr = self.getIPAddress( host )
3585 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003586
Jon Halld80cc142015-07-06 13:36:05 -07003587 # remove IP from interface intf
3588 # Ex: h1 ifconfig h1-eth0 inet 0
3589 main.log.info( "Remove IP from interface " )
3590 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3591 self.handle.sendline( cmd2 )
3592 self.handle.expect( "mininet>" )
3593 response = self.handle.before
3594 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003595
Jon Halld80cc142015-07-06 13:36:05 -07003596 # create VLAN interface
3597 # Ex: h1 vconfig add h1-eth0 100
3598 main.log.info( "Create Vlan" )
3599 cmd3 = host + " vconfig add " + intf + " " + vlan
3600 self.handle.sendline( cmd3 )
3601 self.handle.expect( "mininet>" )
3602 response = self.handle.before
3603 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003604
Jon Halld80cc142015-07-06 13:36:05 -07003605 # assign the host's IP to the VLAN interface
3606 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3607 main.log.info( "Assign the host IP to the vlan interface" )
3608 vintf = intf + "." + vlan
3609 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3610 self.handle.sendline( cmd4 )
3611 self.handle.expect( "mininet>" )
3612 response = self.handle.before
3613 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003614
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003615 # update Mininet node variables
3616 main.log.info( "Update Mininet node variables" )
3617 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3618 self.handle.sendline( cmd5 )
3619 self.handle.expect( "mininet>" )
3620 response = self.handle.before
3621 main.log.info( "====> %s ", response )
3622
3623 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3624 self.handle.sendline( cmd6 )
3625 self.handle.expect( "mininet>" )
3626 response = self.handle.before
3627 main.log.info( "====> %s ", response )
3628
3629 return main.TRUE
3630 except pexpect.TIMEOUT:
3631 main.log.error( self.name + ": TIMEOUT exception found" )
3632 main.log.error( self.name + ": " + self.handle.before )
3633 main.cleanAndExit()
3634 except pexpect.EOF:
3635 main.log.error( self.name + ": EOF exception found" )
3636 main.log.error( self.name + ": " + self.handle.before )
3637 return main.FALSE
3638 except Exception:
3639 main.log.exception( self.name + ": Uncaught exception!" )
3640 return main.FALSE
3641
3642 def removeVLAN( self, host, intf ):
3643 """
3644 Remove vlan tag from a host.
3645 Dependencies:
3646 This class depends on the "vlan" package
3647 $ sudo apt-get install vlan
3648 Configuration:
3649 Load the 8021q module into the kernel
3650 $sudo modprobe 8021q
3651
3652 To make this setup permanent:
3653 $ sudo su -c 'echo "8021q" >> /etc/modules'
3654 """
3655 if self.handle:
3656 try:
3657 # get the ip address of the host
3658 main.log.info( "Get the ip address of the host" )
3659 ipaddr = self.getIPAddress( host )
3660
3661 # remove VLAN interface
3662 # Ex: h1 vconfig rem h1-eth0.100
3663 main.log.info( "Remove Vlan interface" )
3664 cmd2 = host + " vconfig rem " + intf
3665 self.handle.sendline( cmd2 )
3666 self.handle.expect( "mininet>" )
3667 response = self.handle.before
3668 main.log.info( "====> %s ", response )
3669
3670 # assign the host's IP to the original interface
3671 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3672 main.log.info( "Assign the host IP to the original interface" )
3673 original_intf = intf.split(".")[0]
3674 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3675 self.handle.sendline( cmd3 )
3676 self.handle.expect( "mininet>" )
3677 response = self.handle.before
3678 main.log.info( "====> %s ", response )
3679
3680 # update Mininet node variables
3681 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3682 self.handle.sendline( cmd4 )
3683 self.handle.expect( "mininet>" )
3684 response = self.handle.before
3685 main.log.info( "====> %s ", response )
3686
3687 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3688 self.handle.sendline( cmd5 )
3689 self.handle.expect( "mininet>" )
3690 response = self.handle.before
3691 main.log.info( "====> %s ", response )
3692
kaouthera3f13ca22015-05-05 15:01:41 -07003693 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003694 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003695 main.log.error( self.name + ": TIMEOUT exception found" )
3696 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003697 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003698 except pexpect.EOF:
3699 main.log.error( self.name + ": EOF exception found" )
3700 main.log.error( self.name + ": " + self.handle.before )
3701 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003702 except Exception:
3703 main.log.exception( self.name + ": Uncaught exception!" )
3704 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003705
Jon Hall892818c2015-10-20 17:58:34 -07003706 def createHostComponent( self, name ):
3707 """
3708 Creates a new mininet cli component with the same parameters as self.
3709 This new component is intended to be used to login to the hosts created
3710 by mininet.
3711
3712 Arguments:
3713 name - The string of the name of this component. The new component
3714 will be assigned to main.<name> .
3715 In addition, main.<name>.name = str( name )
3716 """
3717 try:
3718 # look to see if this component already exists
3719 getattr( main, name )
3720 except AttributeError:
3721 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003722 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3723 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003724 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003725 except pexpect.EOF:
3726 main.log.error( self.name + ": EOF exception found" )
3727 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003728 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003729 except Exception:
3730 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003731 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003732 else:
3733 # namespace is not clear!
3734 main.log.error( name + " component already exists!" )
3735 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003736 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003737
3738 def removeHostComponent( self, name ):
3739 """
3740 Remove host component
3741 Arguments:
3742 name - The string of the name of the component to delete.
3743 """
3744 try:
3745 # Get host component
3746 component = getattr( main, name )
3747 except AttributeError:
3748 main.log.error( "Component " + name + " does not exist." )
3749 return
3750 try:
3751 # Disconnect from component
3752 component.disconnect()
You Wangf32c6ed2018-08-23 17:10:22 -07003753 component.close_log_handles()
Jon Hall892818c2015-10-20 17:58:34 -07003754 # Delete component
3755 delattr( main, name )
3756 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003757 del( main.componentDictionary[ name ] )
You Wangf32c6ed2018-08-23 17:10:22 -07003758 except StandardError:
3759 self.log.exception( "Exception while closing log files for " + name )
3760 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003761 except pexpect.EOF:
3762 main.log.error( self.name + ": EOF exception found" )
3763 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003764 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003765 except Exception:
3766 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003767 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003768
3769 def startHostCli( self, host=None ):
3770 """
3771 Use the mininet m utility to connect to the host's cli
3772 """
3773 # These are fields that can be used by scapy packets. Initialized to None
3774 self.hostIp = None
3775 self.hostMac = None
3776 try:
3777 if not host:
3778 host = self.name
3779 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003780 self.handle.sendline( "cd" )
3781 self.handle.expect( self.hostPrompt )
3782 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003783 self.handle.expect( self.hostPrompt )
3784 return main.TRUE
3785 except pexpect.TIMEOUT:
3786 main.log.exception( self.name + ": Command timed out" )
3787 return main.FALSE
3788 except pexpect.EOF:
3789 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003790 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003791 except Exception:
3792 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003793 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003794
YPZhang801d46d2016-08-08 13:26:28 -07003795 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003796 '''
3797
YPZhang801d46d2016-08-08 13:26:28 -07003798 Args:
3799 devicename: switch name
3800 intf: port name on switch
3801 status: up or down
3802
3803 Returns: boolean to show success change status
3804
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003805 '''
YPZhang801d46d2016-08-08 13:26:28 -07003806 if status == "down" or status == "up":
3807 try:
3808 cmd = devicename + " ifconfig " + intf + " " + status
3809 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003810 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003811 return main.TRUE
3812 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003813 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003814 return main.FALSE
3815 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003816 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003817 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003818 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003819 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003820 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003821 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003822 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003823 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003824 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003825 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003826 return main.FALSE
3827
You Wang6e5b48e2018-07-23 16:17:38 -07003828 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003829 """
You Wang6e5b48e2018-07-23 16:17:38 -07003830 Moves a host from one switch to another on the fly
3831 Optional:
3832 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3833 prefixLen: length of the host IP prefix
3834 ipv6: move an IPv6 host if True
3835 intfSuffix: suffix of the new interface after host movement
3836 vlan: vlan ID of the host. Use None for non-vlan host
3837 Note: The intf between host and oldSw when detached
3838 using detach(), will still show up in the 'net'
3839 cmd, because switch.detach() doesn't affect switch.intfs[]
3840 ( which is correct behavior since the interfaces
3841 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003842 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003843 if self.handle:
3844 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003845 newIntf = "%s-%s" % ( host, intfSuffix )
3846 commands = [
3847 # Bring link between oldSw-host down
3848 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3849 # Determine hostintf and Oldswitchintf
3850 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
3851 ]
3852 # Determine ip address of the host-oldSw interface
3853 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3854 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3855 commands += [
3856 # Determine mac address of the host-oldSw interface
3857 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3858 # Detach interface between oldSw-host
3859 "px " + oldSw + ".detach( sintf )",
3860 # Add link between host-newSw
3861 "py net.addLink(" + host + "," + newSw + ")",
3862 # Determine hostintf and Newswitchintf
3863 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3864 # Attach interface between newSw-host
3865 "px " + newSw + ".attach( sintf )",
3866 ]
3867 if vlan:
3868 vlanIntf = "%s.%s" % ( newIntf, vlan )
3869 commands += [
3870 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
3871 host + " ip link set up %s" % vlanIntf,
3872 "px hintf.name = '" + vlanIntf + "'",
3873 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
3874 ]
3875 newIntf = vlanIntf
3876 commands += [
3877 # Set mac address of the host-newSw interface
3878 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
3879 # Set IP address of the host-newSw interface
3880 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
3881 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
3882 ]
3883 if ipv6:
3884 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
3885 commands += [
3886 "net",
3887 host + " ifconfig"
3888 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003889 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003890 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003891 self.handle.sendline( cmd )
3892 self.handle.expect( "mininet>" )
3893 main.log.info( "====> %s ", self.handle.before )
3894 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003895 except pexpect.TIMEOUT:
3896 main.log.error( self.name + ": TIMEOUT exception found" )
3897 main.log.error( self.name + ": " + self.handle.before )
3898 main.cleanAndExit()
3899 except pexpect.EOF:
3900 main.log.error( self.name + ": EOF exception found" )
3901 main.log.error( self.name + ": " + self.handle.before )
3902 return main.FALSE
3903 except Exception:
3904 main.log.exception( self.name + ": Uncaught exception!" )
3905 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07003906
You Wang6e5b48e2018-07-23 16:17:38 -07003907 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
3908 macAddr=None, prefixLen=None, ipv6=False,
3909 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07003910 """
You Wang6e5b48e2018-07-23 16:17:38 -07003911 Moves a dual-homed host from one switch-pair to another pair on the fly
3912 Optional:
3913 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3914 prefixLen: length of the host IP prefix
3915 ipv6: move an IPv6 host if True
3916 intfSuffix1: suffix of the first new interface
3917 intfSuffix2: suffix of the second new interface
3918 bondSuffix: suffix of the new bond interface
3919 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07003920 """
You Wang7ea90582018-07-19 15:27:58 -07003921 if self.handle:
3922 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003923 bondIntf = "%s-%s" % ( host, bondSuffix )
3924 newIntf = "%s-%s" % ( host, intfSuffix1 )
3925 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07003926 commands = [
3927 # Bring link between oldSw-host down
3928 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3929 # Bring link between oldPairSw-host down
3930 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
3931 # Determine hostintf and Oldswitchintf
3932 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07003933 ]
3934 # Determine ip address of the host-oldSw interface
3935 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3936 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3937 commands += [
3938 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07003939 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3940 # Detach interface between oldSw-host
3941 "px " + oldSw + ".detach( sintf )",
3942 # Determine hostintf and Oldpairswitchintf
3943 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
3944 # Detach interface between oldPairSw-host
3945 "px " + oldPairSw + ".detach( sintfpair )",
3946 # Add link between host-newSw
3947 "py net.addLink(" + host + "," + newSw + ", 2)",
3948 # Add link between host-newPairSw
3949 "py net.addLink(" + host + "," + newPairSw + ")",
3950 # Determine hostintf and Newswitchintf
3951 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3952 # Determine hostintf and NewPairswitchintf
3953 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
3954 # Attach interface between newSw-host
3955 "px " + newSw + ".attach( sintf )",
3956 # Attach interface between newPairSw-host
3957 "px " + newPairSw + ".attach( sintfpair )",
3958 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07003959 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07003960 host + ' ip link set %s down' % newIntf,
3961 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07003962 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
3963 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07003964 host + ' ip addr flush dev %s' % newIntf,
3965 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07003966 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07003967 "px lowestIntf = min( [ hintf, hintfpair ] )",
3968 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07003969 "px lowestIntf.name = '" + bondIntf + "'",
3970 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07003971 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
3972 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07003973 ]
3974 if vlan:
3975 vlanIntf = "%s.%s" % ( bondIntf, vlan )
3976 commands += [
3977 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
3978 host + " ip link set up %s" % vlanIntf,
3979 "px lowestIntf.name = '" + vlanIntf + "'",
3980 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
3981 ]
3982 bondIntf = vlanIntf
3983 commands += [
3984 # Set macaddress of the host-newSw interface
3985 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07003986 # Set ipaddress of the host-newSw interface
3987 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
3988 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07003989 ]
You Wang6e5b48e2018-07-23 16:17:38 -07003990 if ipv6:
3991 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
3992 commands += [
3993 "net",
3994 host + " ifconfig"
3995 ]
You Wang7ea90582018-07-19 15:27:58 -07003996 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003997 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07003998 self.handle.sendline( cmd )
3999 self.handle.expect( "mininet>" )
4000 main.log.info( "====> %s ", self.handle.before )
4001 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07004002 except pexpect.TIMEOUT:
4003 main.log.error( self.name + ": TIMEOUT exception found" )
4004 main.log.error( self.name + ": " + self.handle.before )
4005 main.cleanAndExit()
4006 except pexpect.EOF:
4007 main.log.error( self.name + ": EOF exception found" )
4008 main.log.error( self.name + ": " + self.handle.before )
4009 return main.FALSE
4010 except Exception:
4011 main.log.exception( self.name + ": Uncaught exception!" )
4012 return main.FALSE
4013
adminbae64d82013-08-01 10:50:15 -07004014if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004015 sys.modules[ __name__ ] = MininetCliDriver()