blob: 661ada7db3a3fb49a90d837dfbaffdfe4e644035 [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 Wanga01d7f72019-02-27 11:23:39 -0800388 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
389 self.handle.send( "" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700390 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 Wanga01d7f72019-02-27 11:23:39 -0800400 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
401 self.handle.send( "" )
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
You Wanga01d7f72019-02-27 11:23:39 -0800493 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
Jon Hall3c910162018-03-07 14:42:16 -0800494 response += self.handle.before + self.handle.after
You Wanga01d7f72019-02-27 11:23:39 -0800495 self.handle.send( "" )
Jon Hall3c910162018-03-07 14:42:16 -0800496 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
You Wanga01d7f72019-02-27 11:23:39 -0800561 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
Jon Hall3c910162018-03-07 14:42:16 -0800562 response += self.handle.before + self.handle.after
You Wanga01d7f72019-02-27 11:23:39 -0800563 self.handle.send( "" )
Jon Hall3c910162018-03-07 14:42:16 -0800564 self.handle.expect( "mininet>" )
565 response += self.handle.before + self.handle.after
566 main.log.debug( response )
You Wangba231e72018-03-01 13:18:21 -0800567 return main.FALSE
568 except pexpect.EOF:
569 main.log.error( self.name + ": EOF exception found" )
570 main.log.error( self.name + ": " + self.handle.before )
571 main.cleanAndExit()
572 except Exception:
573 main.log.exception( self.name + ": Uncaught exception!" )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700574
575 main.cleanAndExit()
576
You Wang32833172018-10-23 15:19:31 -0700577 def discoverHosts( self, hostList=[], wait=1000, dstIp="6.6.6.6", dstIp6="1020::3fe" ):
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700578 '''
You Wang32833172018-10-23 15:19:31 -0700579 Hosts in hostList will do a single ARP/ND to a non-existent address for ONOS to
580 discover them. A host will use arping/ndisc6 to send ARP/ND depending on if it
581 has IPv4/IPv6 addresses configured.
You Wang48381752018-05-07 13:50:57 -0700582 Optional:
583 hostList: a list of names of the hosts that need to be discovered. If not
584 specified mininet will send ping from all the hosts
You Wang32833172018-10-23 15:19:31 -0700585 wait: timeout for ARP/ND in milliseconds
You Wang48381752018-05-07 13:50:57 -0700586 dstIp: destination address used by IPv4 hosts
587 dstIp6: destination address used by IPv6 hosts
588 Returns:
You Wang32833172018-10-23 15:19:31 -0700589 main.TRUE if all packets were successfully sent. Otherwise main.FALSE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700590 '''
591 try:
You Wang32833172018-10-23 15:19:31 -0700592 hosts = self.getHosts()
You Wang48381752018-05-07 13:50:57 -0700593 if not hostList:
You Wang48381752018-05-07 13:50:57 -0700594 hostList = hosts.keys()
595 discoveryResult = main.TRUE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700596 for host in hostList:
You Wang0b82aa52018-06-06 14:33:58 -0700597 flushCmd = ""
You Wang036ec2c2019-02-27 15:44:15 -0800598 cmds = []
You Wang48381752018-05-07 13:50:57 -0700599 if self.getIPAddress( host ):
You Wang0b82aa52018-06-06 14:33:58 -0700600 flushCmd = "{} ip neigh flush all".format( host )
You Wang036ec2c2019-02-27 15:44:15 -0800601 cmds.append( "{} arping -c 1 -w {} {}".format( host, wait, dstIp ) )
You Wang32833172018-10-23 15:19:31 -0700602 main.log.debug( "Sending IPv4 arping from host {}".format( host ) )
You Wang48381752018-05-07 13:50:57 -0700603 elif self.getIPAddress( host, proto='IPV6' ):
You Wang0b82aa52018-06-06 14:33:58 -0700604 flushCmd = "{} ip -6 neigh flush all".format( host )
You Wang036ec2c2019-02-27 15:44:15 -0800605 # FIXME: we are using the same ipv6Addr for all interfaces
606 ipv6Addr = self.getIPAddress( host, proto='IPV6' )
You Wangad347c92019-02-20 16:13:47 -0800607 for intf in hosts[ host ][ 'interfaces' ]:
608 intfName = intf[ 'name' ]
You Wang036ec2c2019-02-27 15:44:15 -0800609 cmds.append( "{} ndsend {} {}".format( host, ipv6Addr, intfName ) )
You Wangad347c92019-02-20 16:13:47 -0800610 main.log.debug( "Sending IPv6 ND from interface {} on host {}".format( intfName, host ) )
You Wang48381752018-05-07 13:50:57 -0700611 else:
612 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
613 discoveryResult = main.FALSE
You Wang036ec2c2019-02-27 15:44:15 -0800614 if flushCmd:
You Wang0b82aa52018-06-06 14:33:58 -0700615 self.handle.sendline( flushCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700616 self.handle.expect( "mininet>" )
You Wang036ec2c2019-02-27 15:44:15 -0800617 for cmd in cmds:
You Wang48381752018-05-07 13:50:57 -0700618 self.handle.sendline( cmd )
Jon Halla604fd42018-05-04 14:27:27 -0700619 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700620 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700621 except pexpect.TIMEOUT:
622 main.log.exception( self.name + ": TIMEOUT exception" )
623 response = self.handle.before
624 # NOTE: Send ctrl-c to make sure command is stopped
You Wanga01d7f72019-02-27 11:23:39 -0800625 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700626 response += self.handle.before + self.handle.after
You Wanga01d7f72019-02-27 11:23:39 -0800627 self.handle.send( "" )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700628 self.handle.expect( "mininet>" )
629 response += self.handle.before + self.handle.after
630 main.log.debug( response )
631 return main.FALSE
632 except pexpect.EOF:
633 main.log.error( self.name + ": EOF exception found" )
634 main.log.error( self.name + ": " + self.handle.before )
635 main.cleanAndExit()
636 except Exception:
637 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800638 main.cleanAndExit()
639
640 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
641 """
642 Verify ping from each host in srcList to each host in dstList
643
644 acceptableFailed: max number of acceptable failed pings
645
646 Returns main.TRUE if all src hosts can reach all dst hosts
647 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
648 """
649 try:
650 main.log.info( "Verifying ping from each src host to each dst host" )
651 isReachable = main.TRUE
652 wait = int( wait )
653 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
654 pingResponse = "Ping output:\n"
655 failedPingsTotal = 0
656 for host in srcList:
657 pingResponse += str( str( host ) + " -> " )
658 for temp in dstList:
659 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700660 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
661 assert dstIP, "Not able to get IP address of host {}".format( temp )
662 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800663 while failedPings <= acceptableFailed:
664 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
665 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700666 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800667 response = self.handle.before
668 if re.search( ',\s0\%\spacket\sloss', response ):
669 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800670 break
671 else:
672 failedPings += 1
673 time.sleep(1)
674 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700675 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800676 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700677 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800678 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700679 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800680 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700681 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700682 except AssertionError:
683 main.log.exception( "" )
684 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700685 except pexpect.TIMEOUT:
686 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800687 response = self.handle.before
688 # NOTE: Send ctrl-c to make sure command is stopped
You Wanga01d7f72019-02-27 11:23:39 -0800689 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
Jon Hall3c910162018-03-07 14:42:16 -0800690 response += self.handle.before + self.handle.after
You Wanga01d7f72019-02-27 11:23:39 -0800691 self.handle.send( "" )
Jon Hall3c910162018-03-07 14:42:16 -0800692 self.handle.expect( "mininet>" )
693 response += self.handle.before + self.handle.after
694 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700695 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700696 except pexpect.EOF:
697 main.log.error( self.name + ": EOF exception found" )
698 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700699 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700700 except Exception:
701 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700702 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700703
Jon Hall7eb38402015-01-08 17:19:54 -0800704 def pingHost( self, **pingParams ):
705 """
Jon Hall3b489db2015-10-05 14:38:37 -0700706 Ping from one mininet host to another
707 Currently the only supported Params: SRC, TARGET, and WAIT
708 """
709 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700710 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700711 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800712 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700713 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700714 try:
Jon Hall61282e32015-03-19 11:34:11 -0700715 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800716 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700717 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700718 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700719 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800720 main.log.error(
721 self.name +
722 ": timeout when waiting for response from mininet" )
723 main.log.error( "response: " + str( self.handle.before ) )
724 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700725 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800726 main.log.error(
727 self.name +
728 ": timeout when waiting for response from mininet" )
729 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700730 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700731 if re.search( ',\s0\%\spacket\sloss', response ):
732 main.log.info( self.name + ": no packets lost, host is reachable" )
733 return main.TRUE
734 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800735 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700736 self.name +
737 ": PACKET LOST, HOST IS NOT REACHABLE" )
738 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800739 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800740 main.log.error( self.name + ": EOF exception found" )
741 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700742 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700743 except Exception:
744 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700745 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700746
747 def ping6pair( self, **pingParams ):
748 """
GlennRC2cf7d952015-09-11 16:32:13 -0700749 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700750 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000751 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700752 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
753 """
Jon Hall3b489db2015-10-05 14:38:37 -0700754 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700755 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700756 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530757 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700758 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700759 try:
760 main.log.info( "Sending: " + command )
761 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700762 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700763 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700764 if i == 1:
765 main.log.error(
766 self.name +
767 ": timeout when waiting for response from mininet" )
768 main.log.error( "response: " + str( self.handle.before ) )
769 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
770 if i == 1:
771 main.log.error(
772 self.name +
773 ": timeout when waiting for response from mininet" )
774 main.log.error( "response: " + str( self.handle.before ) )
775 response = self.handle.before
776 main.log.info( self.name + ": Ping Response: " + response )
777 if re.search( ',\s0\%\spacket\sloss', response ):
778 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700779 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700780 else:
alisone4121a92016-11-22 16:31:36 -0800781 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700782 self.name +
783 ": PACKET LOST, HOST IS NOT REACHABLE" )
784 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700785 except pexpect.EOF:
786 main.log.error( self.name + ": EOF exception found" )
787 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700788 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700789 except Exception:
790 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700791 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800792
You Wangdb927a52016-02-26 11:03:28 -0800793 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
794 """
795 Description:
796 Ping a set of destination host from host CLI.
797 Logging into a Mininet host CLI is required before calling this funtion.
798 Params:
799 dstIPList is a list of destination ip addresses
800 Returns:
801 main.TRUE if the destination host is reachable
802 main.FALSE otherwise
803 """
804 isReachable = main.TRUE
805 wait = int( wait )
806 cmd = "ping"
807 if IPv6:
808 cmd = cmd + "6"
809 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
810 try:
811 for dstIP in dstIPList:
812 pingCmd = cmd + " " + dstIP
813 self.handle.sendline( pingCmd )
814 i = self.handle.expect( [ self.hostPrompt,
815 '\*\*\* Unknown command: ' + pingCmd,
816 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700817 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700818 # For some reason we need to send something
819 # Otherwise ping results won't be read by handle
820 self.handle.sendline( "" )
821 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800822 if i == 0:
823 response = self.handle.before
824 if not re.search( ',\s0\%\spacket\sloss', response ):
825 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
826 isReachable = main.FALSE
827 elif i == 1:
828 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700829 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800830 elif i == 2:
831 main.log.error( self.name + ": timeout when waiting for response" )
832 isReachable = main.FALSE
833 else:
834 main.log.error( self.name + ": unknown response: " + self.handle.before )
835 isReachable = main.FALSE
836 except pexpect.TIMEOUT:
837 main.log.exception( self.name + ": TIMEOUT exception" )
You Wangd4fae5c2018-08-22 13:56:49 -0700838 self.exitFromCmd( [ self.hostPrompt, self.bashPrompt ] )
You Wangdb927a52016-02-26 11:03:28 -0800839 isReachable = main.FALSE
840 except pexpect.EOF:
841 main.log.error( self.name + ": EOF exception found" )
842 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700843 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800844 except Exception:
845 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700846 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800847 return isReachable
848
Jon Hall7eb38402015-01-08 17:19:54 -0800849 def checkIP( self, host ):
850 """
851 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700852 try:
853 if self.handle:
854 try:
855 response = self.execute(
856 cmd=host +
857 " ifconfig",
858 prompt="mininet>",
859 timeout=10 )
860 except pexpect.EOF:
861 main.log.error( self.name + ": EOF exception found" )
862 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700863 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700864
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700865 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
866 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
867 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
868 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
869 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
870 "[0-9]|25[0-5]|[0-9]{1,2})"
871 # pattern = "inet addr:10.0.0.6"
872 if re.search( pattern, response ):
873 main.log.info( self.name + ": Host Ip configured properly" )
874 return main.TRUE
875 else:
876 main.log.error( self.name + ": Host IP not found" )
877 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700878 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700879 main.log.error( self.name + ": Connection failed to the host" )
880 except Exception:
881 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700882 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800883
Jon Hall7eb38402015-01-08 17:19:54 -0800884 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800885 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700886 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800887 response = self.execute(
888 cmd="h1 /usr/sbin/sshd -D&",
889 prompt="mininet>",
890 timeout=10 )
891 response = self.execute(
892 cmd="h4 /usr/sbin/sshd -D&",
893 prompt="mininet>",
894 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700895 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800896 vars( self )[ key ] = connectargs[ key ]
897 response = self.execute(
898 cmd="xterm h1 h4 ",
899 prompt="mininet>",
900 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800901 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800902 main.log.error( self.name + ": EOF exception found" )
903 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700904 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700905 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800906 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700907 if self.flag == 0:
908 self.flag = 1
909 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800910 else:
adminbae64d82013-08-01 10:50:15 -0700911 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800912
Jon Hall7eb38402015-01-08 17:19:54 -0800913 def changeIP( self, host, intf, newIP, newNetmask ):
914 """
915 Changes the ip address of a host on the fly
916 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800917 if self.handle:
918 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800919 cmd = host + " ifconfig " + intf + " " + \
920 newIP + " " + 'netmask' + " " + newNetmask
921 self.handle.sendline( cmd )
922 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800923 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800924 main.log.info( "response = " + response )
925 main.log.info(
926 "Ip of host " +
927 host +
928 " changed to new IP " +
929 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800930 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700931 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700932 main.log.error( self.name + ": TIMEOUT exception found" )
933 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700934 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800935 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800936 main.log.error( self.name + ": EOF exception found" )
937 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800938 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700939 except Exception:
940 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700941 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800942
Jon Hall7eb38402015-01-08 17:19:54 -0800943 def changeDefaultGateway( self, host, newGW ):
944 """
945 Changes the default gateway of a host
946 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800947 if self.handle:
948 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800949 cmd = host + " route add default gw " + newGW
950 self.handle.sendline( cmd )
951 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800952 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800953 main.log.info( "response = " + response )
954 main.log.info(
955 "Default gateway of host " +
956 host +
957 " changed to " +
958 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800959 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700960 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700961 main.log.error( self.name + ": TIMEOUT exception found" )
962 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700963 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800964 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800965 main.log.error( self.name + ": EOF exception found" )
966 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800967 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700968 except Exception:
969 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700970 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800971
You Wange24d6272018-03-27 21:18:50 -0700972 def addRoute( self, host, dstIP, interface, ipv6=False ):
973 """
974 Add a route to host
975 Ex: h1 route add -host 224.2.0.1 h1-eth0
976 """
977 if self.handle:
978 try:
979 cmd = str( host )
980 if ipv6:
981 cmd += " route -A inet6 add "
982 else:
983 cmd += " route add -host "
984 cmd += str( dstIP ) + " " + str( interface )
985 self.handle.sendline( cmd )
986 self.handle.expect( "mininet>" )
987 response = self.handle.before
988 main.log.debug( "response = " + response )
989 return main.TRUE
990 except pexpect.TIMEOUT:
991 main.log.error( self.name + ": TIMEOUT exception found" )
992 main.log.error( self.name + ": " + self.handle.before )
993 main.cleanAndExit()
994 except pexpect.EOF:
995 main.log.error( self.name + ": EOF exception found" )
996 main.log.error( self.name + ": " + self.handle.before )
997 return main.FALSE
998 except Exception:
999 main.log.exception( self.name + ": Uncaught exception!" )
1000 main.cleanAndExit()
1001
Jon Hall7eb38402015-01-08 17:19:54 -08001002 def addStaticMACAddress( self, host, GW, macaddr ):
1003 """
Jon Hallefbd9792015-03-05 16:11:36 -08001004 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001005 if self.handle:
1006 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001007 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1008 cmd = host + " arp -s " + GW + " " + macaddr
1009 self.handle.sendline( cmd )
1010 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001011 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001012 main.log.info( "response = " + response )
1013 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001014 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001015 GW +
1016 " changed to " +
1017 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001018 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001019 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001020 main.log.error( self.name + ": TIMEOUT exception found" )
1021 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001022 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001023 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001024 main.log.error( self.name + ": EOF exception found" )
1025 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001026 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001027 except Exception:
1028 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001029 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001030
Jon Hall7eb38402015-01-08 17:19:54 -08001031 def verifyStaticGWandMAC( self, host ):
1032 """
1033 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001034 if self.handle:
1035 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001036 # h1 arp -an
1037 cmd = host + " arp -an "
1038 self.handle.sendline( cmd )
1039 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001040 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001041 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001042 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001043 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001044 main.log.error( self.name + ": TIMEOUT exception found" )
1045 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001046 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001047 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001048 main.log.error( self.name + ": EOF exception found" )
1049 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001050 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001051 except Exception:
1052 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001053 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001054
Jon Hall7eb38402015-01-08 17:19:54 -08001055 def getMacAddress( self, host ):
1056 """
1057 Verifies the host's ip configured or not."""
1058 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001059 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001060 response = self.execute(
1061 cmd=host +
1062 " ifconfig",
1063 prompt="mininet>",
1064 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001065 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001066 main.log.error( self.name + ": EOF exception found" )
1067 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001068 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001069 except Exception:
1070 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001071 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001072
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001073 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001074 macAddressSearch = re.search( pattern, response, re.I )
1075 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001076 main.log.info(
1077 self.name +
1078 ": Mac-Address of Host " +
1079 host +
1080 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001081 macAddress )
1082 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001083 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001084 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001085
Jon Hall7eb38402015-01-08 17:19:54 -08001086 def getInterfaceMACAddress( self, host, interface ):
1087 """
1088 Return the IP address of the interface on the given host"""
1089 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001090 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001091 response = self.execute( cmd=host + " ifconfig " + interface,
1092 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001093 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001094 main.log.error( self.name + ": EOF exception found" )
1095 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001096 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001097 except Exception:
1098 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001099 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001100
1101 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001102 macAddressSearch = re.search( pattern, response, re.I )
1103 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001104 main.log.info( "No mac address found in %s" % response )
1105 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001106 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001107 main.log.info(
1108 "Mac-Address of " +
1109 host +
1110 ":" +
1111 interface +
1112 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001113 macAddress )
1114 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001115 else:
1116 main.log.error( "Connection failed to the host" )
1117
You Wang5da39c82018-04-26 22:55:08 -07001118 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001119 """
1120 Verifies the host's ip configured or not."""
1121 if self.handle:
1122 try:
1123 response = self.execute(
1124 cmd=host +
1125 " ifconfig",
1126 prompt="mininet>",
1127 timeout=10 )
1128 except pexpect.EOF:
1129 main.log.error( self.name + ": EOF exception found" )
1130 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001131 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001132 except Exception:
1133 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001134 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001135
sathishmad953462015-12-03 17:42:07 +05301136 pattern = ''
1137 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001138 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301139 else:
Jon Hall439c8912016-04-15 02:22:03 -07001140 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001141 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001142 if not ipAddressSearch:
1143 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001144 main.log.info(
1145 self.name +
1146 ": IP-Address of Host " +
1147 host +
1148 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001149 ipAddressSearch.group( 1 ) )
1150 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001151 else:
1152 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001153
Jon Hall7eb38402015-01-08 17:19:54 -08001154 def getSwitchDPID( self, switch ):
1155 """
1156 return the datapath ID of the switch"""
1157 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001158 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001159 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001160 response = self.execute(
1161 cmd=cmd,
1162 prompt="mininet>",
1163 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001164 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001165 main.log.error( self.name + ": EOF exception found" )
1166 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001167 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001168 except Exception:
1169 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001170 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001171 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001172 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001173 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001174 main.log.info(
1175 "Couldn't find DPID for switch %s, found: %s" %
1176 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001177 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001178 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001179 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001180 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001181
Jon Hall7eb38402015-01-08 17:19:54 -08001182 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001183 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001184 self.handle.sendline( "" )
1185 self.expect( "mininet>" )
1186 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001187 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001188 response = self.execute(
1189 cmd=cmd,
1190 prompt="mininet>",
1191 timeout=10 )
1192 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001193 response = self.handle.before
1194 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001195 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001196 main.log.error( self.name + ": TIMEOUT exception found" )
1197 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001198 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001199 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001200 main.log.error( self.name + ": EOF exception found" )
1201 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001202 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001203 except Exception:
1204 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001205 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001206
Jon Hall7eb38402015-01-08 17:19:54 -08001207 def getInterfaces( self, node ):
1208 """
1209 return information dict about interfaces connected to the node"""
1210 if self.handle:
1211 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001212 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001213 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001214 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001215 response = self.execute(
1216 cmd=cmd,
1217 prompt="mininet>",
You Wang7d14d642019-01-23 15:10:08 -08001218 timeout=10,
1219 logCmd=False )
Jon Hallfbc828e2015-01-06 17:30:19 -08001220 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001221 main.log.error( self.name + ": EOF exception found" )
1222 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001223 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001224 except Exception:
1225 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001226 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001227 return response
1228 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001229 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001230
Jon Hall7eb38402015-01-08 17:19:54 -08001231 def dump( self ):
1232 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001233 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001234 response = self.execute(
1235 cmd='dump',
1236 prompt='mininet>',
1237 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001238 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001239 main.log.error( self.name + ": EOF exception found" )
1240 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001241 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001242 except Exception:
1243 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001244 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001245 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001246
Jon Hall7eb38402015-01-08 17:19:54 -08001247 def intfs( self ):
1248 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001249 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001250 response = self.execute(
1251 cmd='intfs',
1252 prompt='mininet>',
1253 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001254 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001255 main.log.error( self.name + ": EOF exception found" )
1256 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001257 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001258 except Exception:
1259 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001260 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001261 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001262
Jon Hall7eb38402015-01-08 17:19:54 -08001263 def net( self ):
1264 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001265 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001266 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001267 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001268 main.log.error( self.name + ": EOF exception found" )
1269 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001270 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001271 except Exception:
1272 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001273 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001274 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001275
Devin Lima7cfdbd2017-09-29 15:02:22 -07001276 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001277 main.log.info( self.name + ": List network links" )
1278 try:
1279 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001280 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001281 except pexpect.EOF:
1282 main.log.error( self.name + ": EOF exception found" )
1283 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001284 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001285 except Exception:
1286 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001287 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001288 return response
1289
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001290 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001291 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001292 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001293
kelvin-onlab7cce9382015-07-17 10:21:03 -07001294 @parm:
1295 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1296 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001297 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001298 try:
1299 for host1 in hosts:
1300 for host2 in hosts:
1301 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001302 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1303 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001304 except Exception:
1305 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001306 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001307
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001308 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001309 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001310 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1311 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001312
kelvin-onlab7cce9382015-07-17 10:21:03 -07001313 @parm:
1314 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1315 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001316 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001317 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1318 try:
1319 # Setup the mininet command
1320 cmd1 = 'iperf ' + host1 + " " + host2
1321 self.handle.sendline( cmd1 )
1322 outcome = self.handle.expect( "mininet>", timeout )
1323 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001324
kelvin-onlab7cce9382015-07-17 10:21:03 -07001325 # checks if there are results in the mininet response
1326 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001327 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001328 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001329 response = response.split( "\r\n" )
1330 response = response[ len( response )-2 ]
1331 response = response.split( ": " )
1332 response = response[ len( response )-1 ]
1333 response = response.replace( "[", "" )
1334 response = response.replace( "]", "" )
1335 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001336
kelvin-onlab7cce9382015-07-17 10:21:03 -07001337 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001338 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001339
kelvin-onlab7cce9382015-07-17 10:21:03 -07001340 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001341 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001342 if len( bandwidth ) == 2:
1343 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001344 return main.TRUE
1345 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001346 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001347 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001348 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001349 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001350 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001351 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001352 main.log.error( self.name + ": TIMEOUT exception found" )
1353 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001354 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001355 # NOTE: Send ctrl-c to make sure iperf is done
You Wanga01d7f72019-02-27 11:23:39 -08001356 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
1357 self.handle.send( "" )
Jon Hall3b489db2015-10-05 14:38:37 -07001358 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001359 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001360 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001361 main.log.error( self.name + ": EOF exception found" )
1362 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001363 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001364 except Exception:
1365 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001366 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001367
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001368 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001369 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1370 try:
1371 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001372 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001373 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001374 outcome1 = self.handle.expect( "mininet>" )
1375 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001376 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001377 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001378 response1 = self.handle.before
1379 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001380 print response1, response2
1381 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001382 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001383 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001384 return main.TRUE
1385 else:
1386 main.log.error( self.name + ": iperf test failed" )
1387 return main.FALSE
1388 except pexpect.TIMEOUT:
1389 main.log.error( self.name + ": TIMEOUT exception found" )
1390 main.log.error( self.name + " response: " + repr( self.handle.before ) )
You Wanga01d7f72019-02-27 11:23:39 -08001391 self.exitFromCmd( [ "Interrupt", "mininet>" ] )
1392 self.handle.send( "" )
Jon Hall439c8912016-04-15 02:22:03 -07001393 self.handle.expect( "mininet>" )
1394 return main.FALSE
1395 except pexpect.EOF:
1396 main.log.error( self.name + ": EOF exception found" )
1397 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001398 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001399 except Exception:
1400 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001401 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001402
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001403 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001404 '''
GlennRC61321f22015-07-16 13:36:54 -07001405 Runs the iperfudp function with a given set of hosts and specified
1406 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001407
GlennRC61321f22015-07-16 13:36:54 -07001408 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001409 bandwidth: the targeted bandwidth, in megabits ('M')
1410 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001411 try:
1412 for host1 in hosts:
1413 for host2 in hosts:
1414 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001415 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1416 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001417 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001418 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001419 return main.FALSE
1420 except Exception:
1421 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001422 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001423
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001424 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001425 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001426 Creates an iperf UDP test with a specific bandwidth.
1427 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001428
kelvin-onlab7cce9382015-07-17 10:21:03 -07001429 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001430 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1431 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001432 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001433 try:
1434 # setup the mininet command
1435 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001436 self.handle.sendline( cmd )
1437 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001438 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001439
kelvin-onlab7cce9382015-07-17 10:21:03 -07001440 # check if there are in results in the mininet response
1441 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001442 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001443 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001444 response = response.split( "\r\n" )
1445 response = response[ len( response )-2 ]
1446 response = response.split( ": " )
1447 response = response[ len( response )-1 ]
1448 response = response.replace( "[", "" )
1449 response = response.replace( "]", "" )
1450 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001451
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001452 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001453
kelvin-onlab7cce9382015-07-17 10:21:03 -07001454 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001455 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001456 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001457 # if one entry is blank then something is wrong
1458 for item in mnBandwidth:
1459 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001460 main.log.error( self.name + ": Could not parse iperf output" )
1461 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001462 return main.FALSE
1463 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001464 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001465 return main.TRUE
1466 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001467 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001468 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001469
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001470 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001471 main.log.error( self.name + ": TIMEOUT exception found" )
1472 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001473 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001474 except pexpect.EOF:
1475 main.log.error( self.name + ": EOF exception found" )
1476 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001477 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001478 except Exception:
1479 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001480 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001481
Jon Hall7eb38402015-01-08 17:19:54 -08001482 def nodes( self ):
1483 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001484 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001485 response = self.execute(
1486 cmd='nodes',
1487 prompt='mininet>',
1488 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001489 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001490 main.log.error( self.name + ": EOF exception found" )
1491 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001492 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001493 except Exception:
1494 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001495 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001496 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001497
Jon Hall7eb38402015-01-08 17:19:54 -08001498 def pingpair( self ):
1499 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001500 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001501 response = self.execute(
1502 cmd='pingpair',
1503 prompt='mininet>',
1504 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001505 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001506 main.log.error( self.name + ": EOF exception found" )
1507 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001508 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001509 except Exception:
1510 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001511 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001512
Jon Hall7eb38402015-01-08 17:19:54 -08001513 if re.search( ',\s0\%\spacket\sloss', response ):
1514 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001515 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001516 else:
alisone4121a92016-11-22 16:31:36 -08001517 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001518 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001519
Jon Hall7eb38402015-01-08 17:19:54 -08001520 def link( self, **linkargs ):
1521 """
GlennRCed771242016-01-13 17:02:47 -08001522 Bring link( s ) between two nodes up or down
1523 """
Jon Hall6094a362014-04-11 14:46:56 -07001524 try:
GlennRCed771242016-01-13 17:02:47 -08001525 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1526 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1527 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1528 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1529
1530 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1531 cmd = "link {} {} {}".format( end1, end2, option )
1532 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001533 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001534 response = self.handle.before
1535 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001536 if "not in network" in response:
1537 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1538 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001539 return main.TRUE
1540 except pexpect.TIMEOUT:
1541 main.log.exception( self.name + ": Command timed out" )
1542 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001543 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001544 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001545 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001546 except Exception:
1547 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001548 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001549
pingping-lin8244a3b2015-09-16 13:36:56 -07001550 def switch( self, **switchargs ):
1551 """
1552 start/stop a switch
1553 """
1554 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1555 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1556 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1557 command = "switch " + str( sw ) + " " + str( option )
1558 main.log.info( command )
1559 try:
1560 self.handle.sendline( command )
1561 self.handle.expect( "mininet>" )
1562 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001563 main.log.error( self.name + ": TIMEOUT exception found" )
1564 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001565 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001566 except pexpect.EOF:
1567 main.log.error( self.name + ": EOF exception found" )
1568 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001569 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001570 return main.TRUE
1571
pingping-lin5bb663b2015-09-24 11:47:50 -07001572 def node( self, nodeName, commandStr ):
1573 """
1574 Carry out a command line on a given node
1575 @parm:
1576 nodeName: the node name in Mininet testbed
1577 commandStr: the command line will be carried out on the node
1578 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1579 """
1580 command = str( nodeName ) + " " + str( commandStr )
1581 main.log.info( command )
1582
1583 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001584 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001585 if re.search( "Unknown command", response ):
1586 main.log.warn( response )
1587 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001588 if re.search( "Permission denied", response ):
1589 main.log.warn( response )
1590 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001591 except pexpect.EOF:
1592 main.log.error( self.name + ": EOF exception found" )
1593 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001594 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001595 main.log.info( " response is :" )
1596 main.log.info( response )
1597 return response
1598
Jon Hall7eb38402015-01-08 17:19:54 -08001599 def yank( self, **yankargs ):
1600 """
1601 yank a mininet switch interface to a host"""
1602 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001603 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001604 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1605 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001606 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001607 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001608 response = self.execute(
1609 cmd=command,
1610 prompt="mininet>",
1611 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001612 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001613 main.log.error( self.name + ": EOF exception found" )
1614 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001615 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001616 except Exception:
1617 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001618 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001619 return main.TRUE
1620
Jon Hall7eb38402015-01-08 17:19:54 -08001621 def plug( self, **plugargs ):
1622 """
1623 plug the yanked mininet switch interface to a switch"""
1624 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001625 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001626 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1627 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001628 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001629 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001630 response = self.execute(
1631 cmd=command,
1632 prompt="mininet>",
1633 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001634 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001635 main.log.error( self.name + ": EOF exception found" )
1636 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001637 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001638 except Exception:
1639 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001640 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001641 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001642
Jon Hall7eb38402015-01-08 17:19:54 -08001643 def dpctl( self, **dpctlargs ):
1644 """
1645 Run dpctl command on all switches."""
1646 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001647 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001648 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1649 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1650 command = "dpctl " + cmd + " " + str( cmdargs )
1651 try:
1652 response = self.execute(
1653 cmd=command,
1654 prompt="mininet>",
1655 timeout=10 )
1656 except pexpect.EOF:
1657 main.log.error( self.name + ": EOF exception found" )
1658 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001659 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001660 except Exception:
1661 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001662 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001663 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001664
kelvin-onlabd3b64892015-01-20 13:26:24 -08001665 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001666 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001667 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001668 try:
1669 fileInput = path + '/lib/Mininet/INSTALL'
1670 version = super( Mininet, self ).getVersion()
1671 pattern = 'Mininet\s\w\.\w\.\w\w*'
1672 for line in open( fileInput, 'r' ).readlines():
1673 result = re.match( pattern, line )
1674 if result:
1675 version = result.group( 0 )
1676 return version
1677 except Exception:
1678 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001679 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001680
kelvin-onlabd3b64892015-01-20 13:26:24 -08001681 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001682 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001683 Parameters:
1684 sw: The name of an OVS switch. Example "s1"
1685 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001686 The output of the command from the mininet cli
1687 or main.FALSE on timeout"""
1688 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001689 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001690 response = self.execute(
1691 cmd=command,
1692 prompt="mininet>",
1693 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001694 if response:
Jon Hallab611372018-02-21 15:26:05 -08001695 if "no bridge named" in response:
1696 main.log.error( self.name + ": Error in getSwController: " +
1697 self.handle.before )
1698 return main.FALSE
1699 else:
1700 return response
admin2a9548d2014-06-17 14:08:07 -07001701 else:
1702 return main.FALSE
1703 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001704 main.log.error( self.name + ": EOF exception found" )
1705 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001706 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001707 except Exception:
1708 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001709 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001710
Charles Chan029be652015-08-24 01:46:10 +08001711 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001712 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001713 Description:
1714 Assign switches to the controllers ( for ovs use only )
1715 Required:
1716 sw - Name of the switch. This can be a list or a string.
1717 ip - Ip addresses of controllers. This can be a list or a string.
1718 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001719 port - ONOS use port 6653, if no list of ports is passed, then
1720 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001721 ptcp - ptcp number, This can be a string or a list that has
1722 the same length as switch. This is optional and not required
1723 when using ovs switches.
1724 NOTE: If switches and ptcp are given in a list type they should have the
1725 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1726 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001727
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001728 Return:
1729 Returns main.TRUE if mininet correctly assigned switches to
1730 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001731 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001732 """
1733 assignResult = main.TRUE
1734 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001735 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001736 command = "sh ovs-vsctl set-controller "
1737 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001738 try:
1739 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001740 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001741 if isinstance( port, types.StringType ) or \
1742 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001743 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001744 elif isinstance( port, types.ListType ):
1745 main.log.error( self.name + ": Only one controller " +
1746 "assigned and a list of ports has" +
1747 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001748 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001749 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001750 main.log.error( self.name + ": Invalid controller port " +
1751 "number. Please specify correct " +
1752 "controller port" )
1753 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001754
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001755 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001756 if isinstance( port, types.StringType ) or \
1757 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001758 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001759 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1760 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001761 elif isinstance( port, types.ListType ):
1762 if ( len( ip ) != len( port ) ):
1763 main.log.error( self.name + ": Port list = " +
1764 str( len( port ) ) +
1765 "should be the same as controller" +
1766 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001767 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001768 else:
1769 onosIp = ""
1770 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001771 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1772 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001773 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001774 main.log.error( self.name + ": Invalid controller port " +
1775 "number. Please specify correct " +
1776 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001777 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001778 else:
1779 main.log.error( self.name + ": Invalid ip address" )
1780 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001781
1782 if isinstance( sw, types.StringType ):
1783 command += sw + " "
1784 if ptcp:
1785 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001786 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001787 elif isinstance( ptcp, types.ListType ):
1788 main.log.error( self.name + ": Only one switch is " +
1789 "being set and multiple PTCP is " +
1790 "being passed " )
1791 else:
1792 main.log.error( self.name + ": Invalid PTCP" )
1793 ptcp = ""
1794 command += onosIp
1795 commandList.append( command )
1796
1797 elif isinstance( sw, types.ListType ):
1798 if ptcp:
1799 if isinstance( ptcp, types.ListType ):
1800 if len( ptcp ) != len( sw ):
1801 main.log.error( self.name + ": PTCP length = " +
1802 str( len( ptcp ) ) +
1803 " is not the same as switch" +
1804 " length = " +
1805 str( len( sw ) ) )
1806 return main.FALSE
1807 else:
1808 for switch, ptcpNum in zip( sw, ptcp ):
1809 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001810 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001811 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001812 tempCmd += onosIp
1813 commandList.append( tempCmd )
1814 else:
1815 main.log.error( self.name + ": Invalid PTCP" )
1816 return main.FALSE
1817 else:
1818 for switch in sw:
1819 tempCmd = "sh ovs-vsctl set-controller "
1820 tempCmd += switch + " " + onosIp
1821 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001822 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001823 main.log.error( self.name + ": Invalid switch type " )
1824 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001825
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001826 for cmd in commandList:
1827 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001828 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08001829 if "no bridge named" in self.handle.before:
1830 main.log.error( self.name + ": Error in assignSwController: " +
1831 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001832 except pexpect.TIMEOUT:
1833 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1834 return main.FALSE
1835 except pexpect.EOF:
1836 main.log.error( self.name + ": EOF exception found" )
1837 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001838 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001839 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001840 except pexpect.EOF:
1841 main.log.error( self.name + ": EOF exception found" )
1842 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001843 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001844 except Exception:
1845 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001846 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001847
kelvin-onlabd3b64892015-01-20 13:26:24 -08001848 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001849 """
1850 Removes the controller target from sw"""
1851 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001852 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001853 response = self.execute(
1854 cmd=command,
1855 prompt="mininet>",
1856 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001857 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001858 main.log.error( self.name + ": EOF exception found" )
1859 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001860 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001861 except Exception:
1862 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001863 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001864 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001865 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001866
kelvin-onlabd3b64892015-01-20 13:26:24 -08001867 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001868 """
Jon Hallb1290e82014-11-18 16:17:48 -05001869 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001870 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001871 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001872 NOTE: cannot currently specify what type of switch
1873 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001874 sw = name of the new switch as a string
1875 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001876 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001877 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001878 """
1879 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001880 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001881 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001882 response = self.execute(
1883 cmd=command,
1884 prompt="mininet>",
1885 timeout=10 )
1886 if re.search( "already exists!", response ):
1887 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001888 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001889 elif re.search( "Error", response ):
1890 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001891 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001892 elif re.search( "usage:", response ):
1893 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001894 return main.FALSE
1895 else:
1896 return main.TRUE
1897 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001898 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001899 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001900 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001901 except Exception:
1902 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001903 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001904
kelvin-onlabd3b64892015-01-20 13:26:24 -08001905 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001906 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001907 delete a switch from the mininet topology
1908 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001909 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001910 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001911 sw = name of the switch as a string
1912 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001913 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001914 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001915 response = self.execute(
1916 cmd=command,
1917 prompt="mininet>",
1918 timeout=10 )
1919 if re.search( "no switch named", response ):
1920 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001921 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001922 elif re.search( "Error", response ):
1923 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001924 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001925 elif re.search( "usage:", response ):
1926 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001927 return main.FALSE
1928 else:
1929 return main.TRUE
1930 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001931 main.log.error( self.name + ": EOF exception found" )
1932 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001933 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001934 except Exception:
1935 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001936 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001937
You Wangb1665b52019-02-01 15:49:48 -08001938 def getSwitchRandom( self, timeout=60, nonCut=True, excludeNodes=[], skipSwitches=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07001939 """
1940 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001941 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001942 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001943 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07001944 it just randomly returns one switch from all current switches in
1945 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08001946 excludeNodes will be pased to getGraphDict method
You Wangb1665b52019-02-01 15:49:48 -08001947 Switches specified in skipSwitches will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07001948 Returns the name of the chosen switch.
1949 """
1950 import random
1951 candidateSwitches = []
1952 try:
1953 if not nonCut:
You Wangb1665b52019-02-01 15:49:48 -08001954 switches = self.getSwitches( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07001955 assert len( switches ) != 0
1956 for switchName in switches.keys():
1957 candidateSwitches.append( switchName )
1958 else:
You Wang7d14d642019-01-23 15:10:08 -08001959 graphDict = self.getGraphDict( timeout=timeout, useId=False,
You Wang7d14d642019-01-23 15:10:08 -08001960 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001961 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001962 return None
1963 self.graph.update( graphDict )
1964 candidateSwitches = self.graph.getNonCutVertices()
You Wangb1665b52019-02-01 15:49:48 -08001965 candidateSwitches = [ switch for switch in candidateSwitches if switch not in skipSwitches ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001966 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001967 return None
1968 elif len( candidateSwitches ) == 0:
1969 main.log.info( self.name + ": No candidate switch for deletion" )
1970 return None
1971 else:
1972 switch = random.sample( candidateSwitches, 1 )
1973 return switch[ 0 ]
1974 except KeyError:
1975 main.log.exception( self.name + ": KeyError exception found" )
1976 return None
1977 except AssertionError:
1978 main.log.exception( self.name + ": AssertionError exception found" )
1979 return None
1980 except Exception:
1981 main.log.exception( self.name + ": Uncaught exception" )
1982 return None
1983
1984 def delSwitchRandom( self, timeout=60, nonCut=True ):
1985 """
1986 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001987 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001988 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001989 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07001990 otherwise it just randomly delete one switch from all current
1991 switches in Mininet.
1992 Returns the name of the deleted switch
1993 """
1994 try:
1995 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001996 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001997 return None
1998 else:
1999 deletionResult = self.delSwitch( switch )
2000 if deletionResult:
2001 return switch
2002 else:
2003 return None
2004 except Exception:
2005 main.log.exception( self.name + ": Uncaught exception" )
2006 return None
2007
kelvin-onlabd3b64892015-01-20 13:26:24 -08002008 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002009 """
2010 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002011 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002012 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002013 NOTE: cannot currently specify what type of link
2014 required params:
2015 node1 = the string node name of the first endpoint of the link
2016 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002017 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002018 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002019 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002020 response = self.execute(
2021 cmd=command,
2022 prompt="mininet>",
2023 timeout=10 )
2024 if re.search( "doesnt exist!", response ):
2025 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002026 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002027 elif re.search( "Error", response ):
2028 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002029 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002030 elif re.search( "usage:", response ):
2031 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002032 return main.FALSE
2033 else:
2034 return main.TRUE
2035 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002036 main.log.error( self.name + ": EOF exception found" )
2037 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002038 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002039 except Exception:
2040 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002041 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002042
kelvin-onlabd3b64892015-01-20 13:26:24 -08002043 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002044 """
2045 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002046 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002047 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002048 required params:
2049 node1 = the string node name of the first endpoint of the link
2050 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002051 returns: main.FALSE on an error, else main.TRUE
2052 """
Jon Hallffb386d2014-11-21 13:43:38 -08002053 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002054 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002055 response = self.execute(
2056 cmd=command,
2057 prompt="mininet>",
2058 timeout=10 )
2059 if re.search( "no node named", response ):
2060 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002061 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002062 elif re.search( "Error", response ):
2063 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002064 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002065 elif re.search( "usage:", response ):
2066 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002067 return main.FALSE
2068 else:
2069 return main.TRUE
2070 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002071 main.log.error( self.name + ": EOF exception found" )
2072 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002073 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002074 except Exception:
2075 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002076 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002077
You Wangb1665b52019-02-01 15:49:48 -08002078 def getLinkRandom( self, timeout=60, nonCut=True, excludeNodes=[], skipLinks=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07002079 """
2080 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002081 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002082 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002083 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002084 it just randomly returns one link from all current links in
2085 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08002086 excludeNodes will be passed to getLinks method to exclude unexpected links.
You Wangb1665b52019-02-01 15:49:48 -08002087 Any link that has either end included in skipLinks will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07002088 Returns the link as a list, e.g. [ 's1', 's2' ]
2089 """
2090 import random
2091 candidateLinks = []
2092 try:
2093 if not nonCut:
You Wang7d14d642019-01-23 15:10:08 -08002094 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07002095 assert len( links ) != 0
2096 for link in links:
2097 # Exclude host-switch link
2098 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2099 continue
2100 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2101 else:
You Wang7d14d642019-01-23 15:10:08 -08002102 graphDict = self.getGraphDict( timeout=timeout, useId=False,
You Wang7d14d642019-01-23 15:10:08 -08002103 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002104 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002105 return None
2106 self.graph.update( graphDict )
2107 candidateLinks = self.graph.getNonCutEdges()
You Wangb1665b52019-02-01 15:49:48 -08002108 candidateLinks = [ link for link in candidateLinks
2109 if link[0] not in skipLinks and link[1] not in skipLinks ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002110 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002111 return None
2112 elif len( candidateLinks ) == 0:
2113 main.log.info( self.name + ": No candidate link for deletion" )
2114 return None
2115 else:
2116 link = random.sample( candidateLinks, 1 )
2117 return link[ 0 ]
2118 except KeyError:
2119 main.log.exception( self.name + ": KeyError exception found" )
2120 return None
2121 except AssertionError:
2122 main.log.exception( self.name + ": AssertionError exception found" )
2123 return None
2124 except Exception:
2125 main.log.exception( self.name + ": Uncaught exception" )
2126 return None
2127
2128 def delLinkRandom( self, timeout=60, nonCut=True ):
2129 """
2130 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002131 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002132 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002133 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002134 otherwise it just randomly delete one link from all current links
2135 in Mininet.
2136 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2137 """
2138 try:
2139 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002140 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002141 return None
2142 else:
2143 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2144 if deletionResult:
2145 return link
2146 else:
2147 return None
2148 except Exception:
2149 main.log.exception( self.name + ": Uncaught exception" )
2150 return None
2151
kelvin-onlabd3b64892015-01-20 13:26:24 -08002152 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002153 """
Jon Hallb1290e82014-11-18 16:17:48 -05002154 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002155 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002156 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002157 NOTE: cannot currently specify what type of host
2158 required params:
2159 hostname = the string hostname
2160 optional key-value params
2161 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002162 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002163 """
2164 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002165 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002166 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002167 response = self.execute(
2168 cmd=command,
2169 prompt="mininet>",
2170 timeout=10 )
2171 if re.search( "already exists!", response ):
2172 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002173 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002174 elif re.search( "doesnt exists!", response ):
2175 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002176 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002177 elif re.search( "Error", response ):
2178 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002179 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002180 elif re.search( "usage:", response ):
2181 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002182 return main.FALSE
2183 else:
2184 return main.TRUE
2185 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002186 main.log.error( self.name + ": EOF exception found" )
2187 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002188 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002189 except Exception:
2190 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002191 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002192
kelvin-onlabd3b64892015-01-20 13:26:24 -08002193 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002194 """
2195 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002196 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002197 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002198 NOTE: this uses a custom mn function
2199 required params:
2200 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002201 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002202 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002203 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002204 response = self.execute(
2205 cmd=command,
2206 prompt="mininet>",
2207 timeout=10 )
2208 if re.search( "no host named", response ):
2209 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002210 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002211 elif re.search( "Error", response ):
2212 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002213 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002214 elif re.search( "usage:", response ):
2215 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002216 return main.FALSE
2217 else:
2218 return main.TRUE
2219 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002220 main.log.error( self.name + ": EOF exception found" )
2221 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002222 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002223 except Exception:
2224 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002225 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002226
Jon Hall7eb38402015-01-08 17:19:54 -08002227 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002228 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002229 Called at the end of the test to stop the mininet and
2230 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002231 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002232 try:
2233 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002234 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002235 timeout=2 )
2236 response = main.TRUE
2237 if i == 0:
2238 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002239 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002240 return main.TRUE
2241 # print "Disconnecting Mininet"
2242 if self.handle:
2243 self.handle.sendline( "exit" )
2244 self.handle.expect( "exit" )
2245 self.handle.expect( "(.*)" )
2246 else:
2247 main.log.error( "Connection failed to the host" )
2248 return response
2249 except pexpect.EOF:
2250 main.log.error( self.name + ": EOF exception found" )
2251 main.log.error( self.name + ": " + self.handle.before )
You Wangd4fae5c2018-08-22 13:56:49 -07002252 # Do not exit the entire test when pexpect.EOF is caught
2253 # FIXME: We might need to do something else here
2254 return main.ERROR
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002255 except Exception:
2256 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002257 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002258
Devin Lima7cfdbd2017-09-29 15:02:22 -07002259 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002260 """
Jon Hall21270ac2015-02-16 17:59:55 -08002261 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002262 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002263 main.FALSE if the pexpect handle does not exist.
2264
Jon Halld61331b2015-02-17 16:35:47 -08002265 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002266 """
Jon Halld61331b2015-02-17 16:35:47 -08002267 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002268 response = ''
2269 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002270 try:
Jon Halld80cc142015-07-06 13:36:05 -07002271 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002272 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002273 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002274 pexpect.EOF,
2275 pexpect.TIMEOUT ],
2276 timeout )
2277 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002278 main.log.info( "Exiting mininet.." )
2279 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002280 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002281 prompt=self.prompt,
2282 timeout=exitTimeout )
2283 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002284 self.handle.sendline( "sudo mn -c" )
2285 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002286
Jeremyd9e4eb12016-04-13 12:09:06 -07002287 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002288 main.log.info( " Mininet trying to exit while not " +
2289 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002290 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002291 elif i == 2:
2292 main.log.error( "Something went wrong exiting mininet" )
2293 elif i == 3: # timeout
2294 main.log.error( "Something went wrong exiting mininet " +
2295 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002296
You Wang18db8592018-04-02 13:52:03 -07002297 self.handle.sendline( "" )
2298 self.handle.expect( self.prompt )
2299 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2300
Hari Krishnab35c6d02015-03-18 11:13:51 -07002301 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002302 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002303 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002304 self.handle.sendline(
2305 "sudo kill -9 \`ps -ef | grep \"" +
2306 fileName +
2307 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002308 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002309 main.log.error( self.name + ": TIMEOUT exception found" )
2310 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002311 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002312 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002313 main.log.error( self.name + ": EOF exception found" )
2314 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002315 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002316 except Exception:
2317 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002318 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002319 else:
2320 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002321 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002322 return response
2323
YPZhang26a139e2016-04-25 14:01:55 -07002324 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002325 """
2326 Description:
2327 Sends arp message from mininet host for hosts discovery
2328 Required:
2329 host - hosts name
2330 Optional:
2331 ip - ip address that does not exist in the network so there would
2332 be no reply.
2333 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002334 if ethDevice:
2335 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002336 cmd = srcHost + " arping -c1 "
2337 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002338 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 -07002339 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002340 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002341 if output:
2342 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002343 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002344 i = self.handle.expect( [ "mininet>", "arping: " ] )
2345 if i == 0:
2346 return main.TRUE
2347 elif i == 1:
2348 response = self.handle.before + self.handle.after
2349 self.handle.expect( "mininet>" )
2350 response += self.handle.before + self.handle.after
2351 main.log.warn( "Error sending arping, output was: " +
2352 response )
2353 return main.FALSE
2354 except pexpect.TIMEOUT:
2355 main.log.error( self.name + ": TIMEOUT exception found" )
2356 main.log.warn( self.handle.before )
2357 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002358 except pexpect.EOF:
2359 main.log.error( self.name + ": EOF exception found" )
2360 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002361 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002362 except Exception:
2363 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002364 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002365
Jon Hall7eb38402015-01-08 17:19:54 -08002366 def decToHex( self, num ):
2367 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002368
Jon Hall7eb38402015-01-08 17:19:54 -08002369 def getSwitchFlowCount( self, switch ):
2370 """
2371 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002372 if self.handle:
2373 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2374 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002375 response = self.execute(
2376 cmd=cmd,
2377 prompt="mininet>",
2378 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002379 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002380 main.log.error( self.name + ": EOF exception found" )
2381 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002382 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002383 except Exception:
2384 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002385 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002386 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002387 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002388 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002389 main.log.info(
2390 "Couldn't find flows on switch %s, found: %s" %
2391 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002392 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002393 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002394 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002395 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002396
Jon Hall9ed8f372016-02-24 17:34:07 -08002397 def checkFlows( self, sw, dumpFormat=None ):
2398 if dumpFormat:
2399 command = "sh ovs-ofctl -F " + \
2400 dumpFormat + " dump-flows " + str( sw )
2401 else:
2402 command = "sh ovs-ofctl dump-flows " + str( sw )
2403 try:
2404 response = self.execute(
2405 cmd=command,
2406 prompt="mininet>",
2407 timeout=10 )
2408 return response
2409 except pexpect.EOF:
2410 main.log.error( self.name + ": EOF exception found" )
2411 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002412 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002413 except Exception:
2414 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002415 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002416
GlennRC68467eb2015-11-16 18:01:01 -08002417 def flowTableComp( self, flowTable1, flowTable2 ):
2418 # This function compares the selctors and treatments of each flow
2419 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002420 assert flowTable1, "flowTable1 is empty or None"
2421 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002422 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002423 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002424 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002425 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002426 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2427 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002428 for field in dFields:
2429 try:
2430 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002431 except KeyError:
2432 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002433 try:
2434 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002435 except KeyError:
2436 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002437 for i in range( len( flowTable1 ) ):
2438 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002439 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002440 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002441 returnValue = main.FALSE
2442 break
2443 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002444 except AssertionError:
2445 main.log.exception( "Nothing to compare" )
2446 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002447 except Exception:
2448 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002449 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002450
GlennRC528ad292015-11-12 10:38:18 -08002451 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002452 '''
GlennRC956ea742015-11-05 16:14:15 -08002453 Discription: Parses flows into json format.
2454 NOTE: this can parse any string thats separated with commas
2455 Arguments:
2456 Required:
2457 flows: a list of strings that represnt flows
2458 Optional:
2459 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2460 debug: prints out the final result
2461 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002462 '''
GlennRC528ad292015-11-12 10:38:18 -08002463 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002464 try:
2465 for flow in flowTable:
2466 jsonFlow = {}
2467 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002468 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002469 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002470 for i in range( len( parsedFlow ) ):
2471 item = parsedFlow[ i ]
2472 if item[ 0 ] == " ":
2473 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002474 # grab the selector and treatment from the parsed flow
2475 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002476 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002477 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002478 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002479 index = 0
2480 # parse the flags
2481 # NOTE: This only parses one flag
2482 flag = {}
2483 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002484 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002485 index += 1
2486 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002487 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002488 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002489 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002490 # the priority is stuck in the selecter so put it back
2491 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002492 if 'priority' in sel[0]:
2493 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002494 # parse selector
2495 criteria = []
2496 for item in sel:
2497 # this is the type of the packet e.g. "arp"
2498 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002499 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002500 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002501 field = item.split( "=" )
2502 criteria.append( { field[ 0 ]: field[ 1 ] } )
2503 selector = { "selector": { "criteria": sorted( criteria ) } }
2504 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002505 # get rid of the action part e.g. "action=output:2"
2506 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002507 treat = treat.split( "=" )
2508 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002509 # parse treatment
2510 action = []
2511 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002512 if ":" in item:
2513 field = item.split( ":" )
2514 action.append( { field[ 0 ]: field[ 1 ] } )
2515 else:
2516 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2517 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002518 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002519 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002520 # parse the rest of the flow
2521 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002522 field = item.split( "=" )
2523 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002524 # add the treatment and the selector to the json flow
2525 jsonFlow.update( selector )
2526 jsonFlow.update( treatment )
2527 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002528
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002529 if debug:
2530 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002531
You Wang91c37cf2016-05-23 09:39:42 -07002532 # add the json flow to the json flow table
2533 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002534
You Wang91c37cf2016-05-23 09:39:42 -07002535 return jsonFlowTable
2536
2537 except IndexError:
2538 main.log.exception( self.name + ": IndexError found" )
2539 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002540 except pexpect.EOF:
2541 main.log.error( self.name + ": EOF exception found" )
2542 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002543 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002544 except Exception:
2545 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002546 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002547
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002548 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002549 '''
2550 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002551 Each element is a flow.
2552 Arguments:
2553 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002554 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002555 a list of switches.
2556 Optional:
2557 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2558 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002559 '''
GlennRC956ea742015-11-05 16:14:15 -08002560 try:
2561 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002562 if isinstance( sw, list ):
2563 switches.extend( sw )
2564 else:
2565 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002566
2567 flows = []
2568 for s in switches:
2569 cmd = "sh ovs-ofctl dump-flows " + s
2570
GlennRC528ad292015-11-12 10:38:18 -08002571 if "1.0" == version:
2572 cmd += " -F OpenFlow10-table_id"
2573 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002574 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002575
2576 main.log.info( "Sending: " + cmd )
2577 self.handle.sendline( cmd )
2578 self.handle.expect( "mininet>" )
2579 response = self.handle.before
2580 response = response.split( "\r\n" )
2581 # dump the first two elements and the last
2582 # the first element is the command that was sent
2583 # the second is the table header
2584 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002585 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002586 flows.extend( response )
2587
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002588 if debug:
2589 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002590
GlennRC528ad292015-11-12 10:38:18 -08002591 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002592
GlennRC956ea742015-11-05 16:14:15 -08002593 except pexpect.EOF:
2594 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002595 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002596 except Exception:
2597 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002598 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002599
2600 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002601 '''
GlennRC956ea742015-11-05 16:14:15 -08002602 Discription: Checks whether the ID provided matches a flow ID in Mininet
2603 Arguments:
2604 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002605 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002606 a list of switches.
2607 flowId: the flow ID in hex format. Can also be a list of IDs
2608 Optional:
2609 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2610 debug: prints out the final result
2611 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2612 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002613 '''
GlennRC956ea742015-11-05 16:14:15 -08002614 try:
2615 main.log.info( "Getting flows from Mininet" )
2616 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002617 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002618 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002619
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002620 if debug:
2621 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002622
2623 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002624 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002625 result = False
2626 for f in flows:
2627 if flowId in f.get( 'cookie' ):
2628 result = True
2629 break
2630 # flowId is a list
2631 else:
2632 result = True
2633 # Get flow IDs from Mininet
2634 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2635 # Save the IDs that are not in Mininet
2636 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2637
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002638 if debug:
2639 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002640
2641 # Print out the IDs that are not in Mininet
2642 if absentIds:
2643 main.log.warn( "Absent ids: {}".format( absentIds ) )
2644 result = False
2645
2646 return main.TRUE if result else main.FALSE
2647
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002648 except pexpect.EOF:
2649 main.log.error( self.name + ": EOF exception found" )
2650 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002651 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002652 except Exception:
2653 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002654 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002655
Charles Chan029be652015-08-24 01:46:10 +08002656 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002657 """
Jon Hallefbd9792015-03-05 16:11:36 -08002658 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002659 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002660 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002661 self.handle.sendline( "" )
2662 self.handle.expect( "mininet>" )
2663 self.handle.sendline(
2664 "sh sudo tcpdump -n -i " +
2665 intf +
2666 " " +
2667 port +
2668 " -w " +
2669 filename.strip() +
2670 " &" )
2671 self.handle.sendline( "" )
2672 i = self.handle.expect( [ 'No\ssuch\device',
2673 'listening\son',
2674 pexpect.TIMEOUT,
2675 "mininet>" ],
2676 timeout=10 )
2677 main.log.warn( self.handle.before + self.handle.after )
2678 self.handle.sendline( "" )
2679 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002680 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002681 main.log.error(
2682 self.name +
2683 ": tcpdump - No such device exists. " +
2684 "tcpdump attempted on: " +
2685 intf )
admin2a9548d2014-06-17 14:08:07 -07002686 return main.FALSE
2687 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002688 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002689 return main.TRUE
2690 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002691 main.log.error(
2692 self.name +
2693 ": tcpdump command timed out! Check interface name," +
2694 " given interface was: " +
2695 intf )
admin2a9548d2014-06-17 14:08:07 -07002696 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002697 elif i == 3:
2698 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002699 return main.TRUE
2700 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002701 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002702 return main.FALSE
2703 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002704 main.log.error( self.name + ": EOF exception found" )
2705 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002706 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002707 except Exception:
2708 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002709 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002710
kelvin-onlabd3b64892015-01-20 13:26:24 -08002711 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002712 """
2713 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002714 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002715 self.handle.sendline( "sh sudo pkill tcpdump" )
2716 self.handle.expect( "mininet>" )
2717 self.handle.sendline( "" )
2718 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002719 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002720 main.log.error( self.name + ": TIMEOUT exception found" )
2721 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002722 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002723 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002724 main.log.error( self.name + ": EOF exception found" )
2725 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002726 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002727 except Exception:
2728 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002729 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002730
Jon Halld80cc142015-07-06 13:36:05 -07002731 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002732 """
2733 Read ports from a Mininet switch.
2734
2735 Returns a json structure containing information about the
2736 ports of the given switch.
2737 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002738 try:
2739 response = self.getInterfaces( nodeName )
2740 # TODO: Sanity check on response. log if no such switch exists
2741 ports = []
2742 for line in response.split( "\n" ):
2743 if not line.startswith( "name=" ):
2744 continue
2745 portVars = {}
2746 for var in line.split( "," ):
2747 key, value = var.split( "=" )
2748 portVars[ key ] = value
2749 isUp = portVars.pop( 'enabled', "True" )
2750 isUp = "True" in isUp
2751 if verbose:
2752 main.log.info( "Reading switch port %s(%s)" %
2753 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2754 mac = portVars[ 'mac' ]
2755 if mac == 'None':
2756 mac = None
2757 ips = []
2758 ip = portVars[ 'ip' ]
2759 if ip == 'None':
2760 ip = None
2761 ips.append( ip )
2762 name = portVars[ 'name' ]
2763 if name == 'None':
2764 name = None
2765 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2766 if name == 'lo':
2767 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2768 else:
2769 portNo = re.search( portRe, name ).group( 'port' )
2770 ports.append( { 'of_port': portNo,
2771 'mac': str( mac ).replace( '\'', '' ),
2772 'name': name,
2773 'ips': ips,
2774 'enabled': isUp } )
2775 return ports
2776 except pexpect.EOF:
2777 main.log.error( self.name + ": EOF exception found" )
2778 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002779 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002780 except Exception:
2781 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002782 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002783
You Wangdb8cd0a2016-05-26 15:19:45 -07002784 def getOVSPorts( self, nodeName ):
2785 """
2786 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2787
2788 Returns a list of dictionaries containing information about each
2789 port of the given switch.
2790 """
2791 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2792 try:
2793 response = self.execute(
2794 cmd=command,
2795 prompt="mininet>",
You Wang7d14d642019-01-23 15:10:08 -08002796 timeout=10,
2797 logCmd=False )
You Wangdb8cd0a2016-05-26 15:19:45 -07002798 ports = []
2799 if response:
2800 for line in response.split( "\n" ):
2801 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2802 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002803 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002804 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2805 result = re.search( pattern, line )
2806 if result:
2807 index = result.group( 'index' )
2808 name = result.group( 'name' )
2809 # This port number is extracted from port name
2810 port = result.group( 'port' )
2811 mac = result.group( 'mac' )
2812 ports.append( { 'index': index,
2813 'name': name,
2814 'port': port,
2815 'mac': mac } )
2816 return ports
2817 except pexpect.EOF:
2818 main.log.error( self.name + ": EOF exception found" )
2819 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002820 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002821 except Exception:
2822 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002823 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002824
You Wangb1665b52019-02-01 15:49:48 -08002825 def getSwitches( self, verbose=False, updateTimeout=1000, excludeNodes=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002826 """
2827 Read switches from Mininet.
2828
2829 Returns a dictionary whose keys are the switch names and the value is
2830 a dictionary containing information about the switch.
You Wangb1665b52019-02-01 15:49:48 -08002831 If excludeNodes is specified, switches with names included in excludeNodes
2832 will be ingored.
Jon Hallafa8a472015-06-12 14:02:42 -07002833 """
Jon Halla22481b2015-07-28 17:46:01 -07002834 # NOTE: To support new Mininet switch classes, just append the new
2835 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002836
Jon Halla22481b2015-07-28 17:46:01 -07002837 # Regex patterns to parse 'dump' output
2838 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002839 # <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 -07002840 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002841 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2842 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2843 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
You Wangb1665b52019-02-01 15:49:48 -08002844 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
You Wang7d14d642019-01-23 15:10:08 -08002845 try:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002846 swRE = r"<(?P<class>" + switchClasses + r")" +\
2847 r"(?P<options>\{.*\})?\s" +\
2848 r"(?P<name>[^:]+)\:\s" +\
2849 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2850 r"\spid=(?P<pid>(\d)+)"
2851 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002852 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002853 output = {}
2854 dump = self.dump().split( "\n" )
2855 for line in dump:
2856 result = re.search( swRE, line, re.I )
2857 if result:
2858 name = result.group( 'name' )
You Wangb1665b52019-02-01 15:49:48 -08002859 if name in excludeNodes:
2860 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002861 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2862 pid = result.group( 'pid' )
2863 swClass = result.group( 'class' )
2864 options = result.group( 'options' )
2865 if verbose:
2866 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2867 ports = self.getPorts( name )
2868 output[ name ] = { "dpid": dpid,
2869 "ports": ports,
2870 "swClass": swClass,
2871 "pid": pid,
2872 "options": options }
2873 return output
2874 except pexpect.EOF:
2875 main.log.error( self.name + ": EOF exception found" )
2876 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002877 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002878 except Exception:
2879 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002880 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002881
You Wangd66de192018-04-30 17:30:12 -07002882 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002883 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2884 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002885 """
2886 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002887 Optional:
2888 hostClass: it is used to match the class of the mininet host. It
2889 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002890 Returns a dictionary whose keys are the host names and the value is
2891 a dictionary containing information about the host.
2892 """
2893 # Regex patterns to parse dump output
2894 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002895 # <Host h1: pid=12725>
2896 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2897 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2898 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002899 # NOTE: Does not correctly match hosts with multi-links
2900 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2901 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002902 try:
You Wang53dba1e2018-02-02 17:45:44 -08002903 if not isinstance( hostClass, types.ListType ):
2904 hostClass = [ str( hostClass ) ]
2905 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002906 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2907 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2908 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002909 if update:
2910 # update mn port info
2911 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002912 # Get mininet dump
2913 dump = self.dump().split( "\n" )
2914 hosts = {}
2915 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002916 result = re.search( hostRE, line )
2917 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002918 name = result.group( 'name' )
2919 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002920 if getInterfaces:
2921 response = self.getInterfaces( name )
2922 # Populate interface info
2923 for line in response.split( "\n" ):
2924 if line.startswith( "name=" ):
2925 portVars = {}
2926 for var in line.split( "," ):
2927 key, value = var.split( "=" )
2928 portVars[ key ] = value
2929 isUp = portVars.pop( 'enabled', "True" )
2930 isUp = "True" in isUp
2931 if verbose:
2932 main.log.info( "Reading host port %s(%s)" %
2933 ( portVars[ 'name' ],
2934 portVars[ 'mac' ] ) )
2935 mac = portVars[ 'mac' ]
2936 if mac == 'None':
2937 mac = None
2938 ips = []
2939 ip = portVars[ 'ip' ]
2940 if ip == 'None':
2941 ip = None
2942 ips.append( ip )
2943 intfName = portVars[ 'name' ]
2944 if name == 'None':
2945 name = None
2946 interfaces.append( {
2947 "name": intfName,
2948 "ips": ips,
2949 "mac": str( mac ),
2950 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002951 hosts[ name ] = { "interfaces": interfaces }
2952 return hosts
2953 except pexpect.EOF:
2954 main.log.error( self.name + ": EOF exception found" )
2955 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002956 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002957 except Exception:
2958 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002959 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002960
You Wang7d14d642019-01-23 15:10:08 -08002961 def getLinks( self, timeout=20, updateTimeout=1000, excludeNodes=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002962 """
2963 Gathers information about current Mininet links. These links may not
2964 be up if one of the ports is down.
2965
2966 Returns a list of dictionaries with link endpoints.
2967
2968 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002969 { 'node1': str( node1 name )
2970 'node2': str( node2 name )
2971 'port1': str( port1 of_port )
2972 'port2': str( port2 of_port ) }
You Wang7d14d642019-01-23 15:10:08 -08002973
You Wangb1665b52019-02-01 15:49:48 -08002974 If either node1 or node2 name matches any of the names sepcified in
2975 excludeNodes, the link will be excluded from the returned value
You Wang7d14d642019-01-23 15:10:08 -08002976
Jon Hallafa8a472015-06-12 14:02:42 -07002977 Note: The port number returned is the eth#, not necessarily the of_port
2978 number. In Mininet, for OVS switch, these should be the same. For
2979 hosts, this is just the eth#.
2980 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002981 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002982 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002983 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002984
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002985 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002986 # s1-eth3<->s2-eth1 (OK OK)
2987 # s13-eth3<->h27-eth0 (OK OK)
You Wang7d14d642019-01-23 15:10:08 -08002988 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d\.]+)\<\-\>" +\
2989 "(?P<node2>[\w]+)\-eth(?P<port2>[\d\.]+)"
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002990 links = []
2991 for line in response:
2992 match = re.search( linkRE, line )
2993 if match:
2994 node1 = match.group( 'node1' )
2995 node2 = match.group( 'node2' )
You Wangb1665b52019-02-01 15:49:48 -08002996 if any( node1 == node or node2 == node for node in excludeNodes ):
You Wang7d14d642019-01-23 15:10:08 -08002997 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002998 port1 = match.group( 'port1' )
2999 port2 = match.group( 'port2' )
3000 links.append( { 'node1': node1,
3001 'node2': node2,
3002 'port1': port1,
3003 'port2': port2 } )
3004 return links
3005
3006 except pexpect.EOF:
3007 main.log.error( self.name + ": EOF exception found" )
3008 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003009 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003010 except Exception:
3011 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003012 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003013
3014 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003015 """
3016 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003017 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003018
Jon Hallafa8a472015-06-12 14:02:42 -07003019 Dependencies:
3020 1. numpy - "sudo pip install numpy"
3021 """
3022 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003023 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003024 try:
3025 mnDPIDs = []
3026 for swName, switch in switches.iteritems():
3027 mnDPIDs.append( switch[ 'dpid' ].lower() )
3028 mnDPIDs.sort()
3029 if switchesJson == "": # if rest call fails
3030 main.log.error(
3031 self.name +
3032 ".compareSwitches(): Empty JSON object given from ONOS" )
3033 return main.FALSE
3034 onos = switchesJson
3035 onosDPIDs = []
3036 for switch in onos:
3037 if switch[ 'available' ]:
3038 onosDPIDs.append(
3039 switch[ 'id' ].replace(
3040 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003041 '' ).replace(
3042 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003043 '' ).lower() )
3044 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003045
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003046 if mnDPIDs != onosDPIDs:
3047 switchResults = main.FALSE
3048 main.log.error( "Switches in MN but not in ONOS:" )
3049 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3050 main.log.error( str( list1 ) )
3051 main.log.error( "Switches in ONOS but not in MN:" )
3052 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3053 main.log.error( str( list2 ) )
3054 else: # list of dpid's match in onos and mn
3055 switchResults = main.TRUE
3056 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003057
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003058 # FIXME: this does not look for extra ports in ONOS, only checks that
3059 # ONOS has what is in MN
3060 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003061
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003062 # PORTS
3063 for name, mnSwitch in switches.iteritems():
3064 mnPorts = []
3065 onosPorts = []
3066 switchResult = main.TRUE
3067 for port in mnSwitch[ 'ports' ]:
3068 if port[ 'enabled' ]:
3069 mnPorts.append( int( port[ 'of_port' ] ) )
3070 for onosSwitch in portsJson:
3071 if onosSwitch[ 'device' ][ 'available' ]:
3072 if onosSwitch[ 'device' ][ 'id' ].replace(
3073 ':',
3074 '' ).replace(
3075 "of",
3076 '' ) == mnSwitch[ 'dpid' ]:
3077 for port in onosSwitch[ 'ports' ]:
3078 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003079 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003080 # onosPorts.append( 'local' )
3081 onosPorts.append( long( uint64( -2 ) ) )
3082 else:
3083 onosPorts.append( int( port[ 'port' ] ) )
3084 break
3085 mnPorts.sort( key=float )
3086 onosPorts.sort( key=float )
3087
3088 mnPortsLog = mnPorts
3089 onosPortsLog = onosPorts
3090 mnPorts = [ x for x in mnPorts ]
3091 onosPorts = [ x for x in onosPorts ]
3092
3093 # TODO: handle other reserved port numbers besides LOCAL
3094 # NOTE: Reserved ports
3095 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3096 # long( uint64( -2 ) )
3097 for mnPort in mnPortsLog:
3098 if mnPort in onosPorts:
3099 # don't set results to true here as this is just one of
3100 # many checks and it might override a failure
3101 mnPorts.remove( mnPort )
3102 onosPorts.remove( mnPort )
3103
3104 # NOTE: OVS reports this as down since there is no link
3105 # So ignoring these for now
3106 # TODO: Come up with a better way of handling these
3107 if 65534 in mnPorts:
3108 mnPorts.remove( 65534 )
3109 if long( uint64( -2 ) ) in onosPorts:
3110 onosPorts.remove( long( uint64( -2 ) ) )
3111 if len( mnPorts ): # the ports of this switch don't match
3112 switchResult = main.FALSE
3113 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3114 if len( onosPorts ): # the ports of this switch don't match
3115 switchResult = main.FALSE
3116 main.log.warn(
3117 "Ports in ONOS but not MN: " +
3118 str( onosPorts ) )
3119 if switchResult == main.FALSE:
3120 main.log.error(
3121 "The list of ports for switch %s(%s) does not match:" %
3122 ( name, mnSwitch[ 'dpid' ] ) )
3123 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3124 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3125 portsResults = portsResults and switchResult
3126 finalResults = finalResults and portsResults
3127 return finalResults
3128 except pexpect.EOF:
3129 main.log.error( self.name + ": EOF exception found" )
3130 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003131 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003132 except Exception:
3133 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003134 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003135
Jon Hallafa8a472015-06-12 14:02:42 -07003136 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003137 """
3138 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003139 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003140
Jon Hallafa8a472015-06-12 14:02:42 -07003141 """
Jon Hall7eb38402015-01-08 17:19:54 -08003142 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003143 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003144 try:
3145 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003146
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003147 mnLinks = []
3148 for l in links:
3149 try:
3150 node1 = switches[ l[ 'node1' ] ]
3151 node2 = switches[ l[ 'node2' ] ]
3152 enabled = True
3153 for port in node1[ 'ports' ]:
3154 if port[ 'of_port' ] == l[ 'port1' ]:
3155 enabled = enabled and port[ 'enabled' ]
3156 for port in node2[ 'ports' ]:
3157 if port[ 'of_port' ] == l[ 'port2' ]:
3158 enabled = enabled and port[ 'enabled' ]
3159 if enabled:
3160 mnLinks.append( l )
3161 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003162 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003163 if 2 * len( mnLinks ) == len( onos ):
3164 linkResults = main.TRUE
3165 else:
3166 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003167 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003168 "Mininet has " + str( len( mnLinks ) ) +
3169 " bidirectional links and ONOS has " +
3170 str( len( onos ) ) + " unidirectional links" )
3171
3172 # iterate through MN links and check if an ONOS link exists in
3173 # both directions
3174 for link in mnLinks:
3175 # TODO: Find a more efficient search method
3176 node1 = None
3177 port1 = None
3178 node2 = None
3179 port2 = None
3180 firstDir = main.FALSE
3181 secondDir = main.FALSE
3182 for swName, switch in switches.iteritems():
3183 if swName == link[ 'node1' ]:
3184 node1 = switch[ 'dpid' ]
3185 for port in switch[ 'ports' ]:
3186 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3187 port1 = port[ 'of_port' ]
3188 if node1 is not None and node2 is not None:
3189 break
3190 if swName == link[ 'node2' ]:
3191 node2 = switch[ 'dpid' ]
3192 for port in switch[ 'ports' ]:
3193 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3194 port2 = port[ 'of_port' ]
3195 if node1 is not None and node2 is not None:
3196 break
3197
3198 for onosLink in onos:
3199 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3200 ":", '' ).replace( "of", '' )
3201 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3202 ":", '' ).replace( "of", '' )
3203 onosPort1 = onosLink[ 'src' ][ 'port' ]
3204 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3205
3206 # check onos link from node1 to node2
3207 if str( onosNode1 ) == str( node1 ) and str(
3208 onosNode2 ) == str( node2 ):
3209 if int( onosPort1 ) == int( port1 ) and int(
3210 onosPort2 ) == int( port2 ):
3211 firstDir = main.TRUE
3212 else:
Jon Hallab611372018-02-21 15:26:05 -08003213 # The right switches, but wrong ports, could be
3214 # another link between these devices, or onos
3215 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003216 main.log.warn(
3217 'The port numbers do not match for ' +
3218 str( link ) +
3219 ' between ONOS and MN. When checking ONOS for ' +
3220 'link %s/%s -> %s/%s' %
3221 ( node1, port1, node2, port2 ) +
3222 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003223 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3224 '. This could be another link between these devices' +
3225 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003226
3227 # check onos link from node2 to node1
3228 elif ( str( onosNode1 ) == str( node2 ) and
3229 str( onosNode2 ) == str( node1 ) ):
3230 if ( int( onosPort1 ) == int( port2 )
3231 and int( onosPort2 ) == int( port1 ) ):
3232 secondDir = main.TRUE
3233 else:
Jon Hallab611372018-02-21 15:26:05 -08003234 # The right switches, but wrong ports, could be
3235 # another link between these devices, or onos
3236 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003237 main.log.warn(
3238 'The port numbers do not match for ' +
3239 str( link ) +
3240 ' between ONOS and MN. When checking ONOS for ' +
3241 'link %s/%s -> %s/%s' %
3242 ( node1, port1, node2, port2 ) +
3243 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003244 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3245 '. This could be another link between these devices' +
3246 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003247 else: # this is not the link you're looking for
3248 pass
3249 if not firstDir:
3250 main.log.error(
3251 'ONOS does not have the link %s/%s -> %s/%s' %
3252 ( node1, port1, node2, port2 ) )
3253 if not secondDir:
3254 main.log.error(
3255 'ONOS does not have the link %s/%s -> %s/%s' %
3256 ( node2, port2, node1, port1 ) )
3257 linkResults = linkResults and firstDir and secondDir
3258 return linkResults
3259 except pexpect.EOF:
3260 main.log.error( self.name + ": EOF exception found" )
3261 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003262 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003263 except Exception:
3264 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003265 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003266
Jon Hallafa8a472015-06-12 14:02:42 -07003267 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003268 """
Jon Hallafa8a472015-06-12 14:02:42 -07003269 Compare mn and onos Hosts.
3270 Since Mininet hosts are quiet, ONOS will only know of them when they
3271 speak. For this reason, we will only check that the hosts in ONOS
3272 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003273
Jon Hallafa8a472015-06-12 14:02:42 -07003274 Arguments:
3275 hostsJson: parsed json object from the onos hosts api
3276 Returns:
3277 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003278 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003279 try:
3280 hostResults = main.TRUE
3281 for onosHost in hostsJson:
3282 onosMAC = onosHost[ 'mac' ].lower()
3283 match = False
3284 for mnHost, info in hosts.iteritems():
3285 for mnIntf in info[ 'interfaces' ]:
3286 if onosMAC == mnIntf[ 'mac' ].lower():
3287 match = True
3288 for ip in mnIntf[ 'ips' ]:
3289 if ip in onosHost[ 'ipAddresses' ]:
3290 pass # all is well
3291 else:
3292 # misssing ip
3293 main.log.error( "ONOS host " +
3294 onosHost[ 'id' ] +
3295 " has a different IP(" +
3296 str( onosHost[ 'ipAddresses' ] ) +
3297 ") than the Mininet host(" +
3298 str( ip ) +
3299 ")." )
3300 output = json.dumps(
3301 onosHost,
3302 sort_keys=True,
3303 indent=4,
3304 separators=( ',', ': ' ) )
3305 main.log.info( output )
3306 hostResults = main.FALSE
3307 if not match:
3308 hostResults = main.FALSE
3309 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3310 "corresponding Mininet host." )
3311 output = json.dumps( onosHost,
3312 sort_keys=True,
3313 indent=4,
3314 separators=( ',', ': ' ) )
3315 main.log.info( output )
3316 return hostResults
3317 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003318 main.log.error( self.name + ": EOF exception found" )
3319 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003320 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003321 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003322 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003323 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003324
You Wangd66de192018-04-30 17:30:12 -07003325 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003326 """
3327 Description:
3328 Verify that all hosts have IP address assigned to them
3329 Optional:
3330 hostList: If specified, verifications only happen to the hosts
3331 in hostList
3332 prefix: at least one of the ip address assigned to the host
3333 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003334 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003335 Returns:
3336 main.TRUE if all hosts have specific IP address assigned;
3337 main.FALSE otherwise
3338 """
3339 try:
You Wangd66de192018-04-30 17:30:12 -07003340 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003341 if not hostList:
3342 hostList = hosts.keys()
3343 for hostName in hosts.keys():
3344 if hostName not in hostList:
3345 continue
3346 ipList = []
3347 self.handle.sendline( str( hostName ) + " ip a" )
3348 self.handle.expect( "mininet>" )
3349 ipa = self.handle.before
3350 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3351 ipList += re.findall( ipv4Pattern, ipa )
3352 # It's tricky to make regex for IPv6 addresses and this one is simplified
3353 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})/'
3354 ipList += re.findall( ipv6Pattern, ipa )
3355 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3356 if not ipList:
3357 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3358 else:
3359 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3360 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3361 else:
3362 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3363 hostList.remove( hostName )
3364 return main.FALSE if hostList else main.TRUE
3365 except KeyError:
3366 main.log.exception( self.name + ": host data not as expected: " + hosts )
3367 return None
3368 except pexpect.EOF:
3369 main.log.error( self.name + ": EOF exception found" )
3370 main.log.error( self.name + ": " + self.handle.before )
3371 main.cleanAndExit()
3372 except Exception:
3373 main.log.exception( self.name + ": Uncaught exception" )
3374 return None
3375
Jon Hallafa8a472015-06-12 14:02:42 -07003376 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003377 """
3378 Returns a list of all hosts
3379 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003380 try:
3381 self.handle.sendline( "" )
3382 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003383
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003384 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3385 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003386
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003387 handlePy = self.handle.before
3388 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3389 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003390
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003391 self.handle.sendline( "" )
3392 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003393
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003394 hostStr = handlePy.replace( "]", "" )
3395 hostStr = hostStr.replace( "'", "" )
3396 hostStr = hostStr.replace( "[", "" )
3397 hostStr = hostStr.replace( " ", "" )
3398 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003399
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003400 return hostList
3401 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003402 main.log.error( self.name + ": TIMEOUT exception found" )
3403 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003404 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003405 except pexpect.EOF:
3406 main.log.error( self.name + ": EOF exception found" )
3407 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003408 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003409 except Exception:
3410 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003411 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003412
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003413 def getSwitch( self ):
3414 """
3415 Returns a list of all switches
3416 Again, don't ask question just use it...
3417 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003418 try:
3419 # get host list...
3420 hostList = self.getHosts()
3421 # Make host set
3422 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003423
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003424 # Getting all the nodes in mininet
3425 self.handle.sendline( "" )
3426 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003427
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003428 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3429 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003430
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003431 handlePy = self.handle.before
3432 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3433 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003434
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003435 self.handle.sendline( "" )
3436 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003437
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003438 nodesStr = handlePy.replace( "]", "" )
3439 nodesStr = nodesStr.replace( "'", "" )
3440 nodesStr = nodesStr.replace( "[", "" )
3441 nodesStr = nodesStr.replace( " ", "" )
3442 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003443
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003444 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003445 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003446 nodesSet.discard( 'c0' )
3447 nodesSet.discard( 'c1' )
3448 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003449
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003450 switchSet = nodesSet - hostSet
3451 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003452
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003453 return switchList
3454 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003455 main.log.error( self.name + ": TIMEOUT exception found" )
3456 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003457 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003458 except pexpect.EOF:
3459 main.log.error( self.name + ": EOF exception found" )
3460 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003461 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003462 except Exception:
3463 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003464 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003465
You Wang7d14d642019-01-23 15:10:08 -08003466 def getGraphDict( self, timeout=60, useId=True, includeHost=False,
You Wangb1665b52019-02-01 15:49:48 -08003467 excludeNodes=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07003468 """
3469 Return a dictionary which describes the latest Mininet topology data as a
3470 graph.
3471 An example of the dictionary:
3472 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3473 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3474 Each vertex should at least have an 'edges' attribute which describes the
3475 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003476 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003477 list of attributes.
3478 An example of the edges dictionary:
3479 'edges': { vertex2: { 'port': ..., 'weight': ... },
3480 vertex3: { 'port': ..., 'weight': ... } }
3481 If useId == True, dpid/mac will be used instead of names to identify
3482 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3483 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003484 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003485 in topology data.
You Wangb1665b52019-02-01 15:49:48 -08003486 excludeNodes will be passed to getSwitches and getLinks methods to exclude
3487 unexpected switches and links.
You Wangdb8cd0a2016-05-26 15:19:45 -07003488 Note that link or switch that are brought down by 'link x x down' or 'switch
3489 x down' commands still show in the output of Mininet CLI commands such as
3490 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3491 recommended to use delLink() or delSwitch functions to simulate link/switch
3492 down, and addLink() or addSwitch to add them back.
3493 """
3494 graphDict = {}
3495 try:
You Wang7d14d642019-01-23 15:10:08 -08003496 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003497 portDict = {}
You Wangb1665b52019-02-01 15:49:48 -08003498 switches = self.getSwitches( excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003499 if includeHost:
3500 hosts = self.getHosts()
3501 for link in links:
You Wangb1665b52019-02-01 15:49:48 -08003502 # TODO: support 'includeHost' argument
You Wangdb8cd0a2016-05-26 15:19:45 -07003503 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3504 continue
3505 nodeName1 = link[ 'node1' ]
3506 nodeName2 = link[ 'node2' ]
You Wang7d14d642019-01-23 15:10:08 -08003507 if not self.getOVSPorts( nodeName1 ) or not self.getOVSPorts( nodeName2 ):
3508 # The device is probably offline
3509 continue
You Wangdb8cd0a2016-05-26 15:19:45 -07003510 port1 = link[ 'port1' ]
3511 port2 = link[ 'port2' ]
3512 # Loop for two nodes
3513 for i in range( 2 ):
3514 # Get port index from OVS
3515 # The index extracted from port name may be inconsistent with ONOS
3516 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003517 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003518 portList = self.getOVSPorts( nodeName1 )
3519 if len( portList ) == 0:
3520 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3521 return None
3522 portDict[ nodeName1 ] = portList
3523 for port in portDict[ nodeName1 ]:
3524 if port[ 'port' ] == port1:
3525 portIndex = port[ 'index' ]
3526 break
3527 if portIndex == -1:
3528 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3529 return None
3530 if useId:
3531 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3532 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3533 else:
3534 node1 = nodeName1
3535 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003536 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003537 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003538 graphDict[ node1 ] = { 'edges': {},
3539 'dpid': switches[ nodeName1 ][ 'dpid' ],
3540 'name': nodeName1,
3541 'ports': switches[ nodeName1 ][ 'ports' ],
3542 'swClass': switches[ nodeName1 ][ 'swClass' ],
3543 'pid': switches[ nodeName1 ][ 'pid' ],
3544 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003545 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003546 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003547 else:
3548 # Assert node2 is not connected to any current links of node1
You Wang7d14d642019-01-23 15:10:08 -08003549 # assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
3550 pass
3551 for port in switches[ nodeName1 ][ 'ports' ]:
3552 if port[ 'of_port' ] == str( portIndex ):
3553 # Use -1 as index for disabled port
You Wangb1665b52019-02-01 15:49:48 -08003554 if port[ 'enabled' ]:
You Wang7d14d642019-01-23 15:10:08 -08003555 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
3556 else:
3557 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': -1 }
You Wangdb8cd0a2016-05-26 15:19:45 -07003558 # Swap two nodes/ports
3559 nodeName1, nodeName2 = nodeName2, nodeName1
3560 port1, port2 = port2, port1
You Wang7d14d642019-01-23 15:10:08 -08003561 # Remove links with disabled ports
3562 linksToRemove = []
3563 for node, edges in graphDict.items():
3564 for neighbor, port in edges[ 'edges' ].items():
3565 if port[ 'port' ] == -1:
3566 linksToRemove.append( ( node, neighbor ) )
3567 for node1, node2 in linksToRemove:
3568 for i in range( 2 ):
3569 if graphDict.get( node1 )[ 'edges' ].get( node2 ):
3570 graphDict[ node1 ][ 'edges' ].pop( node2 )
3571 node1, node2 = node2, node1
You Wangdb8cd0a2016-05-26 15:19:45 -07003572 return graphDict
3573 except KeyError:
3574 main.log.exception( self.name + ": KeyError exception found" )
3575 return None
3576 except AssertionError:
3577 main.log.exception( self.name + ": AssertionError exception found" )
3578 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003579 except pexpect.EOF:
3580 main.log.error( self.name + ": EOF exception found" )
3581 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003582 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003583 except Exception:
3584 main.log.exception( self.name + ": Uncaught exception" )
3585 return None
3586
Devin Lima7cfdbd2017-09-29 15:02:22 -07003587 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003588 """
3589 updates the port address and status information for
3590 each port in mn"""
3591 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003592 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003593 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003594 self.handle.sendline( "" )
3595 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003596
Jon Hall7eb38402015-01-08 17:19:54 -08003597 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003598 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003599
Jon Hall7eb38402015-01-08 17:19:54 -08003600 self.handle.sendline( "" )
3601 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003602
Jon Hallb1290e82014-11-18 16:17:48 -05003603 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003604 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003605 main.log.error( self.name + ": TIMEOUT exception found" )
3606 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003607 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003608 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003609 main.log.error( self.name + ": EOF exception found" )
3610 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003611 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003612 except Exception:
3613 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003614 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003615
Jon Halld80cc142015-07-06 13:36:05 -07003616 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003617 """
3618 Add vlan tag to a host.
3619 Dependencies:
3620 This class depends on the "vlan" package
3621 $ sudo apt-get install vlan
3622 Configuration:
3623 Load the 8021q module into the kernel
3624 $sudo modprobe 8021q
3625
3626 To make this setup permanent:
3627 $ sudo su -c 'echo "8021q" >> /etc/modules'
3628 """
3629 if self.handle:
3630 try:
Jon Halld80cc142015-07-06 13:36:05 -07003631 # get the ip address of the host
3632 main.log.info( "Get the ip address of the host" )
3633 ipaddr = self.getIPAddress( host )
3634 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003635
Jon Halld80cc142015-07-06 13:36:05 -07003636 # remove IP from interface intf
3637 # Ex: h1 ifconfig h1-eth0 inet 0
3638 main.log.info( "Remove IP from interface " )
3639 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3640 self.handle.sendline( cmd2 )
3641 self.handle.expect( "mininet>" )
3642 response = self.handle.before
3643 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003644
Jon Halld80cc142015-07-06 13:36:05 -07003645 # create VLAN interface
3646 # Ex: h1 vconfig add h1-eth0 100
3647 main.log.info( "Create Vlan" )
3648 cmd3 = host + " vconfig add " + intf + " " + vlan
3649 self.handle.sendline( cmd3 )
3650 self.handle.expect( "mininet>" )
3651 response = self.handle.before
3652 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003653
Jon Halld80cc142015-07-06 13:36:05 -07003654 # assign the host's IP to the VLAN interface
3655 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3656 main.log.info( "Assign the host IP to the vlan interface" )
3657 vintf = intf + "." + vlan
3658 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3659 self.handle.sendline( cmd4 )
3660 self.handle.expect( "mininet>" )
3661 response = self.handle.before
3662 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003663
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003664 # update Mininet node variables
3665 main.log.info( "Update Mininet node variables" )
3666 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3667 self.handle.sendline( cmd5 )
3668 self.handle.expect( "mininet>" )
3669 response = self.handle.before
3670 main.log.info( "====> %s ", response )
3671
3672 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3673 self.handle.sendline( cmd6 )
3674 self.handle.expect( "mininet>" )
3675 response = self.handle.before
3676 main.log.info( "====> %s ", response )
3677
3678 return main.TRUE
3679 except pexpect.TIMEOUT:
3680 main.log.error( self.name + ": TIMEOUT exception found" )
3681 main.log.error( self.name + ": " + self.handle.before )
3682 main.cleanAndExit()
3683 except pexpect.EOF:
3684 main.log.error( self.name + ": EOF exception found" )
3685 main.log.error( self.name + ": " + self.handle.before )
3686 return main.FALSE
3687 except Exception:
3688 main.log.exception( self.name + ": Uncaught exception!" )
3689 return main.FALSE
3690
3691 def removeVLAN( self, host, intf ):
3692 """
3693 Remove vlan tag from a host.
3694 Dependencies:
3695 This class depends on the "vlan" package
3696 $ sudo apt-get install vlan
3697 Configuration:
3698 Load the 8021q module into the kernel
3699 $sudo modprobe 8021q
3700
3701 To make this setup permanent:
3702 $ sudo su -c 'echo "8021q" >> /etc/modules'
3703 """
3704 if self.handle:
3705 try:
3706 # get the ip address of the host
3707 main.log.info( "Get the ip address of the host" )
3708 ipaddr = self.getIPAddress( host )
3709
3710 # remove VLAN interface
3711 # Ex: h1 vconfig rem h1-eth0.100
3712 main.log.info( "Remove Vlan interface" )
3713 cmd2 = host + " vconfig rem " + intf
3714 self.handle.sendline( cmd2 )
3715 self.handle.expect( "mininet>" )
3716 response = self.handle.before
3717 main.log.info( "====> %s ", response )
3718
3719 # assign the host's IP to the original interface
3720 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3721 main.log.info( "Assign the host IP to the original interface" )
3722 original_intf = intf.split(".")[0]
3723 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3724 self.handle.sendline( cmd3 )
3725 self.handle.expect( "mininet>" )
3726 response = self.handle.before
3727 main.log.info( "====> %s ", response )
3728
3729 # update Mininet node variables
3730 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3731 self.handle.sendline( cmd4 )
3732 self.handle.expect( "mininet>" )
3733 response = self.handle.before
3734 main.log.info( "====> %s ", response )
3735
3736 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3737 self.handle.sendline( cmd5 )
3738 self.handle.expect( "mininet>" )
3739 response = self.handle.before
3740 main.log.info( "====> %s ", response )
3741
kaouthera3f13ca22015-05-05 15:01:41 -07003742 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003743 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003744 main.log.error( self.name + ": TIMEOUT exception found" )
3745 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003746 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003747 except pexpect.EOF:
3748 main.log.error( self.name + ": EOF exception found" )
3749 main.log.error( self.name + ": " + self.handle.before )
3750 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003751 except Exception:
3752 main.log.exception( self.name + ": Uncaught exception!" )
3753 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003754
Jon Hall892818c2015-10-20 17:58:34 -07003755 def createHostComponent( self, name ):
3756 """
3757 Creates a new mininet cli component with the same parameters as self.
3758 This new component is intended to be used to login to the hosts created
3759 by mininet.
3760
3761 Arguments:
3762 name - The string of the name of this component. The new component
3763 will be assigned to main.<name> .
3764 In addition, main.<name>.name = str( name )
3765 """
3766 try:
3767 # look to see if this component already exists
3768 getattr( main, name )
3769 except AttributeError:
3770 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003771 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3772 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003773 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003774 except pexpect.EOF:
3775 main.log.error( self.name + ": EOF exception found" )
3776 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003777 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003778 except Exception:
3779 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003780 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003781 else:
3782 # namespace is not clear!
3783 main.log.error( name + " component already exists!" )
3784 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003785 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003786
3787 def removeHostComponent( self, name ):
3788 """
3789 Remove host component
3790 Arguments:
3791 name - The string of the name of the component to delete.
3792 """
3793 try:
3794 # Get host component
3795 component = getattr( main, name )
3796 except AttributeError:
3797 main.log.error( "Component " + name + " does not exist." )
3798 return
3799 try:
3800 # Disconnect from component
3801 component.disconnect()
You Wangf32c6ed2018-08-23 17:10:22 -07003802 component.close_log_handles()
Jon Hall892818c2015-10-20 17:58:34 -07003803 # Delete component
3804 delattr( main, name )
3805 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003806 del( main.componentDictionary[ name ] )
You Wangf32c6ed2018-08-23 17:10:22 -07003807 except StandardError:
3808 self.log.exception( "Exception while closing log files for " + name )
3809 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003810 except pexpect.EOF:
3811 main.log.error( self.name + ": EOF exception found" )
3812 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003813 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003814 except Exception:
3815 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003816 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003817
3818 def startHostCli( self, host=None ):
3819 """
3820 Use the mininet m utility to connect to the host's cli
3821 """
3822 # These are fields that can be used by scapy packets. Initialized to None
3823 self.hostIp = None
3824 self.hostMac = None
3825 try:
3826 if not host:
3827 host = self.name
3828 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003829 self.handle.sendline( "cd" )
3830 self.handle.expect( self.hostPrompt )
3831 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003832 self.handle.expect( self.hostPrompt )
3833 return main.TRUE
3834 except pexpect.TIMEOUT:
3835 main.log.exception( self.name + ": Command timed out" )
3836 return main.FALSE
3837 except pexpect.EOF:
3838 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003839 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003840 except Exception:
3841 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003842 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003843
YPZhang801d46d2016-08-08 13:26:28 -07003844 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003845 '''
3846
YPZhang801d46d2016-08-08 13:26:28 -07003847 Args:
3848 devicename: switch name
3849 intf: port name on switch
3850 status: up or down
3851
3852 Returns: boolean to show success change status
3853
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003854 '''
YPZhang801d46d2016-08-08 13:26:28 -07003855 if status == "down" or status == "up":
3856 try:
3857 cmd = devicename + " ifconfig " + intf + " " + status
3858 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003859 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003860 return main.TRUE
3861 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003862 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003863 return main.FALSE
3864 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003865 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003866 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003867 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003868 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003869 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003870 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003871 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003872 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003873 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003874 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003875 return main.FALSE
3876
You Wang6e5b48e2018-07-23 16:17:38 -07003877 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003878 """
You Wang6e5b48e2018-07-23 16:17:38 -07003879 Moves a host from one switch to another on the fly
3880 Optional:
3881 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3882 prefixLen: length of the host IP prefix
3883 ipv6: move an IPv6 host if True
3884 intfSuffix: suffix of the new interface after host movement
3885 vlan: vlan ID of the host. Use None for non-vlan host
3886 Note: The intf between host and oldSw when detached
3887 using detach(), will still show up in the 'net'
3888 cmd, because switch.detach() doesn't affect switch.intfs[]
3889 ( which is correct behavior since the interfaces
3890 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003891 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003892 if self.handle:
3893 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003894 newIntf = "%s-%s" % ( host, intfSuffix )
3895 commands = [
3896 # Bring link between oldSw-host down
3897 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3898 # Determine hostintf and Oldswitchintf
3899 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
3900 ]
3901 # Determine ip address of the host-oldSw interface
3902 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3903 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3904 commands += [
3905 # Determine mac address of the host-oldSw interface
3906 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3907 # Detach interface between oldSw-host
3908 "px " + oldSw + ".detach( sintf )",
3909 # Add link between host-newSw
3910 "py net.addLink(" + host + "," + newSw + ")",
3911 # Determine hostintf and Newswitchintf
3912 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3913 # Attach interface between newSw-host
3914 "px " + newSw + ".attach( sintf )",
3915 ]
3916 if vlan:
3917 vlanIntf = "%s.%s" % ( newIntf, vlan )
3918 commands += [
3919 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
3920 host + " ip link set up %s" % vlanIntf,
3921 "px hintf.name = '" + vlanIntf + "'",
3922 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
3923 ]
3924 newIntf = vlanIntf
3925 commands += [
3926 # Set mac address of the host-newSw interface
3927 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
3928 # Set IP address of the host-newSw interface
3929 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
3930 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
3931 ]
3932 if ipv6:
3933 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
3934 commands += [
3935 "net",
3936 host + " ifconfig"
3937 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003938 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003939 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003940 self.handle.sendline( cmd )
3941 self.handle.expect( "mininet>" )
3942 main.log.info( "====> %s ", self.handle.before )
3943 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003944 except pexpect.TIMEOUT:
3945 main.log.error( self.name + ": TIMEOUT exception found" )
3946 main.log.error( self.name + ": " + self.handle.before )
3947 main.cleanAndExit()
3948 except pexpect.EOF:
3949 main.log.error( self.name + ": EOF exception found" )
3950 main.log.error( self.name + ": " + self.handle.before )
3951 return main.FALSE
3952 except Exception:
3953 main.log.exception( self.name + ": Uncaught exception!" )
3954 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07003955
You Wang6e5b48e2018-07-23 16:17:38 -07003956 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
3957 macAddr=None, prefixLen=None, ipv6=False,
3958 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07003959 """
You Wang6e5b48e2018-07-23 16:17:38 -07003960 Moves a dual-homed host from one switch-pair to another pair on the fly
3961 Optional:
3962 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3963 prefixLen: length of the host IP prefix
3964 ipv6: move an IPv6 host if True
3965 intfSuffix1: suffix of the first new interface
3966 intfSuffix2: suffix of the second new interface
3967 bondSuffix: suffix of the new bond interface
3968 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07003969 """
You Wang7ea90582018-07-19 15:27:58 -07003970 if self.handle:
3971 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003972 bondIntf = "%s-%s" % ( host, bondSuffix )
3973 newIntf = "%s-%s" % ( host, intfSuffix1 )
3974 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07003975 commands = [
3976 # Bring link between oldSw-host down
3977 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3978 # Bring link between oldPairSw-host down
3979 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
3980 # Determine hostintf and Oldswitchintf
3981 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07003982 ]
3983 # Determine ip address of the host-oldSw interface
3984 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3985 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3986 commands += [
3987 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07003988 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3989 # Detach interface between oldSw-host
3990 "px " + oldSw + ".detach( sintf )",
3991 # Determine hostintf and Oldpairswitchintf
3992 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
3993 # Detach interface between oldPairSw-host
3994 "px " + oldPairSw + ".detach( sintfpair )",
3995 # Add link between host-newSw
3996 "py net.addLink(" + host + "," + newSw + ", 2)",
3997 # Add link between host-newPairSw
3998 "py net.addLink(" + host + "," + newPairSw + ")",
3999 # Determine hostintf and Newswitchintf
4000 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
4001 # Determine hostintf and NewPairswitchintf
4002 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
4003 # Attach interface between newSw-host
4004 "px " + newSw + ".attach( sintf )",
4005 # Attach interface between newPairSw-host
4006 "px " + newPairSw + ".attach( sintfpair )",
4007 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07004008 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004009 host + ' ip link set %s down' % newIntf,
4010 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004011 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
4012 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07004013 host + ' ip addr flush dev %s' % newIntf,
4014 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004015 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004016 "px lowestIntf = min( [ hintf, hintfpair ] )",
4017 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07004018 "px lowestIntf.name = '" + bondIntf + "'",
4019 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07004020 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
4021 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07004022 ]
4023 if vlan:
4024 vlanIntf = "%s.%s" % ( bondIntf, vlan )
4025 commands += [
4026 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
4027 host + " ip link set up %s" % vlanIntf,
4028 "px lowestIntf.name = '" + vlanIntf + "'",
4029 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
4030 ]
4031 bondIntf = vlanIntf
4032 commands += [
4033 # Set macaddress of the host-newSw interface
4034 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07004035 # Set ipaddress of the host-newSw interface
4036 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
4037 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07004038 ]
You Wang6e5b48e2018-07-23 16:17:38 -07004039 if ipv6:
4040 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
4041 commands += [
4042 "net",
4043 host + " ifconfig"
4044 ]
You Wang7ea90582018-07-19 15:27:58 -07004045 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004046 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07004047 self.handle.sendline( cmd )
4048 self.handle.expect( "mininet>" )
4049 main.log.info( "====> %s ", self.handle.before )
4050 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07004051 except pexpect.TIMEOUT:
4052 main.log.error( self.name + ": TIMEOUT exception found" )
4053 main.log.error( self.name + ": " + self.handle.before )
4054 main.cleanAndExit()
4055 except pexpect.EOF:
4056 main.log.error( self.name + ": EOF exception found" )
4057 main.log.error( self.name + ": " + self.handle.before )
4058 return main.FALSE
4059 except Exception:
4060 main.log.exception( self.name + ": Uncaught exception!" )
4061 return main.FALSE
4062
adminbae64d82013-08-01 10:50:15 -07004063if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004064 sys.modules[ __name__ ] = MininetCliDriver()