blob: 8e1108b7f0261b62e3f545b412ab53c7b04682fc [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
GlennRCd10d3cc2015-09-24 12:47:16 -0700480 pingResponse += "\n"
Jon Hall3c910162018-03-07 14:42:16 -0800481 if not isReachable:
482 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700483 main.log.info( pingResponse + "Failed pings: " + str( failedPings ) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700484 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700485 except pexpect.TIMEOUT:
486 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800487 response = self.handle.before
488 # NOTE: Send ctrl-c to make sure command is stopped
489 self.handle.sendline( "\x03" )
490 self.handle.expect( "Interrupt" )
491 response += self.handle.before + self.handle.after
492 self.handle.expect( "mininet>" )
493 response += self.handle.before + self.handle.after
494 main.log.debug( response )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700495 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400496 except pexpect.EOF:
497 main.log.error( self.name + ": EOF exception found" )
498 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700499 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700500 except Exception:
501 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700502 main.cleanAndExit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400503
You Wangf19d9f42018-02-23 16:34:19 -0800504 def pingIpv6Hosts( self, hostList, wait=1, acceptableFailed=0 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700505 """
You Wangf19d9f42018-02-23 16:34:19 -0800506 IPv6 ping all hosts in hostList.
507
508 acceptableFailed: max number of acceptable failed pings
Hari Krishna9592fc82015-07-31 15:11:15 -0700509
Jon Hall3b489db2015-10-05 14:38:37 -0700510 Returns main.TRUE if all hosts specified can reach each other
Jon Hall3b489db2015-10-05 14:38:37 -0700511 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700512 """
513 try:
514 main.log.info( "Testing reachability between specified IPv6 hosts" )
515 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700516 wait = int( wait )
517 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700518 pingResponse = "IPv6 Pingall output:\n"
You Wangf19d9f42018-02-23 16:34:19 -0800519 failedPingsTotal = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700520 for host in hostList:
521 listIndex = hostList.index( host )
522 # List of hosts to ping other than itself
523 pingList = hostList[ :listIndex ] + \
524 hostList[ ( listIndex + 1 ): ]
525
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700526 pingResponse += str( str( host ) + " -> " )
GlennRC2cf7d952015-09-11 16:32:13 -0700527
Hari Krishna9592fc82015-07-31 15:11:15 -0700528 for temp in pingList:
529 # Current host pings all other hosts specified
You Wangf19d9f42018-02-23 16:34:19 -0800530 failedPings = 0
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700531 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
You Wangf19d9f42018-02-23 16:34:19 -0800532 while failedPings <= acceptableFailed:
533 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
534 self.handle.sendline( pingCmd )
535 self.handle.expect( "mininet>", timeout=wait + 1 )
536 response = self.handle.before
537 if re.search( ',\s0\%\spacket\sloss', response ):
You Wangba231e72018-03-01 13:18:21 -0800538 pingResponse += " " + str( temp )
539 break
540 else:
541 failedPings += 1
542 time.sleep(1)
543 if failedPings > acceptableFailed:
544 # One of the host to host pair is unreachable
545 pingResponse += " X"
546 isReachable = main.FALSE
547 failedPingsTotal += 1
548 pingResponse += "\n"
Jon Hall3c910162018-03-07 14:42:16 -0800549 if not isReachable:
550 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
You Wangba231e72018-03-01 13:18:21 -0800551 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
552 return isReachable
553
554 except pexpect.TIMEOUT:
555 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800556 response = self.handle.before
557 # NOTE: Send ctrl-c to make sure command is stopped
558 self.handle.sendline( "\x03" )
559 self.handle.expect( "Interrupt" )
560 response += self.handle.before + self.handle.after
561 self.handle.expect( "mininet>" )
562 response += self.handle.before + self.handle.after
563 main.log.debug( response )
You Wangba231e72018-03-01 13:18:21 -0800564 return main.FALSE
565 except pexpect.EOF:
566 main.log.error( self.name + ": EOF exception found" )
567 main.log.error( self.name + ": " + self.handle.before )
568 main.cleanAndExit()
569 except Exception:
570 main.log.exception( self.name + ": Uncaught exception!" )
571 main.cleanAndExit()
572
573 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
574 """
575 Verify ping from each host in srcList to each host in dstList
576
577 acceptableFailed: max number of acceptable failed pings
578
579 Returns main.TRUE if all src hosts can reach all dst hosts
580 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
581 """
582 try:
583 main.log.info( "Verifying ping from each src host to each dst host" )
584 isReachable = main.TRUE
585 wait = int( wait )
586 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
587 pingResponse = "Ping output:\n"
588 failedPingsTotal = 0
589 for host in srcList:
590 pingResponse += str( str( host ) + " -> " )
591 for temp in dstList:
592 failedPings = 0
593 if ipv6:
594 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
595 else:
596 pingCmd = str( host ) + cmd + str( temp )
597 while failedPings <= acceptableFailed:
598 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
599 self.handle.sendline( pingCmd )
600 self.handle.expect( "mininet>", timeout=wait + 1 )
601 response = self.handle.before
602 if re.search( ',\s0\%\spacket\sloss', response ):
603 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800604 break
605 else:
606 failedPings += 1
607 time.sleep(1)
608 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700609 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800610 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700611 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800612 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700613 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800614 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700615 return isReachable
616
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700617 except pexpect.TIMEOUT:
618 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800619 response = self.handle.before
620 # NOTE: Send ctrl-c to make sure command is stopped
621 self.handle.sendline( "\x03" )
622 self.handle.expect( "Interrupt" )
623 response += self.handle.before + self.handle.after
624 self.handle.expect( "mininet>" )
625 response += self.handle.before + self.handle.after
626 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700627 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700628 except pexpect.EOF:
629 main.log.error( self.name + ": EOF exception found" )
630 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700631 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700632 except Exception:
633 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700634 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700635
Jon Hall7eb38402015-01-08 17:19:54 -0800636 def pingHost( self, **pingParams ):
637 """
Jon Hall3b489db2015-10-05 14:38:37 -0700638 Ping from one mininet host to another
639 Currently the only supported Params: SRC, TARGET, and WAIT
640 """
641 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700642 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700643 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800644 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700645 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700646 try:
Jon Hall61282e32015-03-19 11:34:11 -0700647 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800648 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700649 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
650 timeout=wait + 1 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700651 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800652 main.log.error(
653 self.name +
654 ": timeout when waiting for response from mininet" )
655 main.log.error( "response: " + str( self.handle.before ) )
656 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700657 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800658 main.log.error(
659 self.name +
660 ": timeout when waiting for response from mininet" )
661 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700662 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700663 if re.search( ',\s0\%\spacket\sloss', response ):
664 main.log.info( self.name + ": no packets lost, host is reachable" )
665 return main.TRUE
666 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800667 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700668 self.name +
669 ": PACKET LOST, HOST IS NOT REACHABLE" )
670 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800671 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800672 main.log.error( self.name + ": EOF exception found" )
673 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700674 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700675 except Exception:
676 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700677 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700678
679 def ping6pair( self, **pingParams ):
680 """
GlennRC2cf7d952015-09-11 16:32:13 -0700681 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700682 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000683 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700684 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
685 """
Jon Hall3b489db2015-10-05 14:38:37 -0700686 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700687 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700688 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530689 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700690 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700691 try:
692 main.log.info( "Sending: " + command )
693 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700694 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
695 timeout=wait + 1 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700696 if i == 1:
697 main.log.error(
698 self.name +
699 ": timeout when waiting for response from mininet" )
700 main.log.error( "response: " + str( self.handle.before ) )
701 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
702 if i == 1:
703 main.log.error(
704 self.name +
705 ": timeout when waiting for response from mininet" )
706 main.log.error( "response: " + str( self.handle.before ) )
707 response = self.handle.before
708 main.log.info( self.name + ": Ping Response: " + response )
709 if re.search( ',\s0\%\spacket\sloss', response ):
710 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700711 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700712 else:
alisone4121a92016-11-22 16:31:36 -0800713 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700714 self.name +
715 ": PACKET LOST, HOST IS NOT REACHABLE" )
716 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700717 except pexpect.EOF:
718 main.log.error( self.name + ": EOF exception found" )
719 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700720 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700721 except Exception:
722 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700723 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800724
You Wangdb927a52016-02-26 11:03:28 -0800725 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
726 """
727 Description:
728 Ping a set of destination host from host CLI.
729 Logging into a Mininet host CLI is required before calling this funtion.
730 Params:
731 dstIPList is a list of destination ip addresses
732 Returns:
733 main.TRUE if the destination host is reachable
734 main.FALSE otherwise
735 """
736 isReachable = main.TRUE
737 wait = int( wait )
738 cmd = "ping"
739 if IPv6:
740 cmd = cmd + "6"
741 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
742 try:
743 for dstIP in dstIPList:
744 pingCmd = cmd + " " + dstIP
745 self.handle.sendline( pingCmd )
746 i = self.handle.expect( [ self.hostPrompt,
747 '\*\*\* Unknown command: ' + pingCmd,
748 pexpect.TIMEOUT ],
749 timeout=wait + 1 )
750 if i == 0:
751 response = self.handle.before
752 if not re.search( ',\s0\%\spacket\sloss', response ):
753 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
754 isReachable = main.FALSE
755 elif i == 1:
756 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700757 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800758 elif i == 2:
759 main.log.error( self.name + ": timeout when waiting for response" )
760 isReachable = main.FALSE
761 else:
762 main.log.error( self.name + ": unknown response: " + self.handle.before )
763 isReachable = main.FALSE
764 except pexpect.TIMEOUT:
765 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800766 response = self.handle.before
767 # NOTE: Send ctrl-c to make sure command is stopped
768 self.handle.sendline( "\x03" )
769 self.handle.expect( "Interrupt" )
770 response += self.handle.before + self.handle.after
771 self.handle.expect( "mininet>" )
772 response += self.handle.before + self.handle.after
773 main.log.debug( response )
You Wangdb927a52016-02-26 11:03:28 -0800774 isReachable = main.FALSE
775 except pexpect.EOF:
776 main.log.error( self.name + ": EOF exception found" )
777 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700778 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800779 except Exception:
780 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700781 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800782 return isReachable
783
Jon Hall7eb38402015-01-08 17:19:54 -0800784 def checkIP( self, host ):
785 """
786 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700787 try:
788 if self.handle:
789 try:
790 response = self.execute(
791 cmd=host +
792 " ifconfig",
793 prompt="mininet>",
794 timeout=10 )
795 except pexpect.EOF:
796 main.log.error( self.name + ": EOF exception found" )
797 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700798 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700799
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700800 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
801 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
802 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
803 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
804 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
805 "[0-9]|25[0-5]|[0-9]{1,2})"
806 # pattern = "inet addr:10.0.0.6"
807 if re.search( pattern, response ):
808 main.log.info( self.name + ": Host Ip configured properly" )
809 return main.TRUE
810 else:
811 main.log.error( self.name + ": Host IP not found" )
812 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700813 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700814 main.log.error( self.name + ": Connection failed to the host" )
815 except Exception:
816 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700817 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800818
Jon Hall7eb38402015-01-08 17:19:54 -0800819 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800820 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700821 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800822 response = self.execute(
823 cmd="h1 /usr/sbin/sshd -D&",
824 prompt="mininet>",
825 timeout=10 )
826 response = self.execute(
827 cmd="h4 /usr/sbin/sshd -D&",
828 prompt="mininet>",
829 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700830 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800831 vars( self )[ key ] = connectargs[ key ]
832 response = self.execute(
833 cmd="xterm h1 h4 ",
834 prompt="mininet>",
835 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800836 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800837 main.log.error( self.name + ": EOF exception found" )
838 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700839 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700840 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800841 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700842 if self.flag == 0:
843 self.flag = 1
844 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800845 else:
adminbae64d82013-08-01 10:50:15 -0700846 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800847
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700848 def moveHost( self, host, oldSw, newSw ):
Jon Hall53c5e662016-04-13 16:06:56 -0700849 """
850 Moves a host from one switch to another on the fly
851 Note: The intf between host and oldSw when detached
852 using detach(), will still show up in the 'net'
853 cmd, because switch.detach() doesn't affect switch.intfs[]
854 ( which is correct behavior since the interfaces
855 haven't moved ).
856 """
857 if self.handle:
858 try:
859 # Bring link between oldSw-host down
860 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
861 "'," + "'down')"
862 print "cmd1= ", cmd
863 response = self.execute( cmd=cmd,
864 prompt="mininet>",
865 timeout=10 )
866
867 # Determine hostintf and Oldswitchintf
868 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
869 ")[0]"
870 print "cmd2= ", cmd
871 self.handle.sendline( cmd )
872 self.handle.expect( "mininet>" )
873
874 # Determine ip and mac address of the host-oldSw interface
875 cmd = "px ipaddr = hintf.IP()"
876 print "cmd3= ", cmd
877 self.handle.sendline( cmd )
878 self.handle.expect( "mininet>" )
879
880 cmd = "px macaddr = hintf.MAC()"
881 print "cmd3= ", cmd
882 self.handle.sendline( cmd )
883 self.handle.expect( "mininet>" )
884
885 # Detach interface between oldSw-host
886 cmd = "px " + oldSw + ".detach( sintf )"
887 print "cmd4= ", cmd
888 self.handle.sendline( cmd )
889 self.handle.expect( "mininet>" )
890
891 # Add link between host-newSw
892 cmd = "py net.addLink(" + host + "," + newSw + ")"
893 print "cmd5= ", cmd
894 self.handle.sendline( cmd )
895 self.handle.expect( "mininet>" )
896
897 # Determine hostintf and Newswitchintf
898 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
899 ")[0]"
900 print "cmd6= ", cmd
901 self.handle.sendline( cmd )
902 self.handle.expect( "mininet>" )
903
904 # Attach interface between newSw-host
905 cmd = "px " + newSw + ".attach( sintf )"
906 print "cmd3= ", cmd
907 self.handle.sendline( cmd )
908 self.handle.expect( "mininet>" )
909
910 # Set ipaddress of the host-newSw interface
911 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
912 print "cmd7 = ", cmd
913 self.handle.sendline( cmd )
914 self.handle.expect( "mininet>" )
915
916 # Set macaddress of the host-newSw interface
917 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
918 print "cmd8 = ", cmd
919 self.handle.sendline( cmd )
920 self.handle.expect( "mininet>" )
921
922 cmd = "net"
923 print "cmd9 = ", cmd
924 self.handle.sendline( cmd )
925 self.handle.expect( "mininet>" )
926 print "output = ", self.handle.before
927
928 # Determine ipaddress of the host-newSw interface
929 cmd = host + " ifconfig"
930 print "cmd10= ", cmd
931 self.handle.sendline( cmd )
932 self.handle.expect( "mininet>" )
933 print "ifconfig o/p = ", self.handle.before
934
935 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700936
937 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700938 main.log.error( self.name + ": TIMEOUT exception found" )
939 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700940 main.cleanAndExit()
Jon Hall53c5e662016-04-13 16:06:56 -0700941 except pexpect.EOF:
942 main.log.error( self.name + ": EOF exception found" )
943 main.log.error( self.name + ": " + self.handle.before )
944 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700945 except Exception:
946 main.log.exception( self.name + ": Uncaught exception!" )
947 return main.FALSE
Jon Hall53c5e662016-04-13 16:06:56 -0700948
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700949 def moveHostv6( self, host, oldSw, newSw ):
kelvin-onlaba1484582015-02-02 15:46:20 -0800950 """
951 Moves a host from one switch to another on the fly
952 Note: The intf between host and oldSw when detached
953 using detach(), will still show up in the 'net'
954 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700955 ( which is correct behavior since the interfaces
956 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800957 """
958 if self.handle:
959 try:
Jon Hall439c8912016-04-15 02:22:03 -0700960 IP = str( self.getIPAddress( host, proto='IPV6' ) ) + "/64"
kelvin-onlaba1484582015-02-02 15:46:20 -0800961 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700962 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800963 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800964 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800965 response = self.execute( cmd=cmd,
966 prompt="mininet>",
967 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700968
kelvin-onlaba1484582015-02-02 15:46:20 -0800969 # Determine hostintf and Oldswitchintf
970 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800971 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800972 print "cmd2= ", cmd
973 self.handle.sendline( cmd )
974 self.handle.expect( "mininet>" )
975
shahshreya73537862015-02-11 15:15:24 -0800976 # Determine ip and mac address of the host-oldSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700977 cmd = "px ipaddr = " + str( IP )
kelvin-onlaba1484582015-02-02 15:46:20 -0800978 print "cmd3= ", cmd
979 self.handle.sendline( cmd )
980 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800981
982 cmd = "px macaddr = hintf.MAC()"
983 print "cmd3= ", cmd
984 self.handle.sendline( cmd )
985 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700986
kelvin-onlaba1484582015-02-02 15:46:20 -0800987 # Detach interface between oldSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700988 cmd = "px " + oldSw + ".detach(sintf)"
kelvin-onlaba1484582015-02-02 15:46:20 -0800989 print "cmd4= ", cmd
990 self.handle.sendline( cmd )
991 self.handle.expect( "mininet>" )
992
993 # Add link between host-newSw
994 cmd = "py net.addLink(" + host + "," + newSw + ")"
995 print "cmd5= ", cmd
996 self.handle.sendline( cmd )
997 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700998
kelvin-onlaba1484582015-02-02 15:46:20 -0800999 # Determine hostintf and Newswitchintf
1000 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -08001001 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -08001002 print "cmd6= ", cmd
1003 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -07001004 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001005
1006 # Attach interface between newSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001007 cmd = "px " + newSw + ".attach(sintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001008 print "cmd6= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001009 self.handle.sendline( cmd )
1010 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -08001011
1012 # Set macaddress of the host-newSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001013 cmd = "px " + host + ".setMAC(mac = macaddr, intf = hintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001014 print "cmd7 = ", cmd
1015 self.handle.sendline( cmd )
1016 self.handle.expect( "mininet>" )
1017
1018 # Set ipaddress of the host-newSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001019 cmd = "px " + host + ".setIP(ip = ipaddr, intf = hintf)"
shahshreya73537862015-02-11 15:15:24 -08001020 print "cmd8 = ", cmd
1021 self.handle.sendline( cmd )
1022 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001023
Jon Hall439c8912016-04-15 02:22:03 -07001024 cmd = host + " ifconfig"
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001025 print "cmd9 =", cmd
1026 response = self.execute( cmd = cmd, prompt="mininet>", timeout=10 )
Jon Hall439c8912016-04-15 02:22:03 -07001027 print response
1028 pattern = "h\d-eth([\w])"
Jeremyd9e4eb12016-04-13 12:09:06 -07001029 ipAddressSearch = re.search( pattern, response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001030 print ipAddressSearch.group( 1 )
1031 intf = host + "-eth" + str( ipAddressSearch.group( 1 ) )
Jon Hall439c8912016-04-15 02:22:03 -07001032 cmd = host + " ip -6 addr add %s dev %s" % ( IP, intf )
1033 print "cmd10 = ", cmd
1034 self.handle.sendline( cmd )
1035 self.handle.expect( "mininet>" )
1036
kelvin-onlaba1484582015-02-02 15:46:20 -08001037 cmd = "net"
Jon Hall439c8912016-04-15 02:22:03 -07001038 print "cmd11 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001039 self.handle.sendline( cmd )
1040 self.handle.expect( "mininet>" )
1041 print "output = ", self.handle.before
1042
1043 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -08001044 cmd = host + " ifconfig"
Jon Hall439c8912016-04-15 02:22:03 -07001045 print "cmd12= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001046 self.handle.sendline( cmd )
1047 self.handle.expect( "mininet>" )
1048 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -07001049
kelvin-onlaba1484582015-02-02 15:46:20 -08001050 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001051 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001052 main.log.error( self.name + ": TIMEOUT exception found" )
1053 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001054 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08001055 except pexpect.EOF:
1056 main.log.error( self.name + ": EOF exception found" )
1057 main.log.error( self.name + ": " + self.handle.before )
1058 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001059 except Exception:
1060 main.log.exception( self.name + ": Uncaught exception!" )
1061 return main.FALSE
kelvin-onlaba1484582015-02-02 15:46:20 -08001062
Jon Hall7eb38402015-01-08 17:19:54 -08001063 def changeIP( self, host, intf, newIP, newNetmask ):
1064 """
1065 Changes the ip address of a host on the fly
1066 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001067 if self.handle:
1068 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001069 cmd = host + " ifconfig " + intf + " " + \
1070 newIP + " " + 'netmask' + " " + newNetmask
1071 self.handle.sendline( cmd )
1072 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001073 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001074 main.log.info( "response = " + response )
1075 main.log.info(
1076 "Ip of host " +
1077 host +
1078 " changed to new IP " +
1079 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -08001080 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001081 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001082 main.log.error( self.name + ": TIMEOUT exception found" )
1083 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001084 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001085 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001086 main.log.error( self.name + ": EOF exception found" )
1087 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001088 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001089 except Exception:
1090 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001091 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001092
Jon Hall7eb38402015-01-08 17:19:54 -08001093 def changeDefaultGateway( self, host, newGW ):
1094 """
1095 Changes the default gateway of a host
1096 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001097 if self.handle:
1098 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001099 cmd = host + " route add default gw " + newGW
1100 self.handle.sendline( cmd )
1101 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001102 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001103 main.log.info( "response = " + response )
1104 main.log.info(
1105 "Default gateway of host " +
1106 host +
1107 " changed to " +
1108 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -08001109 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001110 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001111 main.log.error( self.name + ": TIMEOUT exception found" )
1112 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001113 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001114 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001115 main.log.error( self.name + ": EOF exception found" )
1116 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001117 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001118 except Exception:
1119 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001120 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001121
Jon Hall7eb38402015-01-08 17:19:54 -08001122 def addStaticMACAddress( self, host, GW, macaddr ):
1123 """
Jon Hallefbd9792015-03-05 16:11:36 -08001124 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001125 if self.handle:
1126 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001127 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1128 cmd = host + " arp -s " + GW + " " + macaddr
1129 self.handle.sendline( cmd )
1130 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001131 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001132 main.log.info( "response = " + response )
1133 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001134 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001135 GW +
1136 " changed to " +
1137 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001138 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001139 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001140 main.log.error( self.name + ": TIMEOUT exception found" )
1141 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001142 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001143 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001144 main.log.error( self.name + ": EOF exception found" )
1145 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001146 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001147 except Exception:
1148 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001149 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001150
Jon Hall7eb38402015-01-08 17:19:54 -08001151 def verifyStaticGWandMAC( self, host ):
1152 """
1153 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001154 if self.handle:
1155 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001156 # h1 arp -an
1157 cmd = host + " arp -an "
1158 self.handle.sendline( cmd )
1159 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001160 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001161 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001162 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001163 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001164 main.log.error( self.name + ": TIMEOUT exception found" )
1165 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001166 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001167 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001168 main.log.error( self.name + ": EOF exception found" )
1169 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001170 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001171 except Exception:
1172 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001173 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001174
Jon Hall7eb38402015-01-08 17:19:54 -08001175 def getMacAddress( self, host ):
1176 """
1177 Verifies the host's ip configured or not."""
1178 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001179 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001180 response = self.execute(
1181 cmd=host +
1182 " ifconfig",
1183 prompt="mininet>",
1184 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001185 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001186 main.log.error( self.name + ": EOF exception found" )
1187 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001188 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001189 except Exception:
1190 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001191 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001192
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001193 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001194 macAddressSearch = re.search( pattern, response, re.I )
1195 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001196 main.log.info(
1197 self.name +
1198 ": Mac-Address of Host " +
1199 host +
1200 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001201 macAddress )
1202 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001203 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001204 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001205
Jon Hall7eb38402015-01-08 17:19:54 -08001206 def getInterfaceMACAddress( self, host, interface ):
1207 """
1208 Return the IP address of the interface on the given host"""
1209 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001210 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001211 response = self.execute( cmd=host + " ifconfig " + interface,
1212 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001213 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001214 main.log.error( self.name + ": EOF exception found" )
1215 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001216 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001217 except Exception:
1218 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001219 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001220
1221 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001222 macAddressSearch = re.search( pattern, response, re.I )
1223 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001224 main.log.info( "No mac address found in %s" % response )
1225 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001226 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001227 main.log.info(
1228 "Mac-Address of " +
1229 host +
1230 ":" +
1231 interface +
1232 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001233 macAddress )
1234 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001235 else:
1236 main.log.error( "Connection failed to the host" )
1237
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001238 def getIPAddress( self, host , proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001239 """
1240 Verifies the host's ip configured or not."""
1241 if self.handle:
1242 try:
1243 response = self.execute(
1244 cmd=host +
1245 " ifconfig",
1246 prompt="mininet>",
1247 timeout=10 )
1248 except pexpect.EOF:
1249 main.log.error( self.name + ": EOF exception found" )
1250 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001251 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001252 except Exception:
1253 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001254 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001255
sathishmad953462015-12-03 17:42:07 +05301256 pattern = ''
1257 if proto == 'IPV4':
1258 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
1259 else:
Jon Hall439c8912016-04-15 02:22:03 -07001260 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001261 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001262 if not ipAddressSearch:
1263 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001264 main.log.info(
1265 self.name +
1266 ": IP-Address of Host " +
1267 host +
1268 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001269 ipAddressSearch.group( 1 ) )
1270 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001271 else:
1272 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001273
Jon Hall7eb38402015-01-08 17:19:54 -08001274 def getSwitchDPID( self, switch ):
1275 """
1276 return the datapath ID of the switch"""
1277 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001278 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001279 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001280 response = self.execute(
1281 cmd=cmd,
1282 prompt="mininet>",
1283 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001284 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001285 main.log.error( self.name + ": EOF exception found" )
1286 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001287 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001288 except Exception:
1289 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001290 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001291 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001292 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001293 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001294 main.log.info(
1295 "Couldn't find DPID for switch %s, found: %s" %
1296 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001297 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001298 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001299 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001300 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001301
Jon Hall7eb38402015-01-08 17:19:54 -08001302 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001303 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001304 self.handle.sendline( "" )
1305 self.expect( "mininet>" )
1306 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001307 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001308 response = self.execute(
1309 cmd=cmd,
1310 prompt="mininet>",
1311 timeout=10 )
1312 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001313 response = self.handle.before
1314 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001315 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001316 main.log.error( self.name + ": TIMEOUT exception found" )
1317 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001318 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001319 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001320 main.log.error( self.name + ": EOF exception found" )
1321 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001322 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001323 except Exception:
1324 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001325 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001326
Jon Hall7eb38402015-01-08 17:19:54 -08001327 def getInterfaces( self, node ):
1328 """
1329 return information dict about interfaces connected to the node"""
1330 if self.handle:
1331 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001332 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001333 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001334 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001335 response = self.execute(
1336 cmd=cmd,
1337 prompt="mininet>",
1338 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001339 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001340 main.log.error( self.name + ": EOF exception found" )
1341 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001342 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001343 except Exception:
1344 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001345 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001346 return response
1347 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001348 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001349
Jon Hall7eb38402015-01-08 17:19:54 -08001350 def dump( self ):
1351 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001352 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001353 response = self.execute(
1354 cmd='dump',
1355 prompt='mininet>',
1356 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001357 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001358 main.log.error( self.name + ": EOF exception found" )
1359 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001360 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001361 except Exception:
1362 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001363 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001364 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001365
Jon Hall7eb38402015-01-08 17:19:54 -08001366 def intfs( self ):
1367 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001368 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001369 response = self.execute(
1370 cmd='intfs',
1371 prompt='mininet>',
1372 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001373 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001374 main.log.error( self.name + ": EOF exception found" )
1375 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001376 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001377 except Exception:
1378 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001379 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001380 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001381
Jon Hall7eb38402015-01-08 17:19:54 -08001382 def net( self ):
1383 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001384 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001385 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001386 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001387 main.log.error( self.name + ": EOF exception found" )
1388 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001389 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001390 except Exception:
1391 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001392 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001393 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001394
Devin Lima7cfdbd2017-09-29 15:02:22 -07001395 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001396 main.log.info( self.name + ": List network links" )
1397 try:
1398 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001399 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001400 except pexpect.EOF:
1401 main.log.error( self.name + ": EOF exception found" )
1402 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001403 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001404 except Exception:
1405 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001406 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001407 return response
1408
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001409 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001410 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001411 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001412
kelvin-onlab7cce9382015-07-17 10:21:03 -07001413 @parm:
1414 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1415 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001416 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001417 try:
1418 for host1 in hosts:
1419 for host2 in hosts:
1420 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001421 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1422 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001423 except Exception:
1424 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001425 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001426
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001427 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001428 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001429 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1430 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001431
kelvin-onlab7cce9382015-07-17 10:21:03 -07001432 @parm:
1433 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1434 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001435 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001436 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1437 try:
1438 # Setup the mininet command
1439 cmd1 = 'iperf ' + host1 + " " + host2
1440 self.handle.sendline( cmd1 )
1441 outcome = self.handle.expect( "mininet>", timeout )
1442 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001443
kelvin-onlab7cce9382015-07-17 10:21:03 -07001444 # checks if there are results in the mininet response
1445 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001446 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001447 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001448 response = response.split( "\r\n" )
1449 response = response[ len( response )-2 ]
1450 response = response.split( ": " )
1451 response = response[ len( response )-1 ]
1452 response = response.replace( "[", "" )
1453 response = response.replace( "]", "" )
1454 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001455
kelvin-onlab7cce9382015-07-17 10:21:03 -07001456 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001457 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001458
kelvin-onlab7cce9382015-07-17 10:21:03 -07001459 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001460 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001461 if len( bandwidth ) == 2:
1462 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001463 return main.TRUE
1464 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001465 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001466 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001467 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001468 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001469 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001470 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001471 main.log.error( self.name + ": TIMEOUT exception found" )
1472 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001473 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001474 # NOTE: Send ctrl-c to make sure iperf is done
1475 self.handle.sendline( "\x03" )
1476 self.handle.expect( "Interrupt" )
1477 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001478 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001479 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001480 main.log.error( self.name + ": EOF exception found" )
1481 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001482 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001483 except Exception:
1484 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001485 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001486
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001487 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001488 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1489 try:
1490 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001491 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001492 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001493 outcome1 = self.handle.expect( "mininet>" )
1494 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001495 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001496 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001497 response1 = self.handle.before
1498 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001499 print response1, response2
1500 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001501 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001502 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001503 return main.TRUE
1504 else:
1505 main.log.error( self.name + ": iperf test failed" )
1506 return main.FALSE
1507 except pexpect.TIMEOUT:
1508 main.log.error( self.name + ": TIMEOUT exception found" )
1509 main.log.error( self.name + " response: " + repr( self.handle.before ) )
1510 self.handle.sendline( "\x03" )
1511 self.handle.expect( "Interrupt" )
1512 self.handle.expect( "mininet>" )
1513 return main.FALSE
1514 except pexpect.EOF:
1515 main.log.error( self.name + ": EOF exception found" )
1516 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001517 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001518 except Exception:
1519 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001520 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001521
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001522 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001523 '''
GlennRC61321f22015-07-16 13:36:54 -07001524 Runs the iperfudp function with a given set of hosts and specified
1525 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001526
GlennRC61321f22015-07-16 13:36:54 -07001527 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001528 bandwidth: the targeted bandwidth, in megabits ('M')
1529 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001530 try:
1531 for host1 in hosts:
1532 for host2 in hosts:
1533 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001534 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1535 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001536 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001537 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001538 return main.FALSE
1539 except Exception:
1540 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001541 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001542
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001543 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001544 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001545 Creates an iperf UDP test with a specific bandwidth.
1546 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001547
kelvin-onlab7cce9382015-07-17 10:21:03 -07001548 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001549 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1550 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001551 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001552 try:
1553 # setup the mininet command
1554 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001555 self.handle.sendline( cmd )
1556 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001557 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001558
kelvin-onlab7cce9382015-07-17 10:21:03 -07001559 # check if there are in results in the mininet response
1560 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001561 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001562 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001563 response = response.split( "\r\n" )
1564 response = response[ len( response )-2 ]
1565 response = response.split( ": " )
1566 response = response[ len( response )-1 ]
1567 response = response.replace( "[", "" )
1568 response = response.replace( "]", "" )
1569 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001570
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001571 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001572
kelvin-onlab7cce9382015-07-17 10:21:03 -07001573 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001574 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001575 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001576 # if one entry is blank then something is wrong
1577 for item in mnBandwidth:
1578 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001579 main.log.error( self.name + ": Could not parse iperf output" )
1580 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001581 return main.FALSE
1582 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001583 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001584 return main.TRUE
1585 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001586 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001587 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001588
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001589 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001590 main.log.error( self.name + ": TIMEOUT exception found" )
1591 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001592 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001593 except pexpect.EOF:
1594 main.log.error( self.name + ": EOF exception found" )
1595 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001596 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001597 except Exception:
1598 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001599 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001600
Jon Hall7eb38402015-01-08 17:19:54 -08001601 def nodes( self ):
1602 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001603 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001604 response = self.execute(
1605 cmd='nodes',
1606 prompt='mininet>',
1607 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001608 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001609 main.log.error( self.name + ": EOF exception found" )
1610 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001611 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001612 except Exception:
1613 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001614 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001615 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001616
Jon Hall7eb38402015-01-08 17:19:54 -08001617 def pingpair( self ):
1618 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001619 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001620 response = self.execute(
1621 cmd='pingpair',
1622 prompt='mininet>',
1623 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001624 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001625 main.log.error( self.name + ": EOF exception found" )
1626 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001627 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001628 except Exception:
1629 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001630 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001631
Jon Hall7eb38402015-01-08 17:19:54 -08001632 if re.search( ',\s0\%\spacket\sloss', response ):
1633 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001634 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001635 else:
alisone4121a92016-11-22 16:31:36 -08001636 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001637 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001638
Jon Hall7eb38402015-01-08 17:19:54 -08001639 def link( self, **linkargs ):
1640 """
GlennRCed771242016-01-13 17:02:47 -08001641 Bring link( s ) between two nodes up or down
1642 """
Jon Hall6094a362014-04-11 14:46:56 -07001643 try:
GlennRCed771242016-01-13 17:02:47 -08001644 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1645 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1646 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1647 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1648
1649 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1650 cmd = "link {} {} {}".format( end1, end2, option )
1651 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001652 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001653 response = self.handle.before
1654 main.log.info( response )
1655
1656 return main.TRUE
1657 except pexpect.TIMEOUT:
1658 main.log.exception( self.name + ": Command timed out" )
1659 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001660 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001661 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001662 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001663 except Exception:
1664 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001665 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001666
pingping-lin8244a3b2015-09-16 13:36:56 -07001667 def switch( self, **switchargs ):
1668 """
1669 start/stop a switch
1670 """
1671 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1672 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1673 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1674 command = "switch " + str( sw ) + " " + str( option )
1675 main.log.info( command )
1676 try:
1677 self.handle.sendline( command )
1678 self.handle.expect( "mininet>" )
1679 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001680 main.log.error( self.name + ": TIMEOUT exception found" )
1681 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001682 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001683 except pexpect.EOF:
1684 main.log.error( self.name + ": EOF exception found" )
1685 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001686 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001687 return main.TRUE
1688
pingping-lin5bb663b2015-09-24 11:47:50 -07001689 def node( self, nodeName, commandStr ):
1690 """
1691 Carry out a command line on a given node
1692 @parm:
1693 nodeName: the node name in Mininet testbed
1694 commandStr: the command line will be carried out on the node
1695 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1696 """
1697 command = str( nodeName ) + " " + str( commandStr )
1698 main.log.info( command )
1699
1700 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001701 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001702 if re.search( "Unknown command", response ):
1703 main.log.warn( response )
1704 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001705 if re.search( "Permission denied", response ):
1706 main.log.warn( response )
1707 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001708 except pexpect.EOF:
1709 main.log.error( self.name + ": EOF exception found" )
1710 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001711 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001712 main.log.info( " response is :" )
1713 main.log.info( response )
1714 return response
1715
Jon Hall7eb38402015-01-08 17:19:54 -08001716 def yank( self, **yankargs ):
1717 """
1718 yank a mininet switch interface to a host"""
1719 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001720 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001721 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1722 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001723 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001724 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001725 response = self.execute(
1726 cmd=command,
1727 prompt="mininet>",
1728 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001729 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001730 main.log.error( self.name + ": EOF exception found" )
1731 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001732 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001733 except Exception:
1734 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001735 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001736 return main.TRUE
1737
Jon Hall7eb38402015-01-08 17:19:54 -08001738 def plug( self, **plugargs ):
1739 """
1740 plug the yanked mininet switch interface to a switch"""
1741 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001742 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001743 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1744 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001745 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001746 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001747 response = self.execute(
1748 cmd=command,
1749 prompt="mininet>",
1750 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001751 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001752 main.log.error( self.name + ": EOF exception found" )
1753 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001754 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001755 except Exception:
1756 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001757 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001758 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001759
Jon Hall7eb38402015-01-08 17:19:54 -08001760 def dpctl( self, **dpctlargs ):
1761 """
1762 Run dpctl command on all switches."""
1763 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001764 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001765 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1766 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1767 command = "dpctl " + cmd + " " + str( cmdargs )
1768 try:
1769 response = self.execute(
1770 cmd=command,
1771 prompt="mininet>",
1772 timeout=10 )
1773 except pexpect.EOF:
1774 main.log.error( self.name + ": EOF exception found" )
1775 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001776 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001777 except Exception:
1778 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001779 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001780 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001781
kelvin-onlabd3b64892015-01-20 13:26:24 -08001782 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001783 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001784 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001785 try:
1786 fileInput = path + '/lib/Mininet/INSTALL'
1787 version = super( Mininet, self ).getVersion()
1788 pattern = 'Mininet\s\w\.\w\.\w\w*'
1789 for line in open( fileInput, 'r' ).readlines():
1790 result = re.match( pattern, line )
1791 if result:
1792 version = result.group( 0 )
1793 return version
1794 except Exception:
1795 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001796 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001797
kelvin-onlabd3b64892015-01-20 13:26:24 -08001798 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001799 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001800 Parameters:
1801 sw: The name of an OVS switch. Example "s1"
1802 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001803 The output of the command from the mininet cli
1804 or main.FALSE on timeout"""
1805 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001806 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001807 response = self.execute(
1808 cmd=command,
1809 prompt="mininet>",
1810 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001811 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001812 return response
admin2a9548d2014-06-17 14:08:07 -07001813 else:
1814 return main.FALSE
1815 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001816 main.log.error( self.name + ": EOF exception found" )
1817 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001818 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001819 except Exception:
1820 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001821 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001822
Charles Chan029be652015-08-24 01:46:10 +08001823 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001824 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001825 Description:
1826 Assign switches to the controllers ( for ovs use only )
1827 Required:
1828 sw - Name of the switch. This can be a list or a string.
1829 ip - Ip addresses of controllers. This can be a list or a string.
1830 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001831 port - ONOS use port 6653, if no list of ports is passed, then
1832 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001833 ptcp - ptcp number, This can be a string or a list that has
1834 the same length as switch. This is optional and not required
1835 when using ovs switches.
1836 NOTE: If switches and ptcp are given in a list type they should have the
1837 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1838 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001839
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001840 Return:
1841 Returns main.TRUE if mininet correctly assigned switches to
1842 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001843 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001844 """
1845 assignResult = main.TRUE
1846 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001847 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001848 command = "sh ovs-vsctl set-controller "
1849 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001850 try:
1851 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001852 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001853 if isinstance( port, types.StringType ) or \
1854 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001855 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001856 elif isinstance( port, types.ListType ):
1857 main.log.error( self.name + ": Only one controller " +
1858 "assigned and a list of ports has" +
1859 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001860 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001861 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001862 main.log.error( self.name + ": Invalid controller port " +
1863 "number. Please specify correct " +
1864 "controller port" )
1865 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001866
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001867 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001868 if isinstance( port, types.StringType ) or \
1869 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001870 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001871 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1872 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001873 elif isinstance( port, types.ListType ):
1874 if ( len( ip ) != len( port ) ):
1875 main.log.error( self.name + ": Port list = " +
1876 str( len( port ) ) +
1877 "should be the same as controller" +
1878 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001879 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001880 else:
1881 onosIp = ""
1882 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001883 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1884 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001885 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001886 main.log.error( self.name + ": Invalid controller port " +
1887 "number. Please specify correct " +
1888 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001889 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001890 else:
1891 main.log.error( self.name + ": Invalid ip address" )
1892 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001893
1894 if isinstance( sw, types.StringType ):
1895 command += sw + " "
1896 if ptcp:
1897 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001898 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001899 elif isinstance( ptcp, types.ListType ):
1900 main.log.error( self.name + ": Only one switch is " +
1901 "being set and multiple PTCP is " +
1902 "being passed " )
1903 else:
1904 main.log.error( self.name + ": Invalid PTCP" )
1905 ptcp = ""
1906 command += onosIp
1907 commandList.append( command )
1908
1909 elif isinstance( sw, types.ListType ):
1910 if ptcp:
1911 if isinstance( ptcp, types.ListType ):
1912 if len( ptcp ) != len( sw ):
1913 main.log.error( self.name + ": PTCP length = " +
1914 str( len( ptcp ) ) +
1915 " is not the same as switch" +
1916 " length = " +
1917 str( len( sw ) ) )
1918 return main.FALSE
1919 else:
1920 for switch, ptcpNum in zip( sw, ptcp ):
1921 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001922 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001923 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001924 tempCmd += onosIp
1925 commandList.append( tempCmd )
1926 else:
1927 main.log.error( self.name + ": Invalid PTCP" )
1928 return main.FALSE
1929 else:
1930 for switch in sw:
1931 tempCmd = "sh ovs-vsctl set-controller "
1932 tempCmd += switch + " " + onosIp
1933 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001934 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001935 main.log.error( self.name + ": Invalid switch type " )
1936 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001937
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001938 for cmd in commandList:
1939 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001940 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001941 except pexpect.TIMEOUT:
1942 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1943 return main.FALSE
1944 except pexpect.EOF:
1945 main.log.error( self.name + ": EOF exception found" )
1946 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001947 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001948 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001949 except pexpect.EOF:
1950 main.log.error( self.name + ": EOF exception found" )
1951 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001952 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001953 except Exception:
1954 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001955 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001956
kelvin-onlabd3b64892015-01-20 13:26:24 -08001957 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001958 """
1959 Removes the controller target from sw"""
1960 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001961 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001962 response = self.execute(
1963 cmd=command,
1964 prompt="mininet>",
1965 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001966 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001967 main.log.error( self.name + ": EOF exception found" )
1968 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001969 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001970 except Exception:
1971 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001972 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001973 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001974 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001975
kelvin-onlabd3b64892015-01-20 13:26:24 -08001976 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001977 """
Jon Hallb1290e82014-11-18 16:17:48 -05001978 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001979 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001980 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001981 NOTE: cannot currently specify what type of switch
1982 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001983 sw = name of the new switch as a string
1984 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001985 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001986 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001987 """
1988 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001989 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001990 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001991 response = self.execute(
1992 cmd=command,
1993 prompt="mininet>",
1994 timeout=10 )
1995 if re.search( "already exists!", response ):
1996 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001997 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001998 elif re.search( "Error", response ):
1999 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002000 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002001 elif re.search( "usage:", response ):
2002 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002003 return main.FALSE
2004 else:
2005 return main.TRUE
2006 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002007 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07002008 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002009 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002010 except Exception:
2011 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002012 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002013
kelvin-onlabd3b64892015-01-20 13:26:24 -08002014 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08002015 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08002016 delete a switch from the mininet topology
2017 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002018 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08002019 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08002020 sw = name of the switch as a string
2021 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002022 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05002023 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002024 response = self.execute(
2025 cmd=command,
2026 prompt="mininet>",
2027 timeout=10 )
2028 if re.search( "no switch named", response ):
2029 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002030 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002031 elif re.search( "Error", response ):
2032 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002033 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002034 elif re.search( "usage:", response ):
2035 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002036 return main.FALSE
2037 else:
2038 return main.TRUE
2039 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002040 main.log.error( self.name + ": EOF exception found" )
2041 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002042 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002043 except Exception:
2044 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002045 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002046
You Wangdb8cd0a2016-05-26 15:19:45 -07002047 def getSwitchRandom( self, timeout=60, nonCut=True ):
2048 """
2049 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002050 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002051 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002052 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002053 it just randomly returns one switch from all current switches in
2054 Mininet.
2055 Returns the name of the chosen switch.
2056 """
2057 import random
2058 candidateSwitches = []
2059 try:
2060 if not nonCut:
2061 switches = self.getSwitches( timeout=timeout )
2062 assert len( switches ) != 0
2063 for switchName in switches.keys():
2064 candidateSwitches.append( switchName )
2065 else:
2066 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002067 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002068 return None
2069 self.graph.update( graphDict )
2070 candidateSwitches = self.graph.getNonCutVertices()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002071 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002072 return None
2073 elif len( candidateSwitches ) == 0:
2074 main.log.info( self.name + ": No candidate switch for deletion" )
2075 return None
2076 else:
2077 switch = random.sample( candidateSwitches, 1 )
2078 return switch[ 0 ]
2079 except KeyError:
2080 main.log.exception( self.name + ": KeyError exception found" )
2081 return None
2082 except AssertionError:
2083 main.log.exception( self.name + ": AssertionError exception found" )
2084 return None
2085 except Exception:
2086 main.log.exception( self.name + ": Uncaught exception" )
2087 return None
2088
2089 def delSwitchRandom( self, timeout=60, nonCut=True ):
2090 """
2091 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002092 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002093 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002094 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002095 otherwise it just randomly delete one switch from all current
2096 switches in Mininet.
2097 Returns the name of the deleted switch
2098 """
2099 try:
2100 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002101 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002102 return None
2103 else:
2104 deletionResult = self.delSwitch( switch )
2105 if deletionResult:
2106 return switch
2107 else:
2108 return None
2109 except Exception:
2110 main.log.exception( self.name + ": Uncaught exception" )
2111 return None
2112
kelvin-onlabd3b64892015-01-20 13:26:24 -08002113 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002114 """
2115 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002116 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002117 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002118 NOTE: cannot currently specify what type of link
2119 required params:
2120 node1 = the string node name of the first endpoint of the link
2121 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002122 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002123 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002124 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002125 response = self.execute(
2126 cmd=command,
2127 prompt="mininet>",
2128 timeout=10 )
2129 if re.search( "doesnt exist!", response ):
2130 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002131 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002132 elif re.search( "Error", response ):
2133 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002134 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002135 elif re.search( "usage:", response ):
2136 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002137 return main.FALSE
2138 else:
2139 return main.TRUE
2140 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002141 main.log.error( self.name + ": EOF exception found" )
2142 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002143 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002144 except Exception:
2145 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002146 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002147
kelvin-onlabd3b64892015-01-20 13:26:24 -08002148 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002149 """
2150 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002151 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002152 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002153 required params:
2154 node1 = the string node name of the first endpoint of the link
2155 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002156 returns: main.FALSE on an error, else main.TRUE
2157 """
Jon Hallffb386d2014-11-21 13:43:38 -08002158 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002159 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002160 response = self.execute(
2161 cmd=command,
2162 prompt="mininet>",
2163 timeout=10 )
2164 if re.search( "no node named", response ):
2165 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002166 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002167 elif re.search( "Error", response ):
2168 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002169 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002170 elif re.search( "usage:", response ):
2171 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002172 return main.FALSE
2173 else:
2174 return main.TRUE
2175 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002176 main.log.error( self.name + ": EOF exception found" )
2177 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002178 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002179 except Exception:
2180 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002181 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002182
You Wangdb8cd0a2016-05-26 15:19:45 -07002183 def getLinkRandom( self, timeout=60, nonCut=True ):
2184 """
2185 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002186 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002187 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002188 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002189 it just randomly returns one link from all current links in
2190 Mininet.
2191 Returns the link as a list, e.g. [ 's1', 's2' ]
2192 """
2193 import random
2194 candidateLinks = []
2195 try:
2196 if not nonCut:
2197 links = self.getLinks( timeout=timeout )
2198 assert len( links ) != 0
2199 for link in links:
2200 # Exclude host-switch link
2201 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2202 continue
2203 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2204 else:
2205 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002206 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002207 return None
2208 self.graph.update( graphDict )
2209 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002210 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002211 return None
2212 elif len( candidateLinks ) == 0:
2213 main.log.info( self.name + ": No candidate link for deletion" )
2214 return None
2215 else:
2216 link = random.sample( candidateLinks, 1 )
2217 return link[ 0 ]
2218 except KeyError:
2219 main.log.exception( self.name + ": KeyError exception found" )
2220 return None
2221 except AssertionError:
2222 main.log.exception( self.name + ": AssertionError exception found" )
2223 return None
2224 except Exception:
2225 main.log.exception( self.name + ": Uncaught exception" )
2226 return None
2227
2228 def delLinkRandom( self, timeout=60, nonCut=True ):
2229 """
2230 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002231 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002232 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002233 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002234 otherwise it just randomly delete one link from all current links
2235 in Mininet.
2236 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2237 """
2238 try:
2239 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002240 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002241 return None
2242 else:
2243 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2244 if deletionResult:
2245 return link
2246 else:
2247 return None
2248 except Exception:
2249 main.log.exception( self.name + ": Uncaught exception" )
2250 return None
2251
kelvin-onlabd3b64892015-01-20 13:26:24 -08002252 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002253 """
Jon Hallb1290e82014-11-18 16:17:48 -05002254 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002255 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002256 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002257 NOTE: cannot currently specify what type of host
2258 required params:
2259 hostname = the string hostname
2260 optional key-value params
2261 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002262 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002263 """
2264 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002265 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002266 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002267 response = self.execute(
2268 cmd=command,
2269 prompt="mininet>",
2270 timeout=10 )
2271 if re.search( "already exists!", response ):
2272 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002273 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002274 elif re.search( "doesnt exists!", response ):
2275 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002276 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002277 elif re.search( "Error", response ):
2278 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002279 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002280 elif re.search( "usage:", response ):
2281 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002282 return main.FALSE
2283 else:
2284 return main.TRUE
2285 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002286 main.log.error( self.name + ": EOF exception found" )
2287 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002288 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002289 except Exception:
2290 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002291 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002292
kelvin-onlabd3b64892015-01-20 13:26:24 -08002293 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002294 """
2295 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002296 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002297 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002298 NOTE: this uses a custom mn function
2299 required params:
2300 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002301 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002302 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002303 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002304 response = self.execute(
2305 cmd=command,
2306 prompt="mininet>",
2307 timeout=10 )
2308 if re.search( "no host named", response ):
2309 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002310 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002311 elif re.search( "Error", response ):
2312 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002313 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002314 elif re.search( "usage:", response ):
2315 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002316 return main.FALSE
2317 else:
2318 return main.TRUE
2319 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002320 main.log.error( self.name + ": EOF exception found" )
2321 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002322 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002323 except Exception:
2324 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002325 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002326
Jon Hall7eb38402015-01-08 17:19:54 -08002327 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002328 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002329 Called at the end of the test to stop the mininet and
2330 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002331 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002332 try:
2333 self.handle.sendline( '' )
2334 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
2335 timeout=2 )
2336 response = main.TRUE
2337 if i == 0:
2338 response = self.stopNet()
2339 elif i == 1:
2340 return main.TRUE
2341 # print "Disconnecting Mininet"
2342 if self.handle:
2343 self.handle.sendline( "exit" )
2344 self.handle.expect( "exit" )
2345 self.handle.expect( "(.*)" )
2346 else:
2347 main.log.error( "Connection failed to the host" )
2348 return response
2349 except pexpect.EOF:
2350 main.log.error( self.name + ": EOF exception found" )
2351 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002352 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002353 except Exception:
2354 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002355 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002356
Devin Lima7cfdbd2017-09-29 15:02:22 -07002357 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002358 """
Jon Hall21270ac2015-02-16 17:59:55 -08002359 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002360 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002361 main.FALSE if the pexpect handle does not exist.
2362
Jon Halld61331b2015-02-17 16:35:47 -08002363 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002364 """
Jon Halld61331b2015-02-17 16:35:47 -08002365 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002366 response = ''
2367 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002368 try:
Jon Halld80cc142015-07-06 13:36:05 -07002369 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002370 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002371 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002372 pexpect.EOF,
2373 pexpect.TIMEOUT ],
2374 timeout )
2375 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002376 main.log.info( "Exiting mininet.." )
2377 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002378 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002379 prompt=self.prompt,
2380 timeout=exitTimeout )
2381 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002382 self.handle.sendline( "sudo mn -c" )
2383 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002384
Jeremyd9e4eb12016-04-13 12:09:06 -07002385 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002386 main.log.info( " Mininet trying to exit while not " +
2387 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002388 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002389 elif i == 2:
2390 main.log.error( "Something went wrong exiting mininet" )
2391 elif i == 3: # timeout
2392 main.log.error( "Something went wrong exiting mininet " +
2393 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002394
Hari Krishnab35c6d02015-03-18 11:13:51 -07002395 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002396 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002397 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002398 self.handle.sendline(
2399 "sudo kill -9 \`ps -ef | grep \"" +
2400 fileName +
2401 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002402 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002403 main.log.error( self.name + ": TIMEOUT exception found" )
2404 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002405 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002406 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002407 main.log.error( self.name + ": EOF exception found" )
2408 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002409 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002410 except Exception:
2411 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002412 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002413 else:
2414 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002415 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002416 return response
2417
YPZhang26a139e2016-04-25 14:01:55 -07002418 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002419 """
2420 Description:
2421 Sends arp message from mininet host for hosts discovery
2422 Required:
2423 host - hosts name
2424 Optional:
2425 ip - ip address that does not exist in the network so there would
2426 be no reply.
2427 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002428 if ethDevice:
2429 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002430 cmd = srcHost + " arping -c1 "
2431 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002432 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 -07002433 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002434 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002435 if output:
2436 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002437 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002438 i = self.handle.expect( [ "mininet>", "arping: " ] )
2439 if i == 0:
2440 return main.TRUE
2441 elif i == 1:
2442 response = self.handle.before + self.handle.after
2443 self.handle.expect( "mininet>" )
2444 response += self.handle.before + self.handle.after
2445 main.log.warn( "Error sending arping, output was: " +
2446 response )
2447 return main.FALSE
2448 except pexpect.TIMEOUT:
2449 main.log.error( self.name + ": TIMEOUT exception found" )
2450 main.log.warn( self.handle.before )
2451 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002452 except pexpect.EOF:
2453 main.log.error( self.name + ": EOF exception found" )
2454 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002455 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002456 except Exception:
2457 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002458 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002459
Jon Hall7eb38402015-01-08 17:19:54 -08002460 def decToHex( self, num ):
2461 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002462
Jon Hall7eb38402015-01-08 17:19:54 -08002463 def getSwitchFlowCount( self, switch ):
2464 """
2465 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002466 if self.handle:
2467 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2468 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002469 response = self.execute(
2470 cmd=cmd,
2471 prompt="mininet>",
2472 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002473 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002474 main.log.error( self.name + ": EOF exception found" )
2475 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002476 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002477 except Exception:
2478 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002479 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002480 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002481 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002482 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002483 main.log.info(
2484 "Couldn't find flows on switch %s, found: %s" %
2485 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002486 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002487 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002488 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002489 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002490
Jon Hall9ed8f372016-02-24 17:34:07 -08002491 def checkFlows( self, sw, dumpFormat=None ):
2492 if dumpFormat:
2493 command = "sh ovs-ofctl -F " + \
2494 dumpFormat + " dump-flows " + str( sw )
2495 else:
2496 command = "sh ovs-ofctl dump-flows " + str( sw )
2497 try:
2498 response = self.execute(
2499 cmd=command,
2500 prompt="mininet>",
2501 timeout=10 )
2502 return response
2503 except pexpect.EOF:
2504 main.log.error( self.name + ": EOF exception found" )
2505 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002506 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002507 except Exception:
2508 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002509 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002510
GlennRC68467eb2015-11-16 18:01:01 -08002511 def flowTableComp( self, flowTable1, flowTable2 ):
2512 # This function compares the selctors and treatments of each flow
2513 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002514 assert flowTable1, "flowTable1 is empty or None"
2515 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002516 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002517 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002518 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002519 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002520 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2521 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002522 for field in dFields:
2523 try:
2524 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002525 except KeyError:
2526 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002527 try:
2528 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002529 except KeyError:
2530 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002531 for i in range( len( flowTable1 ) ):
2532 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002533 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002534 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002535 returnValue = main.FALSE
2536 break
2537 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002538 except AssertionError:
2539 main.log.exception( "Nothing to compare" )
2540 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002541 except Exception:
2542 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002543 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002544
GlennRC528ad292015-11-12 10:38:18 -08002545 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002546 '''
GlennRC956ea742015-11-05 16:14:15 -08002547 Discription: Parses flows into json format.
2548 NOTE: this can parse any string thats separated with commas
2549 Arguments:
2550 Required:
2551 flows: a list of strings that represnt flows
2552 Optional:
2553 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2554 debug: prints out the final result
2555 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002556 '''
GlennRC528ad292015-11-12 10:38:18 -08002557 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002558 try:
2559 for flow in flowTable:
2560 jsonFlow = {}
2561 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002562 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002563 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002564 for i in range( len( parsedFlow ) ):
2565 item = parsedFlow[ i ]
2566 if item[ 0 ] == " ":
2567 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002568 # grab the selector and treatment from the parsed flow
2569 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002570 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002571 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002572 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002573 index = 0
2574 # parse the flags
2575 # NOTE: This only parses one flag
2576 flag = {}
2577 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002578 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002579 index += 1
2580 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002581 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002582 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002583 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002584 # the priority is stuck in the selecter so put it back
2585 # in the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002586 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002587 # parse selector
2588 criteria = []
2589 for item in sel:
2590 # this is the type of the packet e.g. "arp"
2591 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002592 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002593 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002594 field = item.split( "=" )
2595 criteria.append( { field[ 0 ]: field[ 1 ] } )
2596 selector = { "selector": { "criteria": sorted( criteria ) } }
2597 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002598 # get rid of the action part e.g. "action=output:2"
2599 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002600 treat = treat.split( "=" )
2601 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002602 # parse treatment
2603 action = []
2604 for item in treat:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002605 field = item.split( ":" )
2606 action.append( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002607 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002608 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002609 # parse the rest of the flow
2610 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002611 field = item.split( "=" )
2612 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002613 # add the treatment and the selector to the json flow
2614 jsonFlow.update( selector )
2615 jsonFlow.update( treatment )
2616 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002617
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002618 if debug:
2619 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002620
You Wang91c37cf2016-05-23 09:39:42 -07002621 # add the json flow to the json flow table
2622 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002623
You Wang91c37cf2016-05-23 09:39:42 -07002624 return jsonFlowTable
2625
2626 except IndexError:
2627 main.log.exception( self.name + ": IndexError found" )
2628 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002629 except pexpect.EOF:
2630 main.log.error( self.name + ": EOF exception found" )
2631 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002632 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002633 except Exception:
2634 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002635 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002636
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002637 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002638 '''
2639 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002640 Each element is a flow.
2641 Arguments:
2642 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002643 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002644 a list of switches.
2645 Optional:
2646 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2647 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002648 '''
GlennRC956ea742015-11-05 16:14:15 -08002649 try:
2650 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002651 if isinstance( sw, list ):
2652 switches.extend( sw )
2653 else:
2654 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002655
2656 flows = []
2657 for s in switches:
2658 cmd = "sh ovs-ofctl dump-flows " + s
2659
GlennRC528ad292015-11-12 10:38:18 -08002660 if "1.0" == version:
2661 cmd += " -F OpenFlow10-table_id"
2662 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002663 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002664
2665 main.log.info( "Sending: " + cmd )
2666 self.handle.sendline( cmd )
2667 self.handle.expect( "mininet>" )
2668 response = self.handle.before
2669 response = response.split( "\r\n" )
2670 # dump the first two elements and the last
2671 # the first element is the command that was sent
2672 # the second is the table header
2673 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002674 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002675 flows.extend( response )
2676
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002677 if debug:
2678 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002679
GlennRC528ad292015-11-12 10:38:18 -08002680 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002681
GlennRC956ea742015-11-05 16:14:15 -08002682 except pexpect.EOF:
2683 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002684 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002685 except Exception:
2686 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002687 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002688
2689 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002690 '''
GlennRC956ea742015-11-05 16:14:15 -08002691 Discription: Checks whether the ID provided matches a flow ID in Mininet
2692 Arguments:
2693 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002694 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002695 a list of switches.
2696 flowId: the flow ID in hex format. Can also be a list of IDs
2697 Optional:
2698 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2699 debug: prints out the final result
2700 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2701 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002702 '''
GlennRC956ea742015-11-05 16:14:15 -08002703 try:
2704 main.log.info( "Getting flows from Mininet" )
2705 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002706 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002707 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002708
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002709 if debug:
2710 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002711
2712 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002713 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002714 result = False
2715 for f in flows:
2716 if flowId in f.get( 'cookie' ):
2717 result = True
2718 break
2719 # flowId is a list
2720 else:
2721 result = True
2722 # Get flow IDs from Mininet
2723 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2724 # Save the IDs that are not in Mininet
2725 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2726
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002727 if debug:
2728 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002729
2730 # Print out the IDs that are not in Mininet
2731 if absentIds:
2732 main.log.warn( "Absent ids: {}".format( absentIds ) )
2733 result = False
2734
2735 return main.TRUE if result else main.FALSE
2736
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002737 except pexpect.EOF:
2738 main.log.error( self.name + ": EOF exception found" )
2739 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002740 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002741 except Exception:
2742 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002743 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002744
Charles Chan029be652015-08-24 01:46:10 +08002745 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002746 """
Jon Hallefbd9792015-03-05 16:11:36 -08002747 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002748 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002749 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002750 self.handle.sendline( "" )
2751 self.handle.expect( "mininet>" )
2752 self.handle.sendline(
2753 "sh sudo tcpdump -n -i " +
2754 intf +
2755 " " +
2756 port +
2757 " -w " +
2758 filename.strip() +
2759 " &" )
2760 self.handle.sendline( "" )
2761 i = self.handle.expect( [ 'No\ssuch\device',
2762 'listening\son',
2763 pexpect.TIMEOUT,
2764 "mininet>" ],
2765 timeout=10 )
2766 main.log.warn( self.handle.before + self.handle.after )
2767 self.handle.sendline( "" )
2768 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002769 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002770 main.log.error(
2771 self.name +
2772 ": tcpdump - No such device exists. " +
2773 "tcpdump attempted on: " +
2774 intf )
admin2a9548d2014-06-17 14:08:07 -07002775 return main.FALSE
2776 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002777 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002778 return main.TRUE
2779 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002780 main.log.error(
2781 self.name +
2782 ": tcpdump command timed out! Check interface name," +
2783 " given interface was: " +
2784 intf )
admin2a9548d2014-06-17 14:08:07 -07002785 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002786 elif i == 3:
2787 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002788 return main.TRUE
2789 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002790 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002791 return main.FALSE
2792 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002793 main.log.error( self.name + ": EOF exception found" )
2794 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002795 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002796 except Exception:
2797 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002798 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002799
kelvin-onlabd3b64892015-01-20 13:26:24 -08002800 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002801 """
2802 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002803 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002804 self.handle.sendline( "sh sudo pkill tcpdump" )
2805 self.handle.expect( "mininet>" )
2806 self.handle.sendline( "" )
2807 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002808 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002809 main.log.error( self.name + ": TIMEOUT exception found" )
2810 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002811 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002812 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002813 main.log.error( self.name + ": EOF exception found" )
2814 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002815 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002816 except Exception:
2817 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002818 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002819
Jon Halld80cc142015-07-06 13:36:05 -07002820 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002821 """
2822 Read ports from a Mininet switch.
2823
2824 Returns a json structure containing information about the
2825 ports of the given switch.
2826 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002827 try:
2828 response = self.getInterfaces( nodeName )
2829 # TODO: Sanity check on response. log if no such switch exists
2830 ports = []
2831 for line in response.split( "\n" ):
2832 if not line.startswith( "name=" ):
2833 continue
2834 portVars = {}
2835 for var in line.split( "," ):
2836 key, value = var.split( "=" )
2837 portVars[ key ] = value
2838 isUp = portVars.pop( 'enabled', "True" )
2839 isUp = "True" in isUp
2840 if verbose:
2841 main.log.info( "Reading switch port %s(%s)" %
2842 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2843 mac = portVars[ 'mac' ]
2844 if mac == 'None':
2845 mac = None
2846 ips = []
2847 ip = portVars[ 'ip' ]
2848 if ip == 'None':
2849 ip = None
2850 ips.append( ip )
2851 name = portVars[ 'name' ]
2852 if name == 'None':
2853 name = None
2854 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2855 if name == 'lo':
2856 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2857 else:
2858 portNo = re.search( portRe, name ).group( 'port' )
2859 ports.append( { 'of_port': portNo,
2860 'mac': str( mac ).replace( '\'', '' ),
2861 'name': name,
2862 'ips': ips,
2863 'enabled': isUp } )
2864 return ports
2865 except pexpect.EOF:
2866 main.log.error( self.name + ": EOF exception found" )
2867 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002868 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002869 except Exception:
2870 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002871 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002872
You Wangdb8cd0a2016-05-26 15:19:45 -07002873 def getOVSPorts( self, nodeName ):
2874 """
2875 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2876
2877 Returns a list of dictionaries containing information about each
2878 port of the given switch.
2879 """
2880 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2881 try:
2882 response = self.execute(
2883 cmd=command,
2884 prompt="mininet>",
2885 timeout=10 )
2886 ports = []
2887 if response:
2888 for line in response.split( "\n" ):
2889 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2890 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002891 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002892 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2893 result = re.search( pattern, line )
2894 if result:
2895 index = result.group( 'index' )
2896 name = result.group( 'name' )
2897 # This port number is extracted from port name
2898 port = result.group( 'port' )
2899 mac = result.group( 'mac' )
2900 ports.append( { 'index': index,
2901 'name': name,
2902 'port': port,
2903 'mac': mac } )
2904 return ports
2905 except pexpect.EOF:
2906 main.log.error( self.name + ": EOF exception found" )
2907 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002908 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002909 except Exception:
2910 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002911 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002912
Devin Lima7cfdbd2017-09-29 15:02:22 -07002913 def getSwitches( self, verbose=False, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002914 """
2915 Read switches from Mininet.
2916
2917 Returns a dictionary whose keys are the switch names and the value is
2918 a dictionary containing information about the switch.
2919 """
Jon Halla22481b2015-07-28 17:46:01 -07002920 # NOTE: To support new Mininet switch classes, just append the new
2921 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002922
Jon Halla22481b2015-07-28 17:46:01 -07002923 # Regex patterns to parse 'dump' output
2924 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002925 # <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 -07002926 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002927 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2928 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2929 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002930 try:
2931 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2932 swRE = r"<(?P<class>" + switchClasses + r")" +\
2933 r"(?P<options>\{.*\})?\s" +\
2934 r"(?P<name>[^:]+)\:\s" +\
2935 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2936 r"\spid=(?P<pid>(\d)+)"
2937 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002938 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002939 output = {}
2940 dump = self.dump().split( "\n" )
2941 for line in dump:
2942 result = re.search( swRE, line, re.I )
2943 if result:
2944 name = result.group( 'name' )
2945 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2946 pid = result.group( 'pid' )
2947 swClass = result.group( 'class' )
2948 options = result.group( 'options' )
2949 if verbose:
2950 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2951 ports = self.getPorts( name )
2952 output[ name ] = { "dpid": dpid,
2953 "ports": ports,
2954 "swClass": swClass,
2955 "pid": pid,
2956 "options": options }
2957 return output
2958 except pexpect.EOF:
2959 main.log.error( self.name + ": EOF exception found" )
2960 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002961 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002962 except Exception:
2963 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002964 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002965
You Wang79f5c5b2018-03-14 11:10:44 -07002966 def getHosts( self, verbose=False, updateTimeout=1000, hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ], getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002967 """
2968 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002969 Optional:
2970 hostClass: it is used to match the class of the mininet host. It
2971 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002972 Returns a dictionary whose keys are the host names and the value is
2973 a dictionary containing information about the host.
2974 """
2975 # Regex patterns to parse dump output
2976 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002977 # <Host h1: pid=12725>
2978 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2979 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2980 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002981 # NOTE: Does not correctly match hosts with multi-links
2982 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2983 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002984 try:
You Wang53dba1e2018-02-02 17:45:44 -08002985 if not isinstance( hostClass, types.ListType ):
2986 hostClass = [ str( hostClass ) ]
2987 classRE = "(" + "|".join([c for c in hostClass]) + ")"
2988 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002989 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
2990 # update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002991 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002992 # Get mininet dump
2993 dump = self.dump().split( "\n" )
2994 hosts = {}
2995 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002996 result = re.search( hostRE, line )
2997 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002998 name = result.group( 'name' )
2999 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07003000 if getInterfaces:
3001 response = self.getInterfaces( name )
3002 # Populate interface info
3003 for line in response.split( "\n" ):
3004 if line.startswith( "name=" ):
3005 portVars = {}
3006 for var in line.split( "," ):
3007 key, value = var.split( "=" )
3008 portVars[ key ] = value
3009 isUp = portVars.pop( 'enabled', "True" )
3010 isUp = "True" in isUp
3011 if verbose:
3012 main.log.info( "Reading host port %s(%s)" %
3013 ( portVars[ 'name' ],
3014 portVars[ 'mac' ] ) )
3015 mac = portVars[ 'mac' ]
3016 if mac == 'None':
3017 mac = None
3018 ips = []
3019 ip = portVars[ 'ip' ]
3020 if ip == 'None':
3021 ip = None
3022 ips.append( ip )
3023 intfName = portVars[ 'name' ]
3024 if name == 'None':
3025 name = None
3026 interfaces.append( {
3027 "name": intfName,
3028 "ips": ips,
3029 "mac": str( mac ),
3030 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003031 hosts[ name ] = { "interfaces": interfaces }
3032 return hosts
3033 except pexpect.EOF:
3034 main.log.error( self.name + ": EOF exception found" )
3035 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003036 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003037 except Exception:
3038 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003039 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003040
Devin Lima7cfdbd2017-09-29 15:02:22 -07003041 def getLinks( self, timeout=20, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07003042 """
3043 Gathers information about current Mininet links. These links may not
3044 be up if one of the ports is down.
3045
3046 Returns a list of dictionaries with link endpoints.
3047
3048 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07003049 { 'node1': str( node1 name )
3050 'node2': str( node2 name )
3051 'port1': str( port1 of_port )
3052 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07003053 Note: The port number returned is the eth#, not necessarily the of_port
3054 number. In Mininet, for OVS switch, these should be the same. For
3055 hosts, this is just the eth#.
3056 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003057 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003058 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003059 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07003060
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003061 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003062 # s1-eth3<->s2-eth1 (OK OK)
3063 # s13-eth3<->h27-eth0 (OK OK)
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003064 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
3065 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
3066 links = []
3067 for line in response:
3068 match = re.search( linkRE, line )
3069 if match:
3070 node1 = match.group( 'node1' )
3071 node2 = match.group( 'node2' )
3072 port1 = match.group( 'port1' )
3073 port2 = match.group( 'port2' )
3074 links.append( { 'node1': node1,
3075 'node2': node2,
3076 'port1': port1,
3077 'port2': port2 } )
3078 return links
3079
3080 except pexpect.EOF:
3081 main.log.error( self.name + ": EOF exception found" )
3082 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003083 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003084 except Exception:
3085 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003086 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003087
3088 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003089 """
3090 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003091 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003092
Jon Hallafa8a472015-06-12 14:02:42 -07003093 Dependencies:
3094 1. numpy - "sudo pip install numpy"
3095 """
3096 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003097 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003098 try:
3099 mnDPIDs = []
3100 for swName, switch in switches.iteritems():
3101 mnDPIDs.append( switch[ 'dpid' ].lower() )
3102 mnDPIDs.sort()
3103 if switchesJson == "": # if rest call fails
3104 main.log.error(
3105 self.name +
3106 ".compareSwitches(): Empty JSON object given from ONOS" )
3107 return main.FALSE
3108 onos = switchesJson
3109 onosDPIDs = []
3110 for switch in onos:
3111 if switch[ 'available' ]:
3112 onosDPIDs.append(
3113 switch[ 'id' ].replace(
3114 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003115 '' ).replace(
3116 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003117 '' ).lower() )
3118 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003119
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003120 if mnDPIDs != onosDPIDs:
3121 switchResults = main.FALSE
3122 main.log.error( "Switches in MN but not in ONOS:" )
3123 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3124 main.log.error( str( list1 ) )
3125 main.log.error( "Switches in ONOS but not in MN:" )
3126 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3127 main.log.error( str( list2 ) )
3128 else: # list of dpid's match in onos and mn
3129 switchResults = main.TRUE
3130 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003131
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003132 # FIXME: this does not look for extra ports in ONOS, only checks that
3133 # ONOS has what is in MN
3134 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003135
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003136 # PORTS
3137 for name, mnSwitch in switches.iteritems():
3138 mnPorts = []
3139 onosPorts = []
3140 switchResult = main.TRUE
3141 for port in mnSwitch[ 'ports' ]:
3142 if port[ 'enabled' ]:
3143 mnPorts.append( int( port[ 'of_port' ] ) )
3144 for onosSwitch in portsJson:
3145 if onosSwitch[ 'device' ][ 'available' ]:
3146 if onosSwitch[ 'device' ][ 'id' ].replace(
3147 ':',
3148 '' ).replace(
3149 "of",
3150 '' ) == mnSwitch[ 'dpid' ]:
3151 for port in onosSwitch[ 'ports' ]:
3152 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003153 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003154 # onosPorts.append( 'local' )
3155 onosPorts.append( long( uint64( -2 ) ) )
3156 else:
3157 onosPorts.append( int( port[ 'port' ] ) )
3158 break
3159 mnPorts.sort( key=float )
3160 onosPorts.sort( key=float )
3161
3162 mnPortsLog = mnPorts
3163 onosPortsLog = onosPorts
3164 mnPorts = [ x for x in mnPorts ]
3165 onosPorts = [ x for x in onosPorts ]
3166
3167 # TODO: handle other reserved port numbers besides LOCAL
3168 # NOTE: Reserved ports
3169 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3170 # long( uint64( -2 ) )
3171 for mnPort in mnPortsLog:
3172 if mnPort in onosPorts:
3173 # don't set results to true here as this is just one of
3174 # many checks and it might override a failure
3175 mnPorts.remove( mnPort )
3176 onosPorts.remove( mnPort )
3177
3178 # NOTE: OVS reports this as down since there is no link
3179 # So ignoring these for now
3180 # TODO: Come up with a better way of handling these
3181 if 65534 in mnPorts:
3182 mnPorts.remove( 65534 )
3183 if long( uint64( -2 ) ) in onosPorts:
3184 onosPorts.remove( long( uint64( -2 ) ) )
3185 if len( mnPorts ): # the ports of this switch don't match
3186 switchResult = main.FALSE
3187 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3188 if len( onosPorts ): # the ports of this switch don't match
3189 switchResult = main.FALSE
3190 main.log.warn(
3191 "Ports in ONOS but not MN: " +
3192 str( onosPorts ) )
3193 if switchResult == main.FALSE:
3194 main.log.error(
3195 "The list of ports for switch %s(%s) does not match:" %
3196 ( name, mnSwitch[ 'dpid' ] ) )
3197 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3198 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3199 portsResults = portsResults and switchResult
3200 finalResults = finalResults and portsResults
3201 return finalResults
3202 except pexpect.EOF:
3203 main.log.error( self.name + ": EOF exception found" )
3204 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003205 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003206 except Exception:
3207 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003208 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003209
Jon Hallafa8a472015-06-12 14:02:42 -07003210 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003211 """
3212 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003213 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003214
Jon Hallafa8a472015-06-12 14:02:42 -07003215 """
Jon Hall7eb38402015-01-08 17:19:54 -08003216 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003217 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003218 try:
3219 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003220
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003221 mnLinks = []
3222 for l in links:
3223 try:
3224 node1 = switches[ l[ 'node1' ] ]
3225 node2 = switches[ l[ 'node2' ] ]
3226 enabled = True
3227 for port in node1[ 'ports' ]:
3228 if port[ 'of_port' ] == l[ 'port1' ]:
3229 enabled = enabled and port[ 'enabled' ]
3230 for port in node2[ 'ports' ]:
3231 if port[ 'of_port' ] == l[ 'port2' ]:
3232 enabled = enabled and port[ 'enabled' ]
3233 if enabled:
3234 mnLinks.append( l )
3235 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003236 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003237 if 2 * len( mnLinks ) == len( onos ):
3238 linkResults = main.TRUE
3239 else:
3240 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003241 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003242 "Mininet has " + str( len( mnLinks ) ) +
3243 " bidirectional links and ONOS has " +
3244 str( len( onos ) ) + " unidirectional links" )
3245
3246 # iterate through MN links and check if an ONOS link exists in
3247 # both directions
3248 for link in mnLinks:
3249 # TODO: Find a more efficient search method
3250 node1 = None
3251 port1 = None
3252 node2 = None
3253 port2 = None
3254 firstDir = main.FALSE
3255 secondDir = main.FALSE
3256 for swName, switch in switches.iteritems():
3257 if swName == link[ 'node1' ]:
3258 node1 = switch[ 'dpid' ]
3259 for port in switch[ 'ports' ]:
3260 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3261 port1 = port[ 'of_port' ]
3262 if node1 is not None and node2 is not None:
3263 break
3264 if swName == link[ 'node2' ]:
3265 node2 = switch[ 'dpid' ]
3266 for port in switch[ 'ports' ]:
3267 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3268 port2 = port[ 'of_port' ]
3269 if node1 is not None and node2 is not None:
3270 break
3271
3272 for onosLink in onos:
3273 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3274 ":", '' ).replace( "of", '' )
3275 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3276 ":", '' ).replace( "of", '' )
3277 onosPort1 = onosLink[ 'src' ][ 'port' ]
3278 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3279
3280 # check onos link from node1 to node2
3281 if str( onosNode1 ) == str( node1 ) and str(
3282 onosNode2 ) == str( node2 ):
3283 if int( onosPort1 ) == int( port1 ) and int(
3284 onosPort2 ) == int( port2 ):
3285 firstDir = main.TRUE
3286 else:
3287 main.log.warn(
3288 'The port numbers do not match for ' +
3289 str( link ) +
3290 ' between ONOS and MN. When checking ONOS for ' +
3291 'link %s/%s -> %s/%s' %
3292 ( node1, port1, node2, port2 ) +
3293 ' ONOS has the values %s/%s -> %s/%s' %
3294 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
3295
3296 # check onos link from node2 to node1
3297 elif ( str( onosNode1 ) == str( node2 ) and
3298 str( onosNode2 ) == str( node1 ) ):
3299 if ( int( onosPort1 ) == int( port2 )
3300 and int( onosPort2 ) == int( port1 ) ):
3301 secondDir = main.TRUE
3302 else:
3303 main.log.warn(
3304 'The port numbers do not match for ' +
3305 str( link ) +
3306 ' between ONOS and MN. When checking ONOS for ' +
3307 'link %s/%s -> %s/%s' %
3308 ( node1, port1, node2, port2 ) +
3309 ' ONOS has the values %s/%s -> %s/%s' %
3310 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
3311 else: # this is not the link you're looking for
3312 pass
3313 if not firstDir:
3314 main.log.error(
3315 'ONOS does not have the link %s/%s -> %s/%s' %
3316 ( node1, port1, node2, port2 ) )
3317 if not secondDir:
3318 main.log.error(
3319 'ONOS does not have the link %s/%s -> %s/%s' %
3320 ( node2, port2, node1, port1 ) )
3321 linkResults = linkResults and firstDir and secondDir
3322 return linkResults
3323 except pexpect.EOF:
3324 main.log.error( self.name + ": EOF exception found" )
3325 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003326 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003327 except Exception:
3328 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003329 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003330
Jon Hallafa8a472015-06-12 14:02:42 -07003331 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003332 """
Jon Hallafa8a472015-06-12 14:02:42 -07003333 Compare mn and onos Hosts.
3334 Since Mininet hosts are quiet, ONOS will only know of them when they
3335 speak. For this reason, we will only check that the hosts in ONOS
3336 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003337
Jon Hallafa8a472015-06-12 14:02:42 -07003338 Arguments:
3339 hostsJson: parsed json object from the onos hosts api
3340 Returns:
3341 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003342 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003343 try:
3344 hostResults = main.TRUE
3345 for onosHost in hostsJson:
3346 onosMAC = onosHost[ 'mac' ].lower()
3347 match = False
3348 for mnHost, info in hosts.iteritems():
3349 for mnIntf in info[ 'interfaces' ]:
3350 if onosMAC == mnIntf[ 'mac' ].lower():
3351 match = True
3352 for ip in mnIntf[ 'ips' ]:
3353 if ip in onosHost[ 'ipAddresses' ]:
3354 pass # all is well
3355 else:
3356 # misssing ip
3357 main.log.error( "ONOS host " +
3358 onosHost[ 'id' ] +
3359 " has a different IP(" +
3360 str( onosHost[ 'ipAddresses' ] ) +
3361 ") than the Mininet host(" +
3362 str( ip ) +
3363 ")." )
3364 output = json.dumps(
3365 onosHost,
3366 sort_keys=True,
3367 indent=4,
3368 separators=( ',', ': ' ) )
3369 main.log.info( output )
3370 hostResults = main.FALSE
3371 if not match:
3372 hostResults = main.FALSE
3373 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3374 "corresponding Mininet host." )
3375 output = json.dumps( onosHost,
3376 sort_keys=True,
3377 indent=4,
3378 separators=( ',', ': ' ) )
3379 main.log.info( output )
3380 return hostResults
3381 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003382 main.log.error( self.name + ": EOF exception found" )
3383 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003384 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003385 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003386 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003387 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003388
You Wang53dba1e2018-02-02 17:45:44 -08003389 def verifyHostIp( self, hostList=[], prefix="" ):
3390 """
3391 Description:
3392 Verify that all hosts have IP address assigned to them
3393 Optional:
3394 hostList: If specified, verifications only happen to the hosts
3395 in hostList
3396 prefix: at least one of the ip address assigned to the host
3397 needs to have the specified prefix
3398 Returns:
3399 main.TRUE if all hosts have specific IP address assigned;
3400 main.FALSE otherwise
3401 """
3402 try:
You Wang79f5c5b2018-03-14 11:10:44 -07003403 hosts = self.getHosts( getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003404 if not hostList:
3405 hostList = hosts.keys()
3406 for hostName in hosts.keys():
3407 if hostName not in hostList:
3408 continue
3409 ipList = []
3410 self.handle.sendline( str( hostName ) + " ip a" )
3411 self.handle.expect( "mininet>" )
3412 ipa = self.handle.before
3413 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3414 ipList += re.findall( ipv4Pattern, ipa )
3415 # It's tricky to make regex for IPv6 addresses and this one is simplified
3416 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})/'
3417 ipList += re.findall( ipv6Pattern, ipa )
3418 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3419 if not ipList:
3420 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3421 else:
3422 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3423 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3424 else:
3425 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3426 hostList.remove( hostName )
3427 return main.FALSE if hostList else main.TRUE
3428 except KeyError:
3429 main.log.exception( self.name + ": host data not as expected: " + hosts )
3430 return None
3431 except pexpect.EOF:
3432 main.log.error( self.name + ": EOF exception found" )
3433 main.log.error( self.name + ": " + self.handle.before )
3434 main.cleanAndExit()
3435 except Exception:
3436 main.log.exception( self.name + ": Uncaught exception" )
3437 return None
3438
Jon Hallafa8a472015-06-12 14:02:42 -07003439 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003440 """
3441 Returns a list of all hosts
3442 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003443 try:
3444 self.handle.sendline( "" )
3445 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003446
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003447 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3448 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003449
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003450 handlePy = self.handle.before
3451 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3452 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003453
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003454 self.handle.sendline( "" )
3455 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003456
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003457 hostStr = handlePy.replace( "]", "" )
3458 hostStr = hostStr.replace( "'", "" )
3459 hostStr = hostStr.replace( "[", "" )
3460 hostStr = hostStr.replace( " ", "" )
3461 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003462
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003463 return hostList
3464 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003465 main.log.error( self.name + ": TIMEOUT exception found" )
3466 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003467 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003468 except pexpect.EOF:
3469 main.log.error( self.name + ": EOF exception found" )
3470 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003471 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003472 except Exception:
3473 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003474 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003475
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003476 def getSwitch( self ):
3477 """
3478 Returns a list of all switches
3479 Again, don't ask question just use it...
3480 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003481 try:
3482 # get host list...
3483 hostList = self.getHosts()
3484 # Make host set
3485 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003486
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003487 # Getting all the nodes in mininet
3488 self.handle.sendline( "" )
3489 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003490
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003491 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3492 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003493
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003494 handlePy = self.handle.before
3495 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3496 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003497
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003498 self.handle.sendline( "" )
3499 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003500
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003501 nodesStr = handlePy.replace( "]", "" )
3502 nodesStr = nodesStr.replace( "'", "" )
3503 nodesStr = nodesStr.replace( "[", "" )
3504 nodesStr = nodesStr.replace( " ", "" )
3505 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003506
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003507 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003508 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003509 nodesSet.discard( 'c0' )
3510 nodesSet.discard( 'c1' )
3511 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003512
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003513 switchSet = nodesSet - hostSet
3514 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003515
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003516 return switchList
3517 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003518 main.log.error( self.name + ": TIMEOUT exception found" )
3519 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003520 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003521 except pexpect.EOF:
3522 main.log.error( self.name + ": EOF exception found" )
3523 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003524 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003525 except Exception:
3526 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003527 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003528
You Wangdb8cd0a2016-05-26 15:19:45 -07003529 def getGraphDict( self, timeout=60, useId=True, includeHost=False ):
3530 """
3531 Return a dictionary which describes the latest Mininet topology data as a
3532 graph.
3533 An example of the dictionary:
3534 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3535 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3536 Each vertex should at least have an 'edges' attribute which describes the
3537 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003538 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003539 list of attributes.
3540 An example of the edges dictionary:
3541 'edges': { vertex2: { 'port': ..., 'weight': ... },
3542 vertex3: { 'port': ..., 'weight': ... } }
3543 If useId == True, dpid/mac will be used instead of names to identify
3544 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3545 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003546 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003547 in topology data.
3548 Note that link or switch that are brought down by 'link x x down' or 'switch
3549 x down' commands still show in the output of Mininet CLI commands such as
3550 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3551 recommended to use delLink() or delSwitch functions to simulate link/switch
3552 down, and addLink() or addSwitch to add them back.
3553 """
3554 graphDict = {}
3555 try:
3556 links = self.getLinks( timeout=timeout )
3557 portDict = {}
3558 if useId:
3559 switches = self.getSwitches()
3560 if includeHost:
3561 hosts = self.getHosts()
3562 for link in links:
3563 # FIXME: support 'includeHost' argument
3564 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3565 continue
3566 nodeName1 = link[ 'node1' ]
3567 nodeName2 = link[ 'node2' ]
3568 port1 = link[ 'port1' ]
3569 port2 = link[ 'port2' ]
3570 # Loop for two nodes
3571 for i in range( 2 ):
3572 # Get port index from OVS
3573 # The index extracted from port name may be inconsistent with ONOS
3574 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003575 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003576 portList = self.getOVSPorts( nodeName1 )
3577 if len( portList ) == 0:
3578 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3579 return None
3580 portDict[ nodeName1 ] = portList
3581 for port in portDict[ nodeName1 ]:
3582 if port[ 'port' ] == port1:
3583 portIndex = port[ 'index' ]
3584 break
3585 if portIndex == -1:
3586 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3587 return None
3588 if useId:
3589 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3590 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3591 else:
3592 node1 = nodeName1
3593 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003594 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003595 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003596 graphDict[ node1 ] = { 'edges': {},
3597 'dpid': switches[ nodeName1 ][ 'dpid' ],
3598 'name': nodeName1,
3599 'ports': switches[ nodeName1 ][ 'ports' ],
3600 'swClass': switches[ nodeName1 ][ 'swClass' ],
3601 'pid': switches[ nodeName1 ][ 'pid' ],
3602 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003603 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003604 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003605 else:
3606 # Assert node2 is not connected to any current links of node1
3607 assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003608 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
You Wangdb8cd0a2016-05-26 15:19:45 -07003609 # Swap two nodes/ports
3610 nodeName1, nodeName2 = nodeName2, nodeName1
3611 port1, port2 = port2, port1
3612 return graphDict
3613 except KeyError:
3614 main.log.exception( self.name + ": KeyError exception found" )
3615 return None
3616 except AssertionError:
3617 main.log.exception( self.name + ": AssertionError exception found" )
3618 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003619 except pexpect.EOF:
3620 main.log.error( self.name + ": EOF exception found" )
3621 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003622 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003623 except Exception:
3624 main.log.exception( self.name + ": Uncaught exception" )
3625 return None
3626
Devin Lima7cfdbd2017-09-29 15:02:22 -07003627 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003628 """
3629 updates the port address and status information for
3630 each port in mn"""
3631 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003632 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003633 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003634 self.handle.sendline( "" )
3635 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003636
Jon Hall7eb38402015-01-08 17:19:54 -08003637 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003638 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003639
Jon Hall7eb38402015-01-08 17:19:54 -08003640 self.handle.sendline( "" )
3641 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003642
Jon Hallb1290e82014-11-18 16:17:48 -05003643 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003644 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003645 main.log.error( self.name + ": TIMEOUT exception found" )
3646 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003647 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003648 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003649 main.log.error( self.name + ": EOF exception found" )
3650 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003651 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003652 except Exception:
3653 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003654 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003655
Jon Halld80cc142015-07-06 13:36:05 -07003656 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003657 """
3658 Add vlan tag to a host.
3659 Dependencies:
3660 This class depends on the "vlan" package
3661 $ sudo apt-get install vlan
3662 Configuration:
3663 Load the 8021q module into the kernel
3664 $sudo modprobe 8021q
3665
3666 To make this setup permanent:
3667 $ sudo su -c 'echo "8021q" >> /etc/modules'
3668 """
3669 if self.handle:
3670 try:
Jon Halld80cc142015-07-06 13:36:05 -07003671 # get the ip address of the host
3672 main.log.info( "Get the ip address of the host" )
3673 ipaddr = self.getIPAddress( host )
3674 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003675
Jon Halld80cc142015-07-06 13:36:05 -07003676 # remove IP from interface intf
3677 # Ex: h1 ifconfig h1-eth0 inet 0
3678 main.log.info( "Remove IP from interface " )
3679 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3680 self.handle.sendline( cmd2 )
3681 self.handle.expect( "mininet>" )
3682 response = self.handle.before
3683 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003684
Jon Halld80cc142015-07-06 13:36:05 -07003685 # create VLAN interface
3686 # Ex: h1 vconfig add h1-eth0 100
3687 main.log.info( "Create Vlan" )
3688 cmd3 = host + " vconfig add " + intf + " " + vlan
3689 self.handle.sendline( cmd3 )
3690 self.handle.expect( "mininet>" )
3691 response = self.handle.before
3692 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003693
Jon Halld80cc142015-07-06 13:36:05 -07003694 # assign the host's IP to the VLAN interface
3695 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3696 main.log.info( "Assign the host IP to the vlan interface" )
3697 vintf = intf + "." + vlan
3698 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3699 self.handle.sendline( cmd4 )
3700 self.handle.expect( "mininet>" )
3701 response = self.handle.before
3702 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003703
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003704 # update Mininet node variables
3705 main.log.info( "Update Mininet node variables" )
3706 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3707 self.handle.sendline( cmd5 )
3708 self.handle.expect( "mininet>" )
3709 response = self.handle.before
3710 main.log.info( "====> %s ", response )
3711
3712 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3713 self.handle.sendline( cmd6 )
3714 self.handle.expect( "mininet>" )
3715 response = self.handle.before
3716 main.log.info( "====> %s ", response )
3717
3718 return main.TRUE
3719 except pexpect.TIMEOUT:
3720 main.log.error( self.name + ": TIMEOUT exception found" )
3721 main.log.error( self.name + ": " + self.handle.before )
3722 main.cleanAndExit()
3723 except pexpect.EOF:
3724 main.log.error( self.name + ": EOF exception found" )
3725 main.log.error( self.name + ": " + self.handle.before )
3726 return main.FALSE
3727 except Exception:
3728 main.log.exception( self.name + ": Uncaught exception!" )
3729 return main.FALSE
3730
3731 def removeVLAN( self, host, intf ):
3732 """
3733 Remove vlan tag from a host.
3734 Dependencies:
3735 This class depends on the "vlan" package
3736 $ sudo apt-get install vlan
3737 Configuration:
3738 Load the 8021q module into the kernel
3739 $sudo modprobe 8021q
3740
3741 To make this setup permanent:
3742 $ sudo su -c 'echo "8021q" >> /etc/modules'
3743 """
3744 if self.handle:
3745 try:
3746 # get the ip address of the host
3747 main.log.info( "Get the ip address of the host" )
3748 ipaddr = self.getIPAddress( host )
3749
3750 # remove VLAN interface
3751 # Ex: h1 vconfig rem h1-eth0.100
3752 main.log.info( "Remove Vlan interface" )
3753 cmd2 = host + " vconfig rem " + intf
3754 self.handle.sendline( cmd2 )
3755 self.handle.expect( "mininet>" )
3756 response = self.handle.before
3757 main.log.info( "====> %s ", response )
3758
3759 # assign the host's IP to the original interface
3760 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3761 main.log.info( "Assign the host IP to the original interface" )
3762 original_intf = intf.split(".")[0]
3763 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3764 self.handle.sendline( cmd3 )
3765 self.handle.expect( "mininet>" )
3766 response = self.handle.before
3767 main.log.info( "====> %s ", response )
3768
3769 # update Mininet node variables
3770 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3771 self.handle.sendline( cmd4 )
3772 self.handle.expect( "mininet>" )
3773 response = self.handle.before
3774 main.log.info( "====> %s ", response )
3775
3776 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3777 self.handle.sendline( cmd5 )
3778 self.handle.expect( "mininet>" )
3779 response = self.handle.before
3780 main.log.info( "====> %s ", response )
3781
kaouthera3f13ca22015-05-05 15:01:41 -07003782 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003783 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003784 main.log.error( self.name + ": TIMEOUT exception found" )
3785 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003786 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003787 except pexpect.EOF:
3788 main.log.error( self.name + ": EOF exception found" )
3789 main.log.error( self.name + ": " + self.handle.before )
3790 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003791 except Exception:
3792 main.log.exception( self.name + ": Uncaught exception!" )
3793 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003794
Jon Hall892818c2015-10-20 17:58:34 -07003795 def createHostComponent( self, name ):
3796 """
3797 Creates a new mininet cli component with the same parameters as self.
3798 This new component is intended to be used to login to the hosts created
3799 by mininet.
3800
3801 Arguments:
3802 name - The string of the name of this component. The new component
3803 will be assigned to main.<name> .
3804 In addition, main.<name>.name = str( name )
3805 """
3806 try:
3807 # look to see if this component already exists
3808 getattr( main, name )
3809 except AttributeError:
3810 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003811 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3812 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003813 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003814 except pexpect.EOF:
3815 main.log.error( self.name + ": EOF exception found" )
3816 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003817 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003818 except Exception:
3819 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003820 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003821 else:
3822 # namespace is not clear!
3823 main.log.error( name + " component already exists!" )
3824 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003825 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003826
3827 def removeHostComponent( self, name ):
3828 """
3829 Remove host component
3830 Arguments:
3831 name - The string of the name of the component to delete.
3832 """
3833 try:
3834 # Get host component
3835 component = getattr( main, name )
3836 except AttributeError:
3837 main.log.error( "Component " + name + " does not exist." )
3838 return
3839 try:
3840 # Disconnect from component
3841 component.disconnect()
3842 # Delete component
3843 delattr( main, name )
3844 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003845 del( main.componentDictionary[ name ] )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003846 except pexpect.EOF:
3847 main.log.error( self.name + ": EOF exception found" )
3848 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003849 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003850 except Exception:
3851 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003852 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003853
3854 def startHostCli( self, host=None ):
3855 """
3856 Use the mininet m utility to connect to the host's cli
3857 """
3858 # These are fields that can be used by scapy packets. Initialized to None
3859 self.hostIp = None
3860 self.hostMac = None
3861 try:
3862 if not host:
3863 host = self.name
3864 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003865 self.handle.sendline( "cd" )
3866 self.handle.expect( self.hostPrompt )
3867 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003868 self.handle.expect( self.hostPrompt )
3869 return main.TRUE
3870 except pexpect.TIMEOUT:
3871 main.log.exception( self.name + ": Command timed out" )
3872 return main.FALSE
3873 except pexpect.EOF:
3874 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003875 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003876 except Exception:
3877 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003878 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003879
YPZhang801d46d2016-08-08 13:26:28 -07003880 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003881 '''
3882
YPZhang801d46d2016-08-08 13:26:28 -07003883 Args:
3884 devicename: switch name
3885 intf: port name on switch
3886 status: up or down
3887
3888 Returns: boolean to show success change status
3889
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003890 '''
YPZhang801d46d2016-08-08 13:26:28 -07003891 if status == "down" or status == "up":
3892 try:
3893 cmd = devicename + " ifconfig " + intf + " " + status
3894 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003895 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003896 return main.TRUE
3897 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003898 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003899 return main.FALSE
3900 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003901 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003902 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003903 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003904 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003905 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003906 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003907 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003908 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003909 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003910 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003911 return main.FALSE
3912
3913
adminbae64d82013-08-01 10:50:15 -07003914if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07003915 sys.modules[ __name__ ] = MininetCliDriver()