blob: 1da21b92b4c83f54f07b6a019ddc9909a87f61a6 [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>',
205 'Exception',
206 '\*\*\*',
207 pexpect.EOF,
208 pexpect.TIMEOUT ],
209 timeout )
210 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -0700211 main.log.info( self.name + ": Mininet built\nTime Took : " + str( time.time() - startTime ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700212 return main.TRUE
213 elif i == 1:
214 response = str( self.handle.before +
215 self.handle.after )
Devin Limdc78e202017-06-09 18:30:07 -0700216 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700217 response += str( self.handle.before +
218 self.handle.after )
219 main.log.error(
220 self.name +
221 ": Launching Mininet failed: " + response )
222 return main.FALSE
223 elif i == 2:
224 self.handle.expect( [ "\n",
225 pexpect.EOF,
226 pexpect.TIMEOUT ],
227 timeout )
228 main.log.info( self.handle.before )
229 elif i == 3:
230 main.log.error( self.name + ": Connection timeout" )
231 return main.FALSE
232 elif i == 4: # timeout
233 main.log.error(
234 self.name +
235 ": Something took too long... " )
236 return main.FALSE
237 # Why did we hit this part?
238 main.log.error( "startNet did not return correctly" )
239 return main.FASLE
240 else: # if no handle
241 main.log.error( self.name + ": Connection failed to the host " +
242 self.user_name + "@" + self.ip_address )
243 main.log.error( self.name + ": Failed to connect to the Mininet" )
244 return main.FALSE
245 except pexpect.TIMEOUT:
246 main.log.exception( self.name + ": TIMEOUT exception found while starting Mininet" )
247 main.log.error( self.name + ": " + self.handle.before )
adminbae64d82013-08-01 10:50:15 -0700248 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700249 except pexpect.EOF:
250 main.log.error( self.name + ": EOF exception found" )
251 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700252 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700253 except Exception:
254 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700255 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800256
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800257 def numSwitchesNlinks( self, topoType, depth, fanout ):
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700258 try:
259 if topoType == 'tree':
260 # In tree topology, if fanout arg is not given, by default it is 2
261 if fanout is None:
262 fanout = 2
263 k = 0
264 count = 0
265 while( k <= depth - 1 ):
266 count = count + pow( fanout, k )
267 k = k + 1
268 numSwitches = count
269 while( k <= depth - 2 ):
270 # depth-2 gives you only core links and not considering
271 # edge links as seen by ONOS. If all the links including
272 # edge links are required, do depth-1
273 count = count + pow( fanout, k )
274 k = k + 1
275 numLinks = count * fanout
276 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
277 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800278
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700279 elif topoType == 'linear':
280 # In linear topology, if fanout or numHostsPerSw is not given,
281 # by default it is 1
282 if fanout is None:
283 fanout = 1
284 numSwitches = depth
285 numHostsPerSw = fanout
286 totalNumHosts = numSwitches * numHostsPerSw
287 numLinks = totalNumHosts + ( numSwitches - 1 )
288 print "num_switches for %s(%d,%d) = %d and links=%d" %\
289 ( topoType, depth, fanout, numSwitches, numLinks )
290 topoDict = { "num_switches": int( numSwitches ),
291 "num_corelinks": int( numLinks ) }
292 return topoDict
293 except Exception:
294 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700295 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400296
kelvin-onlabd3b64892015-01-20 13:26:24 -0800297 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700298 """
299 Calculate the number of switches and links in a topo."""
300 # TODO: combine this function and numSwitchesNlinks
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700301 try:
302 argList = self.options[ 'arg1' ].split( "," )
303 topoArgList = argList[ 0 ].split( " " )
304 argList = map( int, argList[ 1: ] )
305 topoArgList = topoArgList[ 1: ] + argList
Jon Hall689d8e42015-04-03 13:59:24 -0700306
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700307 topoDict = self.numSwitchesNlinks( *topoArgList )
308 return topoDict
309 except Exception:
310 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700311 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400312
GlennRCf07c44a2015-09-18 13:33:46 -0700313 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800314 """
315 Verifies the reachability of the hosts using pingall command.
316 Optional parameter timeout allows you to specify how long to
317 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700318 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700319 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700320 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700321 ping
322 acceptableFailed - Set the number of acceptable failed pings for the
323 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800324 Returns:
325 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700326 otherwise main.FALSE
327 """
328 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700329 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700330 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700331 if self.handle:
332 main.log.info(
333 self.name +
334 ": Checking reachabilty to the hosts using pingall" )
335 response = ""
336 failedPings = 0
337 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700338 cmd = "pingall"
339 if protocol == "IPv6":
340 cmd = "py net.pingAll6()"
341 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700342 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700343 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700344 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700345 pexpect.EOF,
346 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700347 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700348 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700349 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700350 response += self.handle.before
351 break
352 elif i == 1:
353 response += self.handle.before + self.handle.after
354 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700355 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700356 returnValue = main.FALSE
357 if shortCircuit:
358 main.log.error( self.name +
359 ": Aborting pingall - "
360 + str( failedPings ) +
361 " pings failed" )
362 break
Jon Hall390696c2015-05-05 17:13:41 -0700363 if ( time.time() - startTime ) > timeout:
364 returnValue = main.FALSE
365 main.log.error( self.name +
366 ": Aborting pingall - " +
367 "Function took too long " )
368 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700369 elif i == 2:
370 main.log.error( self.name +
371 ": EOF exception found" )
372 main.log.error( self.name + ": " +
373 self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700374 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700375 elif i == 3:
376 response += self.handle.before
377 main.log.error( self.name +
378 ": TIMEOUT exception found" )
379 main.log.error( self.name +
380 ": " +
381 str( response ) )
382 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800383 self.handle.send( "\x03" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700384 self.handle.expect( "Interrupt" )
385 self.handle.expect( "mininet>" )
386 break
387 pattern = "Results\:"
388 main.log.info( "Pingall output: " + str( response ) )
389 if re.search( pattern, response ):
390 main.log.info( self.name + ": Pingall finished with "
391 + str( failedPings ) + " failed pings" )
392 return returnValue
393 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700394 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800395 self.handle.send( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700396 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700397 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700398 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700399 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700400 main.log.error( self.name + ": Connection failed to the host" )
Devin Lim44075962017-08-11 10:56:37 -0700401 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700402 except pexpect.TIMEOUT:
403 if response:
404 main.log.info( "Pingall output: " + str( response ) )
405 main.log.error( self.name + ": pexpect.TIMEOUT found" )
406 return main.FALSE
407 except pexpect.EOF:
408 main.log.error( self.name + ": EOF exception found" )
409 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700410 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -0700411
Jon Hall7eb38402015-01-08 17:19:54 -0800412 def fpingHost( self, **pingParams ):
413 """
414 Uses the fping package for faster pinging...
415 *requires fping to be installed on machine running mininet"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700416 try:
417 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
418 command = args[ "SRC" ] + \
419 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
420 self.handle.sendline( command )
421 self.handle.expect(
422 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
423 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
424 response = self.handle.before
425 if re.search( ":\s-", response ):
426 main.log.info( self.name + ": Ping fail" )
427 return main.FALSE
428 elif re.search( ":\s\d{1,2}\.\d\d", response ):
429 main.log.info( self.name + ": Ping good!" )
430 return main.TRUE
431 main.log.info( self.name + ": Install fping on mininet machine... " )
432 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700433 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700434 except Exception:
435 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700436 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700437
Jon Hall3b489db2015-10-05 14:38:37 -0700438 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400439 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700440 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700441
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400442 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700443 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700444
445 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400446 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700447
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400448 Returns main.FALSE if one or more of hosts specified
449 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700450 wait = int( wait )
451 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400452
453 try:
454 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700455
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400456 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700457 pingResponse = "IPv4 ping across specified hosts\n"
458 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400459 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700460 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400461 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700462 pingList = hostList[ :listIndex ] + \
463 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700464
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700465 pingResponse += str( str( host ) + " -> " )
GlennRCd10d3cc2015-09-24 12:47:16 -0700466
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400467 for temp in pingList:
468 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700469 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700470 self.handle.sendline( pingCmd )
471 self.handle.expect( "mininet>", timeout=wait + 1 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400472 response = self.handle.before
473 if re.search( ',\s0\%\spacket\sloss', response ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700474 pingResponse += str( " h" + str( temp[ 1: ] ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400475 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700476 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400477 # One of the host to host pair is unreachable
478 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700479 failedPings += 1
You Wang11f9ead2018-03-21 14:34:59 -0700480 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
GlennRCd10d3cc2015-09-24 12:47:16 -0700481 pingResponse += "\n"
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700482 main.log.info( pingResponse + "Failed pings: " + str( failedPings ) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700483 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700484 except pexpect.TIMEOUT:
485 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800486 response = self.handle.before
487 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700488 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800489 self.handle.expect( "Interrupt" )
490 response += self.handle.before + self.handle.after
491 self.handle.expect( "mininet>" )
492 response += self.handle.before + self.handle.after
493 main.log.debug( response )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700494 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400495 except pexpect.EOF:
496 main.log.error( self.name + ": EOF exception found" )
497 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700498 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700499 except Exception:
500 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700501 main.cleanAndExit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400502
You Wangf19d9f42018-02-23 16:34:19 -0800503 def pingIpv6Hosts( self, hostList, wait=1, acceptableFailed=0 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700504 """
You Wangf19d9f42018-02-23 16:34:19 -0800505 IPv6 ping all hosts in hostList.
506
507 acceptableFailed: max number of acceptable failed pings
Hari Krishna9592fc82015-07-31 15:11:15 -0700508
Jon Hall3b489db2015-10-05 14:38:37 -0700509 Returns main.TRUE if all hosts specified can reach each other
Jon Hall3b489db2015-10-05 14:38:37 -0700510 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700511 """
512 try:
513 main.log.info( "Testing reachability between specified IPv6 hosts" )
514 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700515 wait = int( wait )
516 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700517 pingResponse = "IPv6 Pingall output:\n"
You Wangf19d9f42018-02-23 16:34:19 -0800518 failedPingsTotal = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700519 for host in hostList:
520 listIndex = hostList.index( host )
521 # List of hosts to ping other than itself
522 pingList = hostList[ :listIndex ] + \
523 hostList[ ( listIndex + 1 ): ]
524
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700525 pingResponse += str( str( host ) + " -> " )
GlennRC2cf7d952015-09-11 16:32:13 -0700526
Hari Krishna9592fc82015-07-31 15:11:15 -0700527 for temp in pingList:
528 # Current host pings all other hosts specified
You Wangf19d9f42018-02-23 16:34:19 -0800529 failedPings = 0
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700530 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
You Wangf19d9f42018-02-23 16:34:19 -0800531 while failedPings <= acceptableFailed:
532 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
533 self.handle.sendline( pingCmd )
534 self.handle.expect( "mininet>", timeout=wait + 1 )
535 response = self.handle.before
536 if re.search( ',\s0\%\spacket\sloss', response ):
You Wangba231e72018-03-01 13:18:21 -0800537 pingResponse += " " + str( temp )
538 break
539 else:
540 failedPings += 1
541 time.sleep(1)
542 if failedPings > acceptableFailed:
543 # One of the host to host pair is unreachable
544 pingResponse += " X"
545 isReachable = main.FALSE
546 failedPingsTotal += 1
You Wang11f9ead2018-03-21 14:34:59 -0700547 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
You Wangba231e72018-03-01 13:18:21 -0800548 pingResponse += "\n"
549 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
550 return isReachable
551
552 except pexpect.TIMEOUT:
553 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800554 response = self.handle.before
555 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700556 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800557 self.handle.expect( "Interrupt" )
558 response += self.handle.before + self.handle.after
559 self.handle.expect( "mininet>" )
560 response += self.handle.before + self.handle.after
561 main.log.debug( response )
You Wangba231e72018-03-01 13:18:21 -0800562 return main.FALSE
563 except pexpect.EOF:
564 main.log.error( self.name + ": EOF exception found" )
565 main.log.error( self.name + ": " + self.handle.before )
566 main.cleanAndExit()
567 except Exception:
568 main.log.exception( self.name + ": Uncaught exception!" )
569 main.cleanAndExit()
570
571 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
572 """
573 Verify ping from each host in srcList to each host in dstList
574
575 acceptableFailed: max number of acceptable failed pings
576
577 Returns main.TRUE if all src hosts can reach all dst hosts
578 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
579 """
580 try:
581 main.log.info( "Verifying ping from each src host to each dst host" )
582 isReachable = main.TRUE
583 wait = int( wait )
584 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
585 pingResponse = "Ping output:\n"
586 failedPingsTotal = 0
587 for host in srcList:
588 pingResponse += str( str( host ) + " -> " )
589 for temp in dstList:
590 failedPings = 0
591 if ipv6:
592 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
593 else:
594 pingCmd = str( host ) + cmd + str( temp )
595 while failedPings <= acceptableFailed:
596 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
597 self.handle.sendline( pingCmd )
598 self.handle.expect( "mininet>", timeout=wait + 1 )
599 response = self.handle.before
600 if re.search( ',\s0\%\spacket\sloss', response ):
601 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800602 break
603 else:
604 failedPings += 1
605 time.sleep(1)
606 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700607 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800608 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700609 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800610 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700611 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800612 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700613 return isReachable
614
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700615 except pexpect.TIMEOUT:
616 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800617 response = self.handle.before
618 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700619 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800620 self.handle.expect( "Interrupt" )
621 response += self.handle.before + self.handle.after
622 self.handle.expect( "mininet>" )
623 response += self.handle.before + self.handle.after
624 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700625 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700626 except pexpect.EOF:
627 main.log.error( self.name + ": EOF exception found" )
628 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700629 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700630 except Exception:
631 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700632 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700633
Jon Hall7eb38402015-01-08 17:19:54 -0800634 def pingHost( self, **pingParams ):
635 """
Jon Hall3b489db2015-10-05 14:38:37 -0700636 Ping from one mininet host to another
637 Currently the only supported Params: SRC, TARGET, and WAIT
638 """
639 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700640 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700641 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800642 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700643 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700644 try:
Jon Hall61282e32015-03-19 11:34:11 -0700645 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800646 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700647 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
648 timeout=wait + 1 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700649 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800650 main.log.error(
651 self.name +
652 ": timeout when waiting for response from mininet" )
653 main.log.error( "response: " + str( self.handle.before ) )
654 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700655 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800656 main.log.error(
657 self.name +
658 ": timeout when waiting for response from mininet" )
659 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700660 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700661 if re.search( ',\s0\%\spacket\sloss', response ):
662 main.log.info( self.name + ": no packets lost, host is reachable" )
663 return main.TRUE
664 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800665 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700666 self.name +
667 ": PACKET LOST, HOST IS NOT REACHABLE" )
668 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800669 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800670 main.log.error( self.name + ": EOF exception found" )
671 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700672 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700673 except Exception:
674 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700675 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700676
677 def ping6pair( self, **pingParams ):
678 """
GlennRC2cf7d952015-09-11 16:32:13 -0700679 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700680 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000681 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700682 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
683 """
Jon Hall3b489db2015-10-05 14:38:37 -0700684 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700685 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700686 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530687 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700688 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700689 try:
690 main.log.info( "Sending: " + command )
691 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700692 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
693 timeout=wait + 1 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700694 if i == 1:
695 main.log.error(
696 self.name +
697 ": timeout when waiting for response from mininet" )
698 main.log.error( "response: " + str( self.handle.before ) )
699 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
700 if i == 1:
701 main.log.error(
702 self.name +
703 ": timeout when waiting for response from mininet" )
704 main.log.error( "response: " + str( self.handle.before ) )
705 response = self.handle.before
706 main.log.info( self.name + ": Ping Response: " + response )
707 if re.search( ',\s0\%\spacket\sloss', response ):
708 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700709 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700710 else:
alisone4121a92016-11-22 16:31:36 -0800711 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700712 self.name +
713 ": PACKET LOST, HOST IS NOT REACHABLE" )
714 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700715 except pexpect.EOF:
716 main.log.error( self.name + ": EOF exception found" )
717 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700718 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700719 except Exception:
720 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700721 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800722
You Wangdb927a52016-02-26 11:03:28 -0800723 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
724 """
725 Description:
726 Ping a set of destination host from host CLI.
727 Logging into a Mininet host CLI is required before calling this funtion.
728 Params:
729 dstIPList is a list of destination ip addresses
730 Returns:
731 main.TRUE if the destination host is reachable
732 main.FALSE otherwise
733 """
734 isReachable = main.TRUE
735 wait = int( wait )
736 cmd = "ping"
737 if IPv6:
738 cmd = cmd + "6"
739 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
740 try:
741 for dstIP in dstIPList:
742 pingCmd = cmd + " " + dstIP
743 self.handle.sendline( pingCmd )
744 i = self.handle.expect( [ self.hostPrompt,
745 '\*\*\* Unknown command: ' + pingCmd,
746 pexpect.TIMEOUT ],
747 timeout=wait + 1 )
748 if i == 0:
749 response = self.handle.before
750 if not re.search( ',\s0\%\spacket\sloss', response ):
751 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
752 isReachable = main.FALSE
753 elif i == 1:
754 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700755 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800756 elif i == 2:
757 main.log.error( self.name + ": timeout when waiting for response" )
758 isReachable = main.FALSE
759 else:
760 main.log.error( self.name + ": unknown response: " + self.handle.before )
761 isReachable = main.FALSE
762 except pexpect.TIMEOUT:
763 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800764 response = self.handle.before
765 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700766 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800767 self.handle.expect( "Interrupt" )
768 response += self.handle.before + self.handle.after
769 self.handle.expect( "mininet>" )
770 response += self.handle.before + self.handle.after
771 main.log.debug( response )
You Wangdb927a52016-02-26 11:03:28 -0800772 isReachable = main.FALSE
773 except pexpect.EOF:
774 main.log.error( self.name + ": EOF exception found" )
775 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700776 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800777 except Exception:
778 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700779 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800780 return isReachable
781
Jon Hall7eb38402015-01-08 17:19:54 -0800782 def checkIP( self, host ):
783 """
784 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700785 try:
786 if self.handle:
787 try:
788 response = self.execute(
789 cmd=host +
790 " ifconfig",
791 prompt="mininet>",
792 timeout=10 )
793 except pexpect.EOF:
794 main.log.error( self.name + ": EOF exception found" )
795 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700796 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700797
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700798 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
799 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
800 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
801 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
802 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
803 "[0-9]|25[0-5]|[0-9]{1,2})"
804 # pattern = "inet addr:10.0.0.6"
805 if re.search( pattern, response ):
806 main.log.info( self.name + ": Host Ip configured properly" )
807 return main.TRUE
808 else:
809 main.log.error( self.name + ": Host IP not found" )
810 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700811 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700812 main.log.error( self.name + ": Connection failed to the host" )
813 except Exception:
814 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700815 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800816
Jon Hall7eb38402015-01-08 17:19:54 -0800817 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800818 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700819 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800820 response = self.execute(
821 cmd="h1 /usr/sbin/sshd -D&",
822 prompt="mininet>",
823 timeout=10 )
824 response = self.execute(
825 cmd="h4 /usr/sbin/sshd -D&",
826 prompt="mininet>",
827 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700828 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800829 vars( self )[ key ] = connectargs[ key ]
830 response = self.execute(
831 cmd="xterm h1 h4 ",
832 prompt="mininet>",
833 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800834 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800835 main.log.error( self.name + ": EOF exception found" )
836 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700837 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700838 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800839 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700840 if self.flag == 0:
841 self.flag = 1
842 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800843 else:
adminbae64d82013-08-01 10:50:15 -0700844 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800845
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700846 def moveHost( self, host, oldSw, newSw ):
Jon Hall53c5e662016-04-13 16:06:56 -0700847 """
848 Moves a host from one switch to another on the fly
849 Note: The intf between host and oldSw when detached
850 using detach(), will still show up in the 'net'
851 cmd, because switch.detach() doesn't affect switch.intfs[]
852 ( which is correct behavior since the interfaces
853 haven't moved ).
854 """
855 if self.handle:
856 try:
857 # Bring link between oldSw-host down
858 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
859 "'," + "'down')"
860 print "cmd1= ", cmd
861 response = self.execute( cmd=cmd,
862 prompt="mininet>",
863 timeout=10 )
864
865 # Determine hostintf and Oldswitchintf
866 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
867 ")[0]"
868 print "cmd2= ", cmd
869 self.handle.sendline( cmd )
870 self.handle.expect( "mininet>" )
871
872 # Determine ip and mac address of the host-oldSw interface
873 cmd = "px ipaddr = hintf.IP()"
874 print "cmd3= ", cmd
875 self.handle.sendline( cmd )
876 self.handle.expect( "mininet>" )
877
878 cmd = "px macaddr = hintf.MAC()"
879 print "cmd3= ", cmd
880 self.handle.sendline( cmd )
881 self.handle.expect( "mininet>" )
882
883 # Detach interface between oldSw-host
884 cmd = "px " + oldSw + ".detach( sintf )"
885 print "cmd4= ", cmd
886 self.handle.sendline( cmd )
887 self.handle.expect( "mininet>" )
888
889 # Add link between host-newSw
890 cmd = "py net.addLink(" + host + "," + newSw + ")"
891 print "cmd5= ", cmd
892 self.handle.sendline( cmd )
893 self.handle.expect( "mininet>" )
894
895 # Determine hostintf and Newswitchintf
896 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
897 ")[0]"
898 print "cmd6= ", cmd
899 self.handle.sendline( cmd )
900 self.handle.expect( "mininet>" )
901
902 # Attach interface between newSw-host
903 cmd = "px " + newSw + ".attach( sintf )"
904 print "cmd3= ", cmd
905 self.handle.sendline( cmd )
906 self.handle.expect( "mininet>" )
907
908 # Set ipaddress of the host-newSw interface
909 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
910 print "cmd7 = ", cmd
911 self.handle.sendline( cmd )
912 self.handle.expect( "mininet>" )
913
914 # Set macaddress of the host-newSw interface
915 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
916 print "cmd8 = ", cmd
917 self.handle.sendline( cmd )
918 self.handle.expect( "mininet>" )
919
920 cmd = "net"
921 print "cmd9 = ", cmd
922 self.handle.sendline( cmd )
923 self.handle.expect( "mininet>" )
924 print "output = ", self.handle.before
925
926 # Determine ipaddress of the host-newSw interface
927 cmd = host + " ifconfig"
928 print "cmd10= ", cmd
929 self.handle.sendline( cmd )
930 self.handle.expect( "mininet>" )
931 print "ifconfig o/p = ", self.handle.before
932
933 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700934
935 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700936 main.log.error( self.name + ": TIMEOUT exception found" )
937 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700938 main.cleanAndExit()
Jon Hall53c5e662016-04-13 16:06:56 -0700939 except pexpect.EOF:
940 main.log.error( self.name + ": EOF exception found" )
941 main.log.error( self.name + ": " + self.handle.before )
942 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700943 except Exception:
944 main.log.exception( self.name + ": Uncaught exception!" )
945 return main.FALSE
Jon Hall53c5e662016-04-13 16:06:56 -0700946
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700947 def moveHostv6( self, host, oldSw, newSw ):
kelvin-onlaba1484582015-02-02 15:46:20 -0800948 """
949 Moves a host from one switch to another on the fly
950 Note: The intf between host and oldSw when detached
951 using detach(), will still show up in the 'net'
952 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700953 ( which is correct behavior since the interfaces
954 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800955 """
956 if self.handle:
957 try:
Jon Hall439c8912016-04-15 02:22:03 -0700958 IP = str( self.getIPAddress( host, proto='IPV6' ) ) + "/64"
kelvin-onlaba1484582015-02-02 15:46:20 -0800959 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700960 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800961 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800962 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800963 response = self.execute( cmd=cmd,
964 prompt="mininet>",
965 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700966
kelvin-onlaba1484582015-02-02 15:46:20 -0800967 # Determine hostintf and Oldswitchintf
968 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800969 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800970 print "cmd2= ", cmd
971 self.handle.sendline( cmd )
972 self.handle.expect( "mininet>" )
973
shahshreya73537862015-02-11 15:15:24 -0800974 # Determine ip and mac address of the host-oldSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700975 cmd = "px ipaddr = " + str( IP )
kelvin-onlaba1484582015-02-02 15:46:20 -0800976 print "cmd3= ", cmd
977 self.handle.sendline( cmd )
978 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800979
980 cmd = "px macaddr = hintf.MAC()"
981 print "cmd3= ", cmd
982 self.handle.sendline( cmd )
983 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700984
kelvin-onlaba1484582015-02-02 15:46:20 -0800985 # Detach interface between oldSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700986 cmd = "px " + oldSw + ".detach(sintf)"
kelvin-onlaba1484582015-02-02 15:46:20 -0800987 print "cmd4= ", cmd
988 self.handle.sendline( cmd )
989 self.handle.expect( "mininet>" )
990
991 # Add link between host-newSw
992 cmd = "py net.addLink(" + host + "," + newSw + ")"
993 print "cmd5= ", cmd
994 self.handle.sendline( cmd )
995 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700996
kelvin-onlaba1484582015-02-02 15:46:20 -0800997 # Determine hostintf and Newswitchintf
998 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800999 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -08001000 print "cmd6= ", cmd
1001 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -07001002 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001003
1004 # Attach interface between newSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001005 cmd = "px " + newSw + ".attach(sintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001006 print "cmd6= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001007 self.handle.sendline( cmd )
1008 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -08001009
1010 # Set macaddress of the host-newSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001011 cmd = "px " + host + ".setMAC(mac = macaddr, intf = hintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001012 print "cmd7 = ", cmd
1013 self.handle.sendline( cmd )
1014 self.handle.expect( "mininet>" )
1015
1016 # Set ipaddress of the host-newSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001017 cmd = "px " + host + ".setIP(ip = ipaddr, intf = hintf)"
shahshreya73537862015-02-11 15:15:24 -08001018 print "cmd8 = ", cmd
1019 self.handle.sendline( cmd )
1020 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001021
Jon Hall439c8912016-04-15 02:22:03 -07001022 cmd = host + " ifconfig"
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001023 print "cmd9 =", cmd
1024 response = self.execute( cmd = cmd, prompt="mininet>", timeout=10 )
Jon Hall439c8912016-04-15 02:22:03 -07001025 print response
1026 pattern = "h\d-eth([\w])"
Jeremyd9e4eb12016-04-13 12:09:06 -07001027 ipAddressSearch = re.search( pattern, response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001028 print ipAddressSearch.group( 1 )
1029 intf = host + "-eth" + str( ipAddressSearch.group( 1 ) )
Jon Hall439c8912016-04-15 02:22:03 -07001030 cmd = host + " ip -6 addr add %s dev %s" % ( IP, intf )
1031 print "cmd10 = ", cmd
1032 self.handle.sendline( cmd )
1033 self.handle.expect( "mininet>" )
1034
kelvin-onlaba1484582015-02-02 15:46:20 -08001035 cmd = "net"
Jon Hall439c8912016-04-15 02:22:03 -07001036 print "cmd11 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001037 self.handle.sendline( cmd )
1038 self.handle.expect( "mininet>" )
1039 print "output = ", self.handle.before
1040
1041 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -08001042 cmd = host + " ifconfig"
Jon Hall439c8912016-04-15 02:22:03 -07001043 print "cmd12= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001044 self.handle.sendline( cmd )
1045 self.handle.expect( "mininet>" )
1046 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -07001047
kelvin-onlaba1484582015-02-02 15:46:20 -08001048 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001049 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001050 main.log.error( self.name + ": TIMEOUT exception found" )
1051 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001052 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08001053 except pexpect.EOF:
1054 main.log.error( self.name + ": EOF exception found" )
1055 main.log.error( self.name + ": " + self.handle.before )
1056 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001057 except Exception:
1058 main.log.exception( self.name + ": Uncaught exception!" )
1059 return main.FALSE
kelvin-onlaba1484582015-02-02 15:46:20 -08001060
Jon Hall7eb38402015-01-08 17:19:54 -08001061 def changeIP( self, host, intf, newIP, newNetmask ):
1062 """
1063 Changes the ip address of a host on the fly
1064 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001065 if self.handle:
1066 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001067 cmd = host + " ifconfig " + intf + " " + \
1068 newIP + " " + 'netmask' + " " + newNetmask
1069 self.handle.sendline( cmd )
1070 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001071 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001072 main.log.info( "response = " + response )
1073 main.log.info(
1074 "Ip of host " +
1075 host +
1076 " changed to new IP " +
1077 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -08001078 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001079 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001080 main.log.error( self.name + ": TIMEOUT exception found" )
1081 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001082 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001083 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001084 main.log.error( self.name + ": EOF exception found" )
1085 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001086 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001087 except Exception:
1088 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001089 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001090
Jon Hall7eb38402015-01-08 17:19:54 -08001091 def changeDefaultGateway( self, host, newGW ):
1092 """
1093 Changes the default gateway of a host
1094 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001095 if self.handle:
1096 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001097 cmd = host + " route add default gw " + newGW
1098 self.handle.sendline( cmd )
1099 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001100 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001101 main.log.info( "response = " + response )
1102 main.log.info(
1103 "Default gateway of host " +
1104 host +
1105 " changed to " +
1106 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -08001107 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001108 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001109 main.log.error( self.name + ": TIMEOUT exception found" )
1110 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001111 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001112 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001113 main.log.error( self.name + ": EOF exception found" )
1114 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001115 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001116 except Exception:
1117 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001118 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001119
Jon Hall7eb38402015-01-08 17:19:54 -08001120 def addStaticMACAddress( self, host, GW, macaddr ):
1121 """
Jon Hallefbd9792015-03-05 16:11:36 -08001122 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001123 if self.handle:
1124 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001125 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1126 cmd = host + " arp -s " + GW + " " + macaddr
1127 self.handle.sendline( cmd )
1128 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001129 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001130 main.log.info( "response = " + response )
1131 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001132 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001133 GW +
1134 " changed to " +
1135 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001136 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001137 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001138 main.log.error( self.name + ": TIMEOUT exception found" )
1139 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001140 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001141 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001142 main.log.error( self.name + ": EOF exception found" )
1143 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001144 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001145 except Exception:
1146 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001147 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001148
Jon Hall7eb38402015-01-08 17:19:54 -08001149 def verifyStaticGWandMAC( self, host ):
1150 """
1151 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001152 if self.handle:
1153 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001154 # h1 arp -an
1155 cmd = host + " arp -an "
1156 self.handle.sendline( cmd )
1157 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001158 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001159 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001160 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001161 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001162 main.log.error( self.name + ": TIMEOUT exception found" )
1163 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001164 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001165 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001166 main.log.error( self.name + ": EOF exception found" )
1167 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001168 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001169 except Exception:
1170 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001171 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001172
Jon Hall7eb38402015-01-08 17:19:54 -08001173 def getMacAddress( self, host ):
1174 """
1175 Verifies the host's ip configured or not."""
1176 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001177 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001178 response = self.execute(
1179 cmd=host +
1180 " ifconfig",
1181 prompt="mininet>",
1182 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001183 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001184 main.log.error( self.name + ": EOF exception found" )
1185 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001186 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001187 except Exception:
1188 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001189 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001190
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001191 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001192 macAddressSearch = re.search( pattern, response, re.I )
1193 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001194 main.log.info(
1195 self.name +
1196 ": Mac-Address of Host " +
1197 host +
1198 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001199 macAddress )
1200 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001201 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001202 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001203
Jon Hall7eb38402015-01-08 17:19:54 -08001204 def getInterfaceMACAddress( self, host, interface ):
1205 """
1206 Return the IP address of the interface on the given host"""
1207 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001208 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001209 response = self.execute( cmd=host + " ifconfig " + interface,
1210 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001211 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001212 main.log.error( self.name + ": EOF exception found" )
1213 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001214 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001215 except Exception:
1216 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001217 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001218
1219 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001220 macAddressSearch = re.search( pattern, response, re.I )
1221 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001222 main.log.info( "No mac address found in %s" % response )
1223 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001224 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001225 main.log.info(
1226 "Mac-Address of " +
1227 host +
1228 ":" +
1229 interface +
1230 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001231 macAddress )
1232 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001233 else:
1234 main.log.error( "Connection failed to the host" )
1235
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001236 def getIPAddress( self, host , proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001237 """
1238 Verifies the host's ip configured or not."""
1239 if self.handle:
1240 try:
1241 response = self.execute(
1242 cmd=host +
1243 " ifconfig",
1244 prompt="mininet>",
1245 timeout=10 )
1246 except pexpect.EOF:
1247 main.log.error( self.name + ": EOF exception found" )
1248 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001249 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001250 except Exception:
1251 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001252 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001253
sathishmad953462015-12-03 17:42:07 +05301254 pattern = ''
1255 if proto == 'IPV4':
1256 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
1257 else:
Jon Hall439c8912016-04-15 02:22:03 -07001258 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001259 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001260 if not ipAddressSearch:
1261 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001262 main.log.info(
1263 self.name +
1264 ": IP-Address of Host " +
1265 host +
1266 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001267 ipAddressSearch.group( 1 ) )
1268 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001269 else:
1270 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001271
Jon Hall7eb38402015-01-08 17:19:54 -08001272 def getSwitchDPID( self, switch ):
1273 """
1274 return the datapath ID of the switch"""
1275 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001276 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001277 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001278 response = self.execute(
1279 cmd=cmd,
1280 prompt="mininet>",
1281 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001282 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001283 main.log.error( self.name + ": EOF exception found" )
1284 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001285 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001286 except Exception:
1287 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001288 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001289 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001290 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001291 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001292 main.log.info(
1293 "Couldn't find DPID for switch %s, found: %s" %
1294 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001295 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001296 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001297 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001298 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001299
Jon Hall7eb38402015-01-08 17:19:54 -08001300 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001301 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001302 self.handle.sendline( "" )
1303 self.expect( "mininet>" )
1304 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001305 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001306 response = self.execute(
1307 cmd=cmd,
1308 prompt="mininet>",
1309 timeout=10 )
1310 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001311 response = self.handle.before
1312 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001313 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001314 main.log.error( self.name + ": TIMEOUT exception found" )
1315 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001316 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001317 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001318 main.log.error( self.name + ": EOF exception found" )
1319 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001320 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001321 except Exception:
1322 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001323 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001324
Jon Hall7eb38402015-01-08 17:19:54 -08001325 def getInterfaces( self, node ):
1326 """
1327 return information dict about interfaces connected to the node"""
1328 if self.handle:
1329 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001330 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001331 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001332 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001333 response = self.execute(
1334 cmd=cmd,
1335 prompt="mininet>",
1336 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001337 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001338 main.log.error( self.name + ": EOF exception found" )
1339 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001340 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001341 except Exception:
1342 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001343 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001344 return response
1345 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001346 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001347
Jon Hall7eb38402015-01-08 17:19:54 -08001348 def dump( self ):
1349 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001350 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001351 response = self.execute(
1352 cmd='dump',
1353 prompt='mininet>',
1354 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001355 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001356 main.log.error( self.name + ": EOF exception found" )
1357 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001358 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001359 except Exception:
1360 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001361 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001362 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001363
Jon Hall7eb38402015-01-08 17:19:54 -08001364 def intfs( self ):
1365 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001366 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001367 response = self.execute(
1368 cmd='intfs',
1369 prompt='mininet>',
1370 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001371 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001372 main.log.error( self.name + ": EOF exception found" )
1373 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001374 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001375 except Exception:
1376 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001377 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001378 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001379
Jon Hall7eb38402015-01-08 17:19:54 -08001380 def net( self ):
1381 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001382 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001383 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001384 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001385 main.log.error( self.name + ": EOF exception found" )
1386 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001387 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001388 except Exception:
1389 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001390 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001391 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001392
Devin Lima7cfdbd2017-09-29 15:02:22 -07001393 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001394 main.log.info( self.name + ": List network links" )
1395 try:
1396 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001397 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001398 except pexpect.EOF:
1399 main.log.error( self.name + ": EOF exception found" )
1400 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001401 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001402 except Exception:
1403 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001404 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001405 return response
1406
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001407 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001408 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001409 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001410
kelvin-onlab7cce9382015-07-17 10:21:03 -07001411 @parm:
1412 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1413 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001414 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001415 try:
1416 for host1 in hosts:
1417 for host2 in hosts:
1418 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001419 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1420 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001421 except Exception:
1422 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001423 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001424
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001425 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001426 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001427 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1428 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001429
kelvin-onlab7cce9382015-07-17 10:21:03 -07001430 @parm:
1431 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1432 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001433 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001434 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1435 try:
1436 # Setup the mininet command
1437 cmd1 = 'iperf ' + host1 + " " + host2
1438 self.handle.sendline( cmd1 )
1439 outcome = self.handle.expect( "mininet>", timeout )
1440 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001441
kelvin-onlab7cce9382015-07-17 10:21:03 -07001442 # checks if there are results in the mininet response
1443 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001444 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001445 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001446 response = response.split( "\r\n" )
1447 response = response[ len( response )-2 ]
1448 response = response.split( ": " )
1449 response = response[ len( response )-1 ]
1450 response = response.replace( "[", "" )
1451 response = response.replace( "]", "" )
1452 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001453
kelvin-onlab7cce9382015-07-17 10:21:03 -07001454 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001455 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001456
kelvin-onlab7cce9382015-07-17 10:21:03 -07001457 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001458 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001459 if len( bandwidth ) == 2:
1460 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001461 return main.TRUE
1462 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001463 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001464 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001465 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001466 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001467 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001468 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001469 main.log.error( self.name + ": TIMEOUT exception found" )
1470 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001471 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001472 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001473 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001474 self.handle.expect( "Interrupt" )
1475 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001476 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001477 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001478 main.log.error( self.name + ": EOF exception found" )
1479 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001480 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001481 except Exception:
1482 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001483 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001484
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001485 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001486 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1487 try:
1488 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001489 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001490 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001491 outcome1 = self.handle.expect( "mininet>" )
1492 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001493 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001494 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001495 response1 = self.handle.before
1496 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001497 print response1, response2
1498 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001499 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001500 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001501 return main.TRUE
1502 else:
1503 main.log.error( self.name + ": iperf test failed" )
1504 return main.FALSE
1505 except pexpect.TIMEOUT:
1506 main.log.error( self.name + ": TIMEOUT exception found" )
1507 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001508 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001509 self.handle.expect( "Interrupt" )
1510 self.handle.expect( "mininet>" )
1511 return main.FALSE
1512 except pexpect.EOF:
1513 main.log.error( self.name + ": EOF exception found" )
1514 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001515 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001516 except Exception:
1517 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001518 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001519
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001520 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001521 '''
GlennRC61321f22015-07-16 13:36:54 -07001522 Runs the iperfudp function with a given set of hosts and specified
1523 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001524
GlennRC61321f22015-07-16 13:36:54 -07001525 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001526 bandwidth: the targeted bandwidth, in megabits ('M')
1527 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001528 try:
1529 for host1 in hosts:
1530 for host2 in hosts:
1531 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001532 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1533 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001534 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001535 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001536 return main.FALSE
1537 except Exception:
1538 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001539 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001540
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001541 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001542 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001543 Creates an iperf UDP test with a specific bandwidth.
1544 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001545
kelvin-onlab7cce9382015-07-17 10:21:03 -07001546 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001547 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1548 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001549 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001550 try:
1551 # setup the mininet command
1552 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001553 self.handle.sendline( cmd )
1554 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001555 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001556
kelvin-onlab7cce9382015-07-17 10:21:03 -07001557 # check if there are in results in the mininet response
1558 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001559 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001560 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001561 response = response.split( "\r\n" )
1562 response = response[ len( response )-2 ]
1563 response = response.split( ": " )
1564 response = response[ len( response )-1 ]
1565 response = response.replace( "[", "" )
1566 response = response.replace( "]", "" )
1567 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001568
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001569 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001570
kelvin-onlab7cce9382015-07-17 10:21:03 -07001571 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001572 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001573 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001574 # if one entry is blank then something is wrong
1575 for item in mnBandwidth:
1576 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001577 main.log.error( self.name + ": Could not parse iperf output" )
1578 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001579 return main.FALSE
1580 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001581 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001582 return main.TRUE
1583 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001584 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001585 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001586
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001587 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001588 main.log.error( self.name + ": TIMEOUT exception found" )
1589 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001590 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -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()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001595 except Exception:
1596 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001597 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001598
Jon Hall7eb38402015-01-08 17:19:54 -08001599 def nodes( self ):
1600 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001601 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001602 response = self.execute(
1603 cmd='nodes',
1604 prompt='mininet>',
1605 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001606 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001607 main.log.error( self.name + ": EOF exception found" )
1608 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001609 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001610 except Exception:
1611 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001612 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001613 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001614
Jon Hall7eb38402015-01-08 17:19:54 -08001615 def pingpair( self ):
1616 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001617 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001618 response = self.execute(
1619 cmd='pingpair',
1620 prompt='mininet>',
1621 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001622 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001623 main.log.error( self.name + ": EOF exception found" )
1624 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001625 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001626 except Exception:
1627 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001628 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001629
Jon Hall7eb38402015-01-08 17:19:54 -08001630 if re.search( ',\s0\%\spacket\sloss', response ):
1631 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001632 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001633 else:
alisone4121a92016-11-22 16:31:36 -08001634 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001635 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001636
Jon Hall7eb38402015-01-08 17:19:54 -08001637 def link( self, **linkargs ):
1638 """
GlennRCed771242016-01-13 17:02:47 -08001639 Bring link( s ) between two nodes up or down
1640 """
Jon Hall6094a362014-04-11 14:46:56 -07001641 try:
GlennRCed771242016-01-13 17:02:47 -08001642 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1643 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1644 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1645 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1646
1647 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1648 cmd = "link {} {} {}".format( end1, end2, option )
1649 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001650 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001651 response = self.handle.before
1652 main.log.info( response )
1653
1654 return main.TRUE
1655 except pexpect.TIMEOUT:
1656 main.log.exception( self.name + ": Command timed out" )
1657 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001658 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001659 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001660 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001661 except Exception:
1662 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001663 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001664
pingping-lin8244a3b2015-09-16 13:36:56 -07001665 def switch( self, **switchargs ):
1666 """
1667 start/stop a switch
1668 """
1669 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1670 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1671 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1672 command = "switch " + str( sw ) + " " + str( option )
1673 main.log.info( command )
1674 try:
1675 self.handle.sendline( command )
1676 self.handle.expect( "mininet>" )
1677 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001678 main.log.error( self.name + ": TIMEOUT exception found" )
1679 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001680 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001681 except pexpect.EOF:
1682 main.log.error( self.name + ": EOF exception found" )
1683 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001684 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001685 return main.TRUE
1686
pingping-lin5bb663b2015-09-24 11:47:50 -07001687 def node( self, nodeName, commandStr ):
1688 """
1689 Carry out a command line on a given node
1690 @parm:
1691 nodeName: the node name in Mininet testbed
1692 commandStr: the command line will be carried out on the node
1693 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1694 """
1695 command = str( nodeName ) + " " + str( commandStr )
1696 main.log.info( command )
1697
1698 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001699 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001700 if re.search( "Unknown command", response ):
1701 main.log.warn( response )
1702 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001703 if re.search( "Permission denied", response ):
1704 main.log.warn( response )
1705 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001706 except pexpect.EOF:
1707 main.log.error( self.name + ": EOF exception found" )
1708 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001709 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001710 main.log.info( " response is :" )
1711 main.log.info( response )
1712 return response
1713
Jon Hall7eb38402015-01-08 17:19:54 -08001714 def yank( self, **yankargs ):
1715 """
1716 yank a mininet switch interface to a host"""
1717 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001718 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001719 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1720 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001721 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001722 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001723 response = self.execute(
1724 cmd=command,
1725 prompt="mininet>",
1726 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001727 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001728 main.log.error( self.name + ": EOF exception found" )
1729 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001730 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001731 except Exception:
1732 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001733 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001734 return main.TRUE
1735
Jon Hall7eb38402015-01-08 17:19:54 -08001736 def plug( self, **plugargs ):
1737 """
1738 plug the yanked mininet switch interface to a switch"""
1739 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001740 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001741 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1742 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001743 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001744 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001745 response = self.execute(
1746 cmd=command,
1747 prompt="mininet>",
1748 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001749 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001750 main.log.error( self.name + ": EOF exception found" )
1751 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001752 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001753 except Exception:
1754 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001755 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001756 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001757
Jon Hall7eb38402015-01-08 17:19:54 -08001758 def dpctl( self, **dpctlargs ):
1759 """
1760 Run dpctl command on all switches."""
1761 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001762 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001763 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1764 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1765 command = "dpctl " + cmd + " " + str( cmdargs )
1766 try:
1767 response = self.execute(
1768 cmd=command,
1769 prompt="mininet>",
1770 timeout=10 )
1771 except pexpect.EOF:
1772 main.log.error( self.name + ": EOF exception found" )
1773 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001774 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001775 except Exception:
1776 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001777 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001778 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001779
kelvin-onlabd3b64892015-01-20 13:26:24 -08001780 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001781 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001782 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001783 try:
1784 fileInput = path + '/lib/Mininet/INSTALL'
1785 version = super( Mininet, self ).getVersion()
1786 pattern = 'Mininet\s\w\.\w\.\w\w*'
1787 for line in open( fileInput, 'r' ).readlines():
1788 result = re.match( pattern, line )
1789 if result:
1790 version = result.group( 0 )
1791 return version
1792 except Exception:
1793 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001794 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001795
kelvin-onlabd3b64892015-01-20 13:26:24 -08001796 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001797 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001798 Parameters:
1799 sw: The name of an OVS switch. Example "s1"
1800 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001801 The output of the command from the mininet cli
1802 or main.FALSE on timeout"""
1803 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001804 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001805 response = self.execute(
1806 cmd=command,
1807 prompt="mininet>",
1808 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001809 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001810 return response
admin2a9548d2014-06-17 14:08:07 -07001811 else:
1812 return main.FALSE
1813 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001814 main.log.error( self.name + ": EOF exception found" )
1815 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001816 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001817 except Exception:
1818 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001819 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001820
Charles Chan029be652015-08-24 01:46:10 +08001821 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001822 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001823 Description:
1824 Assign switches to the controllers ( for ovs use only )
1825 Required:
1826 sw - Name of the switch. This can be a list or a string.
1827 ip - Ip addresses of controllers. This can be a list or a string.
1828 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001829 port - ONOS use port 6653, if no list of ports is passed, then
1830 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001831 ptcp - ptcp number, This can be a string or a list that has
1832 the same length as switch. This is optional and not required
1833 when using ovs switches.
1834 NOTE: If switches and ptcp are given in a list type they should have the
1835 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1836 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001837
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001838 Return:
1839 Returns main.TRUE if mininet correctly assigned switches to
1840 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001841 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001842 """
1843 assignResult = main.TRUE
1844 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001845 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001846 command = "sh ovs-vsctl set-controller "
1847 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001848 try:
1849 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001850 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001851 if isinstance( port, types.StringType ) or \
1852 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001853 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001854 elif isinstance( port, types.ListType ):
1855 main.log.error( self.name + ": Only one controller " +
1856 "assigned and a list of ports has" +
1857 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001858 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001859 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001860 main.log.error( self.name + ": Invalid controller port " +
1861 "number. Please specify correct " +
1862 "controller port" )
1863 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001864
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001865 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001866 if isinstance( port, types.StringType ) or \
1867 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001868 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001869 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1870 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001871 elif isinstance( port, types.ListType ):
1872 if ( len( ip ) != len( port ) ):
1873 main.log.error( self.name + ": Port list = " +
1874 str( len( port ) ) +
1875 "should be the same as controller" +
1876 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001877 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001878 else:
1879 onosIp = ""
1880 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001881 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1882 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001883 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001884 main.log.error( self.name + ": Invalid controller port " +
1885 "number. Please specify correct " +
1886 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001887 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001888 else:
1889 main.log.error( self.name + ": Invalid ip address" )
1890 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001891
1892 if isinstance( sw, types.StringType ):
1893 command += sw + " "
1894 if ptcp:
1895 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001896 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001897 elif isinstance( ptcp, types.ListType ):
1898 main.log.error( self.name + ": Only one switch is " +
1899 "being set and multiple PTCP is " +
1900 "being passed " )
1901 else:
1902 main.log.error( self.name + ": Invalid PTCP" )
1903 ptcp = ""
1904 command += onosIp
1905 commandList.append( command )
1906
1907 elif isinstance( sw, types.ListType ):
1908 if ptcp:
1909 if isinstance( ptcp, types.ListType ):
1910 if len( ptcp ) != len( sw ):
1911 main.log.error( self.name + ": PTCP length = " +
1912 str( len( ptcp ) ) +
1913 " is not the same as switch" +
1914 " length = " +
1915 str( len( sw ) ) )
1916 return main.FALSE
1917 else:
1918 for switch, ptcpNum in zip( sw, ptcp ):
1919 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001920 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001921 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001922 tempCmd += onosIp
1923 commandList.append( tempCmd )
1924 else:
1925 main.log.error( self.name + ": Invalid PTCP" )
1926 return main.FALSE
1927 else:
1928 for switch in sw:
1929 tempCmd = "sh ovs-vsctl set-controller "
1930 tempCmd += switch + " " + onosIp
1931 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001932 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001933 main.log.error( self.name + ": Invalid switch type " )
1934 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001935
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001936 for cmd in commandList:
1937 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001938 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001939 except pexpect.TIMEOUT:
1940 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1941 return main.FALSE
1942 except pexpect.EOF:
1943 main.log.error( self.name + ": EOF exception found" )
1944 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001945 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001946 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001947 except pexpect.EOF:
1948 main.log.error( self.name + ": EOF exception found" )
1949 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001950 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001951 except Exception:
1952 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001953 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001954
kelvin-onlabd3b64892015-01-20 13:26:24 -08001955 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001956 """
1957 Removes the controller target from sw"""
1958 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001959 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001960 response = self.execute(
1961 cmd=command,
1962 prompt="mininet>",
1963 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001964 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001965 main.log.error( self.name + ": EOF exception found" )
1966 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001967 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001968 except Exception:
1969 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001970 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001971 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001972 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001973
kelvin-onlabd3b64892015-01-20 13:26:24 -08001974 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001975 """
Jon Hallb1290e82014-11-18 16:17:48 -05001976 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001977 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001978 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001979 NOTE: cannot currently specify what type of switch
1980 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001981 sw = name of the new switch as a string
1982 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001983 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001984 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001985 """
1986 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001987 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001988 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001989 response = self.execute(
1990 cmd=command,
1991 prompt="mininet>",
1992 timeout=10 )
1993 if re.search( "already exists!", response ):
1994 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001995 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001996 elif re.search( "Error", response ):
1997 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001998 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001999 elif re.search( "usage:", response ):
2000 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002001 return main.FALSE
2002 else:
2003 return main.TRUE
2004 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002005 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07002006 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002007 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002008 except Exception:
2009 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002010 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002011
kelvin-onlabd3b64892015-01-20 13:26:24 -08002012 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08002013 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08002014 delete a switch from the mininet topology
2015 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002016 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08002017 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08002018 sw = name of the switch as a string
2019 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002020 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05002021 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002022 response = self.execute(
2023 cmd=command,
2024 prompt="mininet>",
2025 timeout=10 )
2026 if re.search( "no switch named", response ):
2027 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002028 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002029 elif re.search( "Error", response ):
2030 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002031 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002032 elif re.search( "usage:", response ):
2033 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002034 return main.FALSE
2035 else:
2036 return main.TRUE
2037 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002038 main.log.error( self.name + ": EOF exception found" )
2039 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002040 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002041 except Exception:
2042 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002043 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002044
You Wangdb8cd0a2016-05-26 15:19:45 -07002045 def getSwitchRandom( self, timeout=60, nonCut=True ):
2046 """
2047 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002048 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002049 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002050 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002051 it just randomly returns one switch from all current switches in
2052 Mininet.
2053 Returns the name of the chosen switch.
2054 """
2055 import random
2056 candidateSwitches = []
2057 try:
2058 if not nonCut:
2059 switches = self.getSwitches( timeout=timeout )
2060 assert len( switches ) != 0
2061 for switchName in switches.keys():
2062 candidateSwitches.append( switchName )
2063 else:
2064 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002065 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002066 return None
2067 self.graph.update( graphDict )
2068 candidateSwitches = self.graph.getNonCutVertices()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002069 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002070 return None
2071 elif len( candidateSwitches ) == 0:
2072 main.log.info( self.name + ": No candidate switch for deletion" )
2073 return None
2074 else:
2075 switch = random.sample( candidateSwitches, 1 )
2076 return switch[ 0 ]
2077 except KeyError:
2078 main.log.exception( self.name + ": KeyError exception found" )
2079 return None
2080 except AssertionError:
2081 main.log.exception( self.name + ": AssertionError exception found" )
2082 return None
2083 except Exception:
2084 main.log.exception( self.name + ": Uncaught exception" )
2085 return None
2086
2087 def delSwitchRandom( self, timeout=60, nonCut=True ):
2088 """
2089 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002090 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002091 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002092 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002093 otherwise it just randomly delete one switch from all current
2094 switches in Mininet.
2095 Returns the name of the deleted switch
2096 """
2097 try:
2098 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002099 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002100 return None
2101 else:
2102 deletionResult = self.delSwitch( switch )
2103 if deletionResult:
2104 return switch
2105 else:
2106 return None
2107 except Exception:
2108 main.log.exception( self.name + ": Uncaught exception" )
2109 return None
2110
kelvin-onlabd3b64892015-01-20 13:26:24 -08002111 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002112 """
2113 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002114 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002115 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002116 NOTE: cannot currently specify what type of link
2117 required params:
2118 node1 = the string node name of the first endpoint of the link
2119 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002120 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002121 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002122 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002123 response = self.execute(
2124 cmd=command,
2125 prompt="mininet>",
2126 timeout=10 )
2127 if re.search( "doesnt exist!", response ):
2128 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002129 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002130 elif re.search( "Error", response ):
2131 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002132 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002133 elif re.search( "usage:", response ):
2134 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002135 return main.FALSE
2136 else:
2137 return main.TRUE
2138 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002139 main.log.error( self.name + ": EOF exception found" )
2140 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002141 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002142 except Exception:
2143 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002144 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002145
kelvin-onlabd3b64892015-01-20 13:26:24 -08002146 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002147 """
2148 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002149 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002150 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002151 required params:
2152 node1 = the string node name of the first endpoint of the link
2153 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002154 returns: main.FALSE on an error, else main.TRUE
2155 """
Jon Hallffb386d2014-11-21 13:43:38 -08002156 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002157 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002158 response = self.execute(
2159 cmd=command,
2160 prompt="mininet>",
2161 timeout=10 )
2162 if re.search( "no node named", response ):
2163 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002164 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002165 elif re.search( "Error", response ):
2166 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002167 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002168 elif re.search( "usage:", response ):
2169 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002170 return main.FALSE
2171 else:
2172 return main.TRUE
2173 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002174 main.log.error( self.name + ": EOF exception found" )
2175 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002176 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002177 except Exception:
2178 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002179 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002180
You Wangdb8cd0a2016-05-26 15:19:45 -07002181 def getLinkRandom( self, timeout=60, nonCut=True ):
2182 """
2183 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002184 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002185 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002186 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002187 it just randomly returns one link from all current links in
2188 Mininet.
2189 Returns the link as a list, e.g. [ 's1', 's2' ]
2190 """
2191 import random
2192 candidateLinks = []
2193 try:
2194 if not nonCut:
2195 links = self.getLinks( timeout=timeout )
2196 assert len( links ) != 0
2197 for link in links:
2198 # Exclude host-switch link
2199 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2200 continue
2201 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2202 else:
2203 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002204 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002205 return None
2206 self.graph.update( graphDict )
2207 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002208 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002209 return None
2210 elif len( candidateLinks ) == 0:
2211 main.log.info( self.name + ": No candidate link for deletion" )
2212 return None
2213 else:
2214 link = random.sample( candidateLinks, 1 )
2215 return link[ 0 ]
2216 except KeyError:
2217 main.log.exception( self.name + ": KeyError exception found" )
2218 return None
2219 except AssertionError:
2220 main.log.exception( self.name + ": AssertionError exception found" )
2221 return None
2222 except Exception:
2223 main.log.exception( self.name + ": Uncaught exception" )
2224 return None
2225
2226 def delLinkRandom( self, timeout=60, nonCut=True ):
2227 """
2228 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002229 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002230 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002231 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002232 otherwise it just randomly delete one link from all current links
2233 in Mininet.
2234 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2235 """
2236 try:
2237 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002238 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002239 return None
2240 else:
2241 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2242 if deletionResult:
2243 return link
2244 else:
2245 return None
2246 except Exception:
2247 main.log.exception( self.name + ": Uncaught exception" )
2248 return None
2249
kelvin-onlabd3b64892015-01-20 13:26:24 -08002250 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002251 """
Jon Hallb1290e82014-11-18 16:17:48 -05002252 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002253 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002254 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002255 NOTE: cannot currently specify what type of host
2256 required params:
2257 hostname = the string hostname
2258 optional key-value params
2259 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002260 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002261 """
2262 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002263 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002264 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002265 response = self.execute(
2266 cmd=command,
2267 prompt="mininet>",
2268 timeout=10 )
2269 if re.search( "already exists!", response ):
2270 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002271 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002272 elif re.search( "doesnt exists!", response ):
2273 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002274 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002275 elif re.search( "Error", response ):
2276 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002277 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002278 elif re.search( "usage:", response ):
2279 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002280 return main.FALSE
2281 else:
2282 return main.TRUE
2283 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002284 main.log.error( self.name + ": EOF exception found" )
2285 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002286 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002287 except Exception:
2288 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002289 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002290
kelvin-onlabd3b64892015-01-20 13:26:24 -08002291 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002292 """
2293 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002294 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002295 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002296 NOTE: this uses a custom mn function
2297 required params:
2298 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002299 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002300 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002301 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002302 response = self.execute(
2303 cmd=command,
2304 prompt="mininet>",
2305 timeout=10 )
2306 if re.search( "no host named", response ):
2307 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002308 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002309 elif re.search( "Error", response ):
2310 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002311 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002312 elif re.search( "usage:", response ):
2313 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002314 return main.FALSE
2315 else:
2316 return main.TRUE
2317 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002318 main.log.error( self.name + ": EOF exception found" )
2319 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002320 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002321 except Exception:
2322 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002323 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002324
Jon Hall7eb38402015-01-08 17:19:54 -08002325 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002326 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002327 Called at the end of the test to stop the mininet and
2328 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002329 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002330 try:
2331 self.handle.sendline( '' )
2332 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
2333 timeout=2 )
2334 response = main.TRUE
2335 if i == 0:
2336 response = self.stopNet()
2337 elif i == 1:
2338 return main.TRUE
2339 # print "Disconnecting Mininet"
2340 if self.handle:
2341 self.handle.sendline( "exit" )
2342 self.handle.expect( "exit" )
2343 self.handle.expect( "(.*)" )
2344 else:
2345 main.log.error( "Connection failed to the host" )
2346 return response
2347 except pexpect.EOF:
2348 main.log.error( self.name + ": EOF exception found" )
2349 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002350 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002351 except Exception:
2352 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002353 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002354
Devin Lima7cfdbd2017-09-29 15:02:22 -07002355 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002356 """
Jon Hall21270ac2015-02-16 17:59:55 -08002357 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002358 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002359 main.FALSE if the pexpect handle does not exist.
2360
Jon Halld61331b2015-02-17 16:35:47 -08002361 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002362 """
Jon Halld61331b2015-02-17 16:35:47 -08002363 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002364 response = ''
2365 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002366 try:
Jon Halld80cc142015-07-06 13:36:05 -07002367 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002368 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002369 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002370 pexpect.EOF,
2371 pexpect.TIMEOUT ],
2372 timeout )
2373 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002374 main.log.info( "Exiting mininet.." )
2375 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002376 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002377 prompt=self.prompt,
2378 timeout=exitTimeout )
2379 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002380 self.handle.sendline( "sudo mn -c" )
2381 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002382
Jeremyd9e4eb12016-04-13 12:09:06 -07002383 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002384 main.log.info( " Mininet trying to exit while not " +
2385 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002386 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002387 elif i == 2:
2388 main.log.error( "Something went wrong exiting mininet" )
2389 elif i == 3: # timeout
2390 main.log.error( "Something went wrong exiting mininet " +
2391 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002392
Hari Krishnab35c6d02015-03-18 11:13:51 -07002393 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002394 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002395 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002396 self.handle.sendline(
2397 "sudo kill -9 \`ps -ef | grep \"" +
2398 fileName +
2399 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002400 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002401 main.log.error( self.name + ": TIMEOUT exception found" )
2402 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002403 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002404 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002405 main.log.error( self.name + ": EOF exception found" )
2406 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002407 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002408 except Exception:
2409 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002410 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002411 else:
2412 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002413 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002414 return response
2415
YPZhang26a139e2016-04-25 14:01:55 -07002416 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002417 """
2418 Description:
2419 Sends arp message from mininet host for hosts discovery
2420 Required:
2421 host - hosts name
2422 Optional:
2423 ip - ip address that does not exist in the network so there would
2424 be no reply.
2425 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002426 if ethDevice:
2427 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002428 cmd = srcHost + " arping -c1 "
2429 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002430 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 -07002431 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002432 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002433 if output:
2434 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002435 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002436 i = self.handle.expect( [ "mininet>", "arping: " ] )
2437 if i == 0:
2438 return main.TRUE
2439 elif i == 1:
2440 response = self.handle.before + self.handle.after
2441 self.handle.expect( "mininet>" )
2442 response += self.handle.before + self.handle.after
2443 main.log.warn( "Error sending arping, output was: " +
2444 response )
2445 return main.FALSE
2446 except pexpect.TIMEOUT:
2447 main.log.error( self.name + ": TIMEOUT exception found" )
2448 main.log.warn( self.handle.before )
2449 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002450 except pexpect.EOF:
2451 main.log.error( self.name + ": EOF exception found" )
2452 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002453 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002454 except Exception:
2455 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002456 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002457
Jon Hall7eb38402015-01-08 17:19:54 -08002458 def decToHex( self, num ):
2459 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002460
Jon Hall7eb38402015-01-08 17:19:54 -08002461 def getSwitchFlowCount( self, switch ):
2462 """
2463 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002464 if self.handle:
2465 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2466 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002467 response = self.execute(
2468 cmd=cmd,
2469 prompt="mininet>",
2470 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002471 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002472 main.log.error( self.name + ": EOF exception found" )
2473 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002474 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002475 except Exception:
2476 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002477 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002478 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002479 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002480 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002481 main.log.info(
2482 "Couldn't find flows on switch %s, found: %s" %
2483 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002484 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002485 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002486 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002487 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002488
Jon Hall9ed8f372016-02-24 17:34:07 -08002489 def checkFlows( self, sw, dumpFormat=None ):
2490 if dumpFormat:
2491 command = "sh ovs-ofctl -F " + \
2492 dumpFormat + " dump-flows " + str( sw )
2493 else:
2494 command = "sh ovs-ofctl dump-flows " + str( sw )
2495 try:
2496 response = self.execute(
2497 cmd=command,
2498 prompt="mininet>",
2499 timeout=10 )
2500 return response
2501 except pexpect.EOF:
2502 main.log.error( self.name + ": EOF exception found" )
2503 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002504 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002505 except Exception:
2506 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002507 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002508
GlennRC68467eb2015-11-16 18:01:01 -08002509 def flowTableComp( self, flowTable1, flowTable2 ):
2510 # This function compares the selctors and treatments of each flow
2511 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002512 assert flowTable1, "flowTable1 is empty or None"
2513 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002514 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002515 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002516 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002517 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002518 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2519 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002520 for field in dFields:
2521 try:
2522 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002523 except KeyError:
2524 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002525 try:
2526 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002527 except KeyError:
2528 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002529 for i in range( len( flowTable1 ) ):
2530 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002531 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002532 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002533 returnValue = main.FALSE
2534 break
2535 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002536 except AssertionError:
2537 main.log.exception( "Nothing to compare" )
2538 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002539 except Exception:
2540 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002541 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002542
GlennRC528ad292015-11-12 10:38:18 -08002543 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002544 '''
GlennRC956ea742015-11-05 16:14:15 -08002545 Discription: Parses flows into json format.
2546 NOTE: this can parse any string thats separated with commas
2547 Arguments:
2548 Required:
2549 flows: a list of strings that represnt flows
2550 Optional:
2551 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2552 debug: prints out the final result
2553 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002554 '''
GlennRC528ad292015-11-12 10:38:18 -08002555 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002556 try:
2557 for flow in flowTable:
2558 jsonFlow = {}
2559 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002560 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002561 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002562 for i in range( len( parsedFlow ) ):
2563 item = parsedFlow[ i ]
2564 if item[ 0 ] == " ":
2565 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002566 # grab the selector and treatment from the parsed flow
2567 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002568 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002569 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002570 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002571 index = 0
2572 # parse the flags
2573 # NOTE: This only parses one flag
2574 flag = {}
2575 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002576 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002577 index += 1
2578 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002579 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002580 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002581 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002582 # the priority is stuck in the selecter so put it back
2583 # in the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002584 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002585 # parse selector
2586 criteria = []
2587 for item in sel:
2588 # this is the type of the packet e.g. "arp"
2589 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002590 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002591 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002592 field = item.split( "=" )
2593 criteria.append( { field[ 0 ]: field[ 1 ] } )
2594 selector = { "selector": { "criteria": sorted( criteria ) } }
2595 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002596 # get rid of the action part e.g. "action=output:2"
2597 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002598 treat = treat.split( "=" )
2599 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002600 # parse treatment
2601 action = []
2602 for item in treat:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002603 field = item.split( ":" )
2604 action.append( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002605 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002606 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002607 # parse the rest of the flow
2608 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002609 field = item.split( "=" )
2610 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002611 # add the treatment and the selector to the json flow
2612 jsonFlow.update( selector )
2613 jsonFlow.update( treatment )
2614 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002615
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002616 if debug:
2617 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002618
You Wang91c37cf2016-05-23 09:39:42 -07002619 # add the json flow to the json flow table
2620 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002621
You Wang91c37cf2016-05-23 09:39:42 -07002622 return jsonFlowTable
2623
2624 except IndexError:
2625 main.log.exception( self.name + ": IndexError found" )
2626 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002627 except pexpect.EOF:
2628 main.log.error( self.name + ": EOF exception found" )
2629 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002630 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002631 except Exception:
2632 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002633 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002634
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002635 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002636 '''
2637 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002638 Each element is a flow.
2639 Arguments:
2640 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002641 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002642 a list of switches.
2643 Optional:
2644 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2645 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002646 '''
GlennRC956ea742015-11-05 16:14:15 -08002647 try:
2648 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002649 if isinstance( sw, list ):
2650 switches.extend( sw )
2651 else:
2652 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002653
2654 flows = []
2655 for s in switches:
2656 cmd = "sh ovs-ofctl dump-flows " + s
2657
GlennRC528ad292015-11-12 10:38:18 -08002658 if "1.0" == version:
2659 cmd += " -F OpenFlow10-table_id"
2660 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002661 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002662
2663 main.log.info( "Sending: " + cmd )
2664 self.handle.sendline( cmd )
2665 self.handle.expect( "mininet>" )
2666 response = self.handle.before
2667 response = response.split( "\r\n" )
2668 # dump the first two elements and the last
2669 # the first element is the command that was sent
2670 # the second is the table header
2671 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002672 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002673 flows.extend( response )
2674
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002675 if debug:
2676 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002677
GlennRC528ad292015-11-12 10:38:18 -08002678 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002679
GlennRC956ea742015-11-05 16:14:15 -08002680 except pexpect.EOF:
2681 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002682 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002683 except Exception:
2684 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002685 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002686
2687 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002688 '''
GlennRC956ea742015-11-05 16:14:15 -08002689 Discription: Checks whether the ID provided matches a flow ID in Mininet
2690 Arguments:
2691 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002692 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002693 a list of switches.
2694 flowId: the flow ID in hex format. Can also be a list of IDs
2695 Optional:
2696 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2697 debug: prints out the final result
2698 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2699 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002700 '''
GlennRC956ea742015-11-05 16:14:15 -08002701 try:
2702 main.log.info( "Getting flows from Mininet" )
2703 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002704 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002705 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002706
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002707 if debug:
2708 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002709
2710 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002711 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002712 result = False
2713 for f in flows:
2714 if flowId in f.get( 'cookie' ):
2715 result = True
2716 break
2717 # flowId is a list
2718 else:
2719 result = True
2720 # Get flow IDs from Mininet
2721 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2722 # Save the IDs that are not in Mininet
2723 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2724
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002725 if debug:
2726 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002727
2728 # Print out the IDs that are not in Mininet
2729 if absentIds:
2730 main.log.warn( "Absent ids: {}".format( absentIds ) )
2731 result = False
2732
2733 return main.TRUE if result else main.FALSE
2734
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002735 except pexpect.EOF:
2736 main.log.error( self.name + ": EOF exception found" )
2737 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002738 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002739 except Exception:
2740 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002741 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002742
Charles Chan029be652015-08-24 01:46:10 +08002743 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002744 """
Jon Hallefbd9792015-03-05 16:11:36 -08002745 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002746 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002747 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002748 self.handle.sendline( "" )
2749 self.handle.expect( "mininet>" )
2750 self.handle.sendline(
2751 "sh sudo tcpdump -n -i " +
2752 intf +
2753 " " +
2754 port +
2755 " -w " +
2756 filename.strip() +
2757 " &" )
2758 self.handle.sendline( "" )
2759 i = self.handle.expect( [ 'No\ssuch\device',
2760 'listening\son',
2761 pexpect.TIMEOUT,
2762 "mininet>" ],
2763 timeout=10 )
2764 main.log.warn( self.handle.before + self.handle.after )
2765 self.handle.sendline( "" )
2766 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002767 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002768 main.log.error(
2769 self.name +
2770 ": tcpdump - No such device exists. " +
2771 "tcpdump attempted on: " +
2772 intf )
admin2a9548d2014-06-17 14:08:07 -07002773 return main.FALSE
2774 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002775 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002776 return main.TRUE
2777 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002778 main.log.error(
2779 self.name +
2780 ": tcpdump command timed out! Check interface name," +
2781 " given interface was: " +
2782 intf )
admin2a9548d2014-06-17 14:08:07 -07002783 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002784 elif i == 3:
2785 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002786 return main.TRUE
2787 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002788 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002789 return main.FALSE
2790 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002791 main.log.error( self.name + ": EOF exception found" )
2792 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002793 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002794 except Exception:
2795 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002796 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002797
kelvin-onlabd3b64892015-01-20 13:26:24 -08002798 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002799 """
2800 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002801 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002802 self.handle.sendline( "sh sudo pkill tcpdump" )
2803 self.handle.expect( "mininet>" )
2804 self.handle.sendline( "" )
2805 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002806 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002807 main.log.error( self.name + ": TIMEOUT exception found" )
2808 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002809 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002810 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002811 main.log.error( self.name + ": EOF exception found" )
2812 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002813 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002814 except Exception:
2815 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002816 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002817
Jon Halld80cc142015-07-06 13:36:05 -07002818 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002819 """
2820 Read ports from a Mininet switch.
2821
2822 Returns a json structure containing information about the
2823 ports of the given switch.
2824 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002825 try:
2826 response = self.getInterfaces( nodeName )
2827 # TODO: Sanity check on response. log if no such switch exists
2828 ports = []
2829 for line in response.split( "\n" ):
2830 if not line.startswith( "name=" ):
2831 continue
2832 portVars = {}
2833 for var in line.split( "," ):
2834 key, value = var.split( "=" )
2835 portVars[ key ] = value
2836 isUp = portVars.pop( 'enabled', "True" )
2837 isUp = "True" in isUp
2838 if verbose:
2839 main.log.info( "Reading switch port %s(%s)" %
2840 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2841 mac = portVars[ 'mac' ]
2842 if mac == 'None':
2843 mac = None
2844 ips = []
2845 ip = portVars[ 'ip' ]
2846 if ip == 'None':
2847 ip = None
2848 ips.append( ip )
2849 name = portVars[ 'name' ]
2850 if name == 'None':
2851 name = None
2852 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2853 if name == 'lo':
2854 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2855 else:
2856 portNo = re.search( portRe, name ).group( 'port' )
2857 ports.append( { 'of_port': portNo,
2858 'mac': str( mac ).replace( '\'', '' ),
2859 'name': name,
2860 'ips': ips,
2861 'enabled': isUp } )
2862 return ports
2863 except pexpect.EOF:
2864 main.log.error( self.name + ": EOF exception found" )
2865 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002866 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002867 except Exception:
2868 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002869 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002870
You Wangdb8cd0a2016-05-26 15:19:45 -07002871 def getOVSPorts( self, nodeName ):
2872 """
2873 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2874
2875 Returns a list of dictionaries containing information about each
2876 port of the given switch.
2877 """
2878 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2879 try:
2880 response = self.execute(
2881 cmd=command,
2882 prompt="mininet>",
2883 timeout=10 )
2884 ports = []
2885 if response:
2886 for line in response.split( "\n" ):
2887 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2888 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002889 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002890 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2891 result = re.search( pattern, line )
2892 if result:
2893 index = result.group( 'index' )
2894 name = result.group( 'name' )
2895 # This port number is extracted from port name
2896 port = result.group( 'port' )
2897 mac = result.group( 'mac' )
2898 ports.append( { 'index': index,
2899 'name': name,
2900 'port': port,
2901 'mac': mac } )
2902 return ports
2903 except pexpect.EOF:
2904 main.log.error( self.name + ": EOF exception found" )
2905 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002906 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002907 except Exception:
2908 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002909 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002910
Devin Lima7cfdbd2017-09-29 15:02:22 -07002911 def getSwitches( self, verbose=False, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002912 """
2913 Read switches from Mininet.
2914
2915 Returns a dictionary whose keys are the switch names and the value is
2916 a dictionary containing information about the switch.
2917 """
Jon Halla22481b2015-07-28 17:46:01 -07002918 # NOTE: To support new Mininet switch classes, just append the new
2919 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002920
Jon Halla22481b2015-07-28 17:46:01 -07002921 # Regex patterns to parse 'dump' output
2922 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002923 # <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 -07002924 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002925 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2926 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2927 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002928 try:
2929 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2930 swRE = r"<(?P<class>" + switchClasses + r")" +\
2931 r"(?P<options>\{.*\})?\s" +\
2932 r"(?P<name>[^:]+)\:\s" +\
2933 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2934 r"\spid=(?P<pid>(\d)+)"
2935 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002936 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002937 output = {}
2938 dump = self.dump().split( "\n" )
2939 for line in dump:
2940 result = re.search( swRE, line, re.I )
2941 if result:
2942 name = result.group( 'name' )
2943 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2944 pid = result.group( 'pid' )
2945 swClass = result.group( 'class' )
2946 options = result.group( 'options' )
2947 if verbose:
2948 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2949 ports = self.getPorts( name )
2950 output[ name ] = { "dpid": dpid,
2951 "ports": ports,
2952 "swClass": swClass,
2953 "pid": pid,
2954 "options": options }
2955 return output
2956 except pexpect.EOF:
2957 main.log.error( self.name + ": EOF exception found" )
2958 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002959 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002960 except Exception:
2961 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002962 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002963
You Wang79f5c5b2018-03-14 11:10:44 -07002964 def getHosts( self, verbose=False, updateTimeout=1000, hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ], getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002965 """
2966 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002967 Optional:
2968 hostClass: it is used to match the class of the mininet host. It
2969 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002970 Returns a dictionary whose keys are the host names and the value is
2971 a dictionary containing information about the host.
2972 """
2973 # Regex patterns to parse dump output
2974 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002975 # <Host h1: pid=12725>
2976 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2977 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2978 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002979 # NOTE: Does not correctly match hosts with multi-links
2980 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2981 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002982 try:
You Wang53dba1e2018-02-02 17:45:44 -08002983 if not isinstance( hostClass, types.ListType ):
2984 hostClass = [ str( hostClass ) ]
2985 classRE = "(" + "|".join([c for c in hostClass]) + ")"
2986 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002987 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
2988 # update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002989 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002990 # Get mininet dump
2991 dump = self.dump().split( "\n" )
2992 hosts = {}
2993 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002994 result = re.search( hostRE, line )
2995 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002996 name = result.group( 'name' )
2997 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002998 if getInterfaces:
2999 response = self.getInterfaces( name )
3000 # Populate interface info
3001 for line in response.split( "\n" ):
3002 if line.startswith( "name=" ):
3003 portVars = {}
3004 for var in line.split( "," ):
3005 key, value = var.split( "=" )
3006 portVars[ key ] = value
3007 isUp = portVars.pop( 'enabled', "True" )
3008 isUp = "True" in isUp
3009 if verbose:
3010 main.log.info( "Reading host port %s(%s)" %
3011 ( portVars[ 'name' ],
3012 portVars[ 'mac' ] ) )
3013 mac = portVars[ 'mac' ]
3014 if mac == 'None':
3015 mac = None
3016 ips = []
3017 ip = portVars[ 'ip' ]
3018 if ip == 'None':
3019 ip = None
3020 ips.append( ip )
3021 intfName = portVars[ 'name' ]
3022 if name == 'None':
3023 name = None
3024 interfaces.append( {
3025 "name": intfName,
3026 "ips": ips,
3027 "mac": str( mac ),
3028 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003029 hosts[ name ] = { "interfaces": interfaces }
3030 return hosts
3031 except pexpect.EOF:
3032 main.log.error( self.name + ": EOF exception found" )
3033 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003034 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003035 except Exception:
3036 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003037 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003038
Devin Lima7cfdbd2017-09-29 15:02:22 -07003039 def getLinks( self, timeout=20, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07003040 """
3041 Gathers information about current Mininet links. These links may not
3042 be up if one of the ports is down.
3043
3044 Returns a list of dictionaries with link endpoints.
3045
3046 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07003047 { 'node1': str( node1 name )
3048 'node2': str( node2 name )
3049 'port1': str( port1 of_port )
3050 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07003051 Note: The port number returned is the eth#, not necessarily the of_port
3052 number. In Mininet, for OVS switch, these should be the same. For
3053 hosts, this is just the eth#.
3054 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003055 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003056 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003057 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07003058
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003059 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003060 # s1-eth3<->s2-eth1 (OK OK)
3061 # s13-eth3<->h27-eth0 (OK OK)
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003062 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
3063 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
3064 links = []
3065 for line in response:
3066 match = re.search( linkRE, line )
3067 if match:
3068 node1 = match.group( 'node1' )
3069 node2 = match.group( 'node2' )
3070 port1 = match.group( 'port1' )
3071 port2 = match.group( 'port2' )
3072 links.append( { 'node1': node1,
3073 'node2': node2,
3074 'port1': port1,
3075 'port2': port2 } )
3076 return links
3077
3078 except pexpect.EOF:
3079 main.log.error( self.name + ": EOF exception found" )
3080 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003081 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003082 except Exception:
3083 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003084 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003085
3086 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003087 """
3088 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003089 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003090
Jon Hallafa8a472015-06-12 14:02:42 -07003091 Dependencies:
3092 1. numpy - "sudo pip install numpy"
3093 """
3094 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003095 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003096 try:
3097 mnDPIDs = []
3098 for swName, switch in switches.iteritems():
3099 mnDPIDs.append( switch[ 'dpid' ].lower() )
3100 mnDPIDs.sort()
3101 if switchesJson == "": # if rest call fails
3102 main.log.error(
3103 self.name +
3104 ".compareSwitches(): Empty JSON object given from ONOS" )
3105 return main.FALSE
3106 onos = switchesJson
3107 onosDPIDs = []
3108 for switch in onos:
3109 if switch[ 'available' ]:
3110 onosDPIDs.append(
3111 switch[ 'id' ].replace(
3112 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003113 '' ).replace(
3114 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003115 '' ).lower() )
3116 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003117
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003118 if mnDPIDs != onosDPIDs:
3119 switchResults = main.FALSE
3120 main.log.error( "Switches in MN but not in ONOS:" )
3121 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3122 main.log.error( str( list1 ) )
3123 main.log.error( "Switches in ONOS but not in MN:" )
3124 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3125 main.log.error( str( list2 ) )
3126 else: # list of dpid's match in onos and mn
3127 switchResults = main.TRUE
3128 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003129
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003130 # FIXME: this does not look for extra ports in ONOS, only checks that
3131 # ONOS has what is in MN
3132 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003133
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003134 # PORTS
3135 for name, mnSwitch in switches.iteritems():
3136 mnPorts = []
3137 onosPorts = []
3138 switchResult = main.TRUE
3139 for port in mnSwitch[ 'ports' ]:
3140 if port[ 'enabled' ]:
3141 mnPorts.append( int( port[ 'of_port' ] ) )
3142 for onosSwitch in portsJson:
3143 if onosSwitch[ 'device' ][ 'available' ]:
3144 if onosSwitch[ 'device' ][ 'id' ].replace(
3145 ':',
3146 '' ).replace(
3147 "of",
3148 '' ) == mnSwitch[ 'dpid' ]:
3149 for port in onosSwitch[ 'ports' ]:
3150 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003151 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003152 # onosPorts.append( 'local' )
3153 onosPorts.append( long( uint64( -2 ) ) )
3154 else:
3155 onosPorts.append( int( port[ 'port' ] ) )
3156 break
3157 mnPorts.sort( key=float )
3158 onosPorts.sort( key=float )
3159
3160 mnPortsLog = mnPorts
3161 onosPortsLog = onosPorts
3162 mnPorts = [ x for x in mnPorts ]
3163 onosPorts = [ x for x in onosPorts ]
3164
3165 # TODO: handle other reserved port numbers besides LOCAL
3166 # NOTE: Reserved ports
3167 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3168 # long( uint64( -2 ) )
3169 for mnPort in mnPortsLog:
3170 if mnPort in onosPorts:
3171 # don't set results to true here as this is just one of
3172 # many checks and it might override a failure
3173 mnPorts.remove( mnPort )
3174 onosPorts.remove( mnPort )
3175
3176 # NOTE: OVS reports this as down since there is no link
3177 # So ignoring these for now
3178 # TODO: Come up with a better way of handling these
3179 if 65534 in mnPorts:
3180 mnPorts.remove( 65534 )
3181 if long( uint64( -2 ) ) in onosPorts:
3182 onosPorts.remove( long( uint64( -2 ) ) )
3183 if len( mnPorts ): # the ports of this switch don't match
3184 switchResult = main.FALSE
3185 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3186 if len( onosPorts ): # the ports of this switch don't match
3187 switchResult = main.FALSE
3188 main.log.warn(
3189 "Ports in ONOS but not MN: " +
3190 str( onosPorts ) )
3191 if switchResult == main.FALSE:
3192 main.log.error(
3193 "The list of ports for switch %s(%s) does not match:" %
3194 ( name, mnSwitch[ 'dpid' ] ) )
3195 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3196 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3197 portsResults = portsResults and switchResult
3198 finalResults = finalResults and portsResults
3199 return finalResults
3200 except pexpect.EOF:
3201 main.log.error( self.name + ": EOF exception found" )
3202 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003203 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003204 except Exception:
3205 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003206 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003207
Jon Hallafa8a472015-06-12 14:02:42 -07003208 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003209 """
3210 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003211 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003212
Jon Hallafa8a472015-06-12 14:02:42 -07003213 """
Jon Hall7eb38402015-01-08 17:19:54 -08003214 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003215 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003216 try:
3217 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003218
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003219 mnLinks = []
3220 for l in links:
3221 try:
3222 node1 = switches[ l[ 'node1' ] ]
3223 node2 = switches[ l[ 'node2' ] ]
3224 enabled = True
3225 for port in node1[ 'ports' ]:
3226 if port[ 'of_port' ] == l[ 'port1' ]:
3227 enabled = enabled and port[ 'enabled' ]
3228 for port in node2[ 'ports' ]:
3229 if port[ 'of_port' ] == l[ 'port2' ]:
3230 enabled = enabled and port[ 'enabled' ]
3231 if enabled:
3232 mnLinks.append( l )
3233 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003234 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003235 if 2 * len( mnLinks ) == len( onos ):
3236 linkResults = main.TRUE
3237 else:
3238 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003239 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003240 "Mininet has " + str( len( mnLinks ) ) +
3241 " bidirectional links and ONOS has " +
3242 str( len( onos ) ) + " unidirectional links" )
3243
3244 # iterate through MN links and check if an ONOS link exists in
3245 # both directions
3246 for link in mnLinks:
3247 # TODO: Find a more efficient search method
3248 node1 = None
3249 port1 = None
3250 node2 = None
3251 port2 = None
3252 firstDir = main.FALSE
3253 secondDir = main.FALSE
3254 for swName, switch in switches.iteritems():
3255 if swName == link[ 'node1' ]:
3256 node1 = switch[ 'dpid' ]
3257 for port in switch[ 'ports' ]:
3258 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3259 port1 = port[ 'of_port' ]
3260 if node1 is not None and node2 is not None:
3261 break
3262 if swName == link[ 'node2' ]:
3263 node2 = switch[ 'dpid' ]
3264 for port in switch[ 'ports' ]:
3265 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3266 port2 = port[ 'of_port' ]
3267 if node1 is not None and node2 is not None:
3268 break
3269
3270 for onosLink in onos:
3271 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3272 ":", '' ).replace( "of", '' )
3273 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3274 ":", '' ).replace( "of", '' )
3275 onosPort1 = onosLink[ 'src' ][ 'port' ]
3276 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3277
3278 # check onos link from node1 to node2
3279 if str( onosNode1 ) == str( node1 ) and str(
3280 onosNode2 ) == str( node2 ):
3281 if int( onosPort1 ) == int( port1 ) and int(
3282 onosPort2 ) == int( port2 ):
3283 firstDir = main.TRUE
3284 else:
3285 main.log.warn(
3286 'The port numbers do not match for ' +
3287 str( link ) +
3288 ' between ONOS and MN. When checking ONOS for ' +
3289 'link %s/%s -> %s/%s' %
3290 ( node1, port1, node2, port2 ) +
3291 ' ONOS has the values %s/%s -> %s/%s' %
3292 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
3293
3294 # check onos link from node2 to node1
3295 elif ( str( onosNode1 ) == str( node2 ) and
3296 str( onosNode2 ) == str( node1 ) ):
3297 if ( int( onosPort1 ) == int( port2 )
3298 and int( onosPort2 ) == int( port1 ) ):
3299 secondDir = main.TRUE
3300 else:
3301 main.log.warn(
3302 'The port numbers do not match for ' +
3303 str( link ) +
3304 ' between ONOS and MN. When checking ONOS for ' +
3305 'link %s/%s -> %s/%s' %
3306 ( node1, port1, node2, port2 ) +
3307 ' ONOS has the values %s/%s -> %s/%s' %
3308 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
3309 else: # this is not the link you're looking for
3310 pass
3311 if not firstDir:
3312 main.log.error(
3313 'ONOS does not have the link %s/%s -> %s/%s' %
3314 ( node1, port1, node2, port2 ) )
3315 if not secondDir:
3316 main.log.error(
3317 'ONOS does not have the link %s/%s -> %s/%s' %
3318 ( node2, port2, node1, port1 ) )
3319 linkResults = linkResults and firstDir and secondDir
3320 return linkResults
3321 except pexpect.EOF:
3322 main.log.error( self.name + ": EOF exception found" )
3323 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003324 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003325 except Exception:
3326 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003327 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003328
Jon Hallafa8a472015-06-12 14:02:42 -07003329 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003330 """
Jon Hallafa8a472015-06-12 14:02:42 -07003331 Compare mn and onos Hosts.
3332 Since Mininet hosts are quiet, ONOS will only know of them when they
3333 speak. For this reason, we will only check that the hosts in ONOS
3334 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003335
Jon Hallafa8a472015-06-12 14:02:42 -07003336 Arguments:
3337 hostsJson: parsed json object from the onos hosts api
3338 Returns:
3339 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003340 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003341 try:
3342 hostResults = main.TRUE
3343 for onosHost in hostsJson:
3344 onosMAC = onosHost[ 'mac' ].lower()
3345 match = False
3346 for mnHost, info in hosts.iteritems():
3347 for mnIntf in info[ 'interfaces' ]:
3348 if onosMAC == mnIntf[ 'mac' ].lower():
3349 match = True
3350 for ip in mnIntf[ 'ips' ]:
3351 if ip in onosHost[ 'ipAddresses' ]:
3352 pass # all is well
3353 else:
3354 # misssing ip
3355 main.log.error( "ONOS host " +
3356 onosHost[ 'id' ] +
3357 " has a different IP(" +
3358 str( onosHost[ 'ipAddresses' ] ) +
3359 ") than the Mininet host(" +
3360 str( ip ) +
3361 ")." )
3362 output = json.dumps(
3363 onosHost,
3364 sort_keys=True,
3365 indent=4,
3366 separators=( ',', ': ' ) )
3367 main.log.info( output )
3368 hostResults = main.FALSE
3369 if not match:
3370 hostResults = main.FALSE
3371 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3372 "corresponding Mininet host." )
3373 output = json.dumps( onosHost,
3374 sort_keys=True,
3375 indent=4,
3376 separators=( ',', ': ' ) )
3377 main.log.info( output )
3378 return hostResults
3379 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003380 main.log.error( self.name + ": EOF exception found" )
3381 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003382 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003383 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003384 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003385 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003386
You Wang53dba1e2018-02-02 17:45:44 -08003387 def verifyHostIp( self, hostList=[], prefix="" ):
3388 """
3389 Description:
3390 Verify that all hosts have IP address assigned to them
3391 Optional:
3392 hostList: If specified, verifications only happen to the hosts
3393 in hostList
3394 prefix: at least one of the ip address assigned to the host
3395 needs to have the specified prefix
3396 Returns:
3397 main.TRUE if all hosts have specific IP address assigned;
3398 main.FALSE otherwise
3399 """
3400 try:
You Wang79f5c5b2018-03-14 11:10:44 -07003401 hosts = self.getHosts( getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003402 if not hostList:
3403 hostList = hosts.keys()
3404 for hostName in hosts.keys():
3405 if hostName not in hostList:
3406 continue
3407 ipList = []
3408 self.handle.sendline( str( hostName ) + " ip a" )
3409 self.handle.expect( "mininet>" )
3410 ipa = self.handle.before
3411 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3412 ipList += re.findall( ipv4Pattern, ipa )
3413 # It's tricky to make regex for IPv6 addresses and this one is simplified
3414 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})/'
3415 ipList += re.findall( ipv6Pattern, ipa )
3416 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3417 if not ipList:
3418 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3419 else:
3420 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3421 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3422 else:
3423 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3424 hostList.remove( hostName )
3425 return main.FALSE if hostList else main.TRUE
3426 except KeyError:
3427 main.log.exception( self.name + ": host data not as expected: " + hosts )
3428 return None
3429 except pexpect.EOF:
3430 main.log.error( self.name + ": EOF exception found" )
3431 main.log.error( self.name + ": " + self.handle.before )
3432 main.cleanAndExit()
3433 except Exception:
3434 main.log.exception( self.name + ": Uncaught exception" )
3435 return None
3436
Jon Hallafa8a472015-06-12 14:02:42 -07003437 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003438 """
3439 Returns a list of all hosts
3440 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003441 try:
3442 self.handle.sendline( "" )
3443 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003444
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003445 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3446 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003447
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003448 handlePy = self.handle.before
3449 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3450 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003451
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003452 self.handle.sendline( "" )
3453 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003454
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003455 hostStr = handlePy.replace( "]", "" )
3456 hostStr = hostStr.replace( "'", "" )
3457 hostStr = hostStr.replace( "[", "" )
3458 hostStr = hostStr.replace( " ", "" )
3459 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003460
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003461 return hostList
3462 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003463 main.log.error( self.name + ": TIMEOUT exception found" )
3464 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003465 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003466 except pexpect.EOF:
3467 main.log.error( self.name + ": EOF exception found" )
3468 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003469 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003470 except Exception:
3471 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003472 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003473
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003474 def getSwitch( self ):
3475 """
3476 Returns a list of all switches
3477 Again, don't ask question just use it...
3478 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003479 try:
3480 # get host list...
3481 hostList = self.getHosts()
3482 # Make host set
3483 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003484
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003485 # Getting all the nodes in mininet
3486 self.handle.sendline( "" )
3487 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003488
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003489 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3490 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003491
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003492 handlePy = self.handle.before
3493 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3494 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003495
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003496 self.handle.sendline( "" )
3497 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003498
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003499 nodesStr = handlePy.replace( "]", "" )
3500 nodesStr = nodesStr.replace( "'", "" )
3501 nodesStr = nodesStr.replace( "[", "" )
3502 nodesStr = nodesStr.replace( " ", "" )
3503 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003504
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003505 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003506 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003507 nodesSet.discard( 'c0' )
3508 nodesSet.discard( 'c1' )
3509 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003510
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003511 switchSet = nodesSet - hostSet
3512 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003513
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003514 return switchList
3515 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003516 main.log.error( self.name + ": TIMEOUT exception found" )
3517 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003518 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003519 except pexpect.EOF:
3520 main.log.error( self.name + ": EOF exception found" )
3521 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003522 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003523 except Exception:
3524 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003525 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003526
You Wangdb8cd0a2016-05-26 15:19:45 -07003527 def getGraphDict( self, timeout=60, useId=True, includeHost=False ):
3528 """
3529 Return a dictionary which describes the latest Mininet topology data as a
3530 graph.
3531 An example of the dictionary:
3532 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3533 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3534 Each vertex should at least have an 'edges' attribute which describes the
3535 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003536 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003537 list of attributes.
3538 An example of the edges dictionary:
3539 'edges': { vertex2: { 'port': ..., 'weight': ... },
3540 vertex3: { 'port': ..., 'weight': ... } }
3541 If useId == True, dpid/mac will be used instead of names to identify
3542 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3543 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003544 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003545 in topology data.
3546 Note that link or switch that are brought down by 'link x x down' or 'switch
3547 x down' commands still show in the output of Mininet CLI commands such as
3548 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3549 recommended to use delLink() or delSwitch functions to simulate link/switch
3550 down, and addLink() or addSwitch to add them back.
3551 """
3552 graphDict = {}
3553 try:
3554 links = self.getLinks( timeout=timeout )
3555 portDict = {}
3556 if useId:
3557 switches = self.getSwitches()
3558 if includeHost:
3559 hosts = self.getHosts()
3560 for link in links:
3561 # FIXME: support 'includeHost' argument
3562 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3563 continue
3564 nodeName1 = link[ 'node1' ]
3565 nodeName2 = link[ 'node2' ]
3566 port1 = link[ 'port1' ]
3567 port2 = link[ 'port2' ]
3568 # Loop for two nodes
3569 for i in range( 2 ):
3570 # Get port index from OVS
3571 # The index extracted from port name may be inconsistent with ONOS
3572 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003573 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003574 portList = self.getOVSPorts( nodeName1 )
3575 if len( portList ) == 0:
3576 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3577 return None
3578 portDict[ nodeName1 ] = portList
3579 for port in portDict[ nodeName1 ]:
3580 if port[ 'port' ] == port1:
3581 portIndex = port[ 'index' ]
3582 break
3583 if portIndex == -1:
3584 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3585 return None
3586 if useId:
3587 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3588 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3589 else:
3590 node1 = nodeName1
3591 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003592 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003593 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003594 graphDict[ node1 ] = { 'edges': {},
3595 'dpid': switches[ nodeName1 ][ 'dpid' ],
3596 'name': nodeName1,
3597 'ports': switches[ nodeName1 ][ 'ports' ],
3598 'swClass': switches[ nodeName1 ][ 'swClass' ],
3599 'pid': switches[ nodeName1 ][ 'pid' ],
3600 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003601 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003602 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003603 else:
3604 # Assert node2 is not connected to any current links of node1
3605 assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003606 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
You Wangdb8cd0a2016-05-26 15:19:45 -07003607 # Swap two nodes/ports
3608 nodeName1, nodeName2 = nodeName2, nodeName1
3609 port1, port2 = port2, port1
3610 return graphDict
3611 except KeyError:
3612 main.log.exception( self.name + ": KeyError exception found" )
3613 return None
3614 except AssertionError:
3615 main.log.exception( self.name + ": AssertionError exception found" )
3616 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003617 except pexpect.EOF:
3618 main.log.error( self.name + ": EOF exception found" )
3619 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003620 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003621 except Exception:
3622 main.log.exception( self.name + ": Uncaught exception" )
3623 return None
3624
Devin Lima7cfdbd2017-09-29 15:02:22 -07003625 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003626 """
3627 updates the port address and status information for
3628 each port in mn"""
3629 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003630 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003631 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003632 self.handle.sendline( "" )
3633 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003634
Jon Hall7eb38402015-01-08 17:19:54 -08003635 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003636 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003637
Jon Hall7eb38402015-01-08 17:19:54 -08003638 self.handle.sendline( "" )
3639 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003640
Jon Hallb1290e82014-11-18 16:17:48 -05003641 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003642 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003643 main.log.error( self.name + ": TIMEOUT exception found" )
3644 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003645 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003646 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003647 main.log.error( self.name + ": EOF exception found" )
3648 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003649 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003650 except Exception:
3651 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003652 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003653
Jon Halld80cc142015-07-06 13:36:05 -07003654 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003655 """
3656 Add vlan tag to a host.
3657 Dependencies:
3658 This class depends on the "vlan" package
3659 $ sudo apt-get install vlan
3660 Configuration:
3661 Load the 8021q module into the kernel
3662 $sudo modprobe 8021q
3663
3664 To make this setup permanent:
3665 $ sudo su -c 'echo "8021q" >> /etc/modules'
3666 """
3667 if self.handle:
3668 try:
Jon Halld80cc142015-07-06 13:36:05 -07003669 # get the ip address of the host
3670 main.log.info( "Get the ip address of the host" )
3671 ipaddr = self.getIPAddress( host )
3672 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003673
Jon Halld80cc142015-07-06 13:36:05 -07003674 # remove IP from interface intf
3675 # Ex: h1 ifconfig h1-eth0 inet 0
3676 main.log.info( "Remove IP from interface " )
3677 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3678 self.handle.sendline( cmd2 )
3679 self.handle.expect( "mininet>" )
3680 response = self.handle.before
3681 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003682
Jon Halld80cc142015-07-06 13:36:05 -07003683 # create VLAN interface
3684 # Ex: h1 vconfig add h1-eth0 100
3685 main.log.info( "Create Vlan" )
3686 cmd3 = host + " vconfig add " + intf + " " + vlan
3687 self.handle.sendline( cmd3 )
3688 self.handle.expect( "mininet>" )
3689 response = self.handle.before
3690 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003691
Jon Halld80cc142015-07-06 13:36:05 -07003692 # assign the host's IP to the VLAN interface
3693 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3694 main.log.info( "Assign the host IP to the vlan interface" )
3695 vintf = intf + "." + vlan
3696 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3697 self.handle.sendline( cmd4 )
3698 self.handle.expect( "mininet>" )
3699 response = self.handle.before
3700 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003701
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003702 # update Mininet node variables
3703 main.log.info( "Update Mininet node variables" )
3704 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3705 self.handle.sendline( cmd5 )
3706 self.handle.expect( "mininet>" )
3707 response = self.handle.before
3708 main.log.info( "====> %s ", response )
3709
3710 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3711 self.handle.sendline( cmd6 )
3712 self.handle.expect( "mininet>" )
3713 response = self.handle.before
3714 main.log.info( "====> %s ", response )
3715
3716 return main.TRUE
3717 except pexpect.TIMEOUT:
3718 main.log.error( self.name + ": TIMEOUT exception found" )
3719 main.log.error( self.name + ": " + self.handle.before )
3720 main.cleanAndExit()
3721 except pexpect.EOF:
3722 main.log.error( self.name + ": EOF exception found" )
3723 main.log.error( self.name + ": " + self.handle.before )
3724 return main.FALSE
3725 except Exception:
3726 main.log.exception( self.name + ": Uncaught exception!" )
3727 return main.FALSE
3728
3729 def removeVLAN( self, host, intf ):
3730 """
3731 Remove vlan tag from a host.
3732 Dependencies:
3733 This class depends on the "vlan" package
3734 $ sudo apt-get install vlan
3735 Configuration:
3736 Load the 8021q module into the kernel
3737 $sudo modprobe 8021q
3738
3739 To make this setup permanent:
3740 $ sudo su -c 'echo "8021q" >> /etc/modules'
3741 """
3742 if self.handle:
3743 try:
3744 # get the ip address of the host
3745 main.log.info( "Get the ip address of the host" )
3746 ipaddr = self.getIPAddress( host )
3747
3748 # remove VLAN interface
3749 # Ex: h1 vconfig rem h1-eth0.100
3750 main.log.info( "Remove Vlan interface" )
3751 cmd2 = host + " vconfig rem " + intf
3752 self.handle.sendline( cmd2 )
3753 self.handle.expect( "mininet>" )
3754 response = self.handle.before
3755 main.log.info( "====> %s ", response )
3756
3757 # assign the host's IP to the original interface
3758 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3759 main.log.info( "Assign the host IP to the original interface" )
3760 original_intf = intf.split(".")[0]
3761 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3762 self.handle.sendline( cmd3 )
3763 self.handle.expect( "mininet>" )
3764 response = self.handle.before
3765 main.log.info( "====> %s ", response )
3766
3767 # update Mininet node variables
3768 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3769 self.handle.sendline( cmd4 )
3770 self.handle.expect( "mininet>" )
3771 response = self.handle.before
3772 main.log.info( "====> %s ", response )
3773
3774 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3775 self.handle.sendline( cmd5 )
3776 self.handle.expect( "mininet>" )
3777 response = self.handle.before
3778 main.log.info( "====> %s ", response )
3779
kaouthera3f13ca22015-05-05 15:01:41 -07003780 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003781 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003782 main.log.error( self.name + ": TIMEOUT exception found" )
3783 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003784 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003785 except pexpect.EOF:
3786 main.log.error( self.name + ": EOF exception found" )
3787 main.log.error( self.name + ": " + self.handle.before )
3788 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003789 except Exception:
3790 main.log.exception( self.name + ": Uncaught exception!" )
3791 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003792
Jon Hall892818c2015-10-20 17:58:34 -07003793 def createHostComponent( self, name ):
3794 """
3795 Creates a new mininet cli component with the same parameters as self.
3796 This new component is intended to be used to login to the hosts created
3797 by mininet.
3798
3799 Arguments:
3800 name - The string of the name of this component. The new component
3801 will be assigned to main.<name> .
3802 In addition, main.<name>.name = str( name )
3803 """
3804 try:
3805 # look to see if this component already exists
3806 getattr( main, name )
3807 except AttributeError:
3808 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003809 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3810 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003811 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003812 except pexpect.EOF:
3813 main.log.error( self.name + ": EOF exception found" )
3814 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003815 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003816 except Exception:
3817 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003818 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003819 else:
3820 # namespace is not clear!
3821 main.log.error( name + " component already exists!" )
3822 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003823 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003824
3825 def removeHostComponent( self, name ):
3826 """
3827 Remove host component
3828 Arguments:
3829 name - The string of the name of the component to delete.
3830 """
3831 try:
3832 # Get host component
3833 component = getattr( main, name )
3834 except AttributeError:
3835 main.log.error( "Component " + name + " does not exist." )
3836 return
3837 try:
3838 # Disconnect from component
3839 component.disconnect()
3840 # Delete component
3841 delattr( main, name )
3842 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003843 del( main.componentDictionary[ name ] )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003844 except pexpect.EOF:
3845 main.log.error( self.name + ": EOF exception found" )
3846 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003847 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003848 except Exception:
3849 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003850 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003851
3852 def startHostCli( self, host=None ):
3853 """
3854 Use the mininet m utility to connect to the host's cli
3855 """
3856 # These are fields that can be used by scapy packets. Initialized to None
3857 self.hostIp = None
3858 self.hostMac = None
3859 try:
3860 if not host:
3861 host = self.name
3862 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003863 self.handle.sendline( "cd" )
3864 self.handle.expect( self.hostPrompt )
3865 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003866 self.handle.expect( self.hostPrompt )
3867 return main.TRUE
3868 except pexpect.TIMEOUT:
3869 main.log.exception( self.name + ": Command timed out" )
3870 return main.FALSE
3871 except pexpect.EOF:
3872 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003873 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003874 except Exception:
3875 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003876 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003877
YPZhang801d46d2016-08-08 13:26:28 -07003878 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003879 '''
3880
YPZhang801d46d2016-08-08 13:26:28 -07003881 Args:
3882 devicename: switch name
3883 intf: port name on switch
3884 status: up or down
3885
3886 Returns: boolean to show success change status
3887
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003888 '''
YPZhang801d46d2016-08-08 13:26:28 -07003889 if status == "down" or status == "up":
3890 try:
3891 cmd = devicename + " ifconfig " + intf + " " + status
3892 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003893 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003894 return main.TRUE
3895 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003896 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003897 return main.FALSE
3898 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003899 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003900 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003901 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003902 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003903 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003904 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003905 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003906 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003907 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003908 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003909 return main.FALSE
3910
3911
adminbae64d82013-08-01 10:50:15 -07003912if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07003913 sys.modules[ __name__ ] = MininetCliDriver()