blob: 0446e2c797c1ecbc2542a232a77dbaefcae5cad3 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
Jon Hall7eb38402015-01-08 17:19:54 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004Copyright 2012 Open Networking Foundation (ONF)
adminbae64d82013-08-01 10:50:15 -07005
Jeremy Songsterae01bba2016-07-11 15:39:17 -07006Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
7the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
8or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
adminbae64d82013-08-01 10:50:15 -07009
Jon Hall7eb38402015-01-08 17:19:54 -080010TestON is free software: you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation, either version 2 of the License, or
13( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070014
Jon Hall7eb38402015-01-08 17:19:54 -080015TestON is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070019
Jon Hall7eb38402015-01-08 17:19:54 -080020You should have received a copy of the GNU General Public License
21along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070022
Jon Hallbe6dfc42015-01-12 17:37:25 -080023MininetCliDriver is the basic driver which will handle the Mininet functions
24
25Some functions rely on a modified version of Mininet. These functions
26should all be noted in the comments. To get this MN version run these commands
27from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080028 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080029 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080030 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080031 git pull
32
Jon Hall272a4db2015-01-12 17:43:48 -080033
34 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080035changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070036import pexpect
adminbae64d82013-08-01 10:50:15 -070037import re
38import sys
kelvin-onlabfa6ada82015-06-11 13:06:24 -070039import types
kelvin-onlaba4074292015-07-09 15:19:49 -070040import os
Devin Lima7cfdbd2017-09-29 15:02:22 -070041import time
Jon Hall1ccf82c2014-10-15 14:55:16 -040042from math import pow
adminbae64d82013-08-01 10:50:15 -070043from drivers.common.cli.emulatordriver import Emulator
You Wangdb8cd0a2016-05-26 15:19:45 -070044from core.graph import Graph
adminbae64d82013-08-01 10:50:15 -070045
Jon Hall7eb38402015-01-08 17:19:54 -080046
kelvin-onlab50907142015-04-01 13:37:45 -070047class MininetCliDriver( Emulator ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -070048
Jon Hall7eb38402015-01-08 17:19:54 -080049 """
50 MininetCliDriver is the basic driver which will handle
51 the Mininet functions"""
52 def __init__( self ):
Devin Limdc78e202017-06-09 18:30:07 -070053 super( MininetCliDriver, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070054 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080055 self.name = None
kelvin-onlabd9e23de2015-08-06 10:34:44 -070056 self.home = None
Jon Hall7eb38402015-01-08 17:19:54 -080057 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070058 self.flag = 0
Jon Hall892818c2015-10-20 17:58:34 -070059 # TODO: Refactor driver to use these everywhere
60 self.mnPrompt = "mininet>"
61 self.hostPrompt = "~#"
62 self.bashPrompt = "\$"
63 self.scapyPrompt = ">>>"
You Wangdb8cd0a2016-05-26 15:19:45 -070064 self.graph = Graph()
adminbae64d82013-08-01 10:50:15 -070065
Jon Hall7eb38402015-01-08 17:19:54 -080066 def connect( self, **connectargs ):
67 """
68 Here the main is the TestON instance after creating
69 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080070 try:
71 for key in connectargs:
72 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070073 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080074 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070075 for key in self.options:
76 if key == "home":
77 self.home = self.options[ 'home' ]
78 break
79 if self.home is None or self.home == "":
80 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070081
82 try:
Jon Hall892818c2015-10-20 17:58:34 -070083 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070084 self.ip_address = os.getenv( str( self.ip_address ) )
85 else:
86 main.log.info( self.name +
87 ": Trying to connect to " +
88 self.ip_address )
89
90 except KeyError:
91 main.log.info( "Invalid host name," +
92 " connecting to local host instead" )
93 self.ip_address = 'localhost'
94 except Exception as inst:
95 main.log.error( "Uncaught exception: " + str( inst ) )
96
kelvin-onlaba1484582015-02-02 15:46:20 -080097 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070098 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080099 self ).connect(
100 user_name=self.user_name,
101 ip_address=self.ip_address,
102 port=None,
103 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -0800104
kelvin-onlaba1484582015-02-02 15:46:20 -0800105 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -0800106 main.log.info( "Connection successful to the host " +
107 self.user_name +
108 "@" +
109 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800110 return main.TRUE
111 else:
112 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800113 self.user_name +
114 "@" +
115 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800116 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800117 return main.FALSE
118 except pexpect.EOF:
119 main.log.error( self.name + ": EOF exception found" )
120 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700121 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800122 except Exception:
123 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700124 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -0800125
kelvin-onlab10e8d392015-06-03 13:53:45 -0700126 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800127 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700128 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000129 Starts Mininet accepts a topology(.py) file and/or an optional
kelvin-onlabf512e942015-06-08 19:42:59 -0700130 argument, to start the mininet, as a parameter.
131 Can also send regular mininet command to load up desired topology.
alison12f34c32016-06-10 14:39:21 -0700132 Eg. Pass in a string 'mn --topo=tree,3,3' to mnCmd
kelvin-onlabf512e942015-06-08 19:42:59 -0700133 Options:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000134 topoFile = file path for topology file (.py)
kelvin-onlabf512e942015-06-08 19:42:59 -0700135 args = extra option added when starting the topology from the file
136 mnCmd = Mininet command use to start topology
137 Returns:
138 main.TRUE if the mininet starts successfully, main.FALSE
139 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800140 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700141 try:
142 if self.handle:
143 # make sure old networks are cleaned up
144 main.log.info( self.name +
145 ": Clearing any residual state or processes" )
146 self.handle.sendline( "sudo mn -c" )
147 i = self.handle.expect( [ 'password\sfor\s',
148 'Cleanup\scomplete',
Jon Hallefbd9792015-03-05 16:11:36 -0800149 pexpect.EOF,
150 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700151 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800152 if i == 0:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700153 # Sudo asking for password
154 main.log.info( self.name + ": Sending sudo password" )
155 self.handle.sendline( self.pwd )
Jon Hall173f2a02018-01-11 13:56:37 -0800156 i = self.handle.expect( [ '%s:' % self.user_name,
Devin Limdc78e202017-06-09 18:30:07 -0700157 self.prompt,
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700158 pexpect.EOF,
159 pexpect.TIMEOUT ],
160 timeout )
161 if i == 1:
162 main.log.info( self.name + ": Clean" )
Jon Hall689d8e42015-04-03 13:59:24 -0700163 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700164 main.log.error( self.name + ": Connection terminated" )
165 elif i == 3: # timeout
166 main.log.error( self.name + ": Something while cleaning " +
167 "Mininet took too long... " )
168 # Craft the string to start mininet
169 cmdString = "sudo "
170 if not mnCmd:
171 if topoFile is None or topoFile == '': # If no file is given
172 main.log.info( self.name + ": building fresh Mininet" )
173 cmdString += "mn "
174 if args is None or args == '':
175 # If no args given, use args from .topo file
176 args = self.options[ 'arg1' ] +\
177 " " + self.options[ 'arg2' ] +\
178 " --mac --controller " +\
179 self.options[ 'controller' ] + " " +\
180 self.options[ 'arg3' ]
181 else: # else only use given args
182 pass
183 # TODO: allow use of topo args and method args?
184 else: # Use given topology file
185 main.log.info(
186 "Starting Mininet from topo file " +
187 topoFile )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700188 cmdString += "-E python " + topoFile + " "
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700189 if args is None:
190 args = ''
191 # TODO: allow use of args from .topo file?
192 cmdString += args
193 else:
194 main.log.info( "Starting Mininet topology using '" + mnCmd +
195 "' command" )
196 cmdString += mnCmd
197 # Send the command and check if network started
198 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -0700199 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700200 main.log.info( "Sending '" + cmdString + "' to " + self.name )
201 self.handle.sendline( cmdString )
Devin Lima7cfdbd2017-09-29 15:02:22 -0700202 startTime = time.time()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700203 while True:
204 i = self.handle.expect( [ 'mininet>',
205 'Exception',
206 '\*\*\*',
207 pexpect.EOF,
208 pexpect.TIMEOUT ],
209 timeout )
210 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -0700211 main.log.info( self.name + ": Mininet built\nTime Took : " + str( time.time() - startTime ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700212 return main.TRUE
213 elif i == 1:
214 response = str( self.handle.before +
215 self.handle.after )
Devin Limdc78e202017-06-09 18:30:07 -0700216 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700217 response += str( self.handle.before +
218 self.handle.after )
219 main.log.error(
220 self.name +
221 ": Launching Mininet failed: " + response )
222 return main.FALSE
223 elif i == 2:
224 self.handle.expect( [ "\n",
225 pexpect.EOF,
226 pexpect.TIMEOUT ],
227 timeout )
228 main.log.info( self.handle.before )
229 elif i == 3:
230 main.log.error( self.name + ": Connection timeout" )
231 return main.FALSE
232 elif i == 4: # timeout
233 main.log.error(
234 self.name +
235 ": Something took too long... " )
236 return main.FALSE
237 # Why did we hit this part?
238 main.log.error( "startNet did not return correctly" )
239 return main.FASLE
240 else: # if no handle
241 main.log.error( self.name + ": Connection failed to the host " +
242 self.user_name + "@" + self.ip_address )
243 main.log.error( self.name + ": Failed to connect to the Mininet" )
244 return main.FALSE
245 except pexpect.TIMEOUT:
246 main.log.exception( self.name + ": TIMEOUT exception found while starting Mininet" )
247 main.log.error( self.name + ": " + self.handle.before )
adminbae64d82013-08-01 10:50:15 -0700248 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700249 except pexpect.EOF:
250 main.log.error( self.name + ": EOF exception found" )
251 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700252 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700253 except Exception:
254 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700255 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800256
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800257 def numSwitchesNlinks( self, topoType, depth, fanout ):
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700258 try:
259 if topoType == 'tree':
260 # In tree topology, if fanout arg is not given, by default it is 2
261 if fanout is None:
262 fanout = 2
263 k = 0
264 count = 0
265 while( k <= depth - 1 ):
266 count = count + pow( fanout, k )
267 k = k + 1
268 numSwitches = count
269 while( k <= depth - 2 ):
270 # depth-2 gives you only core links and not considering
271 # edge links as seen by ONOS. If all the links including
272 # edge links are required, do depth-1
273 count = count + pow( fanout, k )
274 k = k + 1
275 numLinks = count * fanout
276 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
277 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800278
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700279 elif topoType == 'linear':
280 # In linear topology, if fanout or numHostsPerSw is not given,
281 # by default it is 1
282 if fanout is None:
283 fanout = 1
284 numSwitches = depth
285 numHostsPerSw = fanout
286 totalNumHosts = numSwitches * numHostsPerSw
287 numLinks = totalNumHosts + ( numSwitches - 1 )
288 print "num_switches for %s(%d,%d) = %d and links=%d" %\
289 ( topoType, depth, fanout, numSwitches, numLinks )
290 topoDict = { "num_switches": int( numSwitches ),
291 "num_corelinks": int( numLinks ) }
292 return topoDict
293 except Exception:
294 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700295 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400296
kelvin-onlabd3b64892015-01-20 13:26:24 -0800297 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700298 """
299 Calculate the number of switches and links in a topo."""
300 # TODO: combine this function and numSwitchesNlinks
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700301 try:
302 argList = self.options[ 'arg1' ].split( "," )
303 topoArgList = argList[ 0 ].split( " " )
304 argList = map( int, argList[ 1: ] )
305 topoArgList = topoArgList[ 1: ] + argList
Jon Hall689d8e42015-04-03 13:59:24 -0700306
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700307 topoDict = self.numSwitchesNlinks( *topoArgList )
308 return topoDict
309 except Exception:
310 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700311 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400312
GlennRCf07c44a2015-09-18 13:33:46 -0700313 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800314 """
315 Verifies the reachability of the hosts using pingall command.
316 Optional parameter timeout allows you to specify how long to
317 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700318 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700319 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700320 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700321 ping
322 acceptableFailed - Set the number of acceptable failed pings for the
323 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800324 Returns:
325 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700326 otherwise main.FALSE
327 """
328 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700329 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700330 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700331 if self.handle:
332 main.log.info(
333 self.name +
334 ": Checking reachabilty to the hosts using pingall" )
335 response = ""
336 failedPings = 0
337 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700338 cmd = "pingall"
339 if protocol == "IPv6":
340 cmd = "py net.pingAll6()"
341 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700342 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700343 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700344 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700345 pexpect.EOF,
346 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700347 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700348 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700349 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700350 response += self.handle.before
351 break
352 elif i == 1:
353 response += self.handle.before + self.handle.after
354 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700355 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700356 returnValue = main.FALSE
357 if shortCircuit:
358 main.log.error( self.name +
359 ": Aborting pingall - "
360 + str( failedPings ) +
361 " pings failed" )
362 break
Jon Hall390696c2015-05-05 17:13:41 -0700363 if ( time.time() - startTime ) > timeout:
364 returnValue = main.FALSE
365 main.log.error( self.name +
366 ": Aborting pingall - " +
367 "Function took too long " )
368 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700369 elif i == 2:
370 main.log.error( self.name +
371 ": EOF exception found" )
372 main.log.error( self.name + ": " +
373 self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700374 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700375 elif i == 3:
376 response += self.handle.before
377 main.log.error( self.name +
378 ": TIMEOUT exception found" )
379 main.log.error( self.name +
380 ": " +
381 str( response ) )
382 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800383 self.handle.send( "\x03" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700384 self.handle.expect( "Interrupt" )
385 self.handle.expect( "mininet>" )
386 break
387 pattern = "Results\:"
388 main.log.info( "Pingall output: " + str( response ) )
389 if re.search( pattern, response ):
390 main.log.info( self.name + ": Pingall finished with "
391 + str( failedPings ) + " failed pings" )
392 return returnValue
393 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700394 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800395 self.handle.send( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700396 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700397 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700398 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700399 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700400 main.log.error( self.name + ": Connection failed to the host" )
Devin Lim44075962017-08-11 10:56:37 -0700401 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700402 except pexpect.TIMEOUT:
403 if response:
404 main.log.info( "Pingall output: " + str( response ) )
405 main.log.error( self.name + ": pexpect.TIMEOUT found" )
406 return main.FALSE
407 except pexpect.EOF:
408 main.log.error( self.name + ": EOF exception found" )
409 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700410 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -0700411
Jon Hall7eb38402015-01-08 17:19:54 -0800412 def fpingHost( self, **pingParams ):
413 """
414 Uses the fping package for faster pinging...
415 *requires fping to be installed on machine running mininet"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700416 try:
417 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
418 command = args[ "SRC" ] + \
419 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
420 self.handle.sendline( command )
421 self.handle.expect(
422 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
423 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
424 response = self.handle.before
425 if re.search( ":\s-", response ):
426 main.log.info( self.name + ": Ping fail" )
427 return main.FALSE
428 elif re.search( ":\s\d{1,2}\.\d\d", response ):
429 main.log.info( self.name + ": Ping good!" )
430 return main.TRUE
431 main.log.info( self.name + ": Install fping on mininet machine... " )
432 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700433 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700434 except Exception:
435 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700436 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700437
Jon Hall3b489db2015-10-05 14:38:37 -0700438 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400439 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700440 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700441
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400442 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700443 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700444
445 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400446 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700447
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400448 Returns main.FALSE if one or more of hosts specified
449 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700450 wait = int( wait )
451 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400452
453 try:
454 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700455
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400456 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700457 pingResponse = "IPv4 ping across specified hosts\n"
458 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400459 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700460 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400461 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700462 pingList = hostList[ :listIndex ] + \
463 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700464
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700465 pingResponse += str( str( host ) + " -> " )
GlennRCd10d3cc2015-09-24 12:47:16 -0700466
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400467 for temp in pingList:
468 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700469 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700470 self.handle.sendline( pingCmd )
471 self.handle.expect( "mininet>", timeout=wait + 1 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400472 response = self.handle.before
473 if re.search( ',\s0\%\spacket\sloss', response ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700474 pingResponse += str( " h" + str( temp[ 1: ] ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400475 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700476 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400477 # One of the host to host pair is unreachable
478 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700479 failedPings += 1
You Wang11f9ead2018-03-21 14:34:59 -0700480 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
GlennRCd10d3cc2015-09-24 12:47:16 -0700481 pingResponse += "\n"
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700482 main.log.info( pingResponse + "Failed pings: " + str( failedPings ) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700483 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700484 except pexpect.TIMEOUT:
485 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800486 response = self.handle.before
487 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700488 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800489 self.handle.expect( "Interrupt" )
490 response += self.handle.before + self.handle.after
491 self.handle.expect( "mininet>" )
492 response += self.handle.before + self.handle.after
493 main.log.debug( response )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700494 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400495 except pexpect.EOF:
496 main.log.error( self.name + ": EOF exception found" )
497 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700498 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700499 except Exception:
500 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700501 main.cleanAndExit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400502
You Wangf19d9f42018-02-23 16:34:19 -0800503 def pingIpv6Hosts( self, hostList, wait=1, acceptableFailed=0 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700504 """
You Wangf19d9f42018-02-23 16:34:19 -0800505 IPv6 ping all hosts in hostList.
506
507 acceptableFailed: max number of acceptable failed pings
Hari Krishna9592fc82015-07-31 15:11:15 -0700508
Jon Hall3b489db2015-10-05 14:38:37 -0700509 Returns main.TRUE if all hosts specified can reach each other
Jon Hall3b489db2015-10-05 14:38:37 -0700510 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700511 """
512 try:
513 main.log.info( "Testing reachability between specified IPv6 hosts" )
514 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700515 wait = int( wait )
516 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700517 pingResponse = "IPv6 Pingall output:\n"
You Wangf19d9f42018-02-23 16:34:19 -0800518 failedPingsTotal = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700519 for host in hostList:
520 listIndex = hostList.index( host )
521 # List of hosts to ping other than itself
522 pingList = hostList[ :listIndex ] + \
523 hostList[ ( listIndex + 1 ): ]
524
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700525 pingResponse += str( str( host ) + " -> " )
GlennRC2cf7d952015-09-11 16:32:13 -0700526
Hari Krishna9592fc82015-07-31 15:11:15 -0700527 for temp in pingList:
528 # Current host pings all other hosts specified
You Wangf19d9f42018-02-23 16:34:19 -0800529 failedPings = 0
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700530 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
You Wangf19d9f42018-02-23 16:34:19 -0800531 while failedPings <= acceptableFailed:
532 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
533 self.handle.sendline( pingCmd )
534 self.handle.expect( "mininet>", timeout=wait + 1 )
535 response = self.handle.before
536 if re.search( ',\s0\%\spacket\sloss', response ):
You Wangba231e72018-03-01 13:18:21 -0800537 pingResponse += " " + str( temp )
538 break
539 else:
540 failedPings += 1
541 time.sleep(1)
542 if failedPings > acceptableFailed:
543 # One of the host to host pair is unreachable
544 pingResponse += " X"
545 isReachable = main.FALSE
546 failedPingsTotal += 1
You Wang11f9ead2018-03-21 14:34:59 -0700547 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
You Wangba231e72018-03-01 13:18:21 -0800548 pingResponse += "\n"
549 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
550 return isReachable
551
552 except pexpect.TIMEOUT:
553 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800554 response = self.handle.before
555 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700556 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800557 self.handle.expect( "Interrupt" )
558 response += self.handle.before + self.handle.after
559 self.handle.expect( "mininet>" )
560 response += self.handle.before + self.handle.after
561 main.log.debug( response )
You Wangba231e72018-03-01 13:18:21 -0800562 return main.FALSE
563 except pexpect.EOF:
564 main.log.error( self.name + ": EOF exception found" )
565 main.log.error( self.name + ": " + self.handle.before )
566 main.cleanAndExit()
567 except Exception:
568 main.log.exception( self.name + ": Uncaught exception!" )
569 main.cleanAndExit()
570
571 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
572 """
573 Verify ping from each host in srcList to each host in dstList
574
575 acceptableFailed: max number of acceptable failed pings
576
577 Returns main.TRUE if all src hosts can reach all dst hosts
578 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
579 """
580 try:
581 main.log.info( "Verifying ping from each src host to each dst host" )
582 isReachable = main.TRUE
583 wait = int( wait )
584 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
585 pingResponse = "Ping output:\n"
586 failedPingsTotal = 0
587 for host in srcList:
588 pingResponse += str( str( host ) + " -> " )
589 for temp in dstList:
590 failedPings = 0
591 if ipv6:
592 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
593 else:
594 pingCmd = str( host ) + cmd + str( temp )
595 while failedPings <= acceptableFailed:
596 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
597 self.handle.sendline( pingCmd )
598 self.handle.expect( "mininet>", timeout=wait + 1 )
599 response = self.handle.before
600 if re.search( ',\s0\%\spacket\sloss', response ):
601 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800602 break
603 else:
604 failedPings += 1
605 time.sleep(1)
606 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700607 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800608 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700609 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800610 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700611 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800612 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700613 return isReachable
614
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700615 except pexpect.TIMEOUT:
616 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800617 response = self.handle.before
618 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700619 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800620 self.handle.expect( "Interrupt" )
621 response += self.handle.before + self.handle.after
622 self.handle.expect( "mininet>" )
623 response += self.handle.before + self.handle.after
624 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700625 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700626 except pexpect.EOF:
627 main.log.error( self.name + ": EOF exception found" )
628 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700629 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700630 except Exception:
631 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700632 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700633
Jon Hall7eb38402015-01-08 17:19:54 -0800634 def pingHost( self, **pingParams ):
635 """
Jon Hall3b489db2015-10-05 14:38:37 -0700636 Ping from one mininet host to another
637 Currently the only supported Params: SRC, TARGET, and WAIT
638 """
639 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700640 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700641 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800642 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700643 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700644 try:
Jon Hall61282e32015-03-19 11:34:11 -0700645 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800646 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700647 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
648 timeout=wait + 1 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700649 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800650 main.log.error(
651 self.name +
652 ": timeout when waiting for response from mininet" )
653 main.log.error( "response: " + str( self.handle.before ) )
654 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700655 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800656 main.log.error(
657 self.name +
658 ": timeout when waiting for response from mininet" )
659 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700660 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700661 if re.search( ',\s0\%\spacket\sloss', response ):
662 main.log.info( self.name + ": no packets lost, host is reachable" )
663 return main.TRUE
664 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800665 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700666 self.name +
667 ": PACKET LOST, HOST IS NOT REACHABLE" )
668 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800669 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800670 main.log.error( self.name + ": EOF exception found" )
671 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700672 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700673 except Exception:
674 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700675 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700676
677 def ping6pair( self, **pingParams ):
678 """
GlennRC2cf7d952015-09-11 16:32:13 -0700679 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700680 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000681 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700682 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
683 """
Jon Hall3b489db2015-10-05 14:38:37 -0700684 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700685 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700686 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530687 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700688 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700689 try:
690 main.log.info( "Sending: " + command )
691 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700692 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
693 timeout=wait + 1 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700694 if i == 1:
695 main.log.error(
696 self.name +
697 ": timeout when waiting for response from mininet" )
698 main.log.error( "response: " + str( self.handle.before ) )
699 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
700 if i == 1:
701 main.log.error(
702 self.name +
703 ": timeout when waiting for response from mininet" )
704 main.log.error( "response: " + str( self.handle.before ) )
705 response = self.handle.before
706 main.log.info( self.name + ": Ping Response: " + response )
707 if re.search( ',\s0\%\spacket\sloss', response ):
708 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700709 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700710 else:
alisone4121a92016-11-22 16:31:36 -0800711 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700712 self.name +
713 ": PACKET LOST, HOST IS NOT REACHABLE" )
714 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700715 except pexpect.EOF:
716 main.log.error( self.name + ": EOF exception found" )
717 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700718 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700719 except Exception:
720 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700721 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800722
You Wangdb927a52016-02-26 11:03:28 -0800723 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
724 """
725 Description:
726 Ping a set of destination host from host CLI.
727 Logging into a Mininet host CLI is required before calling this funtion.
728 Params:
729 dstIPList is a list of destination ip addresses
730 Returns:
731 main.TRUE if the destination host is reachable
732 main.FALSE otherwise
733 """
734 isReachable = main.TRUE
735 wait = int( wait )
736 cmd = "ping"
737 if IPv6:
738 cmd = cmd + "6"
739 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
740 try:
741 for dstIP in dstIPList:
742 pingCmd = cmd + " " + dstIP
743 self.handle.sendline( pingCmd )
744 i = self.handle.expect( [ self.hostPrompt,
745 '\*\*\* Unknown command: ' + pingCmd,
746 pexpect.TIMEOUT ],
747 timeout=wait + 1 )
748 if i == 0:
749 response = self.handle.before
750 if not re.search( ',\s0\%\spacket\sloss', response ):
751 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
752 isReachable = main.FALSE
753 elif i == 1:
754 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700755 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800756 elif i == 2:
757 main.log.error( self.name + ": timeout when waiting for response" )
758 isReachable = main.FALSE
759 else:
760 main.log.error( self.name + ": unknown response: " + self.handle.before )
761 isReachable = main.FALSE
762 except pexpect.TIMEOUT:
763 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800764 response = self.handle.before
765 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700766 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800767 self.handle.expect( "Interrupt" )
768 response += self.handle.before + self.handle.after
769 self.handle.expect( "mininet>" )
770 response += self.handle.before + self.handle.after
771 main.log.debug( response )
You Wangdb927a52016-02-26 11:03:28 -0800772 isReachable = main.FALSE
773 except pexpect.EOF:
774 main.log.error( self.name + ": EOF exception found" )
775 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700776 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800777 except Exception:
778 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700779 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800780 return isReachable
781
Jon Hall7eb38402015-01-08 17:19:54 -0800782 def checkIP( self, host ):
783 """
784 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700785 try:
786 if self.handle:
787 try:
788 response = self.execute(
789 cmd=host +
790 " ifconfig",
791 prompt="mininet>",
792 timeout=10 )
793 except pexpect.EOF:
794 main.log.error( self.name + ": EOF exception found" )
795 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700796 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700797
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700798 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
799 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
800 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
801 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
802 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
803 "[0-9]|25[0-5]|[0-9]{1,2})"
804 # pattern = "inet addr:10.0.0.6"
805 if re.search( pattern, response ):
806 main.log.info( self.name + ": Host Ip configured properly" )
807 return main.TRUE
808 else:
809 main.log.error( self.name + ": Host IP not found" )
810 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700811 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700812 main.log.error( self.name + ": Connection failed to the host" )
813 except Exception:
814 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700815 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800816
Jon Hall7eb38402015-01-08 17:19:54 -0800817 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800818 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700819 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800820 response = self.execute(
821 cmd="h1 /usr/sbin/sshd -D&",
822 prompt="mininet>",
823 timeout=10 )
824 response = self.execute(
825 cmd="h4 /usr/sbin/sshd -D&",
826 prompt="mininet>",
827 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700828 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800829 vars( self )[ key ] = connectargs[ key ]
830 response = self.execute(
831 cmd="xterm h1 h4 ",
832 prompt="mininet>",
833 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800834 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800835 main.log.error( self.name + ": EOF exception found" )
836 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700837 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700838 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800839 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700840 if self.flag == 0:
841 self.flag = 1
842 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800843 else:
adminbae64d82013-08-01 10:50:15 -0700844 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800845
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700846 def moveHost( self, host, oldSw, newSw ):
Jon Hall53c5e662016-04-13 16:06:56 -0700847 """
848 Moves a host from one switch to another on the fly
849 Note: The intf between host and oldSw when detached
850 using detach(), will still show up in the 'net'
851 cmd, because switch.detach() doesn't affect switch.intfs[]
852 ( which is correct behavior since the interfaces
853 haven't moved ).
854 """
855 if self.handle:
856 try:
857 # Bring link between oldSw-host down
858 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
859 "'," + "'down')"
860 print "cmd1= ", cmd
861 response = self.execute( cmd=cmd,
862 prompt="mininet>",
863 timeout=10 )
864
865 # Determine hostintf and Oldswitchintf
866 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
867 ")[0]"
868 print "cmd2= ", cmd
869 self.handle.sendline( cmd )
870 self.handle.expect( "mininet>" )
871
872 # Determine ip and mac address of the host-oldSw interface
873 cmd = "px ipaddr = hintf.IP()"
874 print "cmd3= ", cmd
875 self.handle.sendline( cmd )
876 self.handle.expect( "mininet>" )
877
878 cmd = "px macaddr = hintf.MAC()"
879 print "cmd3= ", cmd
880 self.handle.sendline( cmd )
881 self.handle.expect( "mininet>" )
882
883 # Detach interface between oldSw-host
884 cmd = "px " + oldSw + ".detach( sintf )"
885 print "cmd4= ", cmd
886 self.handle.sendline( cmd )
887 self.handle.expect( "mininet>" )
888
889 # Add link between host-newSw
890 cmd = "py net.addLink(" + host + "," + newSw + ")"
891 print "cmd5= ", cmd
892 self.handle.sendline( cmd )
893 self.handle.expect( "mininet>" )
894
895 # Determine hostintf and Newswitchintf
896 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
897 ")[0]"
898 print "cmd6= ", cmd
899 self.handle.sendline( cmd )
900 self.handle.expect( "mininet>" )
901
902 # Attach interface between newSw-host
903 cmd = "px " + newSw + ".attach( sintf )"
904 print "cmd3= ", cmd
905 self.handle.sendline( cmd )
906 self.handle.expect( "mininet>" )
907
908 # Set ipaddress of the host-newSw interface
909 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
910 print "cmd7 = ", cmd
911 self.handle.sendline( cmd )
912 self.handle.expect( "mininet>" )
913
914 # Set macaddress of the host-newSw interface
915 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
916 print "cmd8 = ", cmd
917 self.handle.sendline( cmd )
918 self.handle.expect( "mininet>" )
919
920 cmd = "net"
921 print "cmd9 = ", cmd
922 self.handle.sendline( cmd )
923 self.handle.expect( "mininet>" )
924 print "output = ", self.handle.before
925
926 # Determine ipaddress of the host-newSw interface
927 cmd = host + " ifconfig"
928 print "cmd10= ", cmd
929 self.handle.sendline( cmd )
930 self.handle.expect( "mininet>" )
931 print "ifconfig o/p = ", self.handle.before
932
933 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700934
935 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700936 main.log.error( self.name + ": TIMEOUT exception found" )
937 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700938 main.cleanAndExit()
Jon Hall53c5e662016-04-13 16:06:56 -0700939 except pexpect.EOF:
940 main.log.error( self.name + ": EOF exception found" )
941 main.log.error( self.name + ": " + self.handle.before )
942 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700943 except Exception:
944 main.log.exception( self.name + ": Uncaught exception!" )
945 return main.FALSE
Jon Hall53c5e662016-04-13 16:06:56 -0700946
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700947 def moveHostv6( self, host, oldSw, newSw ):
kelvin-onlaba1484582015-02-02 15:46:20 -0800948 """
949 Moves a host from one switch to another on the fly
950 Note: The intf between host and oldSw when detached
951 using detach(), will still show up in the 'net'
952 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700953 ( which is correct behavior since the interfaces
954 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800955 """
956 if self.handle:
957 try:
Jon Hall439c8912016-04-15 02:22:03 -0700958 IP = str( self.getIPAddress( host, proto='IPV6' ) ) + "/64"
kelvin-onlaba1484582015-02-02 15:46:20 -0800959 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700960 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800961 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800962 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800963 response = self.execute( cmd=cmd,
964 prompt="mininet>",
965 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700966
kelvin-onlaba1484582015-02-02 15:46:20 -0800967 # Determine hostintf and Oldswitchintf
968 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800969 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800970 print "cmd2= ", cmd
971 self.handle.sendline( cmd )
972 self.handle.expect( "mininet>" )
973
shahshreya73537862015-02-11 15:15:24 -0800974 # Determine ip and mac address of the host-oldSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700975 cmd = "px ipaddr = " + str( IP )
kelvin-onlaba1484582015-02-02 15:46:20 -0800976 print "cmd3= ", cmd
977 self.handle.sendline( cmd )
978 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800979
980 cmd = "px macaddr = hintf.MAC()"
981 print "cmd3= ", cmd
982 self.handle.sendline( cmd )
983 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700984
kelvin-onlaba1484582015-02-02 15:46:20 -0800985 # Detach interface between oldSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700986 cmd = "px " + oldSw + ".detach(sintf)"
kelvin-onlaba1484582015-02-02 15:46:20 -0800987 print "cmd4= ", cmd
988 self.handle.sendline( cmd )
989 self.handle.expect( "mininet>" )
990
991 # Add link between host-newSw
992 cmd = "py net.addLink(" + host + "," + newSw + ")"
993 print "cmd5= ", cmd
994 self.handle.sendline( cmd )
995 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700996
kelvin-onlaba1484582015-02-02 15:46:20 -0800997 # Determine hostintf and Newswitchintf
998 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800999 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -08001000 print "cmd6= ", cmd
1001 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -07001002 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001003
1004 # Attach interface between newSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001005 cmd = "px " + newSw + ".attach(sintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001006 print "cmd6= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001007 self.handle.sendline( cmd )
1008 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -08001009
1010 # Set macaddress of the host-newSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001011 cmd = "px " + host + ".setMAC(mac = macaddr, intf = hintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001012 print "cmd7 = ", cmd
1013 self.handle.sendline( cmd )
1014 self.handle.expect( "mininet>" )
1015
1016 # Set ipaddress of the host-newSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001017 cmd = "px " + host + ".setIP(ip = ipaddr, intf = hintf)"
shahshreya73537862015-02-11 15:15:24 -08001018 print "cmd8 = ", cmd
1019 self.handle.sendline( cmd )
1020 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001021
Jon Hall439c8912016-04-15 02:22:03 -07001022 cmd = host + " ifconfig"
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001023 print "cmd9 =", cmd
1024 response = self.execute( cmd = cmd, prompt="mininet>", timeout=10 )
Jon Hall439c8912016-04-15 02:22:03 -07001025 print response
1026 pattern = "h\d-eth([\w])"
Jeremyd9e4eb12016-04-13 12:09:06 -07001027 ipAddressSearch = re.search( pattern, response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001028 print ipAddressSearch.group( 1 )
1029 intf = host + "-eth" + str( ipAddressSearch.group( 1 ) )
Jon Hall439c8912016-04-15 02:22:03 -07001030 cmd = host + " ip -6 addr add %s dev %s" % ( IP, intf )
1031 print "cmd10 = ", cmd
1032 self.handle.sendline( cmd )
1033 self.handle.expect( "mininet>" )
1034
kelvin-onlaba1484582015-02-02 15:46:20 -08001035 cmd = "net"
Jon Hall439c8912016-04-15 02:22:03 -07001036 print "cmd11 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001037 self.handle.sendline( cmd )
1038 self.handle.expect( "mininet>" )
1039 print "output = ", self.handle.before
1040
1041 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -08001042 cmd = host + " ifconfig"
Jon Hall439c8912016-04-15 02:22:03 -07001043 print "cmd12= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001044 self.handle.sendline( cmd )
1045 self.handle.expect( "mininet>" )
1046 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -07001047
kelvin-onlaba1484582015-02-02 15:46:20 -08001048 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001049 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001050 main.log.error( self.name + ": TIMEOUT exception found" )
1051 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001052 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08001053 except pexpect.EOF:
1054 main.log.error( self.name + ": EOF exception found" )
1055 main.log.error( self.name + ": " + self.handle.before )
1056 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001057 except Exception:
1058 main.log.exception( self.name + ": Uncaught exception!" )
1059 return main.FALSE
kelvin-onlaba1484582015-02-02 15:46:20 -08001060
Jon Hall7eb38402015-01-08 17:19:54 -08001061 def changeIP( self, host, intf, newIP, newNetmask ):
1062 """
1063 Changes the ip address of a host on the fly
1064 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001065 if self.handle:
1066 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001067 cmd = host + " ifconfig " + intf + " " + \
1068 newIP + " " + 'netmask' + " " + newNetmask
1069 self.handle.sendline( cmd )
1070 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001071 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001072 main.log.info( "response = " + response )
1073 main.log.info(
1074 "Ip of host " +
1075 host +
1076 " changed to new IP " +
1077 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -08001078 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001079 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001080 main.log.error( self.name + ": TIMEOUT exception found" )
1081 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001082 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001083 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001084 main.log.error( self.name + ": EOF exception found" )
1085 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001086 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001087 except Exception:
1088 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001089 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001090
Jon Hall7eb38402015-01-08 17:19:54 -08001091 def changeDefaultGateway( self, host, newGW ):
1092 """
1093 Changes the default gateway of a host
1094 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001095 if self.handle:
1096 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001097 cmd = host + " route add default gw " + newGW
1098 self.handle.sendline( cmd )
1099 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001100 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001101 main.log.info( "response = " + response )
1102 main.log.info(
1103 "Default gateway of host " +
1104 host +
1105 " changed to " +
1106 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -08001107 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001108 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001109 main.log.error( self.name + ": TIMEOUT exception found" )
1110 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001111 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001112 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001113 main.log.error( self.name + ": EOF exception found" )
1114 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001115 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001116 except Exception:
1117 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001118 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001119
Jon Hall7eb38402015-01-08 17:19:54 -08001120 def addStaticMACAddress( self, host, GW, macaddr ):
1121 """
Jon Hallefbd9792015-03-05 16:11:36 -08001122 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001123 if self.handle:
1124 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001125 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1126 cmd = host + " arp -s " + GW + " " + macaddr
1127 self.handle.sendline( cmd )
1128 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001129 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001130 main.log.info( "response = " + response )
1131 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001132 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001133 GW +
1134 " changed to " +
1135 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001136 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001137 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001138 main.log.error( self.name + ": TIMEOUT exception found" )
1139 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001140 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001141 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001142 main.log.error( self.name + ": EOF exception found" )
1143 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001144 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001145 except Exception:
1146 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001147 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001148
Jon Hall7eb38402015-01-08 17:19:54 -08001149 def verifyStaticGWandMAC( self, host ):
1150 """
1151 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001152 if self.handle:
1153 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001154 # h1 arp -an
1155 cmd = host + " arp -an "
1156 self.handle.sendline( cmd )
1157 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001158 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001159 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001160 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001161 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001162 main.log.error( self.name + ": TIMEOUT exception found" )
1163 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001164 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001165 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001166 main.log.error( self.name + ": EOF exception found" )
1167 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001168 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001169 except Exception:
1170 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001171 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001172
Jon Hall7eb38402015-01-08 17:19:54 -08001173 def getMacAddress( self, host ):
1174 """
1175 Verifies the host's ip configured or not."""
1176 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001177 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001178 response = self.execute(
1179 cmd=host +
1180 " ifconfig",
1181 prompt="mininet>",
1182 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001183 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001184 main.log.error( self.name + ": EOF exception found" )
1185 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001186 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001187 except Exception:
1188 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001189 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001190
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001191 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001192 macAddressSearch = re.search( pattern, response, re.I )
1193 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001194 main.log.info(
1195 self.name +
1196 ": Mac-Address of Host " +
1197 host +
1198 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001199 macAddress )
1200 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001201 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001202 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001203
Jon Hall7eb38402015-01-08 17:19:54 -08001204 def getInterfaceMACAddress( self, host, interface ):
1205 """
1206 Return the IP address of the interface on the given host"""
1207 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001208 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001209 response = self.execute( cmd=host + " ifconfig " + interface,
1210 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001211 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001212 main.log.error( self.name + ": EOF exception found" )
1213 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001214 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001215 except Exception:
1216 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001217 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001218
1219 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001220 macAddressSearch = re.search( pattern, response, re.I )
1221 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001222 main.log.info( "No mac address found in %s" % response )
1223 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001224 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001225 main.log.info(
1226 "Mac-Address of " +
1227 host +
1228 ":" +
1229 interface +
1230 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001231 macAddress )
1232 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001233 else:
1234 main.log.error( "Connection failed to the host" )
1235
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001236 def getIPAddress( self, host , proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001237 """
1238 Verifies the host's ip configured or not."""
1239 if self.handle:
1240 try:
1241 response = self.execute(
1242 cmd=host +
1243 " ifconfig",
1244 prompt="mininet>",
1245 timeout=10 )
1246 except pexpect.EOF:
1247 main.log.error( self.name + ": EOF exception found" )
1248 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001249 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001250 except Exception:
1251 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001252 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001253
sathishmad953462015-12-03 17:42:07 +05301254 pattern = ''
1255 if proto == 'IPV4':
1256 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
1257 else:
Jon Hall439c8912016-04-15 02:22:03 -07001258 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001259 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001260 if not ipAddressSearch:
1261 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001262 main.log.info(
1263 self.name +
1264 ": IP-Address of Host " +
1265 host +
1266 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001267 ipAddressSearch.group( 1 ) )
1268 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001269 else:
1270 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001271
Jon Hall7eb38402015-01-08 17:19:54 -08001272 def getSwitchDPID( self, switch ):
1273 """
1274 return the datapath ID of the switch"""
1275 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001276 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001277 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001278 response = self.execute(
1279 cmd=cmd,
1280 prompt="mininet>",
1281 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001282 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001283 main.log.error( self.name + ": EOF exception found" )
1284 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001285 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001286 except Exception:
1287 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001288 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001289 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001290 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001291 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001292 main.log.info(
1293 "Couldn't find DPID for switch %s, found: %s" %
1294 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001295 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001296 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001297 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001298 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001299
Jon Hall7eb38402015-01-08 17:19:54 -08001300 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001301 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001302 self.handle.sendline( "" )
1303 self.expect( "mininet>" )
1304 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001305 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001306 response = self.execute(
1307 cmd=cmd,
1308 prompt="mininet>",
1309 timeout=10 )
1310 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001311 response = self.handle.before
1312 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001313 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001314 main.log.error( self.name + ": TIMEOUT exception found" )
1315 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001316 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001317 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001318 main.log.error( self.name + ": EOF exception found" )
1319 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001320 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001321 except Exception:
1322 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001323 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001324
Jon Hall7eb38402015-01-08 17:19:54 -08001325 def getInterfaces( self, node ):
1326 """
1327 return information dict about interfaces connected to the node"""
1328 if self.handle:
1329 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001330 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001331 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001332 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001333 response = self.execute(
1334 cmd=cmd,
1335 prompt="mininet>",
1336 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001337 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001338 main.log.error( self.name + ": EOF exception found" )
1339 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001340 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001341 except Exception:
1342 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001343 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001344 return response
1345 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001346 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001347
Jon Hall7eb38402015-01-08 17:19:54 -08001348 def dump( self ):
1349 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001350 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001351 response = self.execute(
1352 cmd='dump',
1353 prompt='mininet>',
1354 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001355 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001356 main.log.error( self.name + ": EOF exception found" )
1357 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001358 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001359 except Exception:
1360 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001361 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001362 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001363
Jon Hall7eb38402015-01-08 17:19:54 -08001364 def intfs( self ):
1365 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001366 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001367 response = self.execute(
1368 cmd='intfs',
1369 prompt='mininet>',
1370 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001371 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001372 main.log.error( self.name + ": EOF exception found" )
1373 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001374 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001375 except Exception:
1376 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001377 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001378 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001379
Jon Hall7eb38402015-01-08 17:19:54 -08001380 def net( self ):
1381 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001382 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001383 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001384 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001385 main.log.error( self.name + ": EOF exception found" )
1386 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001387 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001388 except Exception:
1389 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001390 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001391 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001392
Devin Lima7cfdbd2017-09-29 15:02:22 -07001393 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001394 main.log.info( self.name + ": List network links" )
1395 try:
1396 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001397 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001398 except pexpect.EOF:
1399 main.log.error( self.name + ": EOF exception found" )
1400 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001401 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001402 except Exception:
1403 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001404 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001405 return response
1406
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001407 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001408 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001409 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001410
kelvin-onlab7cce9382015-07-17 10:21:03 -07001411 @parm:
1412 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1413 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001414 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001415 try:
1416 for host1 in hosts:
1417 for host2 in hosts:
1418 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001419 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1420 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001421 except Exception:
1422 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001423 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001424
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001425 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001426 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001427 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1428 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001429
kelvin-onlab7cce9382015-07-17 10:21:03 -07001430 @parm:
1431 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1432 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001433 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001434 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1435 try:
1436 # Setup the mininet command
1437 cmd1 = 'iperf ' + host1 + " " + host2
1438 self.handle.sendline( cmd1 )
1439 outcome = self.handle.expect( "mininet>", timeout )
1440 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001441
kelvin-onlab7cce9382015-07-17 10:21:03 -07001442 # checks if there are results in the mininet response
1443 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001444 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001445 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001446 response = response.split( "\r\n" )
1447 response = response[ len( response )-2 ]
1448 response = response.split( ": " )
1449 response = response[ len( response )-1 ]
1450 response = response.replace( "[", "" )
1451 response = response.replace( "]", "" )
1452 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001453
kelvin-onlab7cce9382015-07-17 10:21:03 -07001454 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001455 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001456
kelvin-onlab7cce9382015-07-17 10:21:03 -07001457 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001458 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001459 if len( bandwidth ) == 2:
1460 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001461 return main.TRUE
1462 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001463 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001464 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001465 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001466 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001467 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001468 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001469 main.log.error( self.name + ": TIMEOUT exception found" )
1470 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001471 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001472 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001473 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001474 self.handle.expect( "Interrupt" )
1475 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001476 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001477 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001478 main.log.error( self.name + ": EOF exception found" )
1479 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001480 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001481 except Exception:
1482 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001483 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001484
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001485 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001486 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1487 try:
1488 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001489 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001490 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001491 outcome1 = self.handle.expect( "mininet>" )
1492 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001493 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001494 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001495 response1 = self.handle.before
1496 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001497 print response1, response2
1498 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001499 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001500 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001501 return main.TRUE
1502 else:
1503 main.log.error( self.name + ": iperf test failed" )
1504 return main.FALSE
1505 except pexpect.TIMEOUT:
1506 main.log.error( self.name + ": TIMEOUT exception found" )
1507 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001508 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001509 self.handle.expect( "Interrupt" )
1510 self.handle.expect( "mininet>" )
1511 return main.FALSE
1512 except pexpect.EOF:
1513 main.log.error( self.name + ": EOF exception found" )
1514 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001515 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001516 except Exception:
1517 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001518 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001519
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001520 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001521 '''
GlennRC61321f22015-07-16 13:36:54 -07001522 Runs the iperfudp function with a given set of hosts and specified
1523 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001524
GlennRC61321f22015-07-16 13:36:54 -07001525 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001526 bandwidth: the targeted bandwidth, in megabits ('M')
1527 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001528 try:
1529 for host1 in hosts:
1530 for host2 in hosts:
1531 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001532 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1533 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001534 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001535 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001536 return main.FALSE
1537 except Exception:
1538 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001539 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001540
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001541 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001542 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001543 Creates an iperf UDP test with a specific bandwidth.
1544 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001545
kelvin-onlab7cce9382015-07-17 10:21:03 -07001546 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001547 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1548 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001549 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001550 try:
1551 # setup the mininet command
1552 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001553 self.handle.sendline( cmd )
1554 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001555 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001556
kelvin-onlab7cce9382015-07-17 10:21:03 -07001557 # check if there are in results in the mininet response
1558 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001559 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001560 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001561 response = response.split( "\r\n" )
1562 response = response[ len( response )-2 ]
1563 response = response.split( ": " )
1564 response = response[ len( response )-1 ]
1565 response = response.replace( "[", "" )
1566 response = response.replace( "]", "" )
1567 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001568
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001569 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001570
kelvin-onlab7cce9382015-07-17 10:21:03 -07001571 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001572 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001573 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001574 # if one entry is blank then something is wrong
1575 for item in mnBandwidth:
1576 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001577 main.log.error( self.name + ": Could not parse iperf output" )
1578 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001579 return main.FALSE
1580 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001581 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001582 return main.TRUE
1583 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001584 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001585 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001586
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001587 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001588 main.log.error( self.name + ": TIMEOUT exception found" )
1589 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001590 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001591 except pexpect.EOF:
1592 main.log.error( self.name + ": EOF exception found" )
1593 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001594 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001595 except Exception:
1596 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001597 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001598
Jon Hall7eb38402015-01-08 17:19:54 -08001599 def nodes( self ):
1600 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001601 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001602 response = self.execute(
1603 cmd='nodes',
1604 prompt='mininet>',
1605 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001606 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001607 main.log.error( self.name + ": EOF exception found" )
1608 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001609 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001610 except Exception:
1611 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001612 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001613 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001614
Jon Hall7eb38402015-01-08 17:19:54 -08001615 def pingpair( self ):
1616 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001617 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001618 response = self.execute(
1619 cmd='pingpair',
1620 prompt='mininet>',
1621 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001622 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001623 main.log.error( self.name + ": EOF exception found" )
1624 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001625 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001626 except Exception:
1627 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001628 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001629
Jon Hall7eb38402015-01-08 17:19:54 -08001630 if re.search( ',\s0\%\spacket\sloss', response ):
1631 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001632 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001633 else:
alisone4121a92016-11-22 16:31:36 -08001634 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001635 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001636
Jon Hall7eb38402015-01-08 17:19:54 -08001637 def link( self, **linkargs ):
1638 """
GlennRCed771242016-01-13 17:02:47 -08001639 Bring link( s ) between two nodes up or down
1640 """
Jon Hall6094a362014-04-11 14:46:56 -07001641 try:
GlennRCed771242016-01-13 17:02:47 -08001642 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1643 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1644 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1645 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1646
1647 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1648 cmd = "link {} {} {}".format( end1, end2, option )
1649 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001650 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001651 response = self.handle.before
1652 main.log.info( response )
1653
1654 return main.TRUE
1655 except pexpect.TIMEOUT:
1656 main.log.exception( self.name + ": Command timed out" )
1657 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001658 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001659 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001660 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001661 except Exception:
1662 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001663 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001664
pingping-lin8244a3b2015-09-16 13:36:56 -07001665 def switch( self, **switchargs ):
1666 """
1667 start/stop a switch
1668 """
1669 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1670 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1671 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1672 command = "switch " + str( sw ) + " " + str( option )
1673 main.log.info( command )
1674 try:
1675 self.handle.sendline( command )
1676 self.handle.expect( "mininet>" )
1677 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001678 main.log.error( self.name + ": TIMEOUT exception found" )
1679 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001680 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001681 except pexpect.EOF:
1682 main.log.error( self.name + ": EOF exception found" )
1683 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001684 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001685 return main.TRUE
1686
pingping-lin5bb663b2015-09-24 11:47:50 -07001687 def node( self, nodeName, commandStr ):
1688 """
1689 Carry out a command line on a given node
1690 @parm:
1691 nodeName: the node name in Mininet testbed
1692 commandStr: the command line will be carried out on the node
1693 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1694 """
1695 command = str( nodeName ) + " " + str( commandStr )
1696 main.log.info( command )
1697
1698 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001699 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001700 if re.search( "Unknown command", response ):
1701 main.log.warn( response )
1702 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001703 if re.search( "Permission denied", response ):
1704 main.log.warn( response )
1705 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001706 except pexpect.EOF:
1707 main.log.error( self.name + ": EOF exception found" )
1708 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001709 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001710 main.log.info( " response is :" )
1711 main.log.info( response )
1712 return response
1713
Jon Hall7eb38402015-01-08 17:19:54 -08001714 def yank( self, **yankargs ):
1715 """
1716 yank a mininet switch interface to a host"""
1717 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001718 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001719 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1720 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001721 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001722 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001723 response = self.execute(
1724 cmd=command,
1725 prompt="mininet>",
1726 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001727 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001728 main.log.error( self.name + ": EOF exception found" )
1729 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001730 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001731 except Exception:
1732 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001733 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001734 return main.TRUE
1735
Jon Hall7eb38402015-01-08 17:19:54 -08001736 def plug( self, **plugargs ):
1737 """
1738 plug the yanked mininet switch interface to a switch"""
1739 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001740 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001741 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1742 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001743 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001744 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001745 response = self.execute(
1746 cmd=command,
1747 prompt="mininet>",
1748 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001749 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001750 main.log.error( self.name + ": EOF exception found" )
1751 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001752 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001753 except Exception:
1754 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001755 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001756 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001757
Jon Hall7eb38402015-01-08 17:19:54 -08001758 def dpctl( self, **dpctlargs ):
1759 """
1760 Run dpctl command on all switches."""
1761 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001762 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001763 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1764 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1765 command = "dpctl " + cmd + " " + str( cmdargs )
1766 try:
1767 response = self.execute(
1768 cmd=command,
1769 prompt="mininet>",
1770 timeout=10 )
1771 except pexpect.EOF:
1772 main.log.error( self.name + ": EOF exception found" )
1773 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001774 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001775 except Exception:
1776 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001777 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001778 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001779
kelvin-onlabd3b64892015-01-20 13:26:24 -08001780 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001781 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001782 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001783 try:
1784 fileInput = path + '/lib/Mininet/INSTALL'
1785 version = super( Mininet, self ).getVersion()
1786 pattern = 'Mininet\s\w\.\w\.\w\w*'
1787 for line in open( fileInput, 'r' ).readlines():
1788 result = re.match( pattern, line )
1789 if result:
1790 version = result.group( 0 )
1791 return version
1792 except Exception:
1793 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001794 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001795
kelvin-onlabd3b64892015-01-20 13:26:24 -08001796 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001797 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001798 Parameters:
1799 sw: The name of an OVS switch. Example "s1"
1800 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001801 The output of the command from the mininet cli
1802 or main.FALSE on timeout"""
1803 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001804 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001805 response = self.execute(
1806 cmd=command,
1807 prompt="mininet>",
1808 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001809 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001810 return response
admin2a9548d2014-06-17 14:08:07 -07001811 else:
1812 return main.FALSE
1813 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001814 main.log.error( self.name + ": EOF exception found" )
1815 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001816 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001817 except Exception:
1818 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001819 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001820
Charles Chan029be652015-08-24 01:46:10 +08001821 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001822 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001823 Description:
1824 Assign switches to the controllers ( for ovs use only )
1825 Required:
1826 sw - Name of the switch. This can be a list or a string.
1827 ip - Ip addresses of controllers. This can be a list or a string.
1828 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001829 port - ONOS use port 6653, if no list of ports is passed, then
1830 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001831 ptcp - ptcp number, This can be a string or a list that has
1832 the same length as switch. This is optional and not required
1833 when using ovs switches.
1834 NOTE: If switches and ptcp are given in a list type they should have the
1835 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1836 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001837
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001838 Return:
1839 Returns main.TRUE if mininet correctly assigned switches to
1840 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001841 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001842 """
1843 assignResult = main.TRUE
1844 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001845 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001846 command = "sh ovs-vsctl set-controller "
1847 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001848 try:
1849 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001850 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001851 if isinstance( port, types.StringType ) or \
1852 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001853 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001854 elif isinstance( port, types.ListType ):
1855 main.log.error( self.name + ": Only one controller " +
1856 "assigned and a list of ports has" +
1857 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001858 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001859 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001860 main.log.error( self.name + ": Invalid controller port " +
1861 "number. Please specify correct " +
1862 "controller port" )
1863 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001864
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001865 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001866 if isinstance( port, types.StringType ) or \
1867 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001868 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001869 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1870 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001871 elif isinstance( port, types.ListType ):
1872 if ( len( ip ) != len( port ) ):
1873 main.log.error( self.name + ": Port list = " +
1874 str( len( port ) ) +
1875 "should be the same as controller" +
1876 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001877 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001878 else:
1879 onosIp = ""
1880 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001881 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1882 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001883 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001884 main.log.error( self.name + ": Invalid controller port " +
1885 "number. Please specify correct " +
1886 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001887 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001888 else:
1889 main.log.error( self.name + ": Invalid ip address" )
1890 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001891
1892 if isinstance( sw, types.StringType ):
1893 command += sw + " "
1894 if ptcp:
1895 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001896 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001897 elif isinstance( ptcp, types.ListType ):
1898 main.log.error( self.name + ": Only one switch is " +
1899 "being set and multiple PTCP is " +
1900 "being passed " )
1901 else:
1902 main.log.error( self.name + ": Invalid PTCP" )
1903 ptcp = ""
1904 command += onosIp
1905 commandList.append( command )
1906
1907 elif isinstance( sw, types.ListType ):
1908 if ptcp:
1909 if isinstance( ptcp, types.ListType ):
1910 if len( ptcp ) != len( sw ):
1911 main.log.error( self.name + ": PTCP length = " +
1912 str( len( ptcp ) ) +
1913 " is not the same as switch" +
1914 " length = " +
1915 str( len( sw ) ) )
1916 return main.FALSE
1917 else:
1918 for switch, ptcpNum in zip( sw, ptcp ):
1919 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001920 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001921 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001922 tempCmd += onosIp
1923 commandList.append( tempCmd )
1924 else:
1925 main.log.error( self.name + ": Invalid PTCP" )
1926 return main.FALSE
1927 else:
1928 for switch in sw:
1929 tempCmd = "sh ovs-vsctl set-controller "
1930 tempCmd += switch + " " + onosIp
1931 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001932 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001933 main.log.error( self.name + ": Invalid switch type " )
1934 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001935
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001936 for cmd in commandList:
1937 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001938 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001939 except pexpect.TIMEOUT:
1940 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1941 return main.FALSE
1942 except pexpect.EOF:
1943 main.log.error( self.name + ": EOF exception found" )
1944 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001945 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001946 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001947 except pexpect.EOF:
1948 main.log.error( self.name + ": EOF exception found" )
1949 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001950 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001951 except Exception:
1952 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001953 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001954
kelvin-onlabd3b64892015-01-20 13:26:24 -08001955 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001956 """
1957 Removes the controller target from sw"""
1958 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001959 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001960 response = self.execute(
1961 cmd=command,
1962 prompt="mininet>",
1963 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001964 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001965 main.log.error( self.name + ": EOF exception found" )
1966 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001967 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001968 except Exception:
1969 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001970 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001971 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001972 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001973
kelvin-onlabd3b64892015-01-20 13:26:24 -08001974 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001975 """
Jon Hallb1290e82014-11-18 16:17:48 -05001976 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001977 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001978 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001979 NOTE: cannot currently specify what type of switch
1980 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001981 sw = name of the new switch as a string
1982 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001983 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001984 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001985 """
1986 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001987 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001988 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001989 response = self.execute(
1990 cmd=command,
1991 prompt="mininet>",
1992 timeout=10 )
1993 if re.search( "already exists!", response ):
1994 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001995 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001996 elif re.search( "Error", response ):
1997 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001998 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001999 elif re.search( "usage:", response ):
2000 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002001 return main.FALSE
2002 else:
2003 return main.TRUE
2004 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002005 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07002006 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002007 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002008 except Exception:
2009 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002010 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002011
kelvin-onlabd3b64892015-01-20 13:26:24 -08002012 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08002013 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08002014 delete a switch from the mininet topology
2015 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002016 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08002017 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08002018 sw = name of the switch as a string
2019 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002020 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05002021 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002022 response = self.execute(
2023 cmd=command,
2024 prompt="mininet>",
2025 timeout=10 )
2026 if re.search( "no switch named", response ):
2027 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002028 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002029 elif re.search( "Error", response ):
2030 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002031 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002032 elif re.search( "usage:", response ):
2033 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002034 return main.FALSE
2035 else:
2036 return main.TRUE
2037 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002038 main.log.error( self.name + ": EOF exception found" )
2039 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002040 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002041 except Exception:
2042 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002043 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002044
You Wangdb8cd0a2016-05-26 15:19:45 -07002045 def getSwitchRandom( self, timeout=60, nonCut=True ):
2046 """
2047 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002048 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002049 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002050 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002051 it just randomly returns one switch from all current switches in
2052 Mininet.
2053 Returns the name of the chosen switch.
2054 """
2055 import random
2056 candidateSwitches = []
2057 try:
2058 if not nonCut:
2059 switches = self.getSwitches( timeout=timeout )
2060 assert len( switches ) != 0
2061 for switchName in switches.keys():
2062 candidateSwitches.append( switchName )
2063 else:
2064 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002065 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002066 return None
2067 self.graph.update( graphDict )
2068 candidateSwitches = self.graph.getNonCutVertices()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002069 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002070 return None
2071 elif len( candidateSwitches ) == 0:
2072 main.log.info( self.name + ": No candidate switch for deletion" )
2073 return None
2074 else:
2075 switch = random.sample( candidateSwitches, 1 )
2076 return switch[ 0 ]
2077 except KeyError:
2078 main.log.exception( self.name + ": KeyError exception found" )
2079 return None
2080 except AssertionError:
2081 main.log.exception( self.name + ": AssertionError exception found" )
2082 return None
2083 except Exception:
2084 main.log.exception( self.name + ": Uncaught exception" )
2085 return None
2086
2087 def delSwitchRandom( self, timeout=60, nonCut=True ):
2088 """
2089 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002090 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002091 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002092 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002093 otherwise it just randomly delete one switch from all current
2094 switches in Mininet.
2095 Returns the name of the deleted switch
2096 """
2097 try:
2098 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002099 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002100 return None
2101 else:
2102 deletionResult = self.delSwitch( switch )
2103 if deletionResult:
2104 return switch
2105 else:
2106 return None
2107 except Exception:
2108 main.log.exception( self.name + ": Uncaught exception" )
2109 return None
2110
kelvin-onlabd3b64892015-01-20 13:26:24 -08002111 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002112 """
2113 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002114 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002115 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002116 NOTE: cannot currently specify what type of link
2117 required params:
2118 node1 = the string node name of the first endpoint of the link
2119 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002120 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002121 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002122 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002123 response = self.execute(
2124 cmd=command,
2125 prompt="mininet>",
2126 timeout=10 )
2127 if re.search( "doesnt exist!", response ):
2128 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002129 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002130 elif re.search( "Error", response ):
2131 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002132 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002133 elif re.search( "usage:", response ):
2134 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002135 return main.FALSE
2136 else:
2137 return main.TRUE
2138 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002139 main.log.error( self.name + ": EOF exception found" )
2140 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002141 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002142 except Exception:
2143 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002144 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002145
kelvin-onlabd3b64892015-01-20 13:26:24 -08002146 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002147 """
2148 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002149 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002150 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002151 required params:
2152 node1 = the string node name of the first endpoint of the link
2153 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002154 returns: main.FALSE on an error, else main.TRUE
2155 """
Jon Hallffb386d2014-11-21 13:43:38 -08002156 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002157 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002158 response = self.execute(
2159 cmd=command,
2160 prompt="mininet>",
2161 timeout=10 )
2162 if re.search( "no node named", response ):
2163 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002164 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002165 elif re.search( "Error", response ):
2166 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002167 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002168 elif re.search( "usage:", response ):
2169 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002170 return main.FALSE
2171 else:
2172 return main.TRUE
2173 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002174 main.log.error( self.name + ": EOF exception found" )
2175 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002176 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002177 except Exception:
2178 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002179 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002180
You Wangdb8cd0a2016-05-26 15:19:45 -07002181 def getLinkRandom( self, timeout=60, nonCut=True ):
2182 """
2183 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002184 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002185 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002186 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002187 it just randomly returns one link from all current links in
2188 Mininet.
2189 Returns the link as a list, e.g. [ 's1', 's2' ]
2190 """
2191 import random
2192 candidateLinks = []
2193 try:
2194 if not nonCut:
2195 links = self.getLinks( timeout=timeout )
2196 assert len( links ) != 0
2197 for link in links:
2198 # Exclude host-switch link
2199 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2200 continue
2201 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2202 else:
2203 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002204 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002205 return None
2206 self.graph.update( graphDict )
2207 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002208 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002209 return None
2210 elif len( candidateLinks ) == 0:
2211 main.log.info( self.name + ": No candidate link for deletion" )
2212 return None
2213 else:
2214 link = random.sample( candidateLinks, 1 )
2215 return link[ 0 ]
2216 except KeyError:
2217 main.log.exception( self.name + ": KeyError exception found" )
2218 return None
2219 except AssertionError:
2220 main.log.exception( self.name + ": AssertionError exception found" )
2221 return None
2222 except Exception:
2223 main.log.exception( self.name + ": Uncaught exception" )
2224 return None
2225
2226 def delLinkRandom( self, timeout=60, nonCut=True ):
2227 """
2228 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002229 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002230 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002231 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002232 otherwise it just randomly delete one link from all current links
2233 in Mininet.
2234 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2235 """
2236 try:
2237 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002238 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002239 return None
2240 else:
2241 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2242 if deletionResult:
2243 return link
2244 else:
2245 return None
2246 except Exception:
2247 main.log.exception( self.name + ": Uncaught exception" )
2248 return None
2249
kelvin-onlabd3b64892015-01-20 13:26:24 -08002250 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002251 """
Jon Hallb1290e82014-11-18 16:17:48 -05002252 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002253 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002254 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002255 NOTE: cannot currently specify what type of host
2256 required params:
2257 hostname = the string hostname
2258 optional key-value params
2259 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002260 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002261 """
2262 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002263 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002264 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002265 response = self.execute(
2266 cmd=command,
2267 prompt="mininet>",
2268 timeout=10 )
2269 if re.search( "already exists!", response ):
2270 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002271 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002272 elif re.search( "doesnt exists!", response ):
2273 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002274 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002275 elif re.search( "Error", response ):
2276 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002277 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002278 elif re.search( "usage:", response ):
2279 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002280 return main.FALSE
2281 else:
2282 return main.TRUE
2283 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002284 main.log.error( self.name + ": EOF exception found" )
2285 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002286 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002287 except Exception:
2288 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002289 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002290
kelvin-onlabd3b64892015-01-20 13:26:24 -08002291 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002292 """
2293 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002294 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002295 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002296 NOTE: this uses a custom mn function
2297 required params:
2298 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002299 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002300 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002301 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002302 response = self.execute(
2303 cmd=command,
2304 prompt="mininet>",
2305 timeout=10 )
2306 if re.search( "no host named", response ):
2307 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002308 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002309 elif re.search( "Error", response ):
2310 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002311 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002312 elif re.search( "usage:", response ):
2313 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002314 return main.FALSE
2315 else:
2316 return main.TRUE
2317 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002318 main.log.error( self.name + ": EOF exception found" )
2319 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002320 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002321 except Exception:
2322 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002323 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002324
Jon Hall7eb38402015-01-08 17:19:54 -08002325 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002326 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002327 Called at the end of the test to stop the mininet and
2328 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002329 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002330 try:
2331 self.handle.sendline( '' )
2332 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
2333 timeout=2 )
2334 response = main.TRUE
2335 if i == 0:
2336 response = self.stopNet()
2337 elif i == 1:
2338 return main.TRUE
2339 # print "Disconnecting Mininet"
2340 if self.handle:
2341 self.handle.sendline( "exit" )
2342 self.handle.expect( "exit" )
2343 self.handle.expect( "(.*)" )
2344 else:
2345 main.log.error( "Connection failed to the host" )
2346 return response
2347 except pexpect.EOF:
2348 main.log.error( self.name + ": EOF exception found" )
2349 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002350 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002351 except Exception:
2352 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002353 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002354
Devin Lima7cfdbd2017-09-29 15:02:22 -07002355 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002356 """
Jon Hall21270ac2015-02-16 17:59:55 -08002357 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002358 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002359 main.FALSE if the pexpect handle does not exist.
2360
Jon Halld61331b2015-02-17 16:35:47 -08002361 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002362 """
Jon Halld61331b2015-02-17 16:35:47 -08002363 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002364 response = ''
2365 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002366 try:
Jon Halld80cc142015-07-06 13:36:05 -07002367 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002368 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002369 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002370 pexpect.EOF,
2371 pexpect.TIMEOUT ],
2372 timeout )
2373 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002374 main.log.info( "Exiting mininet.." )
2375 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002376 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002377 prompt=self.prompt,
2378 timeout=exitTimeout )
2379 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002380 self.handle.sendline( "sudo mn -c" )
2381 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002382
Jeremyd9e4eb12016-04-13 12:09:06 -07002383 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002384 main.log.info( " Mininet trying to exit while not " +
2385 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002386 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002387 elif i == 2:
2388 main.log.error( "Something went wrong exiting mininet" )
2389 elif i == 3: # timeout
2390 main.log.error( "Something went wrong exiting mininet " +
2391 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002392
You Wang18db8592018-04-02 13:52:03 -07002393 self.handle.sendline( "" )
2394 self.handle.expect( self.prompt )
2395 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2396
Hari Krishnab35c6d02015-03-18 11:13:51 -07002397 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002398 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002399 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002400 self.handle.sendline(
2401 "sudo kill -9 \`ps -ef | grep \"" +
2402 fileName +
2403 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002404 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002405 main.log.error( self.name + ": TIMEOUT exception found" )
2406 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002407 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002408 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002409 main.log.error( self.name + ": EOF exception found" )
2410 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002411 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002412 except Exception:
2413 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002414 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002415 else:
2416 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002417 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002418 return response
2419
YPZhang26a139e2016-04-25 14:01:55 -07002420 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002421 """
2422 Description:
2423 Sends arp message from mininet host for hosts discovery
2424 Required:
2425 host - hosts name
2426 Optional:
2427 ip - ip address that does not exist in the network so there would
2428 be no reply.
2429 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002430 if ethDevice:
2431 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002432 cmd = srcHost + " arping -c1 "
2433 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002434 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 -07002435 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002436 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002437 if output:
2438 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002439 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002440 i = self.handle.expect( [ "mininet>", "arping: " ] )
2441 if i == 0:
2442 return main.TRUE
2443 elif i == 1:
2444 response = self.handle.before + self.handle.after
2445 self.handle.expect( "mininet>" )
2446 response += self.handle.before + self.handle.after
2447 main.log.warn( "Error sending arping, output was: " +
2448 response )
2449 return main.FALSE
2450 except pexpect.TIMEOUT:
2451 main.log.error( self.name + ": TIMEOUT exception found" )
2452 main.log.warn( self.handle.before )
2453 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002454 except pexpect.EOF:
2455 main.log.error( self.name + ": EOF exception found" )
2456 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002457 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002458 except Exception:
2459 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002460 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002461
Jon Hall7eb38402015-01-08 17:19:54 -08002462 def decToHex( self, num ):
2463 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002464
Jon Hall7eb38402015-01-08 17:19:54 -08002465 def getSwitchFlowCount( self, switch ):
2466 """
2467 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002468 if self.handle:
2469 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2470 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002471 response = self.execute(
2472 cmd=cmd,
2473 prompt="mininet>",
2474 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002475 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002476 main.log.error( self.name + ": EOF exception found" )
2477 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002478 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002479 except Exception:
2480 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002481 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002482 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002483 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002484 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002485 main.log.info(
2486 "Couldn't find flows on switch %s, found: %s" %
2487 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002488 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002489 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002490 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002491 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002492
Jon Hall9ed8f372016-02-24 17:34:07 -08002493 def checkFlows( self, sw, dumpFormat=None ):
2494 if dumpFormat:
2495 command = "sh ovs-ofctl -F " + \
2496 dumpFormat + " dump-flows " + str( sw )
2497 else:
2498 command = "sh ovs-ofctl dump-flows " + str( sw )
2499 try:
2500 response = self.execute(
2501 cmd=command,
2502 prompt="mininet>",
2503 timeout=10 )
2504 return response
2505 except pexpect.EOF:
2506 main.log.error( self.name + ": EOF exception found" )
2507 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002508 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002509 except Exception:
2510 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002511 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002512
GlennRC68467eb2015-11-16 18:01:01 -08002513 def flowTableComp( self, flowTable1, flowTable2 ):
2514 # This function compares the selctors and treatments of each flow
2515 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002516 assert flowTable1, "flowTable1 is empty or None"
2517 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002518 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002519 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002520 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002521 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002522 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2523 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002524 for field in dFields:
2525 try:
2526 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002527 except KeyError:
2528 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002529 try:
2530 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002531 except KeyError:
2532 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002533 for i in range( len( flowTable1 ) ):
2534 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002535 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002536 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002537 returnValue = main.FALSE
2538 break
2539 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002540 except AssertionError:
2541 main.log.exception( "Nothing to compare" )
2542 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002543 except Exception:
2544 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002545 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002546
GlennRC528ad292015-11-12 10:38:18 -08002547 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002548 '''
GlennRC956ea742015-11-05 16:14:15 -08002549 Discription: Parses flows into json format.
2550 NOTE: this can parse any string thats separated with commas
2551 Arguments:
2552 Required:
2553 flows: a list of strings that represnt flows
2554 Optional:
2555 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2556 debug: prints out the final result
2557 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002558 '''
GlennRC528ad292015-11-12 10:38:18 -08002559 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002560 try:
2561 for flow in flowTable:
2562 jsonFlow = {}
2563 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002564 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002565 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002566 for i in range( len( parsedFlow ) ):
2567 item = parsedFlow[ i ]
2568 if item[ 0 ] == " ":
2569 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002570 # grab the selector and treatment from the parsed flow
2571 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002572 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002573 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002574 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002575 index = 0
2576 # parse the flags
2577 # NOTE: This only parses one flag
2578 flag = {}
2579 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002580 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002581 index += 1
2582 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002583 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002584 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002585 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002586 # the priority is stuck in the selecter so put it back
2587 # in the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002588 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002589 # parse selector
2590 criteria = []
2591 for item in sel:
2592 # this is the type of the packet e.g. "arp"
2593 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002594 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002595 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002596 field = item.split( "=" )
2597 criteria.append( { field[ 0 ]: field[ 1 ] } )
2598 selector = { "selector": { "criteria": sorted( criteria ) } }
2599 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002600 # get rid of the action part e.g. "action=output:2"
2601 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002602 treat = treat.split( "=" )
2603 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002604 # parse treatment
2605 action = []
2606 for item in treat:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002607 field = item.split( ":" )
2608 action.append( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002609 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002610 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002611 # parse the rest of the flow
2612 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002613 field = item.split( "=" )
2614 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002615 # add the treatment and the selector to the json flow
2616 jsonFlow.update( selector )
2617 jsonFlow.update( treatment )
2618 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002619
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002620 if debug:
2621 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002622
You Wang91c37cf2016-05-23 09:39:42 -07002623 # add the json flow to the json flow table
2624 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002625
You Wang91c37cf2016-05-23 09:39:42 -07002626 return jsonFlowTable
2627
2628 except IndexError:
2629 main.log.exception( self.name + ": IndexError found" )
2630 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002631 except pexpect.EOF:
2632 main.log.error( self.name + ": EOF exception found" )
2633 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002634 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002635 except Exception:
2636 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002637 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002638
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002639 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002640 '''
2641 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002642 Each element is a flow.
2643 Arguments:
2644 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002645 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002646 a list of switches.
2647 Optional:
2648 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2649 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002650 '''
GlennRC956ea742015-11-05 16:14:15 -08002651 try:
2652 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002653 if isinstance( sw, list ):
2654 switches.extend( sw )
2655 else:
2656 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002657
2658 flows = []
2659 for s in switches:
2660 cmd = "sh ovs-ofctl dump-flows " + s
2661
GlennRC528ad292015-11-12 10:38:18 -08002662 if "1.0" == version:
2663 cmd += " -F OpenFlow10-table_id"
2664 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002665 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002666
2667 main.log.info( "Sending: " + cmd )
2668 self.handle.sendline( cmd )
2669 self.handle.expect( "mininet>" )
2670 response = self.handle.before
2671 response = response.split( "\r\n" )
2672 # dump the first two elements and the last
2673 # the first element is the command that was sent
2674 # the second is the table header
2675 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002676 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002677 flows.extend( response )
2678
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002679 if debug:
2680 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002681
GlennRC528ad292015-11-12 10:38:18 -08002682 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002683
GlennRC956ea742015-11-05 16:14:15 -08002684 except pexpect.EOF:
2685 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002686 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002687 except Exception:
2688 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002689 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002690
2691 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002692 '''
GlennRC956ea742015-11-05 16:14:15 -08002693 Discription: Checks whether the ID provided matches a flow ID in Mininet
2694 Arguments:
2695 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002696 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002697 a list of switches.
2698 flowId: the flow ID in hex format. Can also be a list of IDs
2699 Optional:
2700 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2701 debug: prints out the final result
2702 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2703 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002704 '''
GlennRC956ea742015-11-05 16:14:15 -08002705 try:
2706 main.log.info( "Getting flows from Mininet" )
2707 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002708 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002709 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002710
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002711 if debug:
2712 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002713
2714 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002715 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002716 result = False
2717 for f in flows:
2718 if flowId in f.get( 'cookie' ):
2719 result = True
2720 break
2721 # flowId is a list
2722 else:
2723 result = True
2724 # Get flow IDs from Mininet
2725 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2726 # Save the IDs that are not in Mininet
2727 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2728
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002729 if debug:
2730 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002731
2732 # Print out the IDs that are not in Mininet
2733 if absentIds:
2734 main.log.warn( "Absent ids: {}".format( absentIds ) )
2735 result = False
2736
2737 return main.TRUE if result else main.FALSE
2738
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002739 except pexpect.EOF:
2740 main.log.error( self.name + ": EOF exception found" )
2741 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002742 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002743 except Exception:
2744 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002745 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002746
Charles Chan029be652015-08-24 01:46:10 +08002747 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002748 """
Jon Hallefbd9792015-03-05 16:11:36 -08002749 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002750 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002751 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002752 self.handle.sendline( "" )
2753 self.handle.expect( "mininet>" )
2754 self.handle.sendline(
2755 "sh sudo tcpdump -n -i " +
2756 intf +
2757 " " +
2758 port +
2759 " -w " +
2760 filename.strip() +
2761 " &" )
2762 self.handle.sendline( "" )
2763 i = self.handle.expect( [ 'No\ssuch\device',
2764 'listening\son',
2765 pexpect.TIMEOUT,
2766 "mininet>" ],
2767 timeout=10 )
2768 main.log.warn( self.handle.before + self.handle.after )
2769 self.handle.sendline( "" )
2770 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002771 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002772 main.log.error(
2773 self.name +
2774 ": tcpdump - No such device exists. " +
2775 "tcpdump attempted on: " +
2776 intf )
admin2a9548d2014-06-17 14:08:07 -07002777 return main.FALSE
2778 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002779 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002780 return main.TRUE
2781 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002782 main.log.error(
2783 self.name +
2784 ": tcpdump command timed out! Check interface name," +
2785 " given interface was: " +
2786 intf )
admin2a9548d2014-06-17 14:08:07 -07002787 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002788 elif i == 3:
2789 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002790 return main.TRUE
2791 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002792 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002793 return main.FALSE
2794 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002795 main.log.error( self.name + ": EOF exception found" )
2796 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002797 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002798 except Exception:
2799 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002800 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002801
kelvin-onlabd3b64892015-01-20 13:26:24 -08002802 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002803 """
2804 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002805 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002806 self.handle.sendline( "sh sudo pkill tcpdump" )
2807 self.handle.expect( "mininet>" )
2808 self.handle.sendline( "" )
2809 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002810 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002811 main.log.error( self.name + ": TIMEOUT exception found" )
2812 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002813 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002814 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002815 main.log.error( self.name + ": EOF exception found" )
2816 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002817 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002818 except Exception:
2819 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002820 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002821
Jon Halld80cc142015-07-06 13:36:05 -07002822 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002823 """
2824 Read ports from a Mininet switch.
2825
2826 Returns a json structure containing information about the
2827 ports of the given switch.
2828 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002829 try:
2830 response = self.getInterfaces( nodeName )
2831 # TODO: Sanity check on response. log if no such switch exists
2832 ports = []
2833 for line in response.split( "\n" ):
2834 if not line.startswith( "name=" ):
2835 continue
2836 portVars = {}
2837 for var in line.split( "," ):
2838 key, value = var.split( "=" )
2839 portVars[ key ] = value
2840 isUp = portVars.pop( 'enabled', "True" )
2841 isUp = "True" in isUp
2842 if verbose:
2843 main.log.info( "Reading switch port %s(%s)" %
2844 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2845 mac = portVars[ 'mac' ]
2846 if mac == 'None':
2847 mac = None
2848 ips = []
2849 ip = portVars[ 'ip' ]
2850 if ip == 'None':
2851 ip = None
2852 ips.append( ip )
2853 name = portVars[ 'name' ]
2854 if name == 'None':
2855 name = None
2856 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2857 if name == 'lo':
2858 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2859 else:
2860 portNo = re.search( portRe, name ).group( 'port' )
2861 ports.append( { 'of_port': portNo,
2862 'mac': str( mac ).replace( '\'', '' ),
2863 'name': name,
2864 'ips': ips,
2865 'enabled': isUp } )
2866 return ports
2867 except pexpect.EOF:
2868 main.log.error( self.name + ": EOF exception found" )
2869 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002870 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002871 except Exception:
2872 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002873 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002874
You Wangdb8cd0a2016-05-26 15:19:45 -07002875 def getOVSPorts( self, nodeName ):
2876 """
2877 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2878
2879 Returns a list of dictionaries containing information about each
2880 port of the given switch.
2881 """
2882 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2883 try:
2884 response = self.execute(
2885 cmd=command,
2886 prompt="mininet>",
2887 timeout=10 )
2888 ports = []
2889 if response:
2890 for line in response.split( "\n" ):
2891 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2892 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002893 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002894 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2895 result = re.search( pattern, line )
2896 if result:
2897 index = result.group( 'index' )
2898 name = result.group( 'name' )
2899 # This port number is extracted from port name
2900 port = result.group( 'port' )
2901 mac = result.group( 'mac' )
2902 ports.append( { 'index': index,
2903 'name': name,
2904 'port': port,
2905 'mac': mac } )
2906 return ports
2907 except pexpect.EOF:
2908 main.log.error( self.name + ": EOF exception found" )
2909 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002910 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002911 except Exception:
2912 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002913 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002914
Devin Lima7cfdbd2017-09-29 15:02:22 -07002915 def getSwitches( self, verbose=False, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002916 """
2917 Read switches from Mininet.
2918
2919 Returns a dictionary whose keys are the switch names and the value is
2920 a dictionary containing information about the switch.
2921 """
Jon Halla22481b2015-07-28 17:46:01 -07002922 # NOTE: To support new Mininet switch classes, just append the new
2923 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002924
Jon Halla22481b2015-07-28 17:46:01 -07002925 # Regex patterns to parse 'dump' output
2926 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002927 # <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 -07002928 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002929 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2930 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2931 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002932 try:
2933 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2934 swRE = r"<(?P<class>" + switchClasses + r")" +\
2935 r"(?P<options>\{.*\})?\s" +\
2936 r"(?P<name>[^:]+)\:\s" +\
2937 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2938 r"\spid=(?P<pid>(\d)+)"
2939 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002940 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002941 output = {}
2942 dump = self.dump().split( "\n" )
2943 for line in dump:
2944 result = re.search( swRE, line, re.I )
2945 if result:
2946 name = result.group( 'name' )
2947 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2948 pid = result.group( 'pid' )
2949 swClass = result.group( 'class' )
2950 options = result.group( 'options' )
2951 if verbose:
2952 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2953 ports = self.getPorts( name )
2954 output[ name ] = { "dpid": dpid,
2955 "ports": ports,
2956 "swClass": swClass,
2957 "pid": pid,
2958 "options": options }
2959 return output
2960 except pexpect.EOF:
2961 main.log.error( self.name + ": EOF exception found" )
2962 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002963 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002964 except Exception:
2965 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002966 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002967
You Wang79f5c5b2018-03-14 11:10:44 -07002968 def getHosts( self, verbose=False, updateTimeout=1000, hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ], getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002969 """
2970 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002971 Optional:
2972 hostClass: it is used to match the class of the mininet host. It
2973 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002974 Returns a dictionary whose keys are the host names and the value is
2975 a dictionary containing information about the host.
2976 """
2977 # Regex patterns to parse dump output
2978 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002979 # <Host h1: pid=12725>
2980 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2981 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2982 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002983 # NOTE: Does not correctly match hosts with multi-links
2984 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2985 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002986 try:
You Wang53dba1e2018-02-02 17:45:44 -08002987 if not isinstance( hostClass, types.ListType ):
2988 hostClass = [ str( hostClass ) ]
2989 classRE = "(" + "|".join([c for c in hostClass]) + ")"
2990 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002991 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
2992 # update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002993 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002994 # Get mininet dump
2995 dump = self.dump().split( "\n" )
2996 hosts = {}
2997 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002998 result = re.search( hostRE, line )
2999 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003000 name = result.group( 'name' )
3001 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07003002 if getInterfaces:
3003 response = self.getInterfaces( name )
3004 # Populate interface info
3005 for line in response.split( "\n" ):
3006 if line.startswith( "name=" ):
3007 portVars = {}
3008 for var in line.split( "," ):
3009 key, value = var.split( "=" )
3010 portVars[ key ] = value
3011 isUp = portVars.pop( 'enabled', "True" )
3012 isUp = "True" in isUp
3013 if verbose:
3014 main.log.info( "Reading host port %s(%s)" %
3015 ( portVars[ 'name' ],
3016 portVars[ 'mac' ] ) )
3017 mac = portVars[ 'mac' ]
3018 if mac == 'None':
3019 mac = None
3020 ips = []
3021 ip = portVars[ 'ip' ]
3022 if ip == 'None':
3023 ip = None
3024 ips.append( ip )
3025 intfName = portVars[ 'name' ]
3026 if name == 'None':
3027 name = None
3028 interfaces.append( {
3029 "name": intfName,
3030 "ips": ips,
3031 "mac": str( mac ),
3032 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003033 hosts[ name ] = { "interfaces": interfaces }
3034 return hosts
3035 except pexpect.EOF:
3036 main.log.error( self.name + ": EOF exception found" )
3037 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003038 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003039 except Exception:
3040 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003041 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003042
Devin Lima7cfdbd2017-09-29 15:02:22 -07003043 def getLinks( self, timeout=20, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07003044 """
3045 Gathers information about current Mininet links. These links may not
3046 be up if one of the ports is down.
3047
3048 Returns a list of dictionaries with link endpoints.
3049
3050 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07003051 { 'node1': str( node1 name )
3052 'node2': str( node2 name )
3053 'port1': str( port1 of_port )
3054 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07003055 Note: The port number returned is the eth#, not necessarily the of_port
3056 number. In Mininet, for OVS switch, these should be the same. For
3057 hosts, this is just the eth#.
3058 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003059 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003060 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003061 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07003062
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003063 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003064 # s1-eth3<->s2-eth1 (OK OK)
3065 # s13-eth3<->h27-eth0 (OK OK)
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003066 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
3067 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
3068 links = []
3069 for line in response:
3070 match = re.search( linkRE, line )
3071 if match:
3072 node1 = match.group( 'node1' )
3073 node2 = match.group( 'node2' )
3074 port1 = match.group( 'port1' )
3075 port2 = match.group( 'port2' )
3076 links.append( { 'node1': node1,
3077 'node2': node2,
3078 'port1': port1,
3079 'port2': port2 } )
3080 return links
3081
3082 except pexpect.EOF:
3083 main.log.error( self.name + ": EOF exception found" )
3084 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003085 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003086 except Exception:
3087 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003088 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003089
3090 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003091 """
3092 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003093 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003094
Jon Hallafa8a472015-06-12 14:02:42 -07003095 Dependencies:
3096 1. numpy - "sudo pip install numpy"
3097 """
3098 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003099 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003100 try:
3101 mnDPIDs = []
3102 for swName, switch in switches.iteritems():
3103 mnDPIDs.append( switch[ 'dpid' ].lower() )
3104 mnDPIDs.sort()
3105 if switchesJson == "": # if rest call fails
3106 main.log.error(
3107 self.name +
3108 ".compareSwitches(): Empty JSON object given from ONOS" )
3109 return main.FALSE
3110 onos = switchesJson
3111 onosDPIDs = []
3112 for switch in onos:
3113 if switch[ 'available' ]:
3114 onosDPIDs.append(
3115 switch[ 'id' ].replace(
3116 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003117 '' ).replace(
3118 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003119 '' ).lower() )
3120 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003121
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003122 if mnDPIDs != onosDPIDs:
3123 switchResults = main.FALSE
3124 main.log.error( "Switches in MN but not in ONOS:" )
3125 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3126 main.log.error( str( list1 ) )
3127 main.log.error( "Switches in ONOS but not in MN:" )
3128 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3129 main.log.error( str( list2 ) )
3130 else: # list of dpid's match in onos and mn
3131 switchResults = main.TRUE
3132 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003133
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003134 # FIXME: this does not look for extra ports in ONOS, only checks that
3135 # ONOS has what is in MN
3136 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003137
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003138 # PORTS
3139 for name, mnSwitch in switches.iteritems():
3140 mnPorts = []
3141 onosPorts = []
3142 switchResult = main.TRUE
3143 for port in mnSwitch[ 'ports' ]:
3144 if port[ 'enabled' ]:
3145 mnPorts.append( int( port[ 'of_port' ] ) )
3146 for onosSwitch in portsJson:
3147 if onosSwitch[ 'device' ][ 'available' ]:
3148 if onosSwitch[ 'device' ][ 'id' ].replace(
3149 ':',
3150 '' ).replace(
3151 "of",
3152 '' ) == mnSwitch[ 'dpid' ]:
3153 for port in onosSwitch[ 'ports' ]:
3154 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003155 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003156 # onosPorts.append( 'local' )
3157 onosPorts.append( long( uint64( -2 ) ) )
3158 else:
3159 onosPorts.append( int( port[ 'port' ] ) )
3160 break
3161 mnPorts.sort( key=float )
3162 onosPorts.sort( key=float )
3163
3164 mnPortsLog = mnPorts
3165 onosPortsLog = onosPorts
3166 mnPorts = [ x for x in mnPorts ]
3167 onosPorts = [ x for x in onosPorts ]
3168
3169 # TODO: handle other reserved port numbers besides LOCAL
3170 # NOTE: Reserved ports
3171 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3172 # long( uint64( -2 ) )
3173 for mnPort in mnPortsLog:
3174 if mnPort in onosPorts:
3175 # don't set results to true here as this is just one of
3176 # many checks and it might override a failure
3177 mnPorts.remove( mnPort )
3178 onosPorts.remove( mnPort )
3179
3180 # NOTE: OVS reports this as down since there is no link
3181 # So ignoring these for now
3182 # TODO: Come up with a better way of handling these
3183 if 65534 in mnPorts:
3184 mnPorts.remove( 65534 )
3185 if long( uint64( -2 ) ) in onosPorts:
3186 onosPorts.remove( long( uint64( -2 ) ) )
3187 if len( mnPorts ): # the ports of this switch don't match
3188 switchResult = main.FALSE
3189 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3190 if len( onosPorts ): # the ports of this switch don't match
3191 switchResult = main.FALSE
3192 main.log.warn(
3193 "Ports in ONOS but not MN: " +
3194 str( onosPorts ) )
3195 if switchResult == main.FALSE:
3196 main.log.error(
3197 "The list of ports for switch %s(%s) does not match:" %
3198 ( name, mnSwitch[ 'dpid' ] ) )
3199 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3200 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3201 portsResults = portsResults and switchResult
3202 finalResults = finalResults and portsResults
3203 return finalResults
3204 except pexpect.EOF:
3205 main.log.error( self.name + ": EOF exception found" )
3206 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003207 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003208 except Exception:
3209 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003210 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003211
Jon Hallafa8a472015-06-12 14:02:42 -07003212 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003213 """
3214 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003215 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003216
Jon Hallafa8a472015-06-12 14:02:42 -07003217 """
Jon Hall7eb38402015-01-08 17:19:54 -08003218 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003219 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003220 try:
3221 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003222
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003223 mnLinks = []
3224 for l in links:
3225 try:
3226 node1 = switches[ l[ 'node1' ] ]
3227 node2 = switches[ l[ 'node2' ] ]
3228 enabled = True
3229 for port in node1[ 'ports' ]:
3230 if port[ 'of_port' ] == l[ 'port1' ]:
3231 enabled = enabled and port[ 'enabled' ]
3232 for port in node2[ 'ports' ]:
3233 if port[ 'of_port' ] == l[ 'port2' ]:
3234 enabled = enabled and port[ 'enabled' ]
3235 if enabled:
3236 mnLinks.append( l )
3237 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003238 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003239 if 2 * len( mnLinks ) == len( onos ):
3240 linkResults = main.TRUE
3241 else:
3242 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003243 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003244 "Mininet has " + str( len( mnLinks ) ) +
3245 " bidirectional links and ONOS has " +
3246 str( len( onos ) ) + " unidirectional links" )
3247
3248 # iterate through MN links and check if an ONOS link exists in
3249 # both directions
3250 for link in mnLinks:
3251 # TODO: Find a more efficient search method
3252 node1 = None
3253 port1 = None
3254 node2 = None
3255 port2 = None
3256 firstDir = main.FALSE
3257 secondDir = main.FALSE
3258 for swName, switch in switches.iteritems():
3259 if swName == link[ 'node1' ]:
3260 node1 = switch[ 'dpid' ]
3261 for port in switch[ 'ports' ]:
3262 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3263 port1 = port[ 'of_port' ]
3264 if node1 is not None and node2 is not None:
3265 break
3266 if swName == link[ 'node2' ]:
3267 node2 = switch[ 'dpid' ]
3268 for port in switch[ 'ports' ]:
3269 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3270 port2 = port[ 'of_port' ]
3271 if node1 is not None and node2 is not None:
3272 break
3273
3274 for onosLink in onos:
3275 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3276 ":", '' ).replace( "of", '' )
3277 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3278 ":", '' ).replace( "of", '' )
3279 onosPort1 = onosLink[ 'src' ][ 'port' ]
3280 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3281
3282 # check onos link from node1 to node2
3283 if str( onosNode1 ) == str( node1 ) and str(
3284 onosNode2 ) == str( node2 ):
3285 if int( onosPort1 ) == int( port1 ) and int(
3286 onosPort2 ) == int( port2 ):
3287 firstDir = main.TRUE
3288 else:
3289 main.log.warn(
3290 'The port numbers do not match for ' +
3291 str( link ) +
3292 ' between ONOS and MN. When checking ONOS for ' +
3293 'link %s/%s -> %s/%s' %
3294 ( node1, port1, node2, port2 ) +
3295 ' ONOS has the values %s/%s -> %s/%s' %
3296 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
3297
3298 # check onos link from node2 to node1
3299 elif ( str( onosNode1 ) == str( node2 ) and
3300 str( onosNode2 ) == str( node1 ) ):
3301 if ( int( onosPort1 ) == int( port2 )
3302 and int( onosPort2 ) == int( port1 ) ):
3303 secondDir = main.TRUE
3304 else:
3305 main.log.warn(
3306 'The port numbers do not match for ' +
3307 str( link ) +
3308 ' between ONOS and MN. When checking ONOS for ' +
3309 'link %s/%s -> %s/%s' %
3310 ( node1, port1, node2, port2 ) +
3311 ' ONOS has the values %s/%s -> %s/%s' %
3312 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
3313 else: # this is not the link you're looking for
3314 pass
3315 if not firstDir:
3316 main.log.error(
3317 'ONOS does not have the link %s/%s -> %s/%s' %
3318 ( node1, port1, node2, port2 ) )
3319 if not secondDir:
3320 main.log.error(
3321 'ONOS does not have the link %s/%s -> %s/%s' %
3322 ( node2, port2, node1, port1 ) )
3323 linkResults = linkResults and firstDir and secondDir
3324 return linkResults
3325 except pexpect.EOF:
3326 main.log.error( self.name + ": EOF exception found" )
3327 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003328 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003329 except Exception:
3330 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003331 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003332
Jon Hallafa8a472015-06-12 14:02:42 -07003333 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003334 """
Jon Hallafa8a472015-06-12 14:02:42 -07003335 Compare mn and onos Hosts.
3336 Since Mininet hosts are quiet, ONOS will only know of them when they
3337 speak. For this reason, we will only check that the hosts in ONOS
3338 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003339
Jon Hallafa8a472015-06-12 14:02:42 -07003340 Arguments:
3341 hostsJson: parsed json object from the onos hosts api
3342 Returns:
3343 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003344 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003345 try:
3346 hostResults = main.TRUE
3347 for onosHost in hostsJson:
3348 onosMAC = onosHost[ 'mac' ].lower()
3349 match = False
3350 for mnHost, info in hosts.iteritems():
3351 for mnIntf in info[ 'interfaces' ]:
3352 if onosMAC == mnIntf[ 'mac' ].lower():
3353 match = True
3354 for ip in mnIntf[ 'ips' ]:
3355 if ip in onosHost[ 'ipAddresses' ]:
3356 pass # all is well
3357 else:
3358 # misssing ip
3359 main.log.error( "ONOS host " +
3360 onosHost[ 'id' ] +
3361 " has a different IP(" +
3362 str( onosHost[ 'ipAddresses' ] ) +
3363 ") than the Mininet host(" +
3364 str( ip ) +
3365 ")." )
3366 output = json.dumps(
3367 onosHost,
3368 sort_keys=True,
3369 indent=4,
3370 separators=( ',', ': ' ) )
3371 main.log.info( output )
3372 hostResults = main.FALSE
3373 if not match:
3374 hostResults = main.FALSE
3375 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3376 "corresponding Mininet host." )
3377 output = json.dumps( onosHost,
3378 sort_keys=True,
3379 indent=4,
3380 separators=( ',', ': ' ) )
3381 main.log.info( output )
3382 return hostResults
3383 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003384 main.log.error( self.name + ": EOF exception found" )
3385 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003386 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003387 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003388 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003389 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003390
You Wang53dba1e2018-02-02 17:45:44 -08003391 def verifyHostIp( self, hostList=[], prefix="" ):
3392 """
3393 Description:
3394 Verify that all hosts have IP address assigned to them
3395 Optional:
3396 hostList: If specified, verifications only happen to the hosts
3397 in hostList
3398 prefix: at least one of the ip address assigned to the host
3399 needs to have the specified prefix
3400 Returns:
3401 main.TRUE if all hosts have specific IP address assigned;
3402 main.FALSE otherwise
3403 """
3404 try:
You Wang79f5c5b2018-03-14 11:10:44 -07003405 hosts = self.getHosts( getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003406 if not hostList:
3407 hostList = hosts.keys()
3408 for hostName in hosts.keys():
3409 if hostName not in hostList:
3410 continue
3411 ipList = []
3412 self.handle.sendline( str( hostName ) + " ip a" )
3413 self.handle.expect( "mininet>" )
3414 ipa = self.handle.before
3415 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3416 ipList += re.findall( ipv4Pattern, ipa )
3417 # It's tricky to make regex for IPv6 addresses and this one is simplified
3418 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})/'
3419 ipList += re.findall( ipv6Pattern, ipa )
3420 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3421 if not ipList:
3422 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3423 else:
3424 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3425 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3426 else:
3427 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3428 hostList.remove( hostName )
3429 return main.FALSE if hostList else main.TRUE
3430 except KeyError:
3431 main.log.exception( self.name + ": host data not as expected: " + hosts )
3432 return None
3433 except pexpect.EOF:
3434 main.log.error( self.name + ": EOF exception found" )
3435 main.log.error( self.name + ": " + self.handle.before )
3436 main.cleanAndExit()
3437 except Exception:
3438 main.log.exception( self.name + ": Uncaught exception" )
3439 return None
3440
Jon Hallafa8a472015-06-12 14:02:42 -07003441 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003442 """
3443 Returns a list of all hosts
3444 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003445 try:
3446 self.handle.sendline( "" )
3447 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003448
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003449 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3450 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003451
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003452 handlePy = self.handle.before
3453 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3454 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003455
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003456 self.handle.sendline( "" )
3457 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003458
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003459 hostStr = handlePy.replace( "]", "" )
3460 hostStr = hostStr.replace( "'", "" )
3461 hostStr = hostStr.replace( "[", "" )
3462 hostStr = hostStr.replace( " ", "" )
3463 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003464
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003465 return hostList
3466 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003467 main.log.error( self.name + ": TIMEOUT exception found" )
3468 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003469 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003470 except pexpect.EOF:
3471 main.log.error( self.name + ": EOF exception found" )
3472 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003473 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003474 except Exception:
3475 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003476 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003477
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003478 def getSwitch( self ):
3479 """
3480 Returns a list of all switches
3481 Again, don't ask question just use it...
3482 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003483 try:
3484 # get host list...
3485 hostList = self.getHosts()
3486 # Make host set
3487 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003488
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003489 # Getting all the nodes in mininet
3490 self.handle.sendline( "" )
3491 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003492
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003493 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3494 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003495
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003496 handlePy = self.handle.before
3497 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3498 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003499
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003500 self.handle.sendline( "" )
3501 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003502
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003503 nodesStr = handlePy.replace( "]", "" )
3504 nodesStr = nodesStr.replace( "'", "" )
3505 nodesStr = nodesStr.replace( "[", "" )
3506 nodesStr = nodesStr.replace( " ", "" )
3507 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003508
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003509 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003510 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003511 nodesSet.discard( 'c0' )
3512 nodesSet.discard( 'c1' )
3513 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003514
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003515 switchSet = nodesSet - hostSet
3516 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003517
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003518 return switchList
3519 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003520 main.log.error( self.name + ": TIMEOUT exception found" )
3521 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003522 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003523 except pexpect.EOF:
3524 main.log.error( self.name + ": EOF exception found" )
3525 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003526 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003527 except Exception:
3528 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003529 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003530
You Wangdb8cd0a2016-05-26 15:19:45 -07003531 def getGraphDict( self, timeout=60, useId=True, includeHost=False ):
3532 """
3533 Return a dictionary which describes the latest Mininet topology data as a
3534 graph.
3535 An example of the dictionary:
3536 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3537 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3538 Each vertex should at least have an 'edges' attribute which describes the
3539 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003540 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003541 list of attributes.
3542 An example of the edges dictionary:
3543 'edges': { vertex2: { 'port': ..., 'weight': ... },
3544 vertex3: { 'port': ..., 'weight': ... } }
3545 If useId == True, dpid/mac will be used instead of names to identify
3546 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3547 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003548 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003549 in topology data.
3550 Note that link or switch that are brought down by 'link x x down' or 'switch
3551 x down' commands still show in the output of Mininet CLI commands such as
3552 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3553 recommended to use delLink() or delSwitch functions to simulate link/switch
3554 down, and addLink() or addSwitch to add them back.
3555 """
3556 graphDict = {}
3557 try:
3558 links = self.getLinks( timeout=timeout )
3559 portDict = {}
3560 if useId:
3561 switches = self.getSwitches()
3562 if includeHost:
3563 hosts = self.getHosts()
3564 for link in links:
3565 # FIXME: support 'includeHost' argument
3566 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3567 continue
3568 nodeName1 = link[ 'node1' ]
3569 nodeName2 = link[ 'node2' ]
3570 port1 = link[ 'port1' ]
3571 port2 = link[ 'port2' ]
3572 # Loop for two nodes
3573 for i in range( 2 ):
3574 # Get port index from OVS
3575 # The index extracted from port name may be inconsistent with ONOS
3576 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003577 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003578 portList = self.getOVSPorts( nodeName1 )
3579 if len( portList ) == 0:
3580 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3581 return None
3582 portDict[ nodeName1 ] = portList
3583 for port in portDict[ nodeName1 ]:
3584 if port[ 'port' ] == port1:
3585 portIndex = port[ 'index' ]
3586 break
3587 if portIndex == -1:
3588 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3589 return None
3590 if useId:
3591 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3592 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3593 else:
3594 node1 = nodeName1
3595 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003596 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003597 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003598 graphDict[ node1 ] = { 'edges': {},
3599 'dpid': switches[ nodeName1 ][ 'dpid' ],
3600 'name': nodeName1,
3601 'ports': switches[ nodeName1 ][ 'ports' ],
3602 'swClass': switches[ nodeName1 ][ 'swClass' ],
3603 'pid': switches[ nodeName1 ][ 'pid' ],
3604 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003605 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003606 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003607 else:
3608 # Assert node2 is not connected to any current links of node1
3609 assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003610 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
You Wangdb8cd0a2016-05-26 15:19:45 -07003611 # Swap two nodes/ports
3612 nodeName1, nodeName2 = nodeName2, nodeName1
3613 port1, port2 = port2, port1
3614 return graphDict
3615 except KeyError:
3616 main.log.exception( self.name + ": KeyError exception found" )
3617 return None
3618 except AssertionError:
3619 main.log.exception( self.name + ": AssertionError exception found" )
3620 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003621 except pexpect.EOF:
3622 main.log.error( self.name + ": EOF exception found" )
3623 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003624 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003625 except Exception:
3626 main.log.exception( self.name + ": Uncaught exception" )
3627 return None
3628
Devin Lima7cfdbd2017-09-29 15:02:22 -07003629 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003630 """
3631 updates the port address and status information for
3632 each port in mn"""
3633 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003634 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003635 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003636 self.handle.sendline( "" )
3637 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003638
Jon Hall7eb38402015-01-08 17:19:54 -08003639 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003640 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003641
Jon Hall7eb38402015-01-08 17:19:54 -08003642 self.handle.sendline( "" )
3643 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003644
Jon Hallb1290e82014-11-18 16:17:48 -05003645 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003646 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003647 main.log.error( self.name + ": TIMEOUT exception found" )
3648 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003649 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003650 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003651 main.log.error( self.name + ": EOF exception found" )
3652 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003653 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003654 except Exception:
3655 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003656 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003657
Jon Halld80cc142015-07-06 13:36:05 -07003658 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003659 """
3660 Add vlan tag to a host.
3661 Dependencies:
3662 This class depends on the "vlan" package
3663 $ sudo apt-get install vlan
3664 Configuration:
3665 Load the 8021q module into the kernel
3666 $sudo modprobe 8021q
3667
3668 To make this setup permanent:
3669 $ sudo su -c 'echo "8021q" >> /etc/modules'
3670 """
3671 if self.handle:
3672 try:
Jon Halld80cc142015-07-06 13:36:05 -07003673 # get the ip address of the host
3674 main.log.info( "Get the ip address of the host" )
3675 ipaddr = self.getIPAddress( host )
3676 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003677
Jon Halld80cc142015-07-06 13:36:05 -07003678 # remove IP from interface intf
3679 # Ex: h1 ifconfig h1-eth0 inet 0
3680 main.log.info( "Remove IP from interface " )
3681 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3682 self.handle.sendline( cmd2 )
3683 self.handle.expect( "mininet>" )
3684 response = self.handle.before
3685 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003686
Jon Halld80cc142015-07-06 13:36:05 -07003687 # create VLAN interface
3688 # Ex: h1 vconfig add h1-eth0 100
3689 main.log.info( "Create Vlan" )
3690 cmd3 = host + " vconfig add " + intf + " " + vlan
3691 self.handle.sendline( cmd3 )
3692 self.handle.expect( "mininet>" )
3693 response = self.handle.before
3694 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003695
Jon Halld80cc142015-07-06 13:36:05 -07003696 # assign the host's IP to the VLAN interface
3697 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3698 main.log.info( "Assign the host IP to the vlan interface" )
3699 vintf = intf + "." + vlan
3700 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3701 self.handle.sendline( cmd4 )
3702 self.handle.expect( "mininet>" )
3703 response = self.handle.before
3704 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003705
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003706 # update Mininet node variables
3707 main.log.info( "Update Mininet node variables" )
3708 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3709 self.handle.sendline( cmd5 )
3710 self.handle.expect( "mininet>" )
3711 response = self.handle.before
3712 main.log.info( "====> %s ", response )
3713
3714 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3715 self.handle.sendline( cmd6 )
3716 self.handle.expect( "mininet>" )
3717 response = self.handle.before
3718 main.log.info( "====> %s ", response )
3719
3720 return main.TRUE
3721 except pexpect.TIMEOUT:
3722 main.log.error( self.name + ": TIMEOUT exception found" )
3723 main.log.error( self.name + ": " + self.handle.before )
3724 main.cleanAndExit()
3725 except pexpect.EOF:
3726 main.log.error( self.name + ": EOF exception found" )
3727 main.log.error( self.name + ": " + self.handle.before )
3728 return main.FALSE
3729 except Exception:
3730 main.log.exception( self.name + ": Uncaught exception!" )
3731 return main.FALSE
3732
3733 def removeVLAN( self, host, intf ):
3734 """
3735 Remove vlan tag from a host.
3736 Dependencies:
3737 This class depends on the "vlan" package
3738 $ sudo apt-get install vlan
3739 Configuration:
3740 Load the 8021q module into the kernel
3741 $sudo modprobe 8021q
3742
3743 To make this setup permanent:
3744 $ sudo su -c 'echo "8021q" >> /etc/modules'
3745 """
3746 if self.handle:
3747 try:
3748 # get the ip address of the host
3749 main.log.info( "Get the ip address of the host" )
3750 ipaddr = self.getIPAddress( host )
3751
3752 # remove VLAN interface
3753 # Ex: h1 vconfig rem h1-eth0.100
3754 main.log.info( "Remove Vlan interface" )
3755 cmd2 = host + " vconfig rem " + intf
3756 self.handle.sendline( cmd2 )
3757 self.handle.expect( "mininet>" )
3758 response = self.handle.before
3759 main.log.info( "====> %s ", response )
3760
3761 # assign the host's IP to the original interface
3762 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3763 main.log.info( "Assign the host IP to the original interface" )
3764 original_intf = intf.split(".")[0]
3765 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3766 self.handle.sendline( cmd3 )
3767 self.handle.expect( "mininet>" )
3768 response = self.handle.before
3769 main.log.info( "====> %s ", response )
3770
3771 # update Mininet node variables
3772 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3773 self.handle.sendline( cmd4 )
3774 self.handle.expect( "mininet>" )
3775 response = self.handle.before
3776 main.log.info( "====> %s ", response )
3777
3778 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3779 self.handle.sendline( cmd5 )
3780 self.handle.expect( "mininet>" )
3781 response = self.handle.before
3782 main.log.info( "====> %s ", response )
3783
kaouthera3f13ca22015-05-05 15:01:41 -07003784 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003785 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003786 main.log.error( self.name + ": TIMEOUT exception found" )
3787 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003788 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003789 except pexpect.EOF:
3790 main.log.error( self.name + ": EOF exception found" )
3791 main.log.error( self.name + ": " + self.handle.before )
3792 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003793 except Exception:
3794 main.log.exception( self.name + ": Uncaught exception!" )
3795 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003796
Jon Hall892818c2015-10-20 17:58:34 -07003797 def createHostComponent( self, name ):
3798 """
3799 Creates a new mininet cli component with the same parameters as self.
3800 This new component is intended to be used to login to the hosts created
3801 by mininet.
3802
3803 Arguments:
3804 name - The string of the name of this component. The new component
3805 will be assigned to main.<name> .
3806 In addition, main.<name>.name = str( name )
3807 """
3808 try:
3809 # look to see if this component already exists
3810 getattr( main, name )
3811 except AttributeError:
3812 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003813 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3814 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003815 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003816 except pexpect.EOF:
3817 main.log.error( self.name + ": EOF exception found" )
3818 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003819 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003820 except Exception:
3821 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003822 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003823 else:
3824 # namespace is not clear!
3825 main.log.error( name + " component already exists!" )
3826 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003827 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003828
3829 def removeHostComponent( self, name ):
3830 """
3831 Remove host component
3832 Arguments:
3833 name - The string of the name of the component to delete.
3834 """
3835 try:
3836 # Get host component
3837 component = getattr( main, name )
3838 except AttributeError:
3839 main.log.error( "Component " + name + " does not exist." )
3840 return
3841 try:
3842 # Disconnect from component
3843 component.disconnect()
3844 # Delete component
3845 delattr( main, name )
3846 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003847 del( main.componentDictionary[ name ] )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003848 except pexpect.EOF:
3849 main.log.error( self.name + ": EOF exception found" )
3850 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003851 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003852 except Exception:
3853 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003854 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003855
3856 def startHostCli( self, host=None ):
3857 """
3858 Use the mininet m utility to connect to the host's cli
3859 """
3860 # These are fields that can be used by scapy packets. Initialized to None
3861 self.hostIp = None
3862 self.hostMac = None
3863 try:
3864 if not host:
3865 host = self.name
3866 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003867 self.handle.sendline( "cd" )
3868 self.handle.expect( self.hostPrompt )
3869 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003870 self.handle.expect( self.hostPrompt )
3871 return main.TRUE
3872 except pexpect.TIMEOUT:
3873 main.log.exception( self.name + ": Command timed out" )
3874 return main.FALSE
3875 except pexpect.EOF:
3876 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003877 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003878 except Exception:
3879 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003880 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003881
YPZhang801d46d2016-08-08 13:26:28 -07003882 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003883 '''
3884
YPZhang801d46d2016-08-08 13:26:28 -07003885 Args:
3886 devicename: switch name
3887 intf: port name on switch
3888 status: up or down
3889
3890 Returns: boolean to show success change status
3891
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003892 '''
YPZhang801d46d2016-08-08 13:26:28 -07003893 if status == "down" or status == "up":
3894 try:
3895 cmd = devicename + " ifconfig " + intf + " " + status
3896 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003897 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003898 return main.TRUE
3899 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003900 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003901 return main.FALSE
3902 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003903 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003904 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003905 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003906 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003907 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003908 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003909 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003910 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003911 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003912 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003913 return main.FALSE
3914
3915
adminbae64d82013-08-01 10:50:15 -07003916if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07003917 sys.modules[ __name__ ] = MininetCliDriver()