blob: a5870195c85bc35afc09291060a191d970663e7a [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 Songsterae01bba2016-07-11 15:39:17 -07004Modified 2016 by ON.Lab
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
Jon Hall1ccf82c2014-10-15 14:55:16 -040041from math import pow
adminbae64d82013-08-01 10:50:15 -070042from drivers.common.cli.emulatordriver import Emulator
You Wangdb8cd0a2016-05-26 15:19:45 -070043from core.graph import Graph
adminbae64d82013-08-01 10:50:15 -070044
Jon Hall7eb38402015-01-08 17:19:54 -080045
kelvin-onlab50907142015-04-01 13:37:45 -070046class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080047
48 """
49 MininetCliDriver is the basic driver which will handle
50 the Mininet functions"""
51 def __init__( self ):
52 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070053 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080054 self.name = None
kelvin-onlabd9e23de2015-08-06 10:34:44 -070055 self.home = None
Jon Hall7eb38402015-01-08 17:19:54 -080056 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070057 self.flag = 0
Jon Hall892818c2015-10-20 17:58:34 -070058 # TODO: Refactor driver to use these everywhere
59 self.mnPrompt = "mininet>"
60 self.hostPrompt = "~#"
61 self.bashPrompt = "\$"
62 self.scapyPrompt = ">>>"
You Wangdb8cd0a2016-05-26 15:19:45 -070063 self.graph = Graph()
adminbae64d82013-08-01 10:50:15 -070064
Jon Hall7eb38402015-01-08 17:19:54 -080065 def connect( self, **connectargs ):
66 """
67 Here the main is the TestON instance after creating
68 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080069 try:
70 for key in connectargs:
71 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070072 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080073 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070074 for key in self.options:
75 if key == "home":
76 self.home = self.options[ 'home' ]
77 break
78 if self.home is None or self.home == "":
79 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070080
81 try:
Jon Hall892818c2015-10-20 17:58:34 -070082 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070083 self.ip_address = os.getenv( str( self.ip_address ) )
84 else:
85 main.log.info( self.name +
86 ": Trying to connect to " +
87 self.ip_address )
88
89 except KeyError:
90 main.log.info( "Invalid host name," +
91 " connecting to local host instead" )
92 self.ip_address = 'localhost'
93 except Exception as inst:
94 main.log.error( "Uncaught exception: " + str( inst ) )
95
kelvin-onlaba1484582015-02-02 15:46:20 -080096 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070097 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080098 self ).connect(
99 user_name=self.user_name,
100 ip_address=self.ip_address,
101 port=None,
102 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -0800103
kelvin-onlaba1484582015-02-02 15:46:20 -0800104 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -0800105 main.log.info( "Connection successful to the host " +
106 self.user_name +
107 "@" +
108 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800109 return main.TRUE
110 else:
111 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800112 self.user_name +
113 "@" +
114 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800115 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800116 return main.FALSE
117 except pexpect.EOF:
118 main.log.error( self.name + ": EOF exception found" )
119 main.log.error( self.name + ": " + self.handle.before )
120 main.cleanup()
121 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800122 except Exception:
123 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800124 main.cleanup()
125 main.exit()
126
kelvin-onlab10e8d392015-06-03 13:53:45 -0700127 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800128 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700129 Description:
130 Starts Mininet accepts a topology(.py) file and/or an optional
131 argument, to start the mininet, as a parameter.
132 Can also send regular mininet command to load up desired topology.
alison12f34c32016-06-10 14:39:21 -0700133 Eg. Pass in a string 'mn --topo=tree,3,3' to mnCmd
kelvin-onlabf512e942015-06-08 19:42:59 -0700134 Options:
135 topoFile = file path for topology file (.py)
136 args = extra option added when starting the topology from the file
137 mnCmd = Mininet command use to start topology
138 Returns:
139 main.TRUE if the mininet starts successfully, main.FALSE
140 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800141 """
Jon Hall7eb38402015-01-08 17:19:54 -0800142 if self.handle:
Jon Hall689d8e42015-04-03 13:59:24 -0700143 # make sure old networks are cleaned up
144 main.log.info( self.name +
145 ": Clearing any residual state or processes" )
Jon Hall7eb38402015-01-08 17:19:54 -0800146 self.handle.sendline( "sudo mn -c" )
147 i = self.handle.expect( [ 'password\sfor\s',
148 'Cleanup\scomplete',
149 pexpect.EOF,
150 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800151 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800152 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700153 # Sudo asking for password
Jon Hall7eb38402015-01-08 17:19:54 -0800154 main.log.info( self.name + ": Sending sudo password" )
155 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800156 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800157 '\$',
158 pexpect.EOF,
159 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800160 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800161 if i == 1:
162 main.log.info( self.name + ": Clean" )
163 elif i == 2:
164 main.log.error( self.name + ": Connection terminated" )
165 elif i == 3: # timeout
Jon Hall689d8e42015-04-03 13:59:24 -0700166 main.log.error( self.name + ": Something while cleaning " +
167 "Mininet took too long... " )
168 # Craft the string to start mininet
169 cmdString = "sudo "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700170 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' ] +\
Jon Halld80cc142015-07-06 13:36:05 -0700177 " " + self.options[ 'arg2' ] +\
178 " --mac --controller " +\
179 self.options[ 'controller' ] + " " +\
180 self.options[ 'arg3' ]
kelvin-onlab10e8d392015-06-03 13:53:45 -0700181 else: # else only use given args
182 pass
183 # TODO: allow use of topo args and method args?
184 else: # Use given topology file
Jon Halld80cc142015-07-06 13:36:05 -0700185 main.log.info(
186 "Starting Mininet from topo file " +
187 topoFile )
Flavio Castrocc38a542016-03-03 13:15:46 -0800188 cmdString += "-E python " + topoFile + " "
kelvin-onlab10e8d392015-06-03 13:53:45 -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
Jon Hall689d8e42015-04-03 13:59:24 -0700197 # Send the command and check if network started
198 self.handle.sendline( "" )
199 self.handle.expect( '\$' )
200 main.log.info( "Sending '" + cmdString + "' to " + self.name )
201 self.handle.sendline( cmdString )
202 while True:
Jon Hall7eb38402015-01-08 17:19:54 -0800203 i = self.handle.expect( [ 'mininet>',
Jon Hall689d8e42015-04-03 13:59:24 -0700204 'Exception',
205 '\*\*\*',
Jon Hallefbd9792015-03-05 16:11:36 -0800206 pexpect.EOF,
207 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700208 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800209 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700210 main.log.info( self.name + ": Mininet built" )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800211 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800212 elif i == 1:
Jon Hall689d8e42015-04-03 13:59:24 -0700213 response = str( self.handle.before +
214 self.handle.after )
215 self.handle.expect( '\$' )
216 response += str( self.handle.before +
Jon Halld80cc142015-07-06 13:36:05 -0700217 self.handle.after )
Jon Hall689d8e42015-04-03 13:59:24 -0700218 main.log.error(
219 self.name +
220 ": Launching Mininet failed: " + response )
221 return main.FALSE
222 elif i == 2:
223 self.handle.expect( [ "\n",
224 pexpect.EOF,
225 pexpect.TIMEOUT ],
226 timeout )
227 main.log.info( self.handle.before )
228 elif i == 3:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800229 main.log.error( self.name + ": Connection timeout" )
230 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700231 elif i == 4: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800232 main.log.error(
233 self.name +
234 ": Something took too long... " )
235 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700236 # Why did we hit this part?
237 main.log.error( "startNet did not return correctly" )
238 return main.FASLE
Jon Hall7eb38402015-01-08 17:19:54 -0800239 else: # if no handle
Jon Hall689d8e42015-04-03 13:59:24 -0700240 main.log.error( self.name + ": Connection failed to the host " +
241 self.user_name + "@" + self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800242 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700243 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800244
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800245 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400246 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800247 # In tree topology, if fanout arg is not given, by default it is 2
248 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400249 fanout = 2
250 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500251 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800252 while( k <= depth - 1 ):
253 count = count + pow( fanout, k )
254 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800255 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800256 while( k <= depth - 2 ):
257 # depth-2 gives you only core links and not considering
258 # edge links as seen by ONOS. If all the links including
259 # edge links are required, do depth-1
260 count = count + pow( fanout, k )
261 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800262 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800263 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800264 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800265
Jon Hall7eb38402015-01-08 17:19:54 -0800266 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800267 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800268 # by default it is 1
269 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400270 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800271 numSwitches = depth
272 numHostsPerSw = fanout
273 totalNumHosts = numSwitches * numHostsPerSw
274 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800275 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800276 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800277 topoDict = { "num_switches": int( numSwitches ),
278 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400279 return topoDict
280
kelvin-onlabd3b64892015-01-20 13:26:24 -0800281 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700282 """
283 Calculate the number of switches and links in a topo."""
284 # TODO: combine this function and numSwitchesNlinks
285 argList = self.options[ 'arg1' ].split( "," )
286 topoArgList = argList[ 0 ].split( " " )
287 argList = map( int, argList[ 1: ] )
288 topoArgList = topoArgList[ 1: ] + argList
289
290 topoDict = self.numSwitchesNlinks( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400291 return topoDict
292
GlennRCf07c44a2015-09-18 13:33:46 -0700293 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800294 """
295 Verifies the reachability of the hosts using pingall command.
296 Optional parameter timeout allows you to specify how long to
297 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700298 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700299 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700300 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700301 ping
302 acceptableFailed - Set the number of acceptable failed pings for the
303 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800304 Returns:
305 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700306 otherwise main.FALSE
307 """
308 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700309 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700310 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700311 if self.handle:
312 main.log.info(
313 self.name +
314 ": Checking reachabilty to the hosts using pingall" )
315 response = ""
316 failedPings = 0
317 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700318 cmd = "pingall"
319 if protocol == "IPv6":
320 cmd = "py net.pingAll6()"
321 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700322 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700323 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700324 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700325 pexpect.EOF,
326 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700327 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700328 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700329 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700330 response += self.handle.before
331 break
332 elif i == 1:
333 response += self.handle.before + self.handle.after
334 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700335 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700336 returnValue = main.FALSE
337 if shortCircuit:
338 main.log.error( self.name +
339 ": Aborting pingall - "
340 + str( failedPings ) +
341 " pings failed" )
342 break
Jon Hall390696c2015-05-05 17:13:41 -0700343 if ( time.time() - startTime ) > timeout:
344 returnValue = main.FALSE
345 main.log.error( self.name +
346 ": Aborting pingall - " +
347 "Function took too long " )
348 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700349 elif i == 2:
350 main.log.error( self.name +
351 ": EOF exception found" )
352 main.log.error( self.name + ": " +
353 self.handle.before )
354 main.cleanup()
355 main.exit()
356 elif i == 3:
357 response += self.handle.before
358 main.log.error( self.name +
359 ": TIMEOUT exception found" )
360 main.log.error( self.name +
361 ": " +
362 str( response ) )
363 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800364 self.handle.send( "\x03" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700365 self.handle.expect( "Interrupt" )
366 self.handle.expect( "mininet>" )
367 break
368 pattern = "Results\:"
369 main.log.info( "Pingall output: " + str( response ) )
370 if re.search( pattern, response ):
371 main.log.info( self.name + ": Pingall finished with "
372 + str( failedPings ) + " failed pings" )
373 return returnValue
374 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700375 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800376 self.handle.send( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700377 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700378 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700379 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700380 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700381 main.log.error( self.name + ": Connection failed to the host" )
382 main.cleanup()
383 main.exit()
384 except pexpect.TIMEOUT:
385 if response:
386 main.log.info( "Pingall output: " + str( response ) )
387 main.log.error( self.name + ": pexpect.TIMEOUT found" )
388 return main.FALSE
389 except pexpect.EOF:
390 main.log.error( self.name + ": EOF exception found" )
391 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500392 main.cleanup()
393 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700394
Jon Hall7eb38402015-01-08 17:19:54 -0800395 def fpingHost( self, **pingParams ):
396 """
397 Uses the fping package for faster pinging...
398 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800399 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800400 command = args[ "SRC" ] + \
401 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
402 self.handle.sendline( command )
403 self.handle.expect(
404 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
405 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
406 response = self.handle.before
407 if re.search( ":\s-", response ):
408 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700409 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800410 elif re.search( ":\s\d{1,2}\.\d\d", response ):
411 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700412 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800413 main.log.info( self.name + ": Install fping on mininet machine... " )
414 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700415 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800416
Jon Hall3b489db2015-10-05 14:38:37 -0700417 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400418 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700419 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700420
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400421 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700422 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700423
424 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400425 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700426
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400427 Returns main.FALSE if one or more of hosts specified
428 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700429 wait = int( wait )
430 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400431
432 try:
433 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700434
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400435 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700436 pingResponse = "IPv4 ping across specified hosts\n"
437 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400438 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700439 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400440 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700441 pingList = hostList[ :listIndex ] + \
442 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700443
444 pingResponse += str(str(host) + " -> ")
445
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400446 for temp in pingList:
447 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700448 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700449 self.handle.sendline( pingCmd )
450 self.handle.expect( "mininet>", timeout=wait + 1 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400451 response = self.handle.before
452 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRCd10d3cc2015-09-24 12:47:16 -0700453 pingResponse += str(" h" + str( temp[1:] ))
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400454 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700455 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400456 # One of the host to host pair is unreachable
457 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700458 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700459 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700460 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700461 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700462 except pexpect.TIMEOUT:
463 main.log.exception( self.name + ": TIMEOUT exception" )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700464 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400465 except pexpect.EOF:
466 main.log.error( self.name + ": EOF exception found" )
467 main.log.error( self.name + ": " + self.handle.before )
468 main.cleanup()
469 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700470 except Exception:
471 main.log.exception( self.name + ": Uncaught exception!" )
472 main.cleanup()
473 main.exit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400474
Jon Hall3b489db2015-10-05 14:38:37 -0700475 def pingIpv6Hosts( self, hostList, prefix='1000::', wait=1 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700476 """
Jon Hall3b489db2015-10-05 14:38:37 -0700477 IPv6 ping all hosts in hostList. If no prefix passed this will use
478 default prefix of 1000::
Hari Krishna9592fc82015-07-31 15:11:15 -0700479
Jon Hall3b489db2015-10-05 14:38:37 -0700480 Returns main.TRUE if all hosts specified can reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700481
Jon Hall3b489db2015-10-05 14:38:37 -0700482 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700483 """
484 try:
485 main.log.info( "Testing reachability between specified IPv6 hosts" )
486 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700487 wait = int( wait )
488 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700489 pingResponse = "IPv6 Pingall output:\n"
490 failedPings = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700491 for host in hostList:
492 listIndex = hostList.index( host )
493 # List of hosts to ping other than itself
494 pingList = hostList[ :listIndex ] + \
495 hostList[ ( listIndex + 1 ): ]
496
GlennRC2cf7d952015-09-11 16:32:13 -0700497 pingResponse += str(str(host) + " -> ")
498
Hari Krishna9592fc82015-07-31 15:11:15 -0700499 for temp in pingList:
500 # Current host pings all other hosts specified
Jon Hall439c8912016-04-15 02:22:03 -0700501 pingCmd = str( host ) + cmd + str( self.getIPAddress(temp,proto='IPv6') )
Jon Hall934576d2015-10-09 10:12:22 -0700502 self.handle.sendline( pingCmd )
503 self.handle.expect( "mininet>", timeout=wait + 1 )
Hari Krishna9592fc82015-07-31 15:11:15 -0700504 response = self.handle.before
505 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRC2cf7d952015-09-11 16:32:13 -0700506 pingResponse += str(" h" + str( temp[1:] ))
Hari Krishna9592fc82015-07-31 15:11:15 -0700507 else:
GlennRC2cf7d952015-09-11 16:32:13 -0700508 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700509 # One of the host to host pair is unreachable
510 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700511 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700512 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700513 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700514 return isReachable
515
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700516 except pexpect.TIMEOUT:
517 main.log.exception( self.name + ": TIMEOUT exception" )
518 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700519 except pexpect.EOF:
520 main.log.error( self.name + ": EOF exception found" )
521 main.log.error( self.name + ": " + self.handle.before )
522 main.cleanup()
523 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700524 except Exception:
525 main.log.exception( self.name + ": Uncaught exception!" )
526 main.cleanup()
527 main.exit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700528
Jon Hall7eb38402015-01-08 17:19:54 -0800529 def pingHost( self, **pingParams ):
530 """
Jon Hall3b489db2015-10-05 14:38:37 -0700531 Ping from one mininet host to another
532 Currently the only supported Params: SRC, TARGET, and WAIT
533 """
534 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
535 wait = args['WAIT']
536 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800537 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700538 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700539 try:
Jon Hall61282e32015-03-19 11:34:11 -0700540 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800541 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700542 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
543 timeout=wait + 1 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700544 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800545 main.log.error(
546 self.name +
547 ": timeout when waiting for response from mininet" )
548 main.log.error( "response: " + str( self.handle.before ) )
549 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700550 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800551 main.log.error(
552 self.name +
553 ": timeout when waiting for response from mininet" )
554 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700555 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700556 if re.search( ',\s0\%\spacket\sloss', response ):
557 main.log.info( self.name + ": no packets lost, host is reachable" )
558 return main.TRUE
559 else:
560 main.log.error(
561 self.name +
562 ": PACKET LOST, HOST IS NOT REACHABLE" )
563 return main.FALSE
564
Jon Hallfbc828e2015-01-06 17:30:19 -0800565 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800566 main.log.error( self.name + ": EOF exception found" )
567 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700568 main.cleanup()
569 main.exit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700570 except Exception:
571 main.log.exception( self.name + ": Uncaught exception!" )
572 main.cleanup()
573 main.exit()
574
575 def ping6pair( self, **pingParams ):
576 """
GlennRC2cf7d952015-09-11 16:32:13 -0700577 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700578 Currently the only supported Params are: SRC, TARGET, and WAIT
Hari Krishna012a1c12015-08-25 14:23:58 -0700579 FLOWLABEL and -I (src interface) will be added later after running some tests.
580 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
581 """
Jon Hall3b489db2015-10-05 14:38:37 -0700582 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
583 wait = args['WAIT']
584 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530585 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700586 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700587 try:
588 main.log.info( "Sending: " + command )
589 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700590 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
591 timeout=wait + 1 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700592 if i == 1:
593 main.log.error(
594 self.name +
595 ": timeout when waiting for response from mininet" )
596 main.log.error( "response: " + str( self.handle.before ) )
597 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
598 if i == 1:
599 main.log.error(
600 self.name +
601 ": timeout when waiting for response from mininet" )
602 main.log.error( "response: " + str( self.handle.before ) )
603 response = self.handle.before
604 main.log.info( self.name + ": Ping Response: " + response )
605 if re.search( ',\s0\%\spacket\sloss', response ):
606 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700607 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700608 else:
609 main.log.error(
610 self.name +
611 ": PACKET LOST, HOST IS NOT REACHABLE" )
612 return main.FALSE
613
614 except pexpect.EOF:
615 main.log.error( self.name + ": EOF exception found" )
616 main.log.error( self.name + ": " + self.handle.before )
617 main.cleanup()
618 main.exit()
619 except Exception:
620 main.log.exception( self.name + ": Uncaught exception!" )
621 main.cleanup()
622 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800623
You Wangdb927a52016-02-26 11:03:28 -0800624 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
625 """
626 Description:
627 Ping a set of destination host from host CLI.
628 Logging into a Mininet host CLI is required before calling this funtion.
629 Params:
630 dstIPList is a list of destination ip addresses
631 Returns:
632 main.TRUE if the destination host is reachable
633 main.FALSE otherwise
634 """
635 isReachable = main.TRUE
636 wait = int( wait )
637 cmd = "ping"
638 if IPv6:
639 cmd = cmd + "6"
640 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
641 try:
642 for dstIP in dstIPList:
643 pingCmd = cmd + " " + dstIP
644 self.handle.sendline( pingCmd )
645 i = self.handle.expect( [ self.hostPrompt,
646 '\*\*\* Unknown command: ' + pingCmd,
647 pexpect.TIMEOUT ],
648 timeout=wait + 1 )
649 if i == 0:
650 response = self.handle.before
651 if not re.search( ',\s0\%\spacket\sloss', response ):
652 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
653 isReachable = main.FALSE
654 elif i == 1:
655 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
656 main.cleanup()
657 main.exit()
658 elif i == 2:
659 main.log.error( self.name + ": timeout when waiting for response" )
660 isReachable = main.FALSE
661 else:
662 main.log.error( self.name + ": unknown response: " + self.handle.before )
663 isReachable = main.FALSE
664 except pexpect.TIMEOUT:
665 main.log.exception( self.name + ": TIMEOUT exception" )
666 isReachable = main.FALSE
667 except pexpect.EOF:
668 main.log.error( self.name + ": EOF exception found" )
669 main.log.error( self.name + ": " + self.handle.before )
670 main.cleanup()
671 main.exit()
672 except Exception:
673 main.log.exception( self.name + ": Uncaught exception!" )
674 main.cleanup()
675 main.exit()
676 return isReachable
677
Jon Hall7eb38402015-01-08 17:19:54 -0800678 def checkIP( self, host ):
679 """
680 Verifies the host's ip configured or not."""
681 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700682 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800683 response = self.execute(
684 cmd=host +
685 " ifconfig",
686 prompt="mininet>",
687 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800688 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800689 main.log.error( self.name + ": EOF exception found" )
690 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700691 main.cleanup()
692 main.exit()
adminbae64d82013-08-01 10:50:15 -0700693
Jon Hall7eb38402015-01-08 17:19:54 -0800694 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800695 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
696 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
697 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
698 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
699 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800700 # pattern = "inet addr:10.0.0.6"
701 if re.search( pattern, response ):
702 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700703 return main.TRUE
704 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800705 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700706 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800707 else:
708 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800709
Jon Hall7eb38402015-01-08 17:19:54 -0800710 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800711 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700712 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800713 response = self.execute(
714 cmd="h1 /usr/sbin/sshd -D&",
715 prompt="mininet>",
716 timeout=10 )
717 response = self.execute(
718 cmd="h4 /usr/sbin/sshd -D&",
719 prompt="mininet>",
720 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700721 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800722 vars( self )[ key ] = connectargs[ key ]
723 response = self.execute(
724 cmd="xterm h1 h4 ",
725 prompt="mininet>",
726 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800727 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800728 main.log.error( self.name + ": EOF exception found" )
729 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700730 main.cleanup()
731 main.exit()
adminbae64d82013-08-01 10:50:15 -0700732 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800733 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700734 if self.flag == 0:
735 self.flag = 1
736 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800737 else:
adminbae64d82013-08-01 10:50:15 -0700738 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800739
Jon Hall53c5e662016-04-13 16:06:56 -0700740 def moveHost( self, host, oldSw, newSw, ):
741 """
742 Moves a host from one switch to another on the fly
743 Note: The intf between host and oldSw when detached
744 using detach(), will still show up in the 'net'
745 cmd, because switch.detach() doesn't affect switch.intfs[]
746 ( which is correct behavior since the interfaces
747 haven't moved ).
748 """
749 if self.handle:
750 try:
751 # Bring link between oldSw-host down
752 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
753 "'," + "'down')"
754 print "cmd1= ", cmd
755 response = self.execute( cmd=cmd,
756 prompt="mininet>",
757 timeout=10 )
758
759 # Determine hostintf and Oldswitchintf
760 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
761 ")[0]"
762 print "cmd2= ", cmd
763 self.handle.sendline( cmd )
764 self.handle.expect( "mininet>" )
765
766 # Determine ip and mac address of the host-oldSw interface
767 cmd = "px ipaddr = hintf.IP()"
768 print "cmd3= ", cmd
769 self.handle.sendline( cmd )
770 self.handle.expect( "mininet>" )
771
772 cmd = "px macaddr = hintf.MAC()"
773 print "cmd3= ", cmd
774 self.handle.sendline( cmd )
775 self.handle.expect( "mininet>" )
776
777 # Detach interface between oldSw-host
778 cmd = "px " + oldSw + ".detach( sintf )"
779 print "cmd4= ", cmd
780 self.handle.sendline( cmd )
781 self.handle.expect( "mininet>" )
782
783 # Add link between host-newSw
784 cmd = "py net.addLink(" + host + "," + newSw + ")"
785 print "cmd5= ", cmd
786 self.handle.sendline( cmd )
787 self.handle.expect( "mininet>" )
788
789 # Determine hostintf and Newswitchintf
790 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
791 ")[0]"
792 print "cmd6= ", cmd
793 self.handle.sendline( cmd )
794 self.handle.expect( "mininet>" )
795
796 # Attach interface between newSw-host
797 cmd = "px " + newSw + ".attach( sintf )"
798 print "cmd3= ", cmd
799 self.handle.sendline( cmd )
800 self.handle.expect( "mininet>" )
801
802 # Set ipaddress of the host-newSw interface
803 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
804 print "cmd7 = ", cmd
805 self.handle.sendline( cmd )
806 self.handle.expect( "mininet>" )
807
808 # Set macaddress of the host-newSw interface
809 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
810 print "cmd8 = ", cmd
811 self.handle.sendline( cmd )
812 self.handle.expect( "mininet>" )
813
814 cmd = "net"
815 print "cmd9 = ", cmd
816 self.handle.sendline( cmd )
817 self.handle.expect( "mininet>" )
818 print "output = ", self.handle.before
819
820 # Determine ipaddress of the host-newSw interface
821 cmd = host + " ifconfig"
822 print "cmd10= ", cmd
823 self.handle.sendline( cmd )
824 self.handle.expect( "mininet>" )
825 print "ifconfig o/p = ", self.handle.before
826
827 return main.TRUE
828 except pexpect.EOF:
829 main.log.error( self.name + ": EOF exception found" )
830 main.log.error( self.name + ": " + self.handle.before )
831 return main.FALSE
832
Jon Hall439c8912016-04-15 02:22:03 -0700833 def moveHostv6( self, host, oldSw, newSw, ):
kelvin-onlaba1484582015-02-02 15:46:20 -0800834 """
835 Moves a host from one switch to another on the fly
836 Note: The intf between host and oldSw when detached
837 using detach(), will still show up in the 'net'
838 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700839 ( which is correct behavior since the interfaces
840 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800841 """
842 if self.handle:
843 try:
Jon Hall439c8912016-04-15 02:22:03 -0700844 IP = str( self.getIPAddress( host, proto='IPV6' ) ) + "/64"
kelvin-onlaba1484582015-02-02 15:46:20 -0800845 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700846 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800847 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800848 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800849 response = self.execute( cmd=cmd,
850 prompt="mininet>",
851 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700852
kelvin-onlaba1484582015-02-02 15:46:20 -0800853 # Determine hostintf and Oldswitchintf
854 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800855 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800856 print "cmd2= ", cmd
857 self.handle.sendline( cmd )
858 self.handle.expect( "mininet>" )
859
shahshreya73537862015-02-11 15:15:24 -0800860 # Determine ip and mac address of the host-oldSw interface
Jon Hall439c8912016-04-15 02:22:03 -0700861 cmd = "px ipaddr = " + str(IP)
kelvin-onlaba1484582015-02-02 15:46:20 -0800862 print "cmd3= ", cmd
863 self.handle.sendline( cmd )
864 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800865
866 cmd = "px macaddr = hintf.MAC()"
867 print "cmd3= ", cmd
868 self.handle.sendline( cmd )
869 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700870
kelvin-onlaba1484582015-02-02 15:46:20 -0800871 # Detach interface between oldSw-host
872 cmd = "px " + oldSw + ".detach( sintf )"
873 print "cmd4= ", cmd
874 self.handle.sendline( cmd )
875 self.handle.expect( "mininet>" )
876
877 # Add link between host-newSw
878 cmd = "py net.addLink(" + host + "," + newSw + ")"
879 print "cmd5= ", cmd
880 self.handle.sendline( cmd )
881 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700882
kelvin-onlaba1484582015-02-02 15:46:20 -0800883 # Determine hostintf and Newswitchintf
884 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800885 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800886 print "cmd6= ", cmd
887 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700888 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800889
890 # Attach interface between newSw-host
891 cmd = "px " + newSw + ".attach( sintf )"
Jon Hall439c8912016-04-15 02:22:03 -0700892 print "cmd6= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800893 self.handle.sendline( cmd )
894 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800895
896 # Set macaddress of the host-newSw interface
897 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
Jon Hall439c8912016-04-15 02:22:03 -0700898 print "cmd7 = ", cmd
899 self.handle.sendline( cmd )
900 self.handle.expect( "mininet>" )
901
902 # Set ipaddress of the host-newSw interface
903 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
shahshreya73537862015-02-11 15:15:24 -0800904 print "cmd8 = ", cmd
905 self.handle.sendline( cmd )
906 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700907
Jon Hall439c8912016-04-15 02:22:03 -0700908 cmd = host + " ifconfig"
909 print "cmd9 =",cmd
910 response = self.execute( cmd = cmd, prompt="mininet>" ,timeout=10 )
911 print response
912 pattern = "h\d-eth([\w])"
Jeremyd9e4eb12016-04-13 12:09:06 -0700913 ipAddressSearch = re.search( pattern, response )
Jon Hall439c8912016-04-15 02:22:03 -0700914 print ipAddressSearch.group(1)
915 intf= host + "-eth" + str(ipAddressSearch.group(1))
916 cmd = host + " ip -6 addr add %s dev %s" % ( IP, intf )
917 print "cmd10 = ", cmd
918 self.handle.sendline( cmd )
919 self.handle.expect( "mininet>" )
920
kelvin-onlaba1484582015-02-02 15:46:20 -0800921 cmd = "net"
Jon Hall439c8912016-04-15 02:22:03 -0700922 print "cmd11 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800923 self.handle.sendline( cmd )
924 self.handle.expect( "mininet>" )
925 print "output = ", self.handle.before
926
927 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800928 cmd = host + " ifconfig"
Jon Hall439c8912016-04-15 02:22:03 -0700929 print "cmd12= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800930 self.handle.sendline( cmd )
931 self.handle.expect( "mininet>" )
932 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700933
kelvin-onlaba1484582015-02-02 15:46:20 -0800934 return main.TRUE
935 except pexpect.EOF:
936 main.log.error( self.name + ": EOF exception found" )
937 main.log.error( self.name + ": " + self.handle.before )
938 return main.FALSE
939
Jon Hall7eb38402015-01-08 17:19:54 -0800940 def changeIP( self, host, intf, newIP, newNetmask ):
941 """
942 Changes the ip address of a host on the fly
943 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800944 if self.handle:
945 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800946 cmd = host + " ifconfig " + intf + " " + \
947 newIP + " " + 'netmask' + " " + newNetmask
948 self.handle.sendline( cmd )
949 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800950 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800951 main.log.info( "response = " + response )
952 main.log.info(
953 "Ip of host " +
954 host +
955 " changed to new IP " +
956 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800957 return main.TRUE
958 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800959 main.log.error( self.name + ": EOF exception found" )
960 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800961 return main.FALSE
962
Jon Hall7eb38402015-01-08 17:19:54 -0800963 def changeDefaultGateway( self, host, newGW ):
964 """
965 Changes the default gateway of a host
966 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800967 if self.handle:
968 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800969 cmd = host + " route add default gw " + newGW
970 self.handle.sendline( cmd )
971 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800972 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800973 main.log.info( "response = " + response )
974 main.log.info(
975 "Default gateway of host " +
976 host +
977 " changed to " +
978 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800979 return main.TRUE
980 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800981 main.log.error( self.name + ": EOF exception found" )
982 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800983 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800984
Jon Hall7eb38402015-01-08 17:19:54 -0800985 def addStaticMACAddress( self, host, GW, macaddr ):
986 """
Jon Hallefbd9792015-03-05 16:11:36 -0800987 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800988 if self.handle:
989 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800990 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
991 cmd = host + " arp -s " + GW + " " + macaddr
992 self.handle.sendline( cmd )
993 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800994 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800995 main.log.info( "response = " + response )
996 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800997 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800998 GW +
999 " changed to " +
1000 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001001 return main.TRUE
1002 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001003 main.log.error( self.name + ": EOF exception found" )
1004 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001005 return main.FALSE
1006
Jon Hall7eb38402015-01-08 17:19:54 -08001007 def verifyStaticGWandMAC( self, host ):
1008 """
1009 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001010 if self.handle:
1011 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001012 # h1 arp -an
1013 cmd = host + " arp -an "
1014 self.handle.sendline( cmd )
1015 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001016 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001017 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001018 return main.TRUE
1019 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001020 main.log.error( self.name + ": EOF exception found" )
1021 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001022 return main.FALSE
1023
Jon Hall7eb38402015-01-08 17:19:54 -08001024 def getMacAddress( self, host ):
1025 """
1026 Verifies the host's ip configured or not."""
1027 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001028 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001029 response = self.execute(
1030 cmd=host +
1031 " ifconfig",
1032 prompt="mininet>",
1033 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001034 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001035 main.log.error( self.name + ": EOF exception found" )
1036 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001037 main.cleanup()
1038 main.exit()
adminbae64d82013-08-01 10:50:15 -07001039
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001040 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001041 macAddressSearch = re.search( pattern, response, re.I )
1042 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001043 main.log.info(
1044 self.name +
1045 ": Mac-Address of Host " +
1046 host +
1047 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001048 macAddress )
1049 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001050 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001051 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001052
Jon Hall7eb38402015-01-08 17:19:54 -08001053 def getInterfaceMACAddress( self, host, interface ):
1054 """
1055 Return the IP address of the interface on the given host"""
1056 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001057 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001058 response = self.execute( cmd=host + " ifconfig " + interface,
1059 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001060 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001061 main.log.error( self.name + ": EOF exception found" )
1062 main.log.error( self.name + ": " + self.handle.before )
1063 main.cleanup()
1064 main.exit()
1065
1066 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001067 macAddressSearch = re.search( pattern, response, re.I )
1068 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001069 main.log.info( "No mac address found in %s" % response )
1070 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001071 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001072 main.log.info(
1073 "Mac-Address of " +
1074 host +
1075 ":" +
1076 interface +
1077 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001078 macAddress )
1079 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001080 else:
1081 main.log.error( "Connection failed to the host" )
1082
sathishmad953462015-12-03 17:42:07 +05301083 def getIPAddress( self, host , proto='IPV4'):
Jon Hall7eb38402015-01-08 17:19:54 -08001084 """
1085 Verifies the host's ip configured or not."""
1086 if self.handle:
1087 try:
1088 response = self.execute(
1089 cmd=host +
1090 " ifconfig",
1091 prompt="mininet>",
1092 timeout=10 )
1093 except pexpect.EOF:
1094 main.log.error( self.name + ": EOF exception found" )
1095 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001096 main.cleanup()
1097 main.exit()
adminbae64d82013-08-01 10:50:15 -07001098
sathishmad953462015-12-03 17:42:07 +05301099 pattern = ''
1100 if proto == 'IPV4':
1101 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
1102 else:
Jon Hall439c8912016-04-15 02:22:03 -07001103 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001104 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -08001105 main.log.info(
1106 self.name +
1107 ": IP-Address of Host " +
1108 host +
1109 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001110 ipAddressSearch.group( 1 ) )
1111 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001112 else:
1113 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001114
Jon Hall7eb38402015-01-08 17:19:54 -08001115 def getSwitchDPID( self, switch ):
1116 """
1117 return the datapath ID of the switch"""
1118 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001119 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001120 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001121 response = self.execute(
1122 cmd=cmd,
1123 prompt="mininet>",
1124 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001125 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001126 main.log.error( self.name + ": EOF exception found" )
1127 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001128 main.cleanup()
1129 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001130 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001131 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001132 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001133 main.log.info(
1134 "Couldn't find DPID for switch %s, found: %s" %
1135 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001136 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001137 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001138 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001139 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001140
Jon Hall7eb38402015-01-08 17:19:54 -08001141 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001142 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001143 self.handle.sendline( "" )
1144 self.expect( "mininet>" )
1145 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001146 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001147 response = self.execute(
1148 cmd=cmd,
1149 prompt="mininet>",
1150 timeout=10 )
1151 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001152 response = self.handle.before
1153 return response
1154 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001155 main.log.error( self.name + ": EOF exception found" )
1156 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -07001157 main.cleanup()
1158 main.exit()
1159
Jon Hall7eb38402015-01-08 17:19:54 -08001160 def getInterfaces( self, node ):
1161 """
1162 return information dict about interfaces connected to the node"""
1163 if self.handle:
1164 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001165 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001166 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001167 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001168 response = self.execute(
1169 cmd=cmd,
1170 prompt="mininet>",
1171 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001172 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001173 main.log.error( self.name + ": EOF exception found" )
1174 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001175 main.cleanup()
1176 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001177 return response
1178 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001179 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001180
Jon Hall7eb38402015-01-08 17:19:54 -08001181 def dump( self ):
1182 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001183 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001184 response = self.execute(
1185 cmd='dump',
1186 prompt='mininet>',
1187 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001188 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001189 main.log.error( self.name + ": EOF exception found" )
1190 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001191 main.cleanup()
1192 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001193 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001194
Jon Hall7eb38402015-01-08 17:19:54 -08001195 def intfs( self ):
1196 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001197 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001198 response = self.execute(
1199 cmd='intfs',
1200 prompt='mininet>',
1201 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001202 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001203 main.log.error( self.name + ": EOF exception found" )
1204 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001205 main.cleanup()
1206 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001207 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001208
Jon Hall7eb38402015-01-08 17:19:54 -08001209 def net( self ):
1210 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001211 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001212 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001213 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001214 main.log.error( self.name + ": EOF exception found" )
1215 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001216 main.cleanup()
1217 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001218 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001219
YPZhang81a7d4e2016-04-18 13:10:17 -07001220 def links( self, timeout=20 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001221 main.log.info( self.name + ": List network links" )
1222 try:
1223 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001224 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001225 except pexpect.EOF:
1226 main.log.error( self.name + ": EOF exception found" )
1227 main.log.error( self.name + ": " + self.handle.before )
1228 main.cleanup()
1229 main.exit()
1230 return response
1231
GlennRC61321f22015-07-16 13:36:54 -07001232 def iperftcpAll(self, hosts, timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001233 '''
1234 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001235
kelvin-onlab7cce9382015-07-17 10:21:03 -07001236 @parm:
1237 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1238 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1239 '''
1240 for host1 in hosts:
1241 for host2 in hosts:
1242 if host1 != host2:
1243 if self.iperftcp(host1, host2, timeout) == main.FALSE:
1244 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
GlennRC61321f22015-07-16 13:36:54 -07001245
1246 def iperftcp(self, host1="h1", host2="h2", timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001247 '''
1248 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1249 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001250
kelvin-onlab7cce9382015-07-17 10:21:03 -07001251 @parm:
1252 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1253 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1254 '''
1255 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1256 try:
1257 # Setup the mininet command
1258 cmd1 = 'iperf ' + host1 + " " + host2
1259 self.handle.sendline( cmd1 )
1260 outcome = self.handle.expect( "mininet>", timeout )
1261 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001262
kelvin-onlab7cce9382015-07-17 10:21:03 -07001263 # checks if there are results in the mininet response
1264 if "Results:" in response:
Jon Hall892818c2015-10-20 17:58:34 -07001265 main.log.report(self.name + ": iperf test completed")
kelvin-onlab7cce9382015-07-17 10:21:03 -07001266 # parse the mn results
1267 response = response.split("\r\n")
1268 response = response[len(response)-2]
1269 response = response.split(": ")
1270 response = response[len(response)-1]
1271 response = response.replace("[", "")
1272 response = response.replace("]", "")
1273 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001274
kelvin-onlab7cce9382015-07-17 10:21:03 -07001275 # this is the bandwith two and from the two hosts
1276 bandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001277
kelvin-onlab7cce9382015-07-17 10:21:03 -07001278 # there should be two elements in the bandwidth list
1279 # ['host1 to host2', 'host2 to host1"]
1280 if len(bandwidth) == 2:
1281 main.log.report(self.name + ": iperf test successful")
1282 return main.TRUE
1283 else:
1284 main.log.error(self.name + ": invalid iperf results")
1285 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001286 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001287 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001288 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001289 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001290 main.log.error( self.name + ": TIMEOUT exception found" )
1291 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001292 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001293 # NOTE: Send ctrl-c to make sure iperf is done
1294 self.handle.sendline( "\x03" )
1295 self.handle.expect( "Interrupt" )
1296 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001297 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001298 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001299 main.log.error( self.name + ": EOF exception found" )
1300 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001301 main.cleanup()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001302 main.exit()
GlennRC61321f22015-07-16 13:36:54 -07001303
Jon Hall439c8912016-04-15 02:22:03 -07001304 def iperftcpipv6(self, host1="h1", host2="h2", timeout=50):
1305 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1306 try:
1307 IP1 = self.getIPAddress( host1, proto='IPV6' )
1308 cmd1 = host1 +' iperf -V -sD -B '+ str(IP1)
1309 self.handle.sendline( cmd1 )
1310 outcome1 = self.handle.expect( "mininet>")
1311 cmd2 = host2 +' iperf -V -c '+ str(IP1) +' -t 5'
1312 self.handle.sendline( cmd2 )
1313 outcome2 = self.handle.expect( "mininet>")
1314 response1 = self.handle.before
1315 response2 = self.handle.after
1316 print response1,response2
1317 pattern = "connected with "+ str(IP1)
1318 if pattern in response1:
1319 main.log.report(self.name + ": iperf test completed")
1320 return main.TRUE
1321 else:
1322 main.log.error( self.name + ": iperf test failed" )
1323 return main.FALSE
1324 except pexpect.TIMEOUT:
1325 main.log.error( self.name + ": TIMEOUT exception found" )
1326 main.log.error( self.name + " response: " + repr( self.handle.before ) )
1327 self.handle.sendline( "\x03" )
1328 self.handle.expect( "Interrupt" )
1329 self.handle.expect( "mininet>" )
1330 return main.FALSE
1331 except pexpect.EOF:
1332 main.log.error( self.name + ": EOF exception found" )
1333 main.log.error( self.name + ": " + self.handle.before )
1334 main.cleanup()
1335 main.exit()
1336
GlennRC61321f22015-07-16 13:36:54 -07001337 def iperfudpAll(self, hosts, bandwidth="10M"):
1338 '''
1339 Runs the iperfudp function with a given set of hosts and specified
1340 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001341
GlennRC61321f22015-07-16 13:36:54 -07001342 @param:
1343 bandwidth: the targeted bandwidth, in megabits ('M')
1344 '''
1345 for host1 in hosts:
1346 for host2 in hosts:
1347 if host1 != host2:
1348 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1349 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1350
1351 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1352
kelvin-onlab7cce9382015-07-17 10:21:03 -07001353 '''
1354 Creates an iperf UDP test with a specific bandwidth.
1355 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001356
kelvin-onlab7cce9382015-07-17 10:21:03 -07001357 @param:
1358 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1359 '''
1360 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1361 try:
1362 # setup the mininet command
1363 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1364 self.handle.sendline(cmd)
1365 self.handle.expect("mininet>")
1366 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001367
kelvin-onlab7cce9382015-07-17 10:21:03 -07001368 # check if there are in results in the mininet response
1369 if "Results:" in response:
Jon Hall892818c2015-10-20 17:58:34 -07001370 main.log.report(self.name + ": iperfudp test completed")
kelvin-onlab7cce9382015-07-17 10:21:03 -07001371 # parse the results
1372 response = response.split("\r\n")
1373 response = response[len(response)-2]
1374 response = response.split(": ")
1375 response = response[len(response)-1]
1376 response = response.replace("[", "")
1377 response = response.replace("]", "")
1378 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001379
kelvin-onlab7cce9382015-07-17 10:21:03 -07001380 mnBandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001381
kelvin-onlab7cce9382015-07-17 10:21:03 -07001382 # check to see if there are at least three entries
1383 # ['bandwidth', 'host1 to host2', 'host2 to host1']
1384 if len(mnBandwidth) == 3:
1385 # if one entry is blank then something is wrong
1386 for item in mnBandwidth:
1387 if item == "":
1388 main.log.error(self.name + ": Could not parse iperf output")
1389 main.log.error(self.name + ": invalid iperfudp results")
1390 return main.FALSE
1391 # otherwise results are vaild
1392 main.log.report(self.name + ": iperfudp test successful")
1393 return main.TRUE
1394 else:
1395 main.log.error(self.name + ": invalid iperfudp results")
1396 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001397
kelvin-onlab7cce9382015-07-17 10:21:03 -07001398 except pexpect.EOF:
1399 main.log.error( self.name + ": EOF exception found" )
1400 main.log.error( self.name + ": " + self.handle.before )
1401 main.cleanup()
1402 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001403
Jon Hall7eb38402015-01-08 17:19:54 -08001404 def nodes( self ):
1405 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001406 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001407 response = self.execute(
1408 cmd='nodes',
1409 prompt='mininet>',
1410 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001411 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001412 main.log.error( self.name + ": EOF exception found" )
1413 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001414 main.cleanup()
1415 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001416 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001417
Jon Hall7eb38402015-01-08 17:19:54 -08001418 def pingpair( self ):
1419 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001420 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001421 response = self.execute(
1422 cmd='pingpair',
1423 prompt='mininet>',
1424 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001425 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001426 main.log.error( self.name + ": EOF exception found" )
1427 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001428 main.cleanup()
1429 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001430
Jon Hall7eb38402015-01-08 17:19:54 -08001431 if re.search( ',\s0\%\spacket\sloss', response ):
1432 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001433 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001434 else:
1435 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001436 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001437
Jon Hall7eb38402015-01-08 17:19:54 -08001438 def link( self, **linkargs ):
1439 """
GlennRCed771242016-01-13 17:02:47 -08001440 Bring link( s ) between two nodes up or down
1441 """
Jon Hall6094a362014-04-11 14:46:56 -07001442 try:
GlennRCed771242016-01-13 17:02:47 -08001443 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1444 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1445 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1446 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1447
1448 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1449 cmd = "link {} {} {}".format( end1, end2, option )
1450 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001451 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001452 response = self.handle.before
1453 main.log.info( response )
1454
1455 return main.TRUE
1456 except pexpect.TIMEOUT:
1457 main.log.exception( self.name + ": Command timed out" )
1458 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001459 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001460 main.log.exception( self.name + ": connection closed." )
Jon Hall6094a362014-04-11 14:46:56 -07001461 main.cleanup()
1462 main.exit()
GlennRCed771242016-01-13 17:02:47 -08001463 except Exception:
1464 main.log.exception( self.name + ": Uncaught exception!" )
1465 main.cleanup()
1466 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001467
pingping-lin8244a3b2015-09-16 13:36:56 -07001468 def switch( self, **switchargs ):
1469 """
1470 start/stop a switch
1471 """
1472 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1473 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1474 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1475 command = "switch " + str( sw ) + " " + str( option )
1476 main.log.info( command )
1477 try:
1478 self.handle.sendline( command )
1479 self.handle.expect( "mininet>" )
1480 except pexpect.TIMEOUT:
1481 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1482 main.cleanup()
1483 main.exit()
1484 except pexpect.EOF:
1485 main.log.error( self.name + ": EOF exception found" )
1486 main.log.error( self.name + ": " + self.handle.before )
1487 main.cleanup()
1488 main.exit()
1489 return main.TRUE
1490
pingping-lin5bb663b2015-09-24 11:47:50 -07001491 def node( self, nodeName, commandStr ):
1492 """
1493 Carry out a command line on a given node
1494 @parm:
1495 nodeName: the node name in Mininet testbed
1496 commandStr: the command line will be carried out on the node
1497 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1498 """
1499 command = str( nodeName ) + " " + str( commandStr )
1500 main.log.info( command )
1501
1502 try:
1503 response = self.execute( cmd = command, prompt = "mininet>" )
1504 if re.search( "Unknown command", response ):
1505 main.log.warn( response )
1506 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001507 if re.search( "Permission denied", response ):
1508 main.log.warn( response )
1509 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001510 except pexpect.TIMEOUT:
1511 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1512 main.cleanup()
1513 main.exit()
1514 except pexpect.EOF:
1515 main.log.error( self.name + ": EOF exception found" )
1516 main.log.error( self.name + ": " + self.handle.before )
1517 main.cleanup()
1518 main.exit()
1519 main.log.info( " response is :" )
1520 main.log.info( response )
1521 return response
1522
Jon Hall7eb38402015-01-08 17:19:54 -08001523 def yank( self, **yankargs ):
1524 """
1525 yank a mininet switch interface to a host"""
1526 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001527 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001528 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1529 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1530 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001531 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001532 response = self.execute(
1533 cmd=command,
1534 prompt="mininet>",
1535 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001536 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001537 main.log.error( self.name + ": EOF exception found" )
1538 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001539 main.cleanup()
1540 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001541 return main.TRUE
1542
Jon Hall7eb38402015-01-08 17:19:54 -08001543 def plug( self, **plugargs ):
1544 """
1545 plug the yanked mininet switch interface to a switch"""
1546 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001547 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001548 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1549 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1550 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001551 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001552 response = self.execute(
1553 cmd=command,
1554 prompt="mininet>",
1555 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001556 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001557 main.log.error( self.name + ": EOF exception found" )
1558 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001559 main.cleanup()
1560 main.exit()
adminbae64d82013-08-01 10:50:15 -07001561 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001562
Jon Hall7eb38402015-01-08 17:19:54 -08001563 def dpctl( self, **dpctlargs ):
1564 """
1565 Run dpctl command on all switches."""
1566 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001567 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001568 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1569 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1570 command = "dpctl " + cmd + " " + str( cmdargs )
1571 try:
1572 response = self.execute(
1573 cmd=command,
1574 prompt="mininet>",
1575 timeout=10 )
1576 except pexpect.EOF:
1577 main.log.error( self.name + ": EOF exception found" )
1578 main.log.error( self.name + ": " + self.handle.before )
1579 main.cleanup()
1580 main.exit()
1581 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001582
kelvin-onlabd3b64892015-01-20 13:26:24 -08001583 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001584 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001585 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001586 fileInput = path + '/lib/Mininet/INSTALL'
1587 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001588 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001589 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001590 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001591 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001592 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001593 return version
adminbae64d82013-08-01 10:50:15 -07001594
kelvin-onlabd3b64892015-01-20 13:26:24 -08001595 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001596 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001597 Parameters:
1598 sw: The name of an OVS switch. Example "s1"
1599 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001600 The output of the command from the mininet cli
1601 or main.FALSE on timeout"""
1602 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001603 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001604 response = self.execute(
1605 cmd=command,
1606 prompt="mininet>",
1607 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001608 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001609 return response
admin2a9548d2014-06-17 14:08:07 -07001610 else:
1611 return main.FALSE
1612 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001613 main.log.error( self.name + ": EOF exception found" )
1614 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001615 main.cleanup()
1616 main.exit()
adminbae64d82013-08-01 10:50:15 -07001617
Charles Chan029be652015-08-24 01:46:10 +08001618 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001619 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001620 Description:
1621 Assign switches to the controllers ( for ovs use only )
1622 Required:
1623 sw - Name of the switch. This can be a list or a string.
1624 ip - Ip addresses of controllers. This can be a list or a string.
1625 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001626 port - ONOS use port 6653, if no list of ports is passed, then
1627 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001628 ptcp - ptcp number, This can be a string or a list that has
1629 the same length as switch. This is optional and not required
1630 when using ovs switches.
1631 NOTE: If switches and ptcp are given in a list type they should have the
1632 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1633 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001634
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001635 Return:
1636 Returns main.TRUE if mininet correctly assigned switches to
1637 controllers, otherwise it will return main.FALSE or an appropriate
1638 exception(s)
1639 """
1640 assignResult = main.TRUE
1641 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001642 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001643 command = "sh ovs-vsctl set-controller "
1644 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001645 try:
1646 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001647 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001648 if isinstance( port, types.StringType ) or \
1649 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001650 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001651 elif isinstance( port, types.ListType ):
1652 main.log.error( self.name + ": Only one controller " +
1653 "assigned and a list of ports has" +
1654 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001655 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001656 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001657 main.log.error( self.name + ": Invalid controller port " +
1658 "number. Please specify correct " +
1659 "controller port" )
1660 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001661
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001662 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001663 if isinstance( port, types.StringType ) or \
1664 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001665 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001666 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1667 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001668 elif isinstance( port, types.ListType ):
1669 if ( len( ip ) != len( port ) ):
1670 main.log.error( self.name + ": Port list = " +
1671 str( len( port ) ) +
1672 "should be the same as controller" +
1673 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001674 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001675 else:
1676 onosIp = ""
1677 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001678 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1679 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001680 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001681 main.log.error( self.name + ": Invalid controller port " +
1682 "number. Please specify correct " +
1683 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001684 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001685 else:
1686 main.log.error( self.name + ": Invalid ip address" )
1687 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001688
1689 if isinstance( sw, types.StringType ):
1690 command += sw + " "
1691 if ptcp:
1692 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001693 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001694 elif isinstance( ptcp, types.ListType ):
1695 main.log.error( self.name + ": Only one switch is " +
1696 "being set and multiple PTCP is " +
1697 "being passed " )
1698 else:
1699 main.log.error( self.name + ": Invalid PTCP" )
1700 ptcp = ""
1701 command += onosIp
1702 commandList.append( command )
1703
1704 elif isinstance( sw, types.ListType ):
1705 if ptcp:
1706 if isinstance( ptcp, types.ListType ):
1707 if len( ptcp ) != len( sw ):
1708 main.log.error( self.name + ": PTCP length = " +
1709 str( len( ptcp ) ) +
1710 " is not the same as switch" +
1711 " length = " +
1712 str( len( sw ) ) )
1713 return main.FALSE
1714 else:
1715 for switch, ptcpNum in zip( sw, ptcp ):
1716 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001717 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001718 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001719 tempCmd += onosIp
1720 commandList.append( tempCmd )
1721 else:
1722 main.log.error( self.name + ": Invalid PTCP" )
1723 return main.FALSE
1724 else:
1725 for switch in sw:
1726 tempCmd = "sh ovs-vsctl set-controller "
1727 tempCmd += switch + " " + onosIp
1728 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001729 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001730 main.log.error( self.name + ": Invalid switch type " )
1731 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001732
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001733 for cmd in commandList:
1734 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001735 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001736 except pexpect.TIMEOUT:
1737 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1738 return main.FALSE
1739 except pexpect.EOF:
1740 main.log.error( self.name + ": EOF exception found" )
1741 main.log.error( self.name + ": " + self.handle.before )
1742 main.cleanup()
1743 main.exit()
1744 return main.TRUE
1745 except Exception:
1746 main.log.exception( self.name + ": Uncaught exception!" )
1747 main.cleanup()
1748 main.exit()
adminbae64d82013-08-01 10:50:15 -07001749
kelvin-onlabd3b64892015-01-20 13:26:24 -08001750 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001751 """
1752 Removes the controller target from sw"""
1753 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001754 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001755 response = self.execute(
1756 cmd=command,
1757 prompt="mininet>",
1758 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001759 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001760 main.log.error( self.name + ": EOF exception found" )
1761 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001762 main.cleanup()
1763 main.exit()
1764 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001765 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001766
kelvin-onlabd3b64892015-01-20 13:26:24 -08001767 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001768 """
Jon Hallb1290e82014-11-18 16:17:48 -05001769 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001770 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001771 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001772 NOTE: cannot currently specify what type of switch
1773 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001774 sw = name of the new switch as a string
1775 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001776 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001777 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001778 """
1779 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001780 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001781 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001782 response = self.execute(
1783 cmd=command,
1784 prompt="mininet>",
1785 timeout=10 )
1786 if re.search( "already exists!", response ):
1787 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001788 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001789 elif re.search( "Error", response ):
1790 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001791 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001792 elif re.search( "usage:", response ):
1793 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001794 return main.FALSE
1795 else:
1796 return main.TRUE
1797 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001798 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001799 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001800 main.cleanup()
1801 main.exit()
1802
kelvin-onlabd3b64892015-01-20 13:26:24 -08001803 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001804 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001805 delete a switch from the mininet topology
1806 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001807 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001808 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001809 sw = name of the switch as a string
1810 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001811 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001812 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001813 response = self.execute(
1814 cmd=command,
1815 prompt="mininet>",
1816 timeout=10 )
1817 if re.search( "no switch named", response ):
1818 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001819 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001820 elif re.search( "Error", response ):
1821 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001822 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001823 elif re.search( "usage:", response ):
1824 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001825 return main.FALSE
1826 else:
1827 return main.TRUE
1828 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001829 main.log.error( self.name + ": EOF exception found" )
1830 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001831 main.cleanup()
1832 main.exit()
1833
You Wangdb8cd0a2016-05-26 15:19:45 -07001834 def getSwitchRandom( self, timeout=60, nonCut=True ):
1835 """
1836 Randomly get a switch from Mininet topology.
1837 If nonCut is True, it gets a list of non-cut switches (the deletion
1838 of a non-cut switch will not increase the number of connected
1839 components of a graph) and randomly returns one of them, otherwise
1840 it just randomly returns one switch from all current switches in
1841 Mininet.
1842 Returns the name of the chosen switch.
1843 """
1844 import random
1845 candidateSwitches = []
1846 try:
1847 if not nonCut:
1848 switches = self.getSwitches( timeout=timeout )
1849 assert len( switches ) != 0
1850 for switchName in switches.keys():
1851 candidateSwitches.append( switchName )
1852 else:
1853 graphDict = self.getGraphDict( timeout=timeout, useId=False )
1854 if graphDict == None:
1855 return None
1856 self.graph.update( graphDict )
1857 candidateSwitches = self.graph.getNonCutVertices()
1858 if candidateSwitches == None:
1859 return None
1860 elif len( candidateSwitches ) == 0:
1861 main.log.info( self.name + ": No candidate switch for deletion" )
1862 return None
1863 else:
1864 switch = random.sample( candidateSwitches, 1 )
1865 return switch[ 0 ]
1866 except KeyError:
1867 main.log.exception( self.name + ": KeyError exception found" )
1868 return None
1869 except AssertionError:
1870 main.log.exception( self.name + ": AssertionError exception found" )
1871 return None
1872 except Exception:
1873 main.log.exception( self.name + ": Uncaught exception" )
1874 return None
1875
1876 def delSwitchRandom( self, timeout=60, nonCut=True ):
1877 """
1878 Randomly delete a switch from Mininet topology.
1879 If nonCut is True, it gets a list of non-cut switches (the deletion
1880 of a non-cut switch will not increase the number of connected
1881 components of a graph) and randomly chooses one for deletion,
1882 otherwise it just randomly delete one switch from all current
1883 switches in Mininet.
1884 Returns the name of the deleted switch
1885 """
1886 try:
1887 switch = self.getSwitchRandom( timeout, nonCut )
1888 if switch == None:
1889 return None
1890 else:
1891 deletionResult = self.delSwitch( switch )
1892 if deletionResult:
1893 return switch
1894 else:
1895 return None
1896 except Exception:
1897 main.log.exception( self.name + ": Uncaught exception" )
1898 return None
1899
kelvin-onlabd3b64892015-01-20 13:26:24 -08001900 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001901 """
1902 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001903 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001904 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001905 NOTE: cannot currently specify what type of link
1906 required params:
1907 node1 = the string node name of the first endpoint of the link
1908 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001909 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001910 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001911 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001912 response = self.execute(
1913 cmd=command,
1914 prompt="mininet>",
1915 timeout=10 )
1916 if re.search( "doesnt exist!", response ):
1917 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001918 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001919 elif re.search( "Error", response ):
1920 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001921 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001922 elif re.search( "usage:", response ):
1923 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001924 return main.FALSE
1925 else:
1926 return main.TRUE
1927 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001928 main.log.error( self.name + ": EOF exception found" )
1929 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001930 main.cleanup()
1931 main.exit()
1932
kelvin-onlabd3b64892015-01-20 13:26:24 -08001933 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001934 """
1935 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001936 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001937 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001938 required params:
1939 node1 = the string node name of the first endpoint of the link
1940 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001941 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001942 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001943 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001944 response = self.execute(
1945 cmd=command,
1946 prompt="mininet>",
1947 timeout=10 )
1948 if re.search( "no node named", response ):
1949 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001950 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001951 elif re.search( "Error", response ):
1952 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001953 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001954 elif re.search( "usage:", response ):
1955 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001956 return main.FALSE
1957 else:
1958 return main.TRUE
1959 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001960 main.log.error( self.name + ": EOF exception found" )
1961 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001962 main.cleanup()
1963 main.exit()
1964
You Wangdb8cd0a2016-05-26 15:19:45 -07001965 def getLinkRandom( self, timeout=60, nonCut=True ):
1966 """
1967 Randomly get a link from Mininet topology.
1968 If nonCut is True, it gets a list of non-cut links (the deletion
1969 of a non-cut link will not increase the number of connected
1970 component of a graph) and randomly returns one of them, otherwise
1971 it just randomly returns one link from all current links in
1972 Mininet.
1973 Returns the link as a list, e.g. [ 's1', 's2' ]
1974 """
1975 import random
1976 candidateLinks = []
1977 try:
1978 if not nonCut:
1979 links = self.getLinks( timeout=timeout )
1980 assert len( links ) != 0
1981 for link in links:
1982 # Exclude host-switch link
1983 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
1984 continue
1985 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
1986 else:
1987 graphDict = self.getGraphDict( timeout=timeout, useId=False )
1988 if graphDict == None:
1989 return None
1990 self.graph.update( graphDict )
1991 candidateLinks = self.graph.getNonCutEdges()
1992 if candidateLinks == None:
1993 return None
1994 elif len( candidateLinks ) == 0:
1995 main.log.info( self.name + ": No candidate link for deletion" )
1996 return None
1997 else:
1998 link = random.sample( candidateLinks, 1 )
1999 return link[ 0 ]
2000 except KeyError:
2001 main.log.exception( self.name + ": KeyError exception found" )
2002 return None
2003 except AssertionError:
2004 main.log.exception( self.name + ": AssertionError exception found" )
2005 return None
2006 except Exception:
2007 main.log.exception( self.name + ": Uncaught exception" )
2008 return None
2009
2010 def delLinkRandom( self, timeout=60, nonCut=True ):
2011 """
2012 Randomly delete a link from Mininet topology.
2013 If nonCut is True, it gets a list of non-cut links (the deletion
2014 of a non-cut link will not increase the number of connected
2015 component of a graph) and randomly chooses one for deletion,
2016 otherwise it just randomly delete one link from all current links
2017 in Mininet.
2018 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2019 """
2020 try:
2021 link = self.getLinkRandom( timeout, nonCut )
2022 if link == None:
2023 return None
2024 else:
2025 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2026 if deletionResult:
2027 return link
2028 else:
2029 return None
2030 except Exception:
2031 main.log.exception( self.name + ": Uncaught exception" )
2032 return None
2033
kelvin-onlabd3b64892015-01-20 13:26:24 -08002034 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002035 """
Jon Hallb1290e82014-11-18 16:17:48 -05002036 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002037 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002038 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002039 NOTE: cannot currently specify what type of host
2040 required params:
2041 hostname = the string hostname
2042 optional key-value params
2043 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002044 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002045 """
2046 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002047 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002048 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002049 response = self.execute(
2050 cmd=command,
2051 prompt="mininet>",
2052 timeout=10 )
2053 if re.search( "already exists!", response ):
2054 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002055 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002056 elif re.search( "doesnt exists!", response ):
2057 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002058 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002059 elif re.search( "Error", response ):
2060 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002061 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002062 elif re.search( "usage:", response ):
2063 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002064 return main.FALSE
2065 else:
2066 return main.TRUE
2067 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002068 main.log.error( self.name + ": EOF exception found" )
2069 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002070 main.cleanup()
2071 main.exit()
2072
kelvin-onlabd3b64892015-01-20 13:26:24 -08002073 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002074 """
2075 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002076 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002077 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002078 NOTE: this uses a custom mn function
2079 required params:
2080 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002081 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002082 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002083 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002084 response = self.execute(
2085 cmd=command,
2086 prompt="mininet>",
2087 timeout=10 )
2088 if re.search( "no host named", response ):
2089 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002090 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002091 elif re.search( "Error", response ):
2092 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002093 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002094 elif re.search( "usage:", response ):
2095 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002096 return main.FALSE
2097 else:
2098 return main.TRUE
2099 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002100 main.log.error( self.name + ": EOF exception found" )
2101 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002102 main.cleanup()
2103 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07002104
Jon Hall7eb38402015-01-08 17:19:54 -08002105 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002106 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002107 Called at the end of the test to stop the mininet and
2108 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002109 """
Jon Halld80cc142015-07-06 13:36:05 -07002110 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08002111 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07002112 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07002113 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08002114 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07002115 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08002116 elif i == 1:
2117 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08002118 # print "Disconnecting Mininet"
2119 if self.handle:
2120 self.handle.sendline( "exit" )
2121 self.handle.expect( "exit" )
2122 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08002123 else:
2124 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08002125 return response
2126
Jon Halld80cc142015-07-06 13:36:05 -07002127 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002128 """
Jon Hall21270ac2015-02-16 17:59:55 -08002129 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002130 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002131 main.FALSE if the pexpect handle does not exist.
2132
Jon Halld61331b2015-02-17 16:35:47 -08002133 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002134 """
Jon Halld61331b2015-02-17 16:35:47 -08002135 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002136 response = ''
2137 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002138 try:
Jon Halld80cc142015-07-06 13:36:05 -07002139 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002140 i = self.handle.expect( [ 'mininet>',
2141 '\$',
2142 pexpect.EOF,
2143 pexpect.TIMEOUT ],
2144 timeout )
2145 if i == 0:
2146 main.log.info( "Exiting mininet..." )
Jeremyd9e4eb12016-04-13 12:09:06 -07002147 response = self.execute( cmd="exit",
2148 prompt="(.*)",
2149 timeout=120 )
2150 main.log.info( self.name + ": Stopped" )
2151 self.handle.sendline( "sudo mn -c" )
2152 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002153
Jeremyd9e4eb12016-04-13 12:09:06 -07002154 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002155 main.log.info( " Mininet trying to exit while not " +
2156 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002157 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002158 elif i == 2:
2159 main.log.error( "Something went wrong exiting mininet" )
2160 elif i == 3: # timeout
2161 main.log.error( "Something went wrong exiting mininet " +
2162 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002163
Hari Krishnab35c6d02015-03-18 11:13:51 -07002164 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002165 self.handle.sendline( "" )
2166 self.handle.expect( '\$' )
2167 self.handle.sendline(
2168 "sudo kill -9 \`ps -ef | grep \"" +
2169 fileName +
2170 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002171 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002172 main.log.error( self.name + ": EOF exception found" )
2173 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07002174 main.cleanup()
2175 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08002176 else:
2177 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002178 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002179 return response
2180
YPZhang26a139e2016-04-25 14:01:55 -07002181 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002182 """
2183 Description:
2184 Sends arp message from mininet host for hosts discovery
2185 Required:
2186 host - hosts name
2187 Optional:
2188 ip - ip address that does not exist in the network so there would
2189 be no reply.
2190 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002191 if ethDevice:
2192 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002193 cmd = srcHost + " arping -c1 "
2194 if noResult:
2195 cmd += "-w10 " # If we don't want the actural arping result, set -w10, arping will exit after 10 ms.
2196 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002197 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002198 if output:
2199 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002200 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002201 i = self.handle.expect( [ "mininet>", "arping: " ] )
2202 if i == 0:
2203 return main.TRUE
2204 elif i == 1:
2205 response = self.handle.before + self.handle.after
2206 self.handle.expect( "mininet>" )
2207 response += self.handle.before + self.handle.after
2208 main.log.warn( "Error sending arping, output was: " +
2209 response )
2210 return main.FALSE
2211 except pexpect.TIMEOUT:
2212 main.log.error( self.name + ": TIMEOUT exception found" )
2213 main.log.warn( self.handle.before )
2214 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002215 except pexpect.EOF:
2216 main.log.error( self.name + ": EOF exception found" )
2217 main.log.error( self.name + ": " + self.handle.before )
2218 main.cleanup()
2219 main.exit()
admin07529932013-11-22 14:58:28 -08002220
Jon Hall7eb38402015-01-08 17:19:54 -08002221 def decToHex( self, num ):
2222 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002223
Jon Hall7eb38402015-01-08 17:19:54 -08002224 def getSwitchFlowCount( self, switch ):
2225 """
2226 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002227 if self.handle:
2228 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2229 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002230 response = self.execute(
2231 cmd=cmd,
2232 prompt="mininet>",
2233 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002234 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002235 main.log.error( self.name + ": EOF exception found" )
2236 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002237 main.cleanup()
2238 main.exit()
2239 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002240 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002241 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002242 main.log.info(
2243 "Couldn't find flows on switch %s, found: %s" %
2244 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002245 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002246 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002247 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002248 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002249
Jon Hall9ed8f372016-02-24 17:34:07 -08002250 def checkFlows( self, sw, dumpFormat=None ):
2251 if dumpFormat:
2252 command = "sh ovs-ofctl -F " + \
2253 dumpFormat + " dump-flows " + str( sw )
2254 else:
2255 command = "sh ovs-ofctl dump-flows " + str( sw )
2256 try:
2257 response = self.execute(
2258 cmd=command,
2259 prompt="mininet>",
2260 timeout=10 )
2261 return response
2262 except pexpect.EOF:
2263 main.log.error( self.name + ": EOF exception found" )
2264 main.log.error( self.name + ": " + self.handle.before )
2265 main.cleanup()
2266 main.exit()
2267
GlennRC68467eb2015-11-16 18:01:01 -08002268 def flowTableComp( self, flowTable1, flowTable2 ):
2269 # This function compares the selctors and treatments of each flow
2270 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002271 assert flowTable1, "flowTable1 is empty or None"
2272 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002273 returnValue = main.TRUE
GlennRC68467eb2015-11-16 18:01:01 -08002274 if len(flowTable1) != len(flowTable2):
2275 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002276 returnValue = main.FALSE
GlennRCfa65fce2015-12-16 13:16:08 -08002277 dFields = ["n_bytes", "cookie", "n_packets", "duration"]
2278 for flow1, flow2 in zip(flowTable1, flowTable2):
Jon Hallacd1b182015-12-17 11:43:20 -08002279 for field in dFields:
2280 try:
2281 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002282 except KeyError:
2283 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002284 try:
2285 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002286 except KeyError:
2287 pass
GlennRC68467eb2015-11-16 18:01:01 -08002288 for i in range( len(flowTable1) ):
GlennRC17bbcf52015-12-14 17:31:50 -08002289 if flowTable1[i] not in flowTable2:
2290 main.log.warn( "Flow tables do not match:" )
2291 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[i] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002292 returnValue = main.FALSE
2293 break
2294 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002295 except AssertionError:
2296 main.log.exception( "Nothing to compare" )
2297 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002298 except Exception:
2299 main.log.exception( "Uncaught exception!" )
2300 main.cleanup()
2301 main.exit()
Jon Hall9043c902015-07-30 14:23:44 -07002302
GlennRC528ad292015-11-12 10:38:18 -08002303 def parseFlowTable( self, flowTable, version="", debug=True ):
GlennRC956ea742015-11-05 16:14:15 -08002304 '''
2305 Discription: Parses flows into json format.
2306 NOTE: this can parse any string thats separated with commas
2307 Arguments:
2308 Required:
2309 flows: a list of strings that represnt flows
2310 Optional:
2311 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2312 debug: prints out the final result
2313 returns: A list of flows in json format
2314 '''
GlennRC528ad292015-11-12 10:38:18 -08002315 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002316 try:
2317 for flow in flowTable:
2318 jsonFlow = {}
2319 # split up the fields of the flow
2320 parsedFlow = flow.split(", ")
2321 # get rid of any spaces in front of the field
2322 for i in range( len(parsedFlow) ):
2323 item = parsedFlow[i]
2324 if item[0] == " ":
2325 parsedFlow[i] = item[1:]
2326 # grab the selector and treatment from the parsed flow
2327 # the last element is the selector and the treatment
2328 temp = parsedFlow.pop(-1)
2329 # split up the selector and the treatment
2330 temp = temp.split(" ")
2331 index = 0
2332 # parse the flags
2333 # NOTE: This only parses one flag
2334 flag = {}
2335 if version == "1.3":
2336 flag = {"flag":[temp[index]]}
2337 index += 1
2338 # the first element is the selector and split it up
2339 sel = temp[index]
GlennRC528ad292015-11-12 10:38:18 -08002340 index += 1
You Wang91c37cf2016-05-23 09:39:42 -07002341 sel = sel.split(",")
2342 # the priority is stuck in the selecter so put it back
2343 # in the flow
2344 parsedFlow.append(sel.pop(0))
2345 # parse selector
2346 criteria = []
2347 for item in sel:
2348 # this is the type of the packet e.g. "arp"
2349 if "=" not in item:
2350 criteria.append( {"type":item} )
2351 else:
2352 field = item.split("=")
2353 criteria.append( {field[0]:field[1]} )
2354 selector = {"selector": {"criteria":sorted(criteria)} }
2355 treat = temp[index]
2356 # get rid of the action part e.g. "action=output:2"
2357 # we will add it back later
2358 treat = treat.split("=")
2359 treat.pop(0)
2360 # parse treatment
2361 action = []
2362 for item in treat:
2363 field = item.split(":")
2364 action.append( {field[0]:field[1]} )
2365 # create the treatment field and add the actions
2366 treatment = {"treatment": {"action":sorted(action)} }
2367 # parse the rest of the flow
2368 for item in parsedFlow:
GlennRC528ad292015-11-12 10:38:18 -08002369 field = item.split("=")
You Wang91c37cf2016-05-23 09:39:42 -07002370 jsonFlow.update( {field[0]:field[1]} )
2371 # add the treatment and the selector to the json flow
2372 jsonFlow.update( selector )
2373 jsonFlow.update( treatment )
2374 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002375
You Wang91c37cf2016-05-23 09:39:42 -07002376 if debug: main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format(jsonFlow) )
GlennRC956ea742015-11-05 16:14:15 -08002377
You Wang91c37cf2016-05-23 09:39:42 -07002378 # add the json flow to the json flow table
2379 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002380
You Wang91c37cf2016-05-23 09:39:42 -07002381 return jsonFlowTable
2382
2383 except IndexError:
2384 main.log.exception( self.name + ": IndexError found" )
2385 return None
2386 except Exception:
2387 main.log.exception( self.name + ": Uncaught exception!" )
2388 main.cleanup()
2389 main.exit()
GlennRC528ad292015-11-12 10:38:18 -08002390
Jon Hall0a543792015-12-14 11:00:26 -08002391 def getFlowTable( self, sw, version="", debug=False):
GlennRC956ea742015-11-05 16:14:15 -08002392 '''
2393 Discription: Returns the flow table(s) on a switch or switches in a list.
2394 Each element is a flow.
2395 Arguments:
2396 Required:
2397 sw: The switch name ("s1") to retrive the flow table. Can also be
2398 a list of switches.
2399 Optional:
2400 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2401 debug: prints out the final result
2402 '''
2403 try:
2404 switches = []
2405 if type(sw) is list:
Jon Hallca7ac292015-11-11 09:28:12 -08002406 switches.extend(sw)
GlennRC956ea742015-11-05 16:14:15 -08002407 else: switches.append(sw)
2408
2409 flows = []
2410 for s in switches:
2411 cmd = "sh ovs-ofctl dump-flows " + s
2412
GlennRC528ad292015-11-12 10:38:18 -08002413 if "1.0" == version:
2414 cmd += " -F OpenFlow10-table_id"
2415 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002416 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002417
2418 main.log.info( "Sending: " + cmd )
2419 self.handle.sendline( cmd )
2420 self.handle.expect( "mininet>" )
2421 response = self.handle.before
2422 response = response.split( "\r\n" )
2423 # dump the first two elements and the last
2424 # the first element is the command that was sent
2425 # the second is the table header
2426 # the last element is empty
2427 response = response[2:-1]
2428 flows.extend( response )
2429
2430 if debug: print "Flows:\n{}\n\n".format(flows)
2431
GlennRC528ad292015-11-12 10:38:18 -08002432 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002433
2434 except pexpect.TIMEOUT:
2435 main.log.exception( self.name + ": Command timed out" )
2436 return None
2437 except pexpect.EOF:
2438 main.log.exception( self.name + ": connection closed." )
2439 main.cleanup()
2440 main.exit()
2441 except Exception:
2442 main.log.exception( self.name + ": Uncaught exception!" )
2443 main.cleanup()
2444 main.exit()
2445
2446 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
2447 '''
2448 Discription: Checks whether the ID provided matches a flow ID in Mininet
2449 Arguments:
2450 Required:
2451 sw: The switch name ("s1") to retrive the flow table. Can also be
2452 a list of switches.
2453 flowId: the flow ID in hex format. Can also be a list of IDs
2454 Optional:
2455 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2456 debug: prints out the final result
2457 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2458 NOTE: prints out IDs that are not present
2459 '''
2460 try:
2461 main.log.info( "Getting flows from Mininet" )
2462 flows = self.getFlowTable( sw, version, debug )
You Wang083ae982016-05-25 09:31:09 -07002463 if flows == None:
2464 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002465
2466 if debug: print "flow ids:\n{}\n\n".format(flowId)
2467
2468 # Check flowId is a list or a string
2469 if type( flowId ) is str:
2470 result = False
2471 for f in flows:
2472 if flowId in f.get( 'cookie' ):
2473 result = True
2474 break
2475 # flowId is a list
2476 else:
2477 result = True
2478 # Get flow IDs from Mininet
2479 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2480 # Save the IDs that are not in Mininet
2481 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2482
2483 if debug: print "mn flow ids:\n{}\n\n".format(mnFlowIds)
2484
2485 # Print out the IDs that are not in Mininet
2486 if absentIds:
2487 main.log.warn( "Absent ids: {}".format( absentIds ) )
2488 result = False
2489
2490 return main.TRUE if result else main.FALSE
2491
2492 except Exception:
2493 main.log.exception( self.name + ": Uncaught exception!" )
2494 main.cleanup()
2495 main.exit()
2496
2497
Charles Chan029be652015-08-24 01:46:10 +08002498 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002499 """
Jon Hallefbd9792015-03-05 16:11:36 -08002500 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002501 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002502 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002503 self.handle.sendline( "" )
2504 self.handle.expect( "mininet>" )
2505 self.handle.sendline(
2506 "sh sudo tcpdump -n -i " +
2507 intf +
2508 " " +
2509 port +
2510 " -w " +
2511 filename.strip() +
2512 " &" )
2513 self.handle.sendline( "" )
2514 i = self.handle.expect( [ 'No\ssuch\device',
2515 'listening\son',
2516 pexpect.TIMEOUT,
2517 "mininet>" ],
2518 timeout=10 )
2519 main.log.warn( self.handle.before + self.handle.after )
2520 self.handle.sendline( "" )
2521 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002522 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002523 main.log.error(
2524 self.name +
2525 ": tcpdump - No such device exists. " +
2526 "tcpdump attempted on: " +
2527 intf )
admin2a9548d2014-06-17 14:08:07 -07002528 return main.FALSE
2529 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002530 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002531 return main.TRUE
2532 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002533 main.log.error(
2534 self.name +
2535 ": tcpdump command timed out! Check interface name," +
2536 " given interface was: " +
2537 intf )
admin2a9548d2014-06-17 14:08:07 -07002538 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002539 elif i == 3:
2540 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002541 return main.TRUE
2542 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002543 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002544 return main.FALSE
2545 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002546 main.log.error( self.name + ": EOF exception found" )
2547 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002548 main.cleanup()
2549 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002550 except Exception:
2551 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002552 main.cleanup()
2553 main.exit()
2554
kelvin-onlabd3b64892015-01-20 13:26:24 -08002555 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002556 """
2557 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002558 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002559 self.handle.sendline( "sh sudo pkill tcpdump" )
2560 self.handle.expect( "mininet>" )
2561 self.handle.sendline( "" )
2562 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002563 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002564 main.log.error( self.name + ": EOF exception found" )
2565 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002566 main.cleanup()
2567 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002568 except Exception:
2569 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002570 main.cleanup()
2571 main.exit()
2572
Jon Halld80cc142015-07-06 13:36:05 -07002573 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002574 """
2575 Read ports from a Mininet switch.
2576
2577 Returns a json structure containing information about the
2578 ports of the given switch.
2579 """
2580 response = self.getInterfaces( nodeName )
2581 # TODO: Sanity check on response. log if no such switch exists
2582 ports = []
2583 for line in response.split( "\n" ):
2584 if not line.startswith( "name=" ):
2585 continue
2586 portVars = {}
2587 for var in line.split( "," ):
2588 key, value = var.split( "=" )
2589 portVars[ key ] = value
2590 isUp = portVars.pop( 'enabled', "True" )
2591 isUp = "True" in isUp
2592 if verbose:
2593 main.log.info( "Reading switch port %s(%s)" %
2594 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2595 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002596 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002597 mac = None
2598 ips = []
2599 ip = portVars[ 'ip' ]
2600 if ip == 'None':
2601 ip = None
2602 ips.append( ip )
2603 name = portVars[ 'name' ]
2604 if name == 'None':
2605 name = None
2606 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2607 if name == 'lo':
2608 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2609 else:
2610 portNo = re.search( portRe, name ).group( 'port' )
2611 ports.append( { 'of_port': portNo,
2612 'mac': str( mac ).replace( '\'', '' ),
2613 'name': name,
2614 'ips': ips,
2615 'enabled': isUp } )
2616 return ports
2617
You Wangdb8cd0a2016-05-26 15:19:45 -07002618 def getOVSPorts( self, nodeName ):
2619 """
2620 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2621
2622 Returns a list of dictionaries containing information about each
2623 port of the given switch.
2624 """
2625 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2626 try:
2627 response = self.execute(
2628 cmd=command,
2629 prompt="mininet>",
2630 timeout=10 )
2631 ports = []
2632 if response:
2633 for line in response.split( "\n" ):
2634 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2635 # Example port:
2636 # 1(s1-eth1): addr:ae:60:72:77:55:51
2637 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2638 result = re.search( pattern, line )
2639 if result:
2640 index = result.group( 'index' )
2641 name = result.group( 'name' )
2642 # This port number is extracted from port name
2643 port = result.group( 'port' )
2644 mac = result.group( 'mac' )
2645 ports.append( { 'index': index,
2646 'name': name,
2647 'port': port,
2648 'mac': mac } )
2649 return ports
2650 except pexpect.EOF:
2651 main.log.error( self.name + ": EOF exception found" )
2652 main.log.error( self.name + ": " + self.handle.before )
2653 main.cleanup()
2654 main.exit()
2655 except Exception:
2656 main.log.exception( self.name + ": Uncaught exception!" )
2657 main.cleanup()
2658 main.exit()
2659
Jon Halld80cc142015-07-06 13:36:05 -07002660 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002661 """
2662 Read switches from Mininet.
2663
2664 Returns a dictionary whose keys are the switch names and the value is
2665 a dictionary containing information about the switch.
2666 """
Jon Halla22481b2015-07-28 17:46:01 -07002667 # NOTE: To support new Mininet switch classes, just append the new
2668 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002669
Jon Halla22481b2015-07-28 17:46:01 -07002670 # Regex patterns to parse 'dump' output
2671 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002672 # <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 -07002673 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002674 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2675 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2676 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2677 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2678 swRE = r"<(?P<class>" + switchClasses + r")" +\
2679 r"(?P<options>\{.*\})?\s" +\
2680 r"(?P<name>[^:]+)\:\s" +\
2681 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2682 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002683 # Update mn port info
2684 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002685 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002686 dump = self.dump().split( "\n" )
2687 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002688 result = re.search( swRE, line, re.I )
2689 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002690 name = result.group( 'name' )
2691 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002692 pid = result.group( 'pid' )
2693 swClass = result.group( 'class' )
2694 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002695 if verbose:
2696 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2697 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002698 output[ name ] = { "dpid": dpid,
2699 "ports": ports,
2700 "swClass": swClass,
2701 "pid": pid,
2702 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002703 return output
2704
Jon Halld80cc142015-07-06 13:36:05 -07002705 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002706 """
2707 Read hosts from Mininet.
2708
2709 Returns a dictionary whose keys are the host names and the value is
2710 a dictionary containing information about the host.
2711 """
2712 # Regex patterns to parse dump output
2713 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002714 # <Host h1: pid=12725>
2715 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2716 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2717 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002718 # NOTE: Does not correctly match hosts with multi-links
2719 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2720 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002721 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002722 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002723 # update mn port info
2724 self.update()
2725 # Get mininet dump
2726 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002727 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002728 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002729 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002730 result = re.search( hostRE, line )
2731 name = result.group( 'name' )
2732 interfaces = []
2733 response = self.getInterfaces( name )
2734 # Populate interface info
2735 for line in response.split( "\n" ):
2736 if line.startswith( "name=" ):
2737 portVars = {}
2738 for var in line.split( "," ):
2739 key, value = var.split( "=" )
2740 portVars[ key ] = value
2741 isUp = portVars.pop( 'enabled', "True" )
2742 isUp = "True" in isUp
2743 if verbose:
2744 main.log.info( "Reading host port %s(%s)" %
2745 ( portVars[ 'name' ],
2746 portVars[ 'mac' ] ) )
2747 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002748 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002749 mac = None
2750 ips = []
2751 ip = portVars[ 'ip' ]
2752 if ip == 'None':
2753 ip = None
2754 ips.append( ip )
2755 intfName = portVars[ 'name' ]
2756 if name == 'None':
2757 name = None
2758 interfaces.append( {
2759 "name": intfName,
2760 "ips": ips,
2761 "mac": str( mac ),
2762 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002763 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002764 return hosts
2765
YPZhang81a7d4e2016-04-18 13:10:17 -07002766 def getLinks( self, timeout=20 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002767 """
2768 Gathers information about current Mininet links. These links may not
2769 be up if one of the ports is down.
2770
2771 Returns a list of dictionaries with link endpoints.
2772
2773 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002774 { 'node1': str( node1 name )
2775 'node2': str( node2 name )
2776 'port1': str( port1 of_port )
2777 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002778 Note: The port number returned is the eth#, not necessarily the of_port
2779 number. In Mininet, for OVS switch, these should be the same. For
2780 hosts, this is just the eth#.
2781 """
2782 self.update()
YPZhang81a7d4e2016-04-18 13:10:17 -07002783 response = self.links(timeout=timeout).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002784
2785 # Examples:
2786 # s1-eth3<->s2-eth1 (OK OK)
2787 # s13-eth3<->h27-eth0 (OK OK)
2788 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2789 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2790 links = []
2791 for line in response:
2792 match = re.search( linkRE, line )
2793 if match:
2794 node1 = match.group( 'node1' )
2795 node2 = match.group( 'node2' )
2796 port1 = match.group( 'port1' )
2797 port2 = match.group( 'port2' )
2798 links.append( { 'node1': node1,
2799 'node2': node2,
2800 'port1': port1,
2801 'port2': port2 } )
2802 return links
2803
2804 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002805 """
2806 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002807 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002808
Jon Hallafa8a472015-06-12 14:02:42 -07002809 Dependencies:
2810 1. numpy - "sudo pip install numpy"
2811 """
2812 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002813 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002814 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002815 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002816 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002817 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002818 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002819 main.log.error(
2820 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002821 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002822 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002823 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002824 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002825 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002826 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002827 onosDPIDs.append(
2828 switch[ 'id' ].replace(
2829 ":",
2830 '' ).replace(
2831 "of",
2832 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002833 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002834
Jon Hall7eb38402015-01-08 17:19:54 -08002835 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002836 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002837 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002838 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002839 main.log.error( str( list1 ) )
2840 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002841 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002842 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002843 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002844 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002845 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002846
Jon Hall7eb38402015-01-08 17:19:54 -08002847 # FIXME: this does not look for extra ports in ONOS, only checks that
2848 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002849 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002850
Jon Hall7eb38402015-01-08 17:19:54 -08002851 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002852 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002853 mnPorts = []
2854 onosPorts = []
2855 switchResult = main.TRUE
2856 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002857 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002858 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002859 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002860 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002861 if onosSwitch[ 'device' ][ 'id' ].replace(
2862 ':',
2863 '' ).replace(
2864 "of",
2865 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002866 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002867 if port[ 'isEnabled' ]:
2868 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002869 # onosPorts.append( 'local' )
2870 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002871 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002872 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002873 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002874 mnPorts.sort( key=float )
2875 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002876
kelvin-onlabd3b64892015-01-20 13:26:24 -08002877 mnPortsLog = mnPorts
2878 onosPortsLog = onosPorts
2879 mnPorts = [ x for x in mnPorts ]
2880 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002881
Jon Hall7eb38402015-01-08 17:19:54 -08002882 # TODO: handle other reserved port numbers besides LOCAL
2883 # NOTE: Reserved ports
2884 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2885 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002886 for mnPort in mnPortsLog:
2887 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002888 # don't set results to true here as this is just one of
2889 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002890 mnPorts.remove( mnPort )
2891 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002892
Jon Hall7eb38402015-01-08 17:19:54 -08002893 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002894 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002895 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002896 if 65534 in mnPorts:
2897 mnPorts.remove( 65534 )
2898 if long( uint64( -2 ) ) in onosPorts:
2899 onosPorts.remove( long( uint64( -2 ) ) )
2900 if len( mnPorts ): # the ports of this switch don't match
2901 switchResult = main.FALSE
2902 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2903 if len( onosPorts ): # the ports of this switch don't match
2904 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002905 main.log.warn(
2906 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002907 str( onosPorts ) )
2908 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002909 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002910 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002911 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002912 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2913 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2914 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002915 finalResults = finalResults and portsResults
2916 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002917
Jon Hallafa8a472015-06-12 14:02:42 -07002918 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002919 """
2920 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002921 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002922
Jon Hallafa8a472015-06-12 14:02:42 -07002923 """
Jon Hall7eb38402015-01-08 17:19:54 -08002924 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002925 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002926 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002927
Jon Halld80cc142015-07-06 13:36:05 -07002928 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002929 for l in links:
2930 try:
2931 node1 = switches[ l[ 'node1' ] ]
2932 node2 = switches[ l[ 'node2' ] ]
2933 enabled = True
2934 for port in node1[ 'ports' ]:
2935 if port[ 'of_port' ] == l[ 'port1' ]:
2936 enabled = enabled and port[ 'enabled' ]
2937 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002938 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002939 enabled = enabled and port[ 'enabled' ]
2940 if enabled:
2941 mnLinks.append( l )
2942 except KeyError:
2943 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002944 if 2 * len( mnLinks ) == len( onos ):
2945 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002946 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002947 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002948 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002949 "Mininet has " + str( len( mnLinks ) ) +
2950 " bidirectional links and ONOS has " +
2951 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002952
Jon Hall7eb38402015-01-08 17:19:54 -08002953 # iterate through MN links and check if an ONOS link exists in
2954 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002955 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002956 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002957 node1 = None
2958 port1 = None
2959 node2 = None
2960 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002961 firstDir = main.FALSE
2962 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002963 for swName, switch in switches.iteritems():
2964 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002965 node1 = switch[ 'dpid' ]
2966 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002967 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002968 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002969 if node1 is not None and node2 is not None:
2970 break
Jon Hallafa8a472015-06-12 14:02:42 -07002971 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002972 node2 = switch[ 'dpid' ]
2973 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002974 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002975 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002976 if node1 is not None and node2 is not None:
2977 break
2978
kelvin-onlabd3b64892015-01-20 13:26:24 -08002979 for onosLink in onos:
2980 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002981 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002982 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002983 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002984 onosPort1 = onosLink[ 'src' ][ 'port' ]
2985 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002986
Jon Hall72cf1dc2014-10-20 21:04:50 -04002987 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002988 if str( onosNode1 ) == str( node1 ) and str(
2989 onosNode2 ) == str( node2 ):
2990 if int( onosPort1 ) == int( port1 ) and int(
2991 onosPort2 ) == int( port2 ):
2992 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002993 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002994 main.log.warn(
2995 'The port numbers do not match for ' +
2996 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002997 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002998 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002999 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08003000 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07003001 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003002
3003 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08003004 elif ( str( onosNode1 ) == str( node2 ) and
3005 str( onosNode2 ) == str( node1 ) ):
3006 if ( int( onosPort1 ) == int( port2 )
3007 and int( onosPort2 ) == int( port1 ) ):
3008 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04003009 else:
Jon Hall7eb38402015-01-08 17:19:54 -08003010 main.log.warn(
3011 'The port numbers do not match for ' +
3012 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08003013 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08003014 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07003015 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08003016 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07003017 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08003018 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04003019 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08003020 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07003021 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08003022 'ONOS does not have the link %s/%s -> %s/%s' %
3023 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003024 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07003025 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08003026 'ONOS does not have the link %s/%s -> %s/%s' %
3027 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003028 linkResults = linkResults and firstDir and secondDir
3029 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04003030
Jon Hallafa8a472015-06-12 14:02:42 -07003031 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003032 """
Jon Hallafa8a472015-06-12 14:02:42 -07003033 Compare mn and onos Hosts.
3034 Since Mininet hosts are quiet, ONOS will only know of them when they
3035 speak. For this reason, we will only check that the hosts in ONOS
3036 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003037
Jon Hallafa8a472015-06-12 14:02:42 -07003038 Arguments:
3039 hostsJson: parsed json object from the onos hosts api
3040 Returns:
3041 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003042 import json
3043 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08003044 for onosHost in hostsJson:
3045 onosMAC = onosHost[ 'mac' ].lower()
3046 match = False
Jon Halld80cc142015-07-06 13:36:05 -07003047 for mnHost, info in hosts.iteritems():
3048 for mnIntf in info[ 'interfaces' ]:
3049 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08003050 match = True
3051 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07003052 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08003053 pass # all is well
3054 else:
3055 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07003056 main.log.error( "ONOS host " +
3057 onosHost[ 'id' ] +
3058 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07003059 str( onosHost[ 'ipAddresses' ] ) +
3060 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07003061 str( ip ) +
3062 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08003063 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07003064 onosHost,
3065 sort_keys=True,
3066 indent=4,
3067 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08003068 main.log.info( output )
3069 hostResults = main.FALSE
3070 if not match:
3071 hostResults = main.FALSE
3072 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3073 "corresponding Mininet host." )
3074 output = json.dumps( onosHost,
3075 sort_keys=True,
3076 indent=4,
3077 separators=( ',', ': ' ) )
3078 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08003079 return hostResults
3080
Jon Hallafa8a472015-06-12 14:02:42 -07003081 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003082 """
3083 Returns a list of all hosts
3084 Don't ask questions just use it"""
3085 self.handle.sendline( "" )
3086 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003087
Jon Hall7eb38402015-01-08 17:19:54 -08003088 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3089 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003090
kelvin-onlabd3b64892015-01-20 13:26:24 -08003091 handlePy = self.handle.before
3092 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3093 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003094
Jon Hall7eb38402015-01-08 17:19:54 -08003095 self.handle.sendline( "" )
3096 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003097
kelvin-onlabd3b64892015-01-20 13:26:24 -08003098 hostStr = handlePy.replace( "]", "" )
3099 hostStr = hostStr.replace( "'", "" )
3100 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07003101 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003102 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003103
kelvin-onlabd3b64892015-01-20 13:26:24 -08003104 return hostList
adminbae64d82013-08-01 10:50:15 -07003105
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003106 def getSwitch( self ):
3107 """
3108 Returns a list of all switches
3109 Again, don't ask question just use it...
3110 """
3111 # get host list...
3112 hostList = self.getHosts()
3113 # Make host set
3114 hostSet = set( hostList )
3115
3116 # Getting all the nodes in mininet
3117 self.handle.sendline( "" )
3118 self.handle.expect( "mininet>" )
3119
3120 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3121 self.handle.expect( "mininet>" )
3122
3123 handlePy = self.handle.before
3124 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3125 handlePy = handlePy.rstrip()
3126
3127 self.handle.sendline( "" )
3128 self.handle.expect( "mininet>" )
3129
3130 nodesStr = handlePy.replace( "]", "" )
3131 nodesStr = nodesStr.replace( "'", "" )
3132 nodesStr = nodesStr.replace( "[", "" )
3133 nodesStr = nodesStr.replace( " ", "" )
3134 nodesList = nodesStr.split( "," )
3135
3136 nodesSet = set( nodesList )
3137 # discarding default controller(s) node
3138 nodesSet.discard( 'c0' )
3139 nodesSet.discard( 'c1' )
3140 nodesSet.discard( 'c2' )
3141
3142 switchSet = nodesSet - hostSet
3143 switchList = list( switchSet )
3144
3145 return switchList
3146
You Wangdb8cd0a2016-05-26 15:19:45 -07003147 def getGraphDict( self, timeout=60, useId=True, includeHost=False ):
3148 """
3149 Return a dictionary which describes the latest Mininet topology data as a
3150 graph.
3151 An example of the dictionary:
3152 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3153 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3154 Each vertex should at least have an 'edges' attribute which describes the
3155 adjacency information. The value of 'edges' attribute is also represented by
3156 a dictionary, which maps each edge (identified by the neighbor vertex) to a
3157 list of attributes.
3158 An example of the edges dictionary:
3159 'edges': { vertex2: { 'port': ..., 'weight': ... },
3160 vertex3: { 'port': ..., 'weight': ... } }
3161 If useId == True, dpid/mac will be used instead of names to identify
3162 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3163 topology.
3164 If includeHost == True, all hosts (and host-switch links) will be included
3165 in topology data.
3166 Note that link or switch that are brought down by 'link x x down' or 'switch
3167 x down' commands still show in the output of Mininet CLI commands such as
3168 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3169 recommended to use delLink() or delSwitch functions to simulate link/switch
3170 down, and addLink() or addSwitch to add them back.
3171 """
3172 graphDict = {}
3173 try:
3174 links = self.getLinks( timeout=timeout )
3175 portDict = {}
3176 if useId:
3177 switches = self.getSwitches()
3178 if includeHost:
3179 hosts = self.getHosts()
3180 for link in links:
3181 # FIXME: support 'includeHost' argument
3182 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3183 continue
3184 nodeName1 = link[ 'node1' ]
3185 nodeName2 = link[ 'node2' ]
3186 port1 = link[ 'port1' ]
3187 port2 = link[ 'port2' ]
3188 # Loop for two nodes
3189 for i in range( 2 ):
3190 # Get port index from OVS
3191 # The index extracted from port name may be inconsistent with ONOS
3192 portIndex = -1
3193 if not nodeName1 in portDict.keys():
3194 portList = self.getOVSPorts( nodeName1 )
3195 if len( portList ) == 0:
3196 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3197 return None
3198 portDict[ nodeName1 ] = portList
3199 for port in portDict[ nodeName1 ]:
3200 if port[ 'port' ] == port1:
3201 portIndex = port[ 'index' ]
3202 break
3203 if portIndex == -1:
3204 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3205 return None
3206 if useId:
3207 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3208 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3209 else:
3210 node1 = nodeName1
3211 node2 = nodeName2
3212 if not node1 in graphDict.keys():
3213 if useId:
3214 graphDict[ node1 ] = { 'edges':{},
3215 'dpid':switches[ nodeName1 ][ 'dpid' ],
3216 'name':nodeName1,
3217 'ports':switches[ nodeName1 ][ 'ports' ],
3218 'swClass':switches[ nodeName1 ][ 'swClass' ],
3219 'pid':switches[ nodeName1 ][ 'pid' ],
3220 'options':switches[ nodeName1 ][ 'options' ] }
3221 else:
3222 graphDict[ node1 ] = { 'edges':{} }
3223 else:
3224 # Assert node2 is not connected to any current links of node1
3225 assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
3226 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port':portIndex }
3227 # Swap two nodes/ports
3228 nodeName1, nodeName2 = nodeName2, nodeName1
3229 port1, port2 = port2, port1
3230 return graphDict
3231 except KeyError:
3232 main.log.exception( self.name + ": KeyError exception found" )
3233 return None
3234 except AssertionError:
3235 main.log.exception( self.name + ": AssertionError exception found" )
3236 return None
3237 except Exception:
3238 main.log.exception( self.name + ": Uncaught exception" )
3239 return None
3240
Jon Hall7eb38402015-01-08 17:19:54 -08003241 def update( self ):
3242 """
3243 updates the port address and status information for
3244 each port in mn"""
3245 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003246 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003247 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003248 self.handle.sendline( "" )
3249 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003250
Jon Hall7eb38402015-01-08 17:19:54 -08003251 self.handle.sendline( "update" )
3252 self.handle.expect( "update" )
3253 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003254
Jon Hall7eb38402015-01-08 17:19:54 -08003255 self.handle.sendline( "" )
3256 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003257
Jon Hallb1290e82014-11-18 16:17:48 -05003258 return main.TRUE
3259 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003260 main.log.error( self.name + ": EOF exception found" )
3261 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05003262 main.cleanup()
3263 main.exit()
3264
Jon Halld80cc142015-07-06 13:36:05 -07003265 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003266 """
3267 Add vlan tag to a host.
3268 Dependencies:
3269 This class depends on the "vlan" package
3270 $ sudo apt-get install vlan
3271 Configuration:
3272 Load the 8021q module into the kernel
3273 $sudo modprobe 8021q
3274
3275 To make this setup permanent:
3276 $ sudo su -c 'echo "8021q" >> /etc/modules'
3277 """
3278 if self.handle:
3279 try:
Jon Halld80cc142015-07-06 13:36:05 -07003280 # get the ip address of the host
3281 main.log.info( "Get the ip address of the host" )
3282 ipaddr = self.getIPAddress( host )
3283 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003284
Jon Halld80cc142015-07-06 13:36:05 -07003285 # remove IP from interface intf
3286 # Ex: h1 ifconfig h1-eth0 inet 0
3287 main.log.info( "Remove IP from interface " )
3288 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3289 self.handle.sendline( cmd2 )
3290 self.handle.expect( "mininet>" )
3291 response = self.handle.before
3292 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003293
Jon Halld80cc142015-07-06 13:36:05 -07003294 # create VLAN interface
3295 # Ex: h1 vconfig add h1-eth0 100
3296 main.log.info( "Create Vlan" )
3297 cmd3 = host + " vconfig add " + intf + " " + vlan
3298 self.handle.sendline( cmd3 )
3299 self.handle.expect( "mininet>" )
3300 response = self.handle.before
3301 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003302
Jon Halld80cc142015-07-06 13:36:05 -07003303 # assign the host's IP to the VLAN interface
3304 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3305 main.log.info( "Assign the host IP to the vlan interface" )
3306 vintf = intf + "." + vlan
3307 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3308 self.handle.sendline( cmd4 )
3309 self.handle.expect( "mininet>" )
3310 response = self.handle.before
3311 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003312
3313 return main.TRUE
3314 except pexpect.EOF:
3315 main.log.error( self.name + ": EOF exception found" )
3316 main.log.error( self.name + ": " + self.handle.before )
3317 return main.FALSE
3318
Jon Hall892818c2015-10-20 17:58:34 -07003319 def createHostComponent( self, name ):
3320 """
3321 Creates a new mininet cli component with the same parameters as self.
3322 This new component is intended to be used to login to the hosts created
3323 by mininet.
3324
3325 Arguments:
3326 name - The string of the name of this component. The new component
3327 will be assigned to main.<name> .
3328 In addition, main.<name>.name = str( name )
3329 """
3330 try:
3331 # look to see if this component already exists
3332 getattr( main, name )
3333 except AttributeError:
3334 # namespace is clear, creating component
3335 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
3336 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
3337 main.componentInit( name )
3338 except Exception:
3339 main.log.exception( self.name + ": Uncaught exception!" )
3340 main.cleanup()
3341 main.exit()
3342 else:
3343 # namespace is not clear!
3344 main.log.error( name + " component already exists!" )
3345 # FIXME: Should we exit here?
3346 main.cleanup()
3347 main.exit()
3348
3349 def removeHostComponent( self, name ):
3350 """
3351 Remove host component
3352 Arguments:
3353 name - The string of the name of the component to delete.
3354 """
3355 try:
3356 # Get host component
3357 component = getattr( main, name )
3358 except AttributeError:
3359 main.log.error( "Component " + name + " does not exist." )
3360 return
3361 try:
3362 # Disconnect from component
3363 component.disconnect()
3364 # Delete component
3365 delattr( main, name )
3366 # Delete component from ComponentDictionary
3367 del( main.componentDictionary[name] )
3368 except Exception:
3369 main.log.exception( self.name + ": Uncaught exception!" )
3370 main.cleanup()
3371 main.exit()
3372
3373 def startHostCli( self, host=None ):
3374 """
3375 Use the mininet m utility to connect to the host's cli
3376 """
3377 # These are fields that can be used by scapy packets. Initialized to None
3378 self.hostIp = None
3379 self.hostMac = None
3380 try:
3381 if not host:
3382 host = self.name
3383 self.handle.sendline( self.home + "/util/m " + host )
3384 self.handle.expect( self.hostPrompt )
3385 return main.TRUE
3386 except pexpect.TIMEOUT:
3387 main.log.exception( self.name + ": Command timed out" )
3388 return main.FALSE
3389 except pexpect.EOF:
3390 main.log.exception( self.name + ": connection closed." )
3391 main.cleanup()
3392 main.exit()
3393 except Exception:
3394 main.log.exception( self.name + ": Uncaught exception!" )
3395 main.cleanup()
3396 main.exit()
3397
Jon Hall892818c2015-10-20 17:58:34 -07003398
adminbae64d82013-08-01 10:50:15 -07003399if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07003400 sys.modules[ __name__ ] = MininetCliDriver()