blob: 1632feee4fe4cc78948693fbbcf0007943e9cdaf [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
4
Jon Hallbe6dfc42015-01-12 17:37:25 -08005author: Anil Kumar ( anilkumar.s@paxterrasolutions.com )
adminbae64d82013-08-01 10:50:15 -07006
7
Jon Hall7eb38402015-01-08 17:19:54 -08008TestON is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 2 of the License, or
11( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070012
Jon Hall7eb38402015-01-08 17:19:54 -080013TestON is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070017
Jon Hall7eb38402015-01-08 17:19:54 -080018You should have received a copy of the GNU General Public License
19along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070020
Jon Hallbe6dfc42015-01-12 17:37:25 -080021MininetCliDriver is the basic driver which will handle the Mininet functions
22
23Some functions rely on a modified version of Mininet. These functions
24should all be noted in the comments. To get this MN version run these commands
25from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080026 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080027 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080028 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080029 git pull
30
Jon Hall272a4db2015-01-12 17:43:48 -080031
32 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080033changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070034import pexpect
adminbae64d82013-08-01 10:50:15 -070035import re
36import sys
kelvin-onlabfa6ada82015-06-11 13:06:24 -070037import types
kelvin-onlaba4074292015-07-09 15:19:49 -070038import os
Jon Hall1ccf82c2014-10-15 14:55:16 -040039from math import pow
adminbae64d82013-08-01 10:50:15 -070040from drivers.common.cli.emulatordriver import Emulator
You Wangdb8cd0a2016-05-26 15:19:45 -070041from core.graph import Graph
adminbae64d82013-08-01 10:50:15 -070042
Jon Hall7eb38402015-01-08 17:19:54 -080043
kelvin-onlab50907142015-04-01 13:37:45 -070044class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080045
46 """
47 MininetCliDriver is the basic driver which will handle
48 the Mininet functions"""
49 def __init__( self ):
50 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070051 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080052 self.name = None
kelvin-onlabd9e23de2015-08-06 10:34:44 -070053 self.home = None
Jon Hall7eb38402015-01-08 17:19:54 -080054 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070055 self.flag = 0
Jon Hall892818c2015-10-20 17:58:34 -070056 # TODO: Refactor driver to use these everywhere
57 self.mnPrompt = "mininet>"
58 self.hostPrompt = "~#"
59 self.bashPrompt = "\$"
60 self.scapyPrompt = ">>>"
You Wangdb8cd0a2016-05-26 15:19:45 -070061 self.graph = Graph()
adminbae64d82013-08-01 10:50:15 -070062
Jon Hall7eb38402015-01-08 17:19:54 -080063 def connect( self, **connectargs ):
64 """
65 Here the main is the TestON instance after creating
66 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080067 try:
68 for key in connectargs:
69 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070070 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080071 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070072 for key in self.options:
73 if key == "home":
74 self.home = self.options[ 'home' ]
75 break
76 if self.home is None or self.home == "":
77 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070078
79 try:
Jon Hall892818c2015-10-20 17:58:34 -070080 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070081 self.ip_address = os.getenv( str( self.ip_address ) )
82 else:
83 main.log.info( self.name +
84 ": Trying to connect to " +
85 self.ip_address )
86
87 except KeyError:
88 main.log.info( "Invalid host name," +
89 " connecting to local host instead" )
90 self.ip_address = 'localhost'
91 except Exception as inst:
92 main.log.error( "Uncaught exception: " + str( inst ) )
93
kelvin-onlaba1484582015-02-02 15:46:20 -080094 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070095 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080096 self ).connect(
97 user_name=self.user_name,
98 ip_address=self.ip_address,
99 port=None,
100 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -0800101
kelvin-onlaba1484582015-02-02 15:46:20 -0800102 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -0800103 main.log.info( "Connection successful to the host " +
104 self.user_name +
105 "@" +
106 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800107 return main.TRUE
108 else:
109 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800110 self.user_name +
111 "@" +
112 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800113 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800114 return main.FALSE
115 except pexpect.EOF:
116 main.log.error( self.name + ": EOF exception found" )
117 main.log.error( self.name + ": " + self.handle.before )
118 main.cleanup()
119 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800120 except Exception:
121 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800122 main.cleanup()
123 main.exit()
124
kelvin-onlab10e8d392015-06-03 13:53:45 -0700125 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800126 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700127 Description:
128 Starts Mininet accepts a topology(.py) file and/or an optional
129 argument, to start the mininet, as a parameter.
130 Can also send regular mininet command to load up desired topology.
alison12f34c32016-06-10 14:39:21 -0700131 Eg. Pass in a string 'mn --topo=tree,3,3' to mnCmd
kelvin-onlabf512e942015-06-08 19:42:59 -0700132 Options:
133 topoFile = file path for topology file (.py)
134 args = extra option added when starting the topology from the file
135 mnCmd = Mininet command use to start topology
136 Returns:
137 main.TRUE if the mininet starts successfully, main.FALSE
138 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800139 """
Jon Hall7eb38402015-01-08 17:19:54 -0800140 if self.handle:
Jon Hall689d8e42015-04-03 13:59:24 -0700141 # make sure old networks are cleaned up
142 main.log.info( self.name +
143 ": Clearing any residual state or processes" )
Jon Hall7eb38402015-01-08 17:19:54 -0800144 self.handle.sendline( "sudo mn -c" )
145 i = self.handle.expect( [ 'password\sfor\s',
146 'Cleanup\scomplete',
147 pexpect.EOF,
148 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800149 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800150 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700151 # Sudo asking for password
Jon Hall7eb38402015-01-08 17:19:54 -0800152 main.log.info( self.name + ": Sending sudo password" )
153 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800154 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800155 '\$',
156 pexpect.EOF,
157 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800158 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800159 if i == 1:
160 main.log.info( self.name + ": Clean" )
161 elif i == 2:
162 main.log.error( self.name + ": Connection terminated" )
163 elif i == 3: # timeout
Jon Hall689d8e42015-04-03 13:59:24 -0700164 main.log.error( self.name + ": Something while cleaning " +
165 "Mininet took too long... " )
166 # Craft the string to start mininet
167 cmdString = "sudo "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700168 if not mnCmd:
169 if topoFile is None or topoFile == '': # If no file is given
170 main.log.info( self.name + ": building fresh Mininet" )
171 cmdString += "mn "
172 if args is None or args == '':
173 # If no args given, use args from .topo file
174 args = self.options[ 'arg1' ] +\
Jon Halld80cc142015-07-06 13:36:05 -0700175 " " + self.options[ 'arg2' ] +\
176 " --mac --controller " +\
177 self.options[ 'controller' ] + " " +\
178 self.options[ 'arg3' ]
kelvin-onlab10e8d392015-06-03 13:53:45 -0700179 else: # else only use given args
180 pass
181 # TODO: allow use of topo args and method args?
182 else: # Use given topology file
Jon Halld80cc142015-07-06 13:36:05 -0700183 main.log.info(
184 "Starting Mininet from topo file " +
185 topoFile )
Flavio Castrocc38a542016-03-03 13:15:46 -0800186 cmdString += "-E python " + topoFile + " "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700187 if args is None:
188 args = ''
189 # TODO: allow use of args from .topo file?
190 cmdString += args
191 else:
192 main.log.info( "Starting Mininet topology using '" + mnCmd +
193 "' command" )
194 cmdString += mnCmd
Jon Hall689d8e42015-04-03 13:59:24 -0700195 # Send the command and check if network started
196 self.handle.sendline( "" )
197 self.handle.expect( '\$' )
198 main.log.info( "Sending '" + cmdString + "' to " + self.name )
199 self.handle.sendline( cmdString )
200 while True:
Jon Hall7eb38402015-01-08 17:19:54 -0800201 i = self.handle.expect( [ 'mininet>',
Jon Hall689d8e42015-04-03 13:59:24 -0700202 'Exception',
203 '\*\*\*',
Jon Hallefbd9792015-03-05 16:11:36 -0800204 pexpect.EOF,
205 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700206 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800207 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700208 main.log.info( self.name + ": Mininet built" )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800209 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800210 elif i == 1:
Jon Hall689d8e42015-04-03 13:59:24 -0700211 response = str( self.handle.before +
212 self.handle.after )
213 self.handle.expect( '\$' )
214 response += str( self.handle.before +
Jon Halld80cc142015-07-06 13:36:05 -0700215 self.handle.after )
Jon Hall689d8e42015-04-03 13:59:24 -0700216 main.log.error(
217 self.name +
218 ": Launching Mininet failed: " + response )
219 return main.FALSE
220 elif i == 2:
221 self.handle.expect( [ "\n",
222 pexpect.EOF,
223 pexpect.TIMEOUT ],
224 timeout )
225 main.log.info( self.handle.before )
226 elif i == 3:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800227 main.log.error( self.name + ": Connection timeout" )
228 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700229 elif i == 4: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800230 main.log.error(
231 self.name +
232 ": Something took too long... " )
233 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700234 # Why did we hit this part?
235 main.log.error( "startNet did not return correctly" )
236 return main.FASLE
Jon Hall7eb38402015-01-08 17:19:54 -0800237 else: # if no handle
Jon Hall689d8e42015-04-03 13:59:24 -0700238 main.log.error( self.name + ": Connection failed to the host " +
239 self.user_name + "@" + self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800240 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700241 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800242
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800243 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400244 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800245 # In tree topology, if fanout arg is not given, by default it is 2
246 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400247 fanout = 2
248 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500249 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800250 while( k <= depth - 1 ):
251 count = count + pow( fanout, k )
252 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800253 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800254 while( k <= depth - 2 ):
255 # depth-2 gives you only core links and not considering
256 # edge links as seen by ONOS. If all the links including
257 # edge links are required, do depth-1
258 count = count + pow( fanout, k )
259 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800260 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800261 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800262 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800263
Jon Hall7eb38402015-01-08 17:19:54 -0800264 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800265 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800266 # by default it is 1
267 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400268 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800269 numSwitches = depth
270 numHostsPerSw = fanout
271 totalNumHosts = numSwitches * numHostsPerSw
272 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800273 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800274 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800275 topoDict = { "num_switches": int( numSwitches ),
276 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400277 return topoDict
278
kelvin-onlabd3b64892015-01-20 13:26:24 -0800279 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700280 """
281 Calculate the number of switches and links in a topo."""
282 # TODO: combine this function and numSwitchesNlinks
283 argList = self.options[ 'arg1' ].split( "," )
284 topoArgList = argList[ 0 ].split( " " )
285 argList = map( int, argList[ 1: ] )
286 topoArgList = topoArgList[ 1: ] + argList
287
288 topoDict = self.numSwitchesNlinks( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400289 return topoDict
290
GlennRCf07c44a2015-09-18 13:33:46 -0700291 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800292 """
293 Verifies the reachability of the hosts using pingall command.
294 Optional parameter timeout allows you to specify how long to
295 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700296 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700297 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700298 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700299 ping
300 acceptableFailed - Set the number of acceptable failed pings for the
301 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800302 Returns:
303 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700304 otherwise main.FALSE
305 """
306 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700307 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700308 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700309 if self.handle:
310 main.log.info(
311 self.name +
312 ": Checking reachabilty to the hosts using pingall" )
313 response = ""
314 failedPings = 0
315 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700316 cmd = "pingall"
317 if protocol == "IPv6":
318 cmd = "py net.pingAll6()"
319 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700320 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700321 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700322 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700323 pexpect.EOF,
324 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700325 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700326 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700327 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700328 response += self.handle.before
329 break
330 elif i == 1:
331 response += self.handle.before + self.handle.after
332 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700333 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700334 returnValue = main.FALSE
335 if shortCircuit:
336 main.log.error( self.name +
337 ": Aborting pingall - "
338 + str( failedPings ) +
339 " pings failed" )
340 break
Jon Hall390696c2015-05-05 17:13:41 -0700341 if ( time.time() - startTime ) > timeout:
342 returnValue = main.FALSE
343 main.log.error( self.name +
344 ": Aborting pingall - " +
345 "Function took too long " )
346 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700347 elif i == 2:
348 main.log.error( self.name +
349 ": EOF exception found" )
350 main.log.error( self.name + ": " +
351 self.handle.before )
352 main.cleanup()
353 main.exit()
354 elif i == 3:
355 response += self.handle.before
356 main.log.error( self.name +
357 ": TIMEOUT exception found" )
358 main.log.error( self.name +
359 ": " +
360 str( response ) )
361 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800362 self.handle.send( "\x03" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700363 self.handle.expect( "Interrupt" )
364 self.handle.expect( "mininet>" )
365 break
366 pattern = "Results\:"
367 main.log.info( "Pingall output: " + str( response ) )
368 if re.search( pattern, response ):
369 main.log.info( self.name + ": Pingall finished with "
370 + str( failedPings ) + " failed pings" )
371 return returnValue
372 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700373 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800374 self.handle.send( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700375 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700376 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700377 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700378 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700379 main.log.error( self.name + ": Connection failed to the host" )
380 main.cleanup()
381 main.exit()
382 except pexpect.TIMEOUT:
383 if response:
384 main.log.info( "Pingall output: " + str( response ) )
385 main.log.error( self.name + ": pexpect.TIMEOUT found" )
386 return main.FALSE
387 except pexpect.EOF:
388 main.log.error( self.name + ": EOF exception found" )
389 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500390 main.cleanup()
391 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700392
Jon Hall7eb38402015-01-08 17:19:54 -0800393 def fpingHost( self, **pingParams ):
394 """
395 Uses the fping package for faster pinging...
396 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800397 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800398 command = args[ "SRC" ] + \
399 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
400 self.handle.sendline( command )
401 self.handle.expect(
402 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
403 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
404 response = self.handle.before
405 if re.search( ":\s-", response ):
406 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700407 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800408 elif re.search( ":\s\d{1,2}\.\d\d", response ):
409 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700410 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800411 main.log.info( self.name + ": Install fping on mininet machine... " )
412 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700413 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800414
Jon Hall3b489db2015-10-05 14:38:37 -0700415 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400416 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700417 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700418
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400419 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700420 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700421
422 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400423 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700424
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400425 Returns main.FALSE if one or more of hosts specified
426 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700427 wait = int( wait )
428 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400429
430 try:
431 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700432
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400433 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700434 pingResponse = "IPv4 ping across specified hosts\n"
435 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400436 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700437 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400438 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700439 pingList = hostList[ :listIndex ] + \
440 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700441
442 pingResponse += str(str(host) + " -> ")
443
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400444 for temp in pingList:
445 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700446 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700447 self.handle.sendline( pingCmd )
448 self.handle.expect( "mininet>", timeout=wait + 1 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400449 response = self.handle.before
450 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRCd10d3cc2015-09-24 12:47:16 -0700451 pingResponse += str(" h" + str( temp[1:] ))
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400452 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700453 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400454 # One of the host to host pair is unreachable
455 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700456 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700457 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700458 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700459 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700460 except pexpect.TIMEOUT:
461 main.log.exception( self.name + ": TIMEOUT exception" )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700462 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400463 except pexpect.EOF:
464 main.log.error( self.name + ": EOF exception found" )
465 main.log.error( self.name + ": " + self.handle.before )
466 main.cleanup()
467 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700468 except Exception:
469 main.log.exception( self.name + ": Uncaught exception!" )
470 main.cleanup()
471 main.exit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400472
Jon Hall3b489db2015-10-05 14:38:37 -0700473 def pingIpv6Hosts( self, hostList, prefix='1000::', wait=1 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700474 """
Jon Hall3b489db2015-10-05 14:38:37 -0700475 IPv6 ping all hosts in hostList. If no prefix passed this will use
476 default prefix of 1000::
Hari Krishna9592fc82015-07-31 15:11:15 -0700477
Jon Hall3b489db2015-10-05 14:38:37 -0700478 Returns main.TRUE if all hosts specified can reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700479
Jon Hall3b489db2015-10-05 14:38:37 -0700480 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700481 """
482 try:
483 main.log.info( "Testing reachability between specified IPv6 hosts" )
484 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700485 wait = int( wait )
486 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700487 pingResponse = "IPv6 Pingall output:\n"
488 failedPings = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700489 for host in hostList:
490 listIndex = hostList.index( host )
491 # List of hosts to ping other than itself
492 pingList = hostList[ :listIndex ] + \
493 hostList[ ( listIndex + 1 ): ]
494
GlennRC2cf7d952015-09-11 16:32:13 -0700495 pingResponse += str(str(host) + " -> ")
496
Hari Krishna9592fc82015-07-31 15:11:15 -0700497 for temp in pingList:
498 # Current host pings all other hosts specified
Jon Hall439c8912016-04-15 02:22:03 -0700499 pingCmd = str( host ) + cmd + str( self.getIPAddress(temp,proto='IPv6') )
Jon Hall934576d2015-10-09 10:12:22 -0700500 self.handle.sendline( pingCmd )
501 self.handle.expect( "mininet>", timeout=wait + 1 )
Hari Krishna9592fc82015-07-31 15:11:15 -0700502 response = self.handle.before
503 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRC2cf7d952015-09-11 16:32:13 -0700504 pingResponse += str(" h" + str( temp[1:] ))
Hari Krishna9592fc82015-07-31 15:11:15 -0700505 else:
GlennRC2cf7d952015-09-11 16:32:13 -0700506 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700507 # One of the host to host pair is unreachable
508 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700509 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700510 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700511 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700512 return isReachable
513
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700514 except pexpect.TIMEOUT:
515 main.log.exception( self.name + ": TIMEOUT exception" )
516 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700517 except pexpect.EOF:
518 main.log.error( self.name + ": EOF exception found" )
519 main.log.error( self.name + ": " + self.handle.before )
520 main.cleanup()
521 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700522 except Exception:
523 main.log.exception( self.name + ": Uncaught exception!" )
524 main.cleanup()
525 main.exit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700526
Jon Hall7eb38402015-01-08 17:19:54 -0800527 def pingHost( self, **pingParams ):
528 """
Jon Hall3b489db2015-10-05 14:38:37 -0700529 Ping from one mininet host to another
530 Currently the only supported Params: SRC, TARGET, and WAIT
531 """
532 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
533 wait = args['WAIT']
534 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800535 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700536 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700537 try:
Jon Hall61282e32015-03-19 11:34:11 -0700538 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800539 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700540 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
541 timeout=wait + 1 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700542 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800543 main.log.error(
544 self.name +
545 ": timeout when waiting for response from mininet" )
546 main.log.error( "response: " + str( self.handle.before ) )
547 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700548 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800549 main.log.error(
550 self.name +
551 ": timeout when waiting for response from mininet" )
552 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700553 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700554 if re.search( ',\s0\%\spacket\sloss', response ):
555 main.log.info( self.name + ": no packets lost, host is reachable" )
556 return main.TRUE
557 else:
558 main.log.error(
559 self.name +
560 ": PACKET LOST, HOST IS NOT REACHABLE" )
561 return main.FALSE
562
Jon Hallfbc828e2015-01-06 17:30:19 -0800563 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800564 main.log.error( self.name + ": EOF exception found" )
565 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700566 main.cleanup()
567 main.exit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700568 except Exception:
569 main.log.exception( self.name + ": Uncaught exception!" )
570 main.cleanup()
571 main.exit()
572
573 def ping6pair( self, **pingParams ):
574 """
GlennRC2cf7d952015-09-11 16:32:13 -0700575 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700576 Currently the only supported Params are: SRC, TARGET, and WAIT
Hari Krishna012a1c12015-08-25 14:23:58 -0700577 FLOWLABEL and -I (src interface) will be added later after running some tests.
578 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
579 """
Jon Hall3b489db2015-10-05 14:38:37 -0700580 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
581 wait = args['WAIT']
582 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530583 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700584 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700585 try:
586 main.log.info( "Sending: " + command )
587 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700588 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
589 timeout=wait + 1 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700590 if i == 1:
591 main.log.error(
592 self.name +
593 ": timeout when waiting for response from mininet" )
594 main.log.error( "response: " + str( self.handle.before ) )
595 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
596 if i == 1:
597 main.log.error(
598 self.name +
599 ": timeout when waiting for response from mininet" )
600 main.log.error( "response: " + str( self.handle.before ) )
601 response = self.handle.before
602 main.log.info( self.name + ": Ping Response: " + response )
603 if re.search( ',\s0\%\spacket\sloss', response ):
604 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700605 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700606 else:
607 main.log.error(
608 self.name +
609 ": PACKET LOST, HOST IS NOT REACHABLE" )
610 return main.FALSE
611
612 except pexpect.EOF:
613 main.log.error( self.name + ": EOF exception found" )
614 main.log.error( self.name + ": " + self.handle.before )
615 main.cleanup()
616 main.exit()
617 except Exception:
618 main.log.exception( self.name + ": Uncaught exception!" )
619 main.cleanup()
620 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800621
You Wangdb927a52016-02-26 11:03:28 -0800622 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
623 """
624 Description:
625 Ping a set of destination host from host CLI.
626 Logging into a Mininet host CLI is required before calling this funtion.
627 Params:
628 dstIPList is a list of destination ip addresses
629 Returns:
630 main.TRUE if the destination host is reachable
631 main.FALSE otherwise
632 """
633 isReachable = main.TRUE
634 wait = int( wait )
635 cmd = "ping"
636 if IPv6:
637 cmd = cmd + "6"
638 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
639 try:
640 for dstIP in dstIPList:
641 pingCmd = cmd + " " + dstIP
642 self.handle.sendline( pingCmd )
643 i = self.handle.expect( [ self.hostPrompt,
644 '\*\*\* Unknown command: ' + pingCmd,
645 pexpect.TIMEOUT ],
646 timeout=wait + 1 )
647 if i == 0:
648 response = self.handle.before
649 if not re.search( ',\s0\%\spacket\sloss', response ):
650 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
651 isReachable = main.FALSE
652 elif i == 1:
653 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
654 main.cleanup()
655 main.exit()
656 elif i == 2:
657 main.log.error( self.name + ": timeout when waiting for response" )
658 isReachable = main.FALSE
659 else:
660 main.log.error( self.name + ": unknown response: " + self.handle.before )
661 isReachable = main.FALSE
662 except pexpect.TIMEOUT:
663 main.log.exception( self.name + ": TIMEOUT exception" )
664 isReachable = main.FALSE
665 except pexpect.EOF:
666 main.log.error( self.name + ": EOF exception found" )
667 main.log.error( self.name + ": " + self.handle.before )
668 main.cleanup()
669 main.exit()
670 except Exception:
671 main.log.exception( self.name + ": Uncaught exception!" )
672 main.cleanup()
673 main.exit()
674 return isReachable
675
Jon Hall7eb38402015-01-08 17:19:54 -0800676 def checkIP( self, host ):
677 """
678 Verifies the host's ip configured or not."""
679 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700680 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800681 response = self.execute(
682 cmd=host +
683 " ifconfig",
684 prompt="mininet>",
685 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800686 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800687 main.log.error( self.name + ": EOF exception found" )
688 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700689 main.cleanup()
690 main.exit()
adminbae64d82013-08-01 10:50:15 -0700691
Jon Hall7eb38402015-01-08 17:19:54 -0800692 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800693 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
694 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
695 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
696 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
697 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800698 # pattern = "inet addr:10.0.0.6"
699 if re.search( pattern, response ):
700 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700701 return main.TRUE
702 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800703 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700704 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800705 else:
706 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800707
Jon Hall7eb38402015-01-08 17:19:54 -0800708 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800709 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700710 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800711 response = self.execute(
712 cmd="h1 /usr/sbin/sshd -D&",
713 prompt="mininet>",
714 timeout=10 )
715 response = self.execute(
716 cmd="h4 /usr/sbin/sshd -D&",
717 prompt="mininet>",
718 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700719 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800720 vars( self )[ key ] = connectargs[ key ]
721 response = self.execute(
722 cmd="xterm h1 h4 ",
723 prompt="mininet>",
724 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800725 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800726 main.log.error( self.name + ": EOF exception found" )
727 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700728 main.cleanup()
729 main.exit()
adminbae64d82013-08-01 10:50:15 -0700730 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800731 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700732 if self.flag == 0:
733 self.flag = 1
734 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800735 else:
adminbae64d82013-08-01 10:50:15 -0700736 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800737
Jon Hall53c5e662016-04-13 16:06:56 -0700738 def moveHost( self, host, oldSw, newSw, ):
739 """
740 Moves a host from one switch to another on the fly
741 Note: The intf between host and oldSw when detached
742 using detach(), will still show up in the 'net'
743 cmd, because switch.detach() doesn't affect switch.intfs[]
744 ( which is correct behavior since the interfaces
745 haven't moved ).
746 """
747 if self.handle:
748 try:
749 # Bring link between oldSw-host down
750 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
751 "'," + "'down')"
752 print "cmd1= ", cmd
753 response = self.execute( cmd=cmd,
754 prompt="mininet>",
755 timeout=10 )
756
757 # Determine hostintf and Oldswitchintf
758 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
759 ")[0]"
760 print "cmd2= ", cmd
761 self.handle.sendline( cmd )
762 self.handle.expect( "mininet>" )
763
764 # Determine ip and mac address of the host-oldSw interface
765 cmd = "px ipaddr = hintf.IP()"
766 print "cmd3= ", cmd
767 self.handle.sendline( cmd )
768 self.handle.expect( "mininet>" )
769
770 cmd = "px macaddr = hintf.MAC()"
771 print "cmd3= ", cmd
772 self.handle.sendline( cmd )
773 self.handle.expect( "mininet>" )
774
775 # Detach interface between oldSw-host
776 cmd = "px " + oldSw + ".detach( sintf )"
777 print "cmd4= ", cmd
778 self.handle.sendline( cmd )
779 self.handle.expect( "mininet>" )
780
781 # Add link between host-newSw
782 cmd = "py net.addLink(" + host + "," + newSw + ")"
783 print "cmd5= ", cmd
784 self.handle.sendline( cmd )
785 self.handle.expect( "mininet>" )
786
787 # Determine hostintf and Newswitchintf
788 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
789 ")[0]"
790 print "cmd6= ", cmd
791 self.handle.sendline( cmd )
792 self.handle.expect( "mininet>" )
793
794 # Attach interface between newSw-host
795 cmd = "px " + newSw + ".attach( sintf )"
796 print "cmd3= ", cmd
797 self.handle.sendline( cmd )
798 self.handle.expect( "mininet>" )
799
800 # Set ipaddress of the host-newSw interface
801 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
802 print "cmd7 = ", cmd
803 self.handle.sendline( cmd )
804 self.handle.expect( "mininet>" )
805
806 # Set macaddress of the host-newSw interface
807 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
808 print "cmd8 = ", cmd
809 self.handle.sendline( cmd )
810 self.handle.expect( "mininet>" )
811
812 cmd = "net"
813 print "cmd9 = ", cmd
814 self.handle.sendline( cmd )
815 self.handle.expect( "mininet>" )
816 print "output = ", self.handle.before
817
818 # Determine ipaddress of the host-newSw interface
819 cmd = host + " ifconfig"
820 print "cmd10= ", cmd
821 self.handle.sendline( cmd )
822 self.handle.expect( "mininet>" )
823 print "ifconfig o/p = ", self.handle.before
824
825 return main.TRUE
826 except pexpect.EOF:
827 main.log.error( self.name + ": EOF exception found" )
828 main.log.error( self.name + ": " + self.handle.before )
829 return main.FALSE
830
Jon Hall439c8912016-04-15 02:22:03 -0700831 def moveHostv6( self, host, oldSw, newSw, ):
kelvin-onlaba1484582015-02-02 15:46:20 -0800832 """
833 Moves a host from one switch to another on the fly
834 Note: The intf between host and oldSw when detached
835 using detach(), will still show up in the 'net'
836 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700837 ( which is correct behavior since the interfaces
838 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800839 """
840 if self.handle:
841 try:
Jon Hall439c8912016-04-15 02:22:03 -0700842 IP = str( self.getIPAddress( host, proto='IPV6' ) ) + "/64"
kelvin-onlaba1484582015-02-02 15:46:20 -0800843 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700844 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800845 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800846 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800847 response = self.execute( cmd=cmd,
848 prompt="mininet>",
849 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700850
kelvin-onlaba1484582015-02-02 15:46:20 -0800851 # Determine hostintf and Oldswitchintf
852 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800853 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800854 print "cmd2= ", cmd
855 self.handle.sendline( cmd )
856 self.handle.expect( "mininet>" )
857
shahshreya73537862015-02-11 15:15:24 -0800858 # Determine ip and mac address of the host-oldSw interface
Jon Hall439c8912016-04-15 02:22:03 -0700859 cmd = "px ipaddr = " + str(IP)
kelvin-onlaba1484582015-02-02 15:46:20 -0800860 print "cmd3= ", cmd
861 self.handle.sendline( cmd )
862 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800863
864 cmd = "px macaddr = hintf.MAC()"
865 print "cmd3= ", cmd
866 self.handle.sendline( cmd )
867 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700868
kelvin-onlaba1484582015-02-02 15:46:20 -0800869 # Detach interface between oldSw-host
870 cmd = "px " + oldSw + ".detach( sintf )"
871 print "cmd4= ", cmd
872 self.handle.sendline( cmd )
873 self.handle.expect( "mininet>" )
874
875 # Add link between host-newSw
876 cmd = "py net.addLink(" + host + "," + newSw + ")"
877 print "cmd5= ", cmd
878 self.handle.sendline( cmd )
879 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700880
kelvin-onlaba1484582015-02-02 15:46:20 -0800881 # Determine hostintf and Newswitchintf
882 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800883 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800884 print "cmd6= ", cmd
885 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700886 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800887
888 # Attach interface between newSw-host
889 cmd = "px " + newSw + ".attach( sintf )"
Jon Hall439c8912016-04-15 02:22:03 -0700890 print "cmd6= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800891 self.handle.sendline( cmd )
892 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800893
894 # Set macaddress of the host-newSw interface
895 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
Jon Hall439c8912016-04-15 02:22:03 -0700896 print "cmd7 = ", cmd
897 self.handle.sendline( cmd )
898 self.handle.expect( "mininet>" )
899
900 # Set ipaddress of the host-newSw interface
901 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
shahshreya73537862015-02-11 15:15:24 -0800902 print "cmd8 = ", cmd
903 self.handle.sendline( cmd )
904 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700905
Jon Hall439c8912016-04-15 02:22:03 -0700906 cmd = host + " ifconfig"
907 print "cmd9 =",cmd
908 response = self.execute( cmd = cmd, prompt="mininet>" ,timeout=10 )
909 print response
910 pattern = "h\d-eth([\w])"
Jeremyd9e4eb12016-04-13 12:09:06 -0700911 ipAddressSearch = re.search( pattern, response )
Jon Hall439c8912016-04-15 02:22:03 -0700912 print ipAddressSearch.group(1)
913 intf= host + "-eth" + str(ipAddressSearch.group(1))
914 cmd = host + " ip -6 addr add %s dev %s" % ( IP, intf )
915 print "cmd10 = ", cmd
916 self.handle.sendline( cmd )
917 self.handle.expect( "mininet>" )
918
kelvin-onlaba1484582015-02-02 15:46:20 -0800919 cmd = "net"
Jon Hall439c8912016-04-15 02:22:03 -0700920 print "cmd11 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800921 self.handle.sendline( cmd )
922 self.handle.expect( "mininet>" )
923 print "output = ", self.handle.before
924
925 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800926 cmd = host + " ifconfig"
Jon Hall439c8912016-04-15 02:22:03 -0700927 print "cmd12= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800928 self.handle.sendline( cmd )
929 self.handle.expect( "mininet>" )
930 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700931
kelvin-onlaba1484582015-02-02 15:46:20 -0800932 return main.TRUE
933 except pexpect.EOF:
934 main.log.error( self.name + ": EOF exception found" )
935 main.log.error( self.name + ": " + self.handle.before )
936 return main.FALSE
937
Jon Hall7eb38402015-01-08 17:19:54 -0800938 def changeIP( self, host, intf, newIP, newNetmask ):
939 """
940 Changes the ip address of a host on the fly
941 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800942 if self.handle:
943 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800944 cmd = host + " ifconfig " + intf + " " + \
945 newIP + " " + 'netmask' + " " + newNetmask
946 self.handle.sendline( cmd )
947 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800948 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800949 main.log.info( "response = " + response )
950 main.log.info(
951 "Ip of host " +
952 host +
953 " changed to new IP " +
954 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800955 return main.TRUE
956 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800957 main.log.error( self.name + ": EOF exception found" )
958 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800959 return main.FALSE
960
Jon Hall7eb38402015-01-08 17:19:54 -0800961 def changeDefaultGateway( self, host, newGW ):
962 """
963 Changes the default gateway of a host
964 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800965 if self.handle:
966 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800967 cmd = host + " route add default gw " + newGW
968 self.handle.sendline( cmd )
969 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800970 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800971 main.log.info( "response = " + response )
972 main.log.info(
973 "Default gateway of host " +
974 host +
975 " changed to " +
976 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800977 return main.TRUE
978 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800979 main.log.error( self.name + ": EOF exception found" )
980 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800981 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800982
Jon Hall7eb38402015-01-08 17:19:54 -0800983 def addStaticMACAddress( self, host, GW, macaddr ):
984 """
Jon Hallefbd9792015-03-05 16:11:36 -0800985 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800986 if self.handle:
987 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800988 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
989 cmd = host + " arp -s " + GW + " " + macaddr
990 self.handle.sendline( cmd )
991 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800992 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800993 main.log.info( "response = " + response )
994 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800995 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800996 GW +
997 " changed to " +
998 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800999 return main.TRUE
1000 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001001 main.log.error( self.name + ": EOF exception found" )
1002 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001003 return main.FALSE
1004
Jon Hall7eb38402015-01-08 17:19:54 -08001005 def verifyStaticGWandMAC( self, host ):
1006 """
1007 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001008 if self.handle:
1009 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001010 # h1 arp -an
1011 cmd = host + " arp -an "
1012 self.handle.sendline( cmd )
1013 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001014 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001015 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001016 return main.TRUE
1017 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001018 main.log.error( self.name + ": EOF exception found" )
1019 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001020 return main.FALSE
1021
Jon Hall7eb38402015-01-08 17:19:54 -08001022 def getMacAddress( self, host ):
1023 """
1024 Verifies the host's ip configured or not."""
1025 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001026 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001027 response = self.execute(
1028 cmd=host +
1029 " ifconfig",
1030 prompt="mininet>",
1031 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001032 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001033 main.log.error( self.name + ": EOF exception found" )
1034 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001035 main.cleanup()
1036 main.exit()
adminbae64d82013-08-01 10:50:15 -07001037
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001038 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001039 macAddressSearch = re.search( pattern, response, re.I )
1040 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001041 main.log.info(
1042 self.name +
1043 ": Mac-Address of Host " +
1044 host +
1045 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001046 macAddress )
1047 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001048 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001049 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001050
Jon Hall7eb38402015-01-08 17:19:54 -08001051 def getInterfaceMACAddress( self, host, interface ):
1052 """
1053 Return the IP address of the interface on the given host"""
1054 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001055 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001056 response = self.execute( cmd=host + " ifconfig " + interface,
1057 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001058 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001059 main.log.error( self.name + ": EOF exception found" )
1060 main.log.error( self.name + ": " + self.handle.before )
1061 main.cleanup()
1062 main.exit()
1063
1064 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001065 macAddressSearch = re.search( pattern, response, re.I )
1066 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001067 main.log.info( "No mac address found in %s" % response )
1068 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001069 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001070 main.log.info(
1071 "Mac-Address of " +
1072 host +
1073 ":" +
1074 interface +
1075 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001076 macAddress )
1077 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001078 else:
1079 main.log.error( "Connection failed to the host" )
1080
sathishmad953462015-12-03 17:42:07 +05301081 def getIPAddress( self, host , proto='IPV4'):
Jon Hall7eb38402015-01-08 17:19:54 -08001082 """
1083 Verifies the host's ip configured or not."""
1084 if self.handle:
1085 try:
1086 response = self.execute(
1087 cmd=host +
1088 " ifconfig",
1089 prompt="mininet>",
1090 timeout=10 )
1091 except pexpect.EOF:
1092 main.log.error( self.name + ": EOF exception found" )
1093 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001094 main.cleanup()
1095 main.exit()
adminbae64d82013-08-01 10:50:15 -07001096
sathishmad953462015-12-03 17:42:07 +05301097 pattern = ''
1098 if proto == 'IPV4':
1099 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
1100 else:
Jon Hall439c8912016-04-15 02:22:03 -07001101 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001102 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -08001103 main.log.info(
1104 self.name +
1105 ": IP-Address of Host " +
1106 host +
1107 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001108 ipAddressSearch.group( 1 ) )
1109 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001110 else:
1111 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001112
Jon Hall7eb38402015-01-08 17:19:54 -08001113 def getSwitchDPID( self, switch ):
1114 """
1115 return the datapath ID of the switch"""
1116 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001117 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001118 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001119 response = self.execute(
1120 cmd=cmd,
1121 prompt="mininet>",
1122 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001123 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001124 main.log.error( self.name + ": EOF exception found" )
1125 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001126 main.cleanup()
1127 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001128 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001129 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001130 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001131 main.log.info(
1132 "Couldn't find DPID for switch %s, found: %s" %
1133 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001134 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001135 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001136 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001137 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001138
Jon Hall7eb38402015-01-08 17:19:54 -08001139 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001140 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001141 self.handle.sendline( "" )
1142 self.expect( "mininet>" )
1143 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001144 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001145 response = self.execute(
1146 cmd=cmd,
1147 prompt="mininet>",
1148 timeout=10 )
1149 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001150 response = self.handle.before
1151 return response
1152 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001153 main.log.error( self.name + ": EOF exception found" )
1154 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -07001155 main.cleanup()
1156 main.exit()
1157
Jon Hall7eb38402015-01-08 17:19:54 -08001158 def getInterfaces( self, node ):
1159 """
1160 return information dict about interfaces connected to the node"""
1161 if self.handle:
1162 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001163 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001164 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001165 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001166 response = self.execute(
1167 cmd=cmd,
1168 prompt="mininet>",
1169 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001170 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001171 main.log.error( self.name + ": EOF exception found" )
1172 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001173 main.cleanup()
1174 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001175 return response
1176 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001177 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001178
Jon Hall7eb38402015-01-08 17:19:54 -08001179 def dump( self ):
1180 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001181 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001182 response = self.execute(
1183 cmd='dump',
1184 prompt='mininet>',
1185 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001186 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001187 main.log.error( self.name + ": EOF exception found" )
1188 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001189 main.cleanup()
1190 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001191 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001192
Jon Hall7eb38402015-01-08 17:19:54 -08001193 def intfs( self ):
1194 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001195 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001196 response = self.execute(
1197 cmd='intfs',
1198 prompt='mininet>',
1199 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001200 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001201 main.log.error( self.name + ": EOF exception found" )
1202 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001203 main.cleanup()
1204 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001205 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001206
Jon Hall7eb38402015-01-08 17:19:54 -08001207 def net( self ):
1208 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001209 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001210 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001211 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001212 main.log.error( self.name + ": EOF exception found" )
1213 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001214 main.cleanup()
1215 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001216 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001217
YPZhang81a7d4e2016-04-18 13:10:17 -07001218 def links( self, timeout=20 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001219 main.log.info( self.name + ": List network links" )
1220 try:
1221 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001222 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001223 except pexpect.EOF:
1224 main.log.error( self.name + ": EOF exception found" )
1225 main.log.error( self.name + ": " + self.handle.before )
1226 main.cleanup()
1227 main.exit()
1228 return response
1229
GlennRC61321f22015-07-16 13:36:54 -07001230 def iperftcpAll(self, hosts, timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001231 '''
1232 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001233
kelvin-onlab7cce9382015-07-17 10:21:03 -07001234 @parm:
1235 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1236 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1237 '''
1238 for host1 in hosts:
1239 for host2 in hosts:
1240 if host1 != host2:
1241 if self.iperftcp(host1, host2, timeout) == main.FALSE:
1242 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
GlennRC61321f22015-07-16 13:36:54 -07001243
1244 def iperftcp(self, host1="h1", host2="h2", timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001245 '''
1246 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1247 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001248
kelvin-onlab7cce9382015-07-17 10:21:03 -07001249 @parm:
1250 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1251 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1252 '''
1253 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1254 try:
1255 # Setup the mininet command
1256 cmd1 = 'iperf ' + host1 + " " + host2
1257 self.handle.sendline( cmd1 )
1258 outcome = self.handle.expect( "mininet>", timeout )
1259 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001260
kelvin-onlab7cce9382015-07-17 10:21:03 -07001261 # checks if there are results in the mininet response
1262 if "Results:" in response:
Jon Hall892818c2015-10-20 17:58:34 -07001263 main.log.report(self.name + ": iperf test completed")
kelvin-onlab7cce9382015-07-17 10:21:03 -07001264 # parse the mn results
1265 response = response.split("\r\n")
1266 response = response[len(response)-2]
1267 response = response.split(": ")
1268 response = response[len(response)-1]
1269 response = response.replace("[", "")
1270 response = response.replace("]", "")
1271 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001272
kelvin-onlab7cce9382015-07-17 10:21:03 -07001273 # this is the bandwith two and from the two hosts
1274 bandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001275
kelvin-onlab7cce9382015-07-17 10:21:03 -07001276 # there should be two elements in the bandwidth list
1277 # ['host1 to host2', 'host2 to host1"]
1278 if len(bandwidth) == 2:
1279 main.log.report(self.name + ": iperf test successful")
1280 return main.TRUE
1281 else:
1282 main.log.error(self.name + ": invalid iperf results")
1283 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001284 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001285 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001286 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001287 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001288 main.log.error( self.name + ": TIMEOUT exception found" )
1289 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001290 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001291 # NOTE: Send ctrl-c to make sure iperf is done
1292 self.handle.sendline( "\x03" )
1293 self.handle.expect( "Interrupt" )
1294 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001295 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001296 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001297 main.log.error( self.name + ": EOF exception found" )
1298 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001299 main.cleanup()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001300 main.exit()
GlennRC61321f22015-07-16 13:36:54 -07001301
Jon Hall439c8912016-04-15 02:22:03 -07001302 def iperftcpipv6(self, host1="h1", host2="h2", timeout=50):
1303 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1304 try:
1305 IP1 = self.getIPAddress( host1, proto='IPV6' )
1306 cmd1 = host1 +' iperf -V -sD -B '+ str(IP1)
1307 self.handle.sendline( cmd1 )
1308 outcome1 = self.handle.expect( "mininet>")
1309 cmd2 = host2 +' iperf -V -c '+ str(IP1) +' -t 5'
1310 self.handle.sendline( cmd2 )
1311 outcome2 = self.handle.expect( "mininet>")
1312 response1 = self.handle.before
1313 response2 = self.handle.after
1314 print response1,response2
1315 pattern = "connected with "+ str(IP1)
1316 if pattern in response1:
1317 main.log.report(self.name + ": iperf test completed")
1318 return main.TRUE
1319 else:
1320 main.log.error( self.name + ": iperf test failed" )
1321 return main.FALSE
1322 except pexpect.TIMEOUT:
1323 main.log.error( self.name + ": TIMEOUT exception found" )
1324 main.log.error( self.name + " response: " + repr( self.handle.before ) )
1325 self.handle.sendline( "\x03" )
1326 self.handle.expect( "Interrupt" )
1327 self.handle.expect( "mininet>" )
1328 return main.FALSE
1329 except pexpect.EOF:
1330 main.log.error( self.name + ": EOF exception found" )
1331 main.log.error( self.name + ": " + self.handle.before )
1332 main.cleanup()
1333 main.exit()
1334
GlennRC61321f22015-07-16 13:36:54 -07001335 def iperfudpAll(self, hosts, bandwidth="10M"):
1336 '''
1337 Runs the iperfudp function with a given set of hosts and specified
1338 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001339
GlennRC61321f22015-07-16 13:36:54 -07001340 @param:
1341 bandwidth: the targeted bandwidth, in megabits ('M')
1342 '''
1343 for host1 in hosts:
1344 for host2 in hosts:
1345 if host1 != host2:
1346 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1347 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1348
1349 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1350
kelvin-onlab7cce9382015-07-17 10:21:03 -07001351 '''
1352 Creates an iperf UDP test with a specific bandwidth.
1353 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001354
kelvin-onlab7cce9382015-07-17 10:21:03 -07001355 @param:
1356 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1357 '''
1358 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1359 try:
1360 # setup the mininet command
1361 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1362 self.handle.sendline(cmd)
1363 self.handle.expect("mininet>")
1364 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001365
kelvin-onlab7cce9382015-07-17 10:21:03 -07001366 # check if there are in results in the mininet response
1367 if "Results:" in response:
Jon Hall892818c2015-10-20 17:58:34 -07001368 main.log.report(self.name + ": iperfudp test completed")
kelvin-onlab7cce9382015-07-17 10:21:03 -07001369 # parse the results
1370 response = response.split("\r\n")
1371 response = response[len(response)-2]
1372 response = response.split(": ")
1373 response = response[len(response)-1]
1374 response = response.replace("[", "")
1375 response = response.replace("]", "")
1376 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001377
kelvin-onlab7cce9382015-07-17 10:21:03 -07001378 mnBandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001379
kelvin-onlab7cce9382015-07-17 10:21:03 -07001380 # check to see if there are at least three entries
1381 # ['bandwidth', 'host1 to host2', 'host2 to host1']
1382 if len(mnBandwidth) == 3:
1383 # if one entry is blank then something is wrong
1384 for item in mnBandwidth:
1385 if item == "":
1386 main.log.error(self.name + ": Could not parse iperf output")
1387 main.log.error(self.name + ": invalid iperfudp results")
1388 return main.FALSE
1389 # otherwise results are vaild
1390 main.log.report(self.name + ": iperfudp test successful")
1391 return main.TRUE
1392 else:
1393 main.log.error(self.name + ": invalid iperfudp results")
1394 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001395
kelvin-onlab7cce9382015-07-17 10:21:03 -07001396 except pexpect.EOF:
1397 main.log.error( self.name + ": EOF exception found" )
1398 main.log.error( self.name + ": " + self.handle.before )
1399 main.cleanup()
1400 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001401
Jon Hall7eb38402015-01-08 17:19:54 -08001402 def nodes( self ):
1403 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001404 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001405 response = self.execute(
1406 cmd='nodes',
1407 prompt='mininet>',
1408 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001409 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001410 main.log.error( self.name + ": EOF exception found" )
1411 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001412 main.cleanup()
1413 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001414 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001415
Jon Hall7eb38402015-01-08 17:19:54 -08001416 def pingpair( self ):
1417 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001418 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001419 response = self.execute(
1420 cmd='pingpair',
1421 prompt='mininet>',
1422 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001423 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001424 main.log.error( self.name + ": EOF exception found" )
1425 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001426 main.cleanup()
1427 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001428
Jon Hall7eb38402015-01-08 17:19:54 -08001429 if re.search( ',\s0\%\spacket\sloss', response ):
1430 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001431 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001432 else:
1433 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001434 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001435
Jon Hall7eb38402015-01-08 17:19:54 -08001436 def link( self, **linkargs ):
1437 """
GlennRCed771242016-01-13 17:02:47 -08001438 Bring link( s ) between two nodes up or down
1439 """
Jon Hall6094a362014-04-11 14:46:56 -07001440 try:
GlennRCed771242016-01-13 17:02:47 -08001441 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1442 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1443 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1444 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1445
1446 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1447 cmd = "link {} {} {}".format( end1, end2, option )
1448 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001449 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001450 response = self.handle.before
1451 main.log.info( response )
1452
1453 return main.TRUE
1454 except pexpect.TIMEOUT:
1455 main.log.exception( self.name + ": Command timed out" )
1456 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001457 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001458 main.log.exception( self.name + ": connection closed." )
Jon Hall6094a362014-04-11 14:46:56 -07001459 main.cleanup()
1460 main.exit()
GlennRCed771242016-01-13 17:02:47 -08001461 except Exception:
1462 main.log.exception( self.name + ": Uncaught exception!" )
1463 main.cleanup()
1464 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001465
pingping-lin8244a3b2015-09-16 13:36:56 -07001466 def switch( self, **switchargs ):
1467 """
1468 start/stop a switch
1469 """
1470 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1471 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1472 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1473 command = "switch " + str( sw ) + " " + str( option )
1474 main.log.info( command )
1475 try:
1476 self.handle.sendline( command )
1477 self.handle.expect( "mininet>" )
1478 except pexpect.TIMEOUT:
1479 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1480 main.cleanup()
1481 main.exit()
1482 except pexpect.EOF:
1483 main.log.error( self.name + ": EOF exception found" )
1484 main.log.error( self.name + ": " + self.handle.before )
1485 main.cleanup()
1486 main.exit()
1487 return main.TRUE
1488
pingping-lin5bb663b2015-09-24 11:47:50 -07001489 def node( self, nodeName, commandStr ):
1490 """
1491 Carry out a command line on a given node
1492 @parm:
1493 nodeName: the node name in Mininet testbed
1494 commandStr: the command line will be carried out on the node
1495 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1496 """
1497 command = str( nodeName ) + " " + str( commandStr )
1498 main.log.info( command )
1499
1500 try:
1501 response = self.execute( cmd = command, prompt = "mininet>" )
1502 if re.search( "Unknown command", response ):
1503 main.log.warn( response )
1504 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001505 if re.search( "Permission denied", response ):
1506 main.log.warn( response )
1507 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001508 except pexpect.TIMEOUT:
1509 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1510 main.cleanup()
1511 main.exit()
1512 except pexpect.EOF:
1513 main.log.error( self.name + ": EOF exception found" )
1514 main.log.error( self.name + ": " + self.handle.before )
1515 main.cleanup()
1516 main.exit()
1517 main.log.info( " response is :" )
1518 main.log.info( response )
1519 return response
1520
Jon Hall7eb38402015-01-08 17:19:54 -08001521 def yank( self, **yankargs ):
1522 """
1523 yank a mininet switch interface to a host"""
1524 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001525 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001526 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1527 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1528 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001529 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001530 response = self.execute(
1531 cmd=command,
1532 prompt="mininet>",
1533 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001534 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001535 main.log.error( self.name + ": EOF exception found" )
1536 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001537 main.cleanup()
1538 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001539 return main.TRUE
1540
Jon Hall7eb38402015-01-08 17:19:54 -08001541 def plug( self, **plugargs ):
1542 """
1543 plug the yanked mininet switch interface to a switch"""
1544 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001545 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001546 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1547 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1548 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001549 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001550 response = self.execute(
1551 cmd=command,
1552 prompt="mininet>",
1553 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001554 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001555 main.log.error( self.name + ": EOF exception found" )
1556 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001557 main.cleanup()
1558 main.exit()
adminbae64d82013-08-01 10:50:15 -07001559 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001560
Jon Hall7eb38402015-01-08 17:19:54 -08001561 def dpctl( self, **dpctlargs ):
1562 """
1563 Run dpctl command on all switches."""
1564 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001565 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001566 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1567 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1568 command = "dpctl " + cmd + " " + str( cmdargs )
1569 try:
1570 response = self.execute(
1571 cmd=command,
1572 prompt="mininet>",
1573 timeout=10 )
1574 except pexpect.EOF:
1575 main.log.error( self.name + ": EOF exception found" )
1576 main.log.error( self.name + ": " + self.handle.before )
1577 main.cleanup()
1578 main.exit()
1579 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001580
kelvin-onlabd3b64892015-01-20 13:26:24 -08001581 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001582 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001583 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001584 fileInput = path + '/lib/Mininet/INSTALL'
1585 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001586 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001587 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001588 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001589 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001590 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001591 return version
adminbae64d82013-08-01 10:50:15 -07001592
kelvin-onlabd3b64892015-01-20 13:26:24 -08001593 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001594 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001595 Parameters:
1596 sw: The name of an OVS switch. Example "s1"
1597 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001598 The output of the command from the mininet cli
1599 or main.FALSE on timeout"""
1600 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001601 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001602 response = self.execute(
1603 cmd=command,
1604 prompt="mininet>",
1605 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001606 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001607 return response
admin2a9548d2014-06-17 14:08:07 -07001608 else:
1609 return main.FALSE
1610 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001611 main.log.error( self.name + ": EOF exception found" )
1612 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001613 main.cleanup()
1614 main.exit()
adminbae64d82013-08-01 10:50:15 -07001615
Charles Chan029be652015-08-24 01:46:10 +08001616 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001617 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001618 Description:
1619 Assign switches to the controllers ( for ovs use only )
1620 Required:
1621 sw - Name of the switch. This can be a list or a string.
1622 ip - Ip addresses of controllers. This can be a list or a string.
1623 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001624 port - ONOS use port 6653, if no list of ports is passed, then
1625 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001626 ptcp - ptcp number, This can be a string or a list that has
1627 the same length as switch. This is optional and not required
1628 when using ovs switches.
1629 NOTE: If switches and ptcp are given in a list type they should have the
1630 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1631 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001632
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001633 Return:
1634 Returns main.TRUE if mininet correctly assigned switches to
1635 controllers, otherwise it will return main.FALSE or an appropriate
1636 exception(s)
1637 """
1638 assignResult = main.TRUE
1639 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001640 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001641 command = "sh ovs-vsctl set-controller "
1642 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001643 try:
1644 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001645 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001646 if isinstance( port, types.StringType ) or \
1647 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001648 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001649 elif isinstance( port, types.ListType ):
1650 main.log.error( self.name + ": Only one controller " +
1651 "assigned and a list of ports has" +
1652 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001653 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001654 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001655 main.log.error( self.name + ": Invalid controller port " +
1656 "number. Please specify correct " +
1657 "controller port" )
1658 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001659
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001660 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001661 if isinstance( port, types.StringType ) or \
1662 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001663 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001664 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1665 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001666 elif isinstance( port, types.ListType ):
1667 if ( len( ip ) != len( port ) ):
1668 main.log.error( self.name + ": Port list = " +
1669 str( len( port ) ) +
1670 "should be the same as controller" +
1671 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001672 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001673 else:
1674 onosIp = ""
1675 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001676 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1677 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001678 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001679 main.log.error( self.name + ": Invalid controller port " +
1680 "number. Please specify correct " +
1681 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001682 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001683 else:
1684 main.log.error( self.name + ": Invalid ip address" )
1685 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001686
1687 if isinstance( sw, types.StringType ):
1688 command += sw + " "
1689 if ptcp:
1690 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001691 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001692 elif isinstance( ptcp, types.ListType ):
1693 main.log.error( self.name + ": Only one switch is " +
1694 "being set and multiple PTCP is " +
1695 "being passed " )
1696 else:
1697 main.log.error( self.name + ": Invalid PTCP" )
1698 ptcp = ""
1699 command += onosIp
1700 commandList.append( command )
1701
1702 elif isinstance( sw, types.ListType ):
1703 if ptcp:
1704 if isinstance( ptcp, types.ListType ):
1705 if len( ptcp ) != len( sw ):
1706 main.log.error( self.name + ": PTCP length = " +
1707 str( len( ptcp ) ) +
1708 " is not the same as switch" +
1709 " length = " +
1710 str( len( sw ) ) )
1711 return main.FALSE
1712 else:
1713 for switch, ptcpNum in zip( sw, ptcp ):
1714 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001715 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001716 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001717 tempCmd += onosIp
1718 commandList.append( tempCmd )
1719 else:
1720 main.log.error( self.name + ": Invalid PTCP" )
1721 return main.FALSE
1722 else:
1723 for switch in sw:
1724 tempCmd = "sh ovs-vsctl set-controller "
1725 tempCmd += switch + " " + onosIp
1726 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001727 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001728 main.log.error( self.name + ": Invalid switch type " )
1729 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001730
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001731 for cmd in commandList:
1732 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001733 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001734 except pexpect.TIMEOUT:
1735 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1736 return main.FALSE
1737 except pexpect.EOF:
1738 main.log.error( self.name + ": EOF exception found" )
1739 main.log.error( self.name + ": " + self.handle.before )
1740 main.cleanup()
1741 main.exit()
1742 return main.TRUE
1743 except Exception:
1744 main.log.exception( self.name + ": Uncaught exception!" )
1745 main.cleanup()
1746 main.exit()
adminbae64d82013-08-01 10:50:15 -07001747
kelvin-onlabd3b64892015-01-20 13:26:24 -08001748 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001749 """
1750 Removes the controller target from sw"""
1751 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001752 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001753 response = self.execute(
1754 cmd=command,
1755 prompt="mininet>",
1756 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001757 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001758 main.log.error( self.name + ": EOF exception found" )
1759 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001760 main.cleanup()
1761 main.exit()
1762 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001763 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001764
kelvin-onlabd3b64892015-01-20 13:26:24 -08001765 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001766 """
Jon Hallb1290e82014-11-18 16:17:48 -05001767 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001768 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001769 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001770 NOTE: cannot currently specify what type of switch
1771 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001772 sw = name of the new switch as a string
1773 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001774 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001775 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001776 """
1777 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001778 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001779 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001780 response = self.execute(
1781 cmd=command,
1782 prompt="mininet>",
1783 timeout=10 )
1784 if re.search( "already exists!", response ):
1785 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001786 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001787 elif re.search( "Error", response ):
1788 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001789 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001790 elif re.search( "usage:", response ):
1791 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001792 return main.FALSE
1793 else:
1794 return main.TRUE
1795 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001796 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001797 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001798 main.cleanup()
1799 main.exit()
1800
kelvin-onlabd3b64892015-01-20 13:26:24 -08001801 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001802 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001803 delete a switch from the mininet topology
1804 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001805 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001806 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001807 sw = name of the switch as a string
1808 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001809 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001810 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001811 response = self.execute(
1812 cmd=command,
1813 prompt="mininet>",
1814 timeout=10 )
1815 if re.search( "no switch named", response ):
1816 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001817 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001818 elif re.search( "Error", response ):
1819 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001820 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001821 elif re.search( "usage:", response ):
1822 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001823 return main.FALSE
1824 else:
1825 return main.TRUE
1826 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001827 main.log.error( self.name + ": EOF exception found" )
1828 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001829 main.cleanup()
1830 main.exit()
1831
You Wangdb8cd0a2016-05-26 15:19:45 -07001832 def getSwitchRandom( self, timeout=60, nonCut=True ):
1833 """
1834 Randomly get a switch from Mininet topology.
1835 If nonCut is True, it gets a list of non-cut switches (the deletion
1836 of a non-cut switch will not increase the number of connected
1837 components of a graph) and randomly returns one of them, otherwise
1838 it just randomly returns one switch from all current switches in
1839 Mininet.
1840 Returns the name of the chosen switch.
1841 """
1842 import random
1843 candidateSwitches = []
1844 try:
1845 if not nonCut:
1846 switches = self.getSwitches( timeout=timeout )
1847 assert len( switches ) != 0
1848 for switchName in switches.keys():
1849 candidateSwitches.append( switchName )
1850 else:
1851 graphDict = self.getGraphDict( timeout=timeout, useId=False )
1852 if graphDict == None:
1853 return None
1854 self.graph.update( graphDict )
1855 candidateSwitches = self.graph.getNonCutVertices()
1856 if candidateSwitches == None:
1857 return None
1858 elif len( candidateSwitches ) == 0:
1859 main.log.info( self.name + ": No candidate switch for deletion" )
1860 return None
1861 else:
1862 switch = random.sample( candidateSwitches, 1 )
1863 return switch[ 0 ]
1864 except KeyError:
1865 main.log.exception( self.name + ": KeyError exception found" )
1866 return None
1867 except AssertionError:
1868 main.log.exception( self.name + ": AssertionError exception found" )
1869 return None
1870 except Exception:
1871 main.log.exception( self.name + ": Uncaught exception" )
1872 return None
1873
1874 def delSwitchRandom( self, timeout=60, nonCut=True ):
1875 """
1876 Randomly delete a switch from Mininet topology.
1877 If nonCut is True, it gets a list of non-cut switches (the deletion
1878 of a non-cut switch will not increase the number of connected
1879 components of a graph) and randomly chooses one for deletion,
1880 otherwise it just randomly delete one switch from all current
1881 switches in Mininet.
1882 Returns the name of the deleted switch
1883 """
1884 try:
1885 switch = self.getSwitchRandom( timeout, nonCut )
1886 if switch == None:
1887 return None
1888 else:
1889 deletionResult = self.delSwitch( switch )
1890 if deletionResult:
1891 return switch
1892 else:
1893 return None
1894 except Exception:
1895 main.log.exception( self.name + ": Uncaught exception" )
1896 return None
1897
kelvin-onlabd3b64892015-01-20 13:26:24 -08001898 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001899 """
1900 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001901 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001902 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001903 NOTE: cannot currently specify what type of link
1904 required params:
1905 node1 = the string node name of the first endpoint of the link
1906 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001907 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001908 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001909 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001910 response = self.execute(
1911 cmd=command,
1912 prompt="mininet>",
1913 timeout=10 )
1914 if re.search( "doesnt exist!", response ):
1915 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001916 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001917 elif re.search( "Error", response ):
1918 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001919 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001920 elif re.search( "usage:", response ):
1921 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001922 return main.FALSE
1923 else:
1924 return main.TRUE
1925 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001926 main.log.error( self.name + ": EOF exception found" )
1927 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001928 main.cleanup()
1929 main.exit()
1930
kelvin-onlabd3b64892015-01-20 13:26:24 -08001931 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001932 """
1933 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001934 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001935 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001936 required params:
1937 node1 = the string node name of the first endpoint of the link
1938 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001939 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001940 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001941 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001942 response = self.execute(
1943 cmd=command,
1944 prompt="mininet>",
1945 timeout=10 )
1946 if re.search( "no node named", response ):
1947 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001948 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001949 elif re.search( "Error", response ):
1950 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001951 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001952 elif re.search( "usage:", response ):
1953 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001954 return main.FALSE
1955 else:
1956 return main.TRUE
1957 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001958 main.log.error( self.name + ": EOF exception found" )
1959 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001960 main.cleanup()
1961 main.exit()
1962
You Wangdb8cd0a2016-05-26 15:19:45 -07001963 def getLinkRandom( self, timeout=60, nonCut=True ):
1964 """
1965 Randomly get a link from Mininet topology.
1966 If nonCut is True, it gets a list of non-cut links (the deletion
1967 of a non-cut link will not increase the number of connected
1968 component of a graph) and randomly returns one of them, otherwise
1969 it just randomly returns one link from all current links in
1970 Mininet.
1971 Returns the link as a list, e.g. [ 's1', 's2' ]
1972 """
1973 import random
1974 candidateLinks = []
1975 try:
1976 if not nonCut:
1977 links = self.getLinks( timeout=timeout )
1978 assert len( links ) != 0
1979 for link in links:
1980 # Exclude host-switch link
1981 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
1982 continue
1983 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
1984 else:
1985 graphDict = self.getGraphDict( timeout=timeout, useId=False )
1986 if graphDict == None:
1987 return None
1988 self.graph.update( graphDict )
1989 candidateLinks = self.graph.getNonCutEdges()
1990 if candidateLinks == None:
1991 return None
1992 elif len( candidateLinks ) == 0:
1993 main.log.info( self.name + ": No candidate link for deletion" )
1994 return None
1995 else:
1996 link = random.sample( candidateLinks, 1 )
1997 return link[ 0 ]
1998 except KeyError:
1999 main.log.exception( self.name + ": KeyError exception found" )
2000 return None
2001 except AssertionError:
2002 main.log.exception( self.name + ": AssertionError exception found" )
2003 return None
2004 except Exception:
2005 main.log.exception( self.name + ": Uncaught exception" )
2006 return None
2007
2008 def delLinkRandom( self, timeout=60, nonCut=True ):
2009 """
2010 Randomly delete a link from Mininet topology.
2011 If nonCut is True, it gets a list of non-cut links (the deletion
2012 of a non-cut link will not increase the number of connected
2013 component of a graph) and randomly chooses one for deletion,
2014 otherwise it just randomly delete one link from all current links
2015 in Mininet.
2016 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2017 """
2018 try:
2019 link = self.getLinkRandom( timeout, nonCut )
2020 if link == None:
2021 return None
2022 else:
2023 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2024 if deletionResult:
2025 return link
2026 else:
2027 return None
2028 except Exception:
2029 main.log.exception( self.name + ": Uncaught exception" )
2030 return None
2031
kelvin-onlabd3b64892015-01-20 13:26:24 -08002032 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002033 """
Jon Hallb1290e82014-11-18 16:17:48 -05002034 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002035 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002036 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002037 NOTE: cannot currently specify what type of host
2038 required params:
2039 hostname = the string hostname
2040 optional key-value params
2041 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002042 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002043 """
2044 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002045 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002046 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002047 response = self.execute(
2048 cmd=command,
2049 prompt="mininet>",
2050 timeout=10 )
2051 if re.search( "already exists!", response ):
2052 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002053 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002054 elif re.search( "doesnt exists!", response ):
2055 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002056 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002057 elif re.search( "Error", response ):
2058 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002059 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002060 elif re.search( "usage:", response ):
2061 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002062 return main.FALSE
2063 else:
2064 return main.TRUE
2065 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002066 main.log.error( self.name + ": EOF exception found" )
2067 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002068 main.cleanup()
2069 main.exit()
2070
kelvin-onlabd3b64892015-01-20 13:26:24 -08002071 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002072 """
2073 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002074 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002075 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002076 NOTE: this uses a custom mn function
2077 required params:
2078 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002079 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002080 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002081 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002082 response = self.execute(
2083 cmd=command,
2084 prompt="mininet>",
2085 timeout=10 )
2086 if re.search( "no host named", response ):
2087 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002088 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002089 elif re.search( "Error", response ):
2090 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002091 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002092 elif re.search( "usage:", response ):
2093 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002094 return main.FALSE
2095 else:
2096 return main.TRUE
2097 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002098 main.log.error( self.name + ": EOF exception found" )
2099 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002100 main.cleanup()
2101 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07002102
Jon Hall7eb38402015-01-08 17:19:54 -08002103 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002104 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002105 Called at the end of the test to stop the mininet and
2106 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002107 """
Jon Halld80cc142015-07-06 13:36:05 -07002108 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08002109 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07002110 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07002111 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08002112 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07002113 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08002114 elif i == 1:
2115 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08002116 # print "Disconnecting Mininet"
2117 if self.handle:
2118 self.handle.sendline( "exit" )
2119 self.handle.expect( "exit" )
2120 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08002121 else:
2122 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08002123 return response
2124
Jon Halld80cc142015-07-06 13:36:05 -07002125 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002126 """
Jon Hall21270ac2015-02-16 17:59:55 -08002127 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002128 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002129 main.FALSE if the pexpect handle does not exist.
2130
Jon Halld61331b2015-02-17 16:35:47 -08002131 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002132 """
Jon Halld61331b2015-02-17 16:35:47 -08002133 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002134 response = ''
2135 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002136 try:
Jon Halld80cc142015-07-06 13:36:05 -07002137 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002138 i = self.handle.expect( [ 'mininet>',
2139 '\$',
2140 pexpect.EOF,
2141 pexpect.TIMEOUT ],
2142 timeout )
2143 if i == 0:
2144 main.log.info( "Exiting mininet..." )
Jeremyd9e4eb12016-04-13 12:09:06 -07002145 response = self.execute( cmd="exit",
2146 prompt="(.*)",
2147 timeout=120 )
2148 main.log.info( self.name + ": Stopped" )
2149 self.handle.sendline( "sudo mn -c" )
2150 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002151
Jeremyd9e4eb12016-04-13 12:09:06 -07002152 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002153 main.log.info( " Mininet trying to exit while not " +
2154 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002155 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002156 elif i == 2:
2157 main.log.error( "Something went wrong exiting mininet" )
2158 elif i == 3: # timeout
2159 main.log.error( "Something went wrong exiting mininet " +
2160 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002161
Hari Krishnab35c6d02015-03-18 11:13:51 -07002162 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002163 self.handle.sendline( "" )
2164 self.handle.expect( '\$' )
2165 self.handle.sendline(
2166 "sudo kill -9 \`ps -ef | grep \"" +
2167 fileName +
2168 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002169 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002170 main.log.error( self.name + ": EOF exception found" )
2171 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07002172 main.cleanup()
2173 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08002174 else:
2175 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002176 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002177 return response
2178
YPZhang26a139e2016-04-25 14:01:55 -07002179 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002180 """
2181 Description:
2182 Sends arp message from mininet host for hosts discovery
2183 Required:
2184 host - hosts name
2185 Optional:
2186 ip - ip address that does not exist in the network so there would
2187 be no reply.
2188 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002189 if ethDevice:
2190 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002191 cmd = srcHost + " arping -c1 "
2192 if noResult:
2193 cmd += "-w10 " # If we don't want the actural arping result, set -w10, arping will exit after 10 ms.
2194 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002195 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002196 if output:
2197 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002198 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002199 i = self.handle.expect( [ "mininet>", "arping: " ] )
2200 if i == 0:
2201 return main.TRUE
2202 elif i == 1:
2203 response = self.handle.before + self.handle.after
2204 self.handle.expect( "mininet>" )
2205 response += self.handle.before + self.handle.after
2206 main.log.warn( "Error sending arping, output was: " +
2207 response )
2208 return main.FALSE
2209 except pexpect.TIMEOUT:
2210 main.log.error( self.name + ": TIMEOUT exception found" )
2211 main.log.warn( self.handle.before )
2212 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002213 except pexpect.EOF:
2214 main.log.error( self.name + ": EOF exception found" )
2215 main.log.error( self.name + ": " + self.handle.before )
2216 main.cleanup()
2217 main.exit()
admin07529932013-11-22 14:58:28 -08002218
Jon Hall7eb38402015-01-08 17:19:54 -08002219 def decToHex( self, num ):
2220 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002221
Jon Hall7eb38402015-01-08 17:19:54 -08002222 def getSwitchFlowCount( self, switch ):
2223 """
2224 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002225 if self.handle:
2226 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2227 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002228 response = self.execute(
2229 cmd=cmd,
2230 prompt="mininet>",
2231 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002232 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002233 main.log.error( self.name + ": EOF exception found" )
2234 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002235 main.cleanup()
2236 main.exit()
2237 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002238 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002239 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002240 main.log.info(
2241 "Couldn't find flows on switch %s, found: %s" %
2242 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002243 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002244 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002245 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002246 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002247
Jon Hall9ed8f372016-02-24 17:34:07 -08002248 def checkFlows( self, sw, dumpFormat=None ):
2249 if dumpFormat:
2250 command = "sh ovs-ofctl -F " + \
2251 dumpFormat + " dump-flows " + str( sw )
2252 else:
2253 command = "sh ovs-ofctl dump-flows " + str( sw )
2254 try:
2255 response = self.execute(
2256 cmd=command,
2257 prompt="mininet>",
2258 timeout=10 )
2259 return response
2260 except pexpect.EOF:
2261 main.log.error( self.name + ": EOF exception found" )
2262 main.log.error( self.name + ": " + self.handle.before )
2263 main.cleanup()
2264 main.exit()
2265
GlennRC68467eb2015-11-16 18:01:01 -08002266 def flowTableComp( self, flowTable1, flowTable2 ):
2267 # This function compares the selctors and treatments of each flow
2268 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002269 assert flowTable1, "flowTable1 is empty or None"
2270 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002271 returnValue = main.TRUE
GlennRC68467eb2015-11-16 18:01:01 -08002272 if len(flowTable1) != len(flowTable2):
2273 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002274 returnValue = main.FALSE
GlennRCfa65fce2015-12-16 13:16:08 -08002275 dFields = ["n_bytes", "cookie", "n_packets", "duration"]
2276 for flow1, flow2 in zip(flowTable1, flowTable2):
Jon Hallacd1b182015-12-17 11:43:20 -08002277 for field in dFields:
2278 try:
2279 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002280 except KeyError:
2281 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002282 try:
2283 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002284 except KeyError:
2285 pass
GlennRC68467eb2015-11-16 18:01:01 -08002286 for i in range( len(flowTable1) ):
GlennRC17bbcf52015-12-14 17:31:50 -08002287 if flowTable1[i] not in flowTable2:
2288 main.log.warn( "Flow tables do not match:" )
2289 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[i] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002290 returnValue = main.FALSE
2291 break
2292 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002293 except AssertionError:
2294 main.log.exception( "Nothing to compare" )
2295 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002296 except Exception:
2297 main.log.exception( "Uncaught exception!" )
2298 main.cleanup()
2299 main.exit()
Jon Hall9043c902015-07-30 14:23:44 -07002300
GlennRC528ad292015-11-12 10:38:18 -08002301 def parseFlowTable( self, flowTable, version="", debug=True ):
GlennRC956ea742015-11-05 16:14:15 -08002302 '''
2303 Discription: Parses flows into json format.
2304 NOTE: this can parse any string thats separated with commas
2305 Arguments:
2306 Required:
2307 flows: a list of strings that represnt flows
2308 Optional:
2309 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2310 debug: prints out the final result
2311 returns: A list of flows in json format
2312 '''
GlennRC528ad292015-11-12 10:38:18 -08002313 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002314 try:
2315 for flow in flowTable:
2316 jsonFlow = {}
2317 # split up the fields of the flow
2318 parsedFlow = flow.split(", ")
2319 # get rid of any spaces in front of the field
2320 for i in range( len(parsedFlow) ):
2321 item = parsedFlow[i]
2322 if item[0] == " ":
2323 parsedFlow[i] = item[1:]
2324 # grab the selector and treatment from the parsed flow
2325 # the last element is the selector and the treatment
2326 temp = parsedFlow.pop(-1)
2327 # split up the selector and the treatment
2328 temp = temp.split(" ")
2329 index = 0
2330 # parse the flags
2331 # NOTE: This only parses one flag
2332 flag = {}
2333 if version == "1.3":
2334 flag = {"flag":[temp[index]]}
2335 index += 1
2336 # the first element is the selector and split it up
2337 sel = temp[index]
GlennRC528ad292015-11-12 10:38:18 -08002338 index += 1
You Wang91c37cf2016-05-23 09:39:42 -07002339 sel = sel.split(",")
2340 # the priority is stuck in the selecter so put it back
2341 # in the flow
2342 parsedFlow.append(sel.pop(0))
2343 # parse selector
2344 criteria = []
2345 for item in sel:
2346 # this is the type of the packet e.g. "arp"
2347 if "=" not in item:
2348 criteria.append( {"type":item} )
2349 else:
2350 field = item.split("=")
2351 criteria.append( {field[0]:field[1]} )
2352 selector = {"selector": {"criteria":sorted(criteria)} }
2353 treat = temp[index]
2354 # get rid of the action part e.g. "action=output:2"
2355 # we will add it back later
2356 treat = treat.split("=")
2357 treat.pop(0)
2358 # parse treatment
2359 action = []
2360 for item in treat:
2361 field = item.split(":")
2362 action.append( {field[0]:field[1]} )
2363 # create the treatment field and add the actions
2364 treatment = {"treatment": {"action":sorted(action)} }
2365 # parse the rest of the flow
2366 for item in parsedFlow:
GlennRC528ad292015-11-12 10:38:18 -08002367 field = item.split("=")
You Wang91c37cf2016-05-23 09:39:42 -07002368 jsonFlow.update( {field[0]:field[1]} )
2369 # add the treatment and the selector to the json flow
2370 jsonFlow.update( selector )
2371 jsonFlow.update( treatment )
2372 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002373
You Wang91c37cf2016-05-23 09:39:42 -07002374 if debug: main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format(jsonFlow) )
GlennRC956ea742015-11-05 16:14:15 -08002375
You Wang91c37cf2016-05-23 09:39:42 -07002376 # add the json flow to the json flow table
2377 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002378
You Wang91c37cf2016-05-23 09:39:42 -07002379 return jsonFlowTable
2380
2381 except IndexError:
2382 main.log.exception( self.name + ": IndexError found" )
2383 return None
2384 except Exception:
2385 main.log.exception( self.name + ": Uncaught exception!" )
2386 main.cleanup()
2387 main.exit()
GlennRC528ad292015-11-12 10:38:18 -08002388
Jon Hall0a543792015-12-14 11:00:26 -08002389 def getFlowTable( self, sw, version="", debug=False):
GlennRC956ea742015-11-05 16:14:15 -08002390 '''
2391 Discription: Returns the flow table(s) on a switch or switches in a list.
2392 Each element is a flow.
2393 Arguments:
2394 Required:
2395 sw: The switch name ("s1") to retrive the flow table. Can also be
2396 a list of switches.
2397 Optional:
2398 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2399 debug: prints out the final result
2400 '''
2401 try:
2402 switches = []
2403 if type(sw) is list:
Jon Hallca7ac292015-11-11 09:28:12 -08002404 switches.extend(sw)
GlennRC956ea742015-11-05 16:14:15 -08002405 else: switches.append(sw)
2406
2407 flows = []
2408 for s in switches:
2409 cmd = "sh ovs-ofctl dump-flows " + s
2410
GlennRC528ad292015-11-12 10:38:18 -08002411 if "1.0" == version:
2412 cmd += " -F OpenFlow10-table_id"
2413 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002414 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002415
2416 main.log.info( "Sending: " + cmd )
2417 self.handle.sendline( cmd )
2418 self.handle.expect( "mininet>" )
2419 response = self.handle.before
2420 response = response.split( "\r\n" )
2421 # dump the first two elements and the last
2422 # the first element is the command that was sent
2423 # the second is the table header
2424 # the last element is empty
2425 response = response[2:-1]
2426 flows.extend( response )
2427
2428 if debug: print "Flows:\n{}\n\n".format(flows)
2429
GlennRC528ad292015-11-12 10:38:18 -08002430 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002431
2432 except pexpect.TIMEOUT:
2433 main.log.exception( self.name + ": Command timed out" )
2434 return None
2435 except pexpect.EOF:
2436 main.log.exception( self.name + ": connection closed." )
2437 main.cleanup()
2438 main.exit()
2439 except Exception:
2440 main.log.exception( self.name + ": Uncaught exception!" )
2441 main.cleanup()
2442 main.exit()
2443
2444 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
2445 '''
2446 Discription: Checks whether the ID provided matches a flow ID in Mininet
2447 Arguments:
2448 Required:
2449 sw: The switch name ("s1") to retrive the flow table. Can also be
2450 a list of switches.
2451 flowId: the flow ID in hex format. Can also be a list of IDs
2452 Optional:
2453 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2454 debug: prints out the final result
2455 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2456 NOTE: prints out IDs that are not present
2457 '''
2458 try:
2459 main.log.info( "Getting flows from Mininet" )
2460 flows = self.getFlowTable( sw, version, debug )
You Wang083ae982016-05-25 09:31:09 -07002461 if flows == None:
2462 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002463
2464 if debug: print "flow ids:\n{}\n\n".format(flowId)
2465
2466 # Check flowId is a list or a string
2467 if type( flowId ) is str:
2468 result = False
2469 for f in flows:
2470 if flowId in f.get( 'cookie' ):
2471 result = True
2472 break
2473 # flowId is a list
2474 else:
2475 result = True
2476 # Get flow IDs from Mininet
2477 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2478 # Save the IDs that are not in Mininet
2479 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2480
2481 if debug: print "mn flow ids:\n{}\n\n".format(mnFlowIds)
2482
2483 # Print out the IDs that are not in Mininet
2484 if absentIds:
2485 main.log.warn( "Absent ids: {}".format( absentIds ) )
2486 result = False
2487
2488 return main.TRUE if result else main.FALSE
2489
2490 except Exception:
2491 main.log.exception( self.name + ": Uncaught exception!" )
2492 main.cleanup()
2493 main.exit()
2494
2495
Charles Chan029be652015-08-24 01:46:10 +08002496 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002497 """
Jon Hallefbd9792015-03-05 16:11:36 -08002498 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002499 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002500 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002501 self.handle.sendline( "" )
2502 self.handle.expect( "mininet>" )
2503 self.handle.sendline(
2504 "sh sudo tcpdump -n -i " +
2505 intf +
2506 " " +
2507 port +
2508 " -w " +
2509 filename.strip() +
2510 " &" )
2511 self.handle.sendline( "" )
2512 i = self.handle.expect( [ 'No\ssuch\device',
2513 'listening\son',
2514 pexpect.TIMEOUT,
2515 "mininet>" ],
2516 timeout=10 )
2517 main.log.warn( self.handle.before + self.handle.after )
2518 self.handle.sendline( "" )
2519 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002520 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002521 main.log.error(
2522 self.name +
2523 ": tcpdump - No such device exists. " +
2524 "tcpdump attempted on: " +
2525 intf )
admin2a9548d2014-06-17 14:08:07 -07002526 return main.FALSE
2527 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002528 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002529 return main.TRUE
2530 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002531 main.log.error(
2532 self.name +
2533 ": tcpdump command timed out! Check interface name," +
2534 " given interface was: " +
2535 intf )
admin2a9548d2014-06-17 14:08:07 -07002536 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002537 elif i == 3:
2538 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002539 return main.TRUE
2540 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002541 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002542 return main.FALSE
2543 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002544 main.log.error( self.name + ": EOF exception found" )
2545 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002546 main.cleanup()
2547 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002548 except Exception:
2549 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002550 main.cleanup()
2551 main.exit()
2552
kelvin-onlabd3b64892015-01-20 13:26:24 -08002553 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002554 """
2555 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002556 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002557 self.handle.sendline( "sh sudo pkill tcpdump" )
2558 self.handle.expect( "mininet>" )
2559 self.handle.sendline( "" )
2560 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002561 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002562 main.log.error( self.name + ": EOF exception found" )
2563 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002564 main.cleanup()
2565 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002566 except Exception:
2567 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002568 main.cleanup()
2569 main.exit()
2570
Jon Halld80cc142015-07-06 13:36:05 -07002571 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002572 """
2573 Read ports from a Mininet switch.
2574
2575 Returns a json structure containing information about the
2576 ports of the given switch.
2577 """
2578 response = self.getInterfaces( nodeName )
2579 # TODO: Sanity check on response. log if no such switch exists
2580 ports = []
2581 for line in response.split( "\n" ):
2582 if not line.startswith( "name=" ):
2583 continue
2584 portVars = {}
2585 for var in line.split( "," ):
2586 key, value = var.split( "=" )
2587 portVars[ key ] = value
2588 isUp = portVars.pop( 'enabled', "True" )
2589 isUp = "True" in isUp
2590 if verbose:
2591 main.log.info( "Reading switch port %s(%s)" %
2592 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2593 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002594 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002595 mac = None
2596 ips = []
2597 ip = portVars[ 'ip' ]
2598 if ip == 'None':
2599 ip = None
2600 ips.append( ip )
2601 name = portVars[ 'name' ]
2602 if name == 'None':
2603 name = None
2604 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2605 if name == 'lo':
2606 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2607 else:
2608 portNo = re.search( portRe, name ).group( 'port' )
2609 ports.append( { 'of_port': portNo,
2610 'mac': str( mac ).replace( '\'', '' ),
2611 'name': name,
2612 'ips': ips,
2613 'enabled': isUp } )
2614 return ports
2615
You Wangdb8cd0a2016-05-26 15:19:45 -07002616 def getOVSPorts( self, nodeName ):
2617 """
2618 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2619
2620 Returns a list of dictionaries containing information about each
2621 port of the given switch.
2622 """
2623 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2624 try:
2625 response = self.execute(
2626 cmd=command,
2627 prompt="mininet>",
2628 timeout=10 )
2629 ports = []
2630 if response:
2631 for line in response.split( "\n" ):
2632 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2633 # Example port:
2634 # 1(s1-eth1): addr:ae:60:72:77:55:51
2635 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2636 result = re.search( pattern, line )
2637 if result:
2638 index = result.group( 'index' )
2639 name = result.group( 'name' )
2640 # This port number is extracted from port name
2641 port = result.group( 'port' )
2642 mac = result.group( 'mac' )
2643 ports.append( { 'index': index,
2644 'name': name,
2645 'port': port,
2646 'mac': mac } )
2647 return ports
2648 except pexpect.EOF:
2649 main.log.error( self.name + ": EOF exception found" )
2650 main.log.error( self.name + ": " + self.handle.before )
2651 main.cleanup()
2652 main.exit()
2653 except Exception:
2654 main.log.exception( self.name + ": Uncaught exception!" )
2655 main.cleanup()
2656 main.exit()
2657
Jon Halld80cc142015-07-06 13:36:05 -07002658 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002659 """
2660 Read switches from Mininet.
2661
2662 Returns a dictionary whose keys are the switch names and the value is
2663 a dictionary containing information about the switch.
2664 """
Jon Halla22481b2015-07-28 17:46:01 -07002665 # NOTE: To support new Mininet switch classes, just append the new
2666 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002667
Jon Halla22481b2015-07-28 17:46:01 -07002668 # Regex patterns to parse 'dump' output
2669 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002670 # <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 -07002671 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002672 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2673 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2674 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2675 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2676 swRE = r"<(?P<class>" + switchClasses + r")" +\
2677 r"(?P<options>\{.*\})?\s" +\
2678 r"(?P<name>[^:]+)\:\s" +\
2679 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2680 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002681 # Update mn port info
2682 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002683 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002684 dump = self.dump().split( "\n" )
2685 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002686 result = re.search( swRE, line, re.I )
2687 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002688 name = result.group( 'name' )
2689 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002690 pid = result.group( 'pid' )
2691 swClass = result.group( 'class' )
2692 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002693 if verbose:
2694 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2695 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002696 output[ name ] = { "dpid": dpid,
2697 "ports": ports,
2698 "swClass": swClass,
2699 "pid": pid,
2700 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002701 return output
2702
Jon Halld80cc142015-07-06 13:36:05 -07002703 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002704 """
2705 Read hosts from Mininet.
2706
2707 Returns a dictionary whose keys are the host names and the value is
2708 a dictionary containing information about the host.
2709 """
2710 # Regex patterns to parse dump output
2711 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002712 # <Host h1: pid=12725>
2713 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2714 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2715 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002716 # NOTE: Does not correctly match hosts with multi-links
2717 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2718 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002719 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002720 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002721 # update mn port info
2722 self.update()
2723 # Get mininet dump
2724 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002725 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002726 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002727 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002728 result = re.search( hostRE, line )
2729 name = result.group( 'name' )
2730 interfaces = []
2731 response = self.getInterfaces( name )
2732 # Populate interface info
2733 for line in response.split( "\n" ):
2734 if line.startswith( "name=" ):
2735 portVars = {}
2736 for var in line.split( "," ):
2737 key, value = var.split( "=" )
2738 portVars[ key ] = value
2739 isUp = portVars.pop( 'enabled', "True" )
2740 isUp = "True" in isUp
2741 if verbose:
2742 main.log.info( "Reading host port %s(%s)" %
2743 ( portVars[ 'name' ],
2744 portVars[ 'mac' ] ) )
2745 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002746 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002747 mac = None
2748 ips = []
2749 ip = portVars[ 'ip' ]
2750 if ip == 'None':
2751 ip = None
2752 ips.append( ip )
2753 intfName = portVars[ 'name' ]
2754 if name == 'None':
2755 name = None
2756 interfaces.append( {
2757 "name": intfName,
2758 "ips": ips,
2759 "mac": str( mac ),
2760 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002761 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002762 return hosts
2763
YPZhang81a7d4e2016-04-18 13:10:17 -07002764 def getLinks( self, timeout=20 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002765 """
2766 Gathers information about current Mininet links. These links may not
2767 be up if one of the ports is down.
2768
2769 Returns a list of dictionaries with link endpoints.
2770
2771 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002772 { 'node1': str( node1 name )
2773 'node2': str( node2 name )
2774 'port1': str( port1 of_port )
2775 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002776 Note: The port number returned is the eth#, not necessarily the of_port
2777 number. In Mininet, for OVS switch, these should be the same. For
2778 hosts, this is just the eth#.
2779 """
2780 self.update()
YPZhang81a7d4e2016-04-18 13:10:17 -07002781 response = self.links(timeout=timeout).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002782
2783 # Examples:
2784 # s1-eth3<->s2-eth1 (OK OK)
2785 # s13-eth3<->h27-eth0 (OK OK)
2786 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2787 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2788 links = []
2789 for line in response:
2790 match = re.search( linkRE, line )
2791 if match:
2792 node1 = match.group( 'node1' )
2793 node2 = match.group( 'node2' )
2794 port1 = match.group( 'port1' )
2795 port2 = match.group( 'port2' )
2796 links.append( { 'node1': node1,
2797 'node2': node2,
2798 'port1': port1,
2799 'port2': port2 } )
2800 return links
2801
2802 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002803 """
2804 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002805 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002806
Jon Hallafa8a472015-06-12 14:02:42 -07002807 Dependencies:
2808 1. numpy - "sudo pip install numpy"
2809 """
2810 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002811 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002812 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002813 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002814 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002815 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002816 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002817 main.log.error(
2818 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002819 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002820 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002821 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002822 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002823 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002824 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002825 onosDPIDs.append(
2826 switch[ 'id' ].replace(
2827 ":",
2828 '' ).replace(
2829 "of",
2830 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002831 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002832
Jon Hall7eb38402015-01-08 17:19:54 -08002833 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002834 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002835 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002836 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002837 main.log.error( str( list1 ) )
2838 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002839 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002840 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002841 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002842 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002843 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002844
Jon Hall7eb38402015-01-08 17:19:54 -08002845 # FIXME: this does not look for extra ports in ONOS, only checks that
2846 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002847 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002848
Jon Hall7eb38402015-01-08 17:19:54 -08002849 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002850 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002851 mnPorts = []
2852 onosPorts = []
2853 switchResult = main.TRUE
2854 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002855 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002856 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002857 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002858 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002859 if onosSwitch[ 'device' ][ 'id' ].replace(
2860 ':',
2861 '' ).replace(
2862 "of",
2863 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002864 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002865 if port[ 'isEnabled' ]:
2866 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002867 # onosPorts.append( 'local' )
2868 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002869 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002870 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002871 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002872 mnPorts.sort( key=float )
2873 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002874
kelvin-onlabd3b64892015-01-20 13:26:24 -08002875 mnPortsLog = mnPorts
2876 onosPortsLog = onosPorts
2877 mnPorts = [ x for x in mnPorts ]
2878 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002879
Jon Hall7eb38402015-01-08 17:19:54 -08002880 # TODO: handle other reserved port numbers besides LOCAL
2881 # NOTE: Reserved ports
2882 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2883 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002884 for mnPort in mnPortsLog:
2885 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002886 # don't set results to true here as this is just one of
2887 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002888 mnPorts.remove( mnPort )
2889 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002890
Jon Hall7eb38402015-01-08 17:19:54 -08002891 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002892 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002893 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002894 if 65534 in mnPorts:
2895 mnPorts.remove( 65534 )
2896 if long( uint64( -2 ) ) in onosPorts:
2897 onosPorts.remove( long( uint64( -2 ) ) )
2898 if len( mnPorts ): # the ports of this switch don't match
2899 switchResult = main.FALSE
2900 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2901 if len( onosPorts ): # the ports of this switch don't match
2902 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002903 main.log.warn(
2904 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002905 str( onosPorts ) )
2906 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002907 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002908 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002909 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002910 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2911 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2912 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002913 finalResults = finalResults and portsResults
2914 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002915
Jon Hallafa8a472015-06-12 14:02:42 -07002916 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002917 """
2918 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002919 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002920
Jon Hallafa8a472015-06-12 14:02:42 -07002921 """
Jon Hall7eb38402015-01-08 17:19:54 -08002922 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002923 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002924 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002925
Jon Halld80cc142015-07-06 13:36:05 -07002926 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002927 for l in links:
2928 try:
2929 node1 = switches[ l[ 'node1' ] ]
2930 node2 = switches[ l[ 'node2' ] ]
2931 enabled = True
2932 for port in node1[ 'ports' ]:
2933 if port[ 'of_port' ] == l[ 'port1' ]:
2934 enabled = enabled and port[ 'enabled' ]
2935 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002936 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002937 enabled = enabled and port[ 'enabled' ]
2938 if enabled:
2939 mnLinks.append( l )
2940 except KeyError:
2941 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002942 if 2 * len( mnLinks ) == len( onos ):
2943 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002944 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002945 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002946 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002947 "Mininet has " + str( len( mnLinks ) ) +
2948 " bidirectional links and ONOS has " +
2949 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002950
Jon Hall7eb38402015-01-08 17:19:54 -08002951 # iterate through MN links and check if an ONOS link exists in
2952 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002953 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002954 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002955 node1 = None
2956 port1 = None
2957 node2 = None
2958 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002959 firstDir = main.FALSE
2960 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002961 for swName, switch in switches.iteritems():
2962 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002963 node1 = switch[ 'dpid' ]
2964 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002965 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002966 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002967 if node1 is not None and node2 is not None:
2968 break
Jon Hallafa8a472015-06-12 14:02:42 -07002969 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002970 node2 = switch[ 'dpid' ]
2971 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002972 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002973 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002974 if node1 is not None and node2 is not None:
2975 break
2976
kelvin-onlabd3b64892015-01-20 13:26:24 -08002977 for onosLink in onos:
2978 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002979 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002980 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002981 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002982 onosPort1 = onosLink[ 'src' ][ 'port' ]
2983 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002984
Jon Hall72cf1dc2014-10-20 21:04:50 -04002985 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002986 if str( onosNode1 ) == str( node1 ) and str(
2987 onosNode2 ) == str( node2 ):
2988 if int( onosPort1 ) == int( port1 ) and int(
2989 onosPort2 ) == int( port2 ):
2990 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002991 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002992 main.log.warn(
2993 'The port numbers do not match for ' +
2994 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002995 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002996 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002997 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002998 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002999 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003000
3001 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08003002 elif ( str( onosNode1 ) == str( node2 ) and
3003 str( onosNode2 ) == str( node1 ) ):
3004 if ( int( onosPort1 ) == int( port2 )
3005 and int( onosPort2 ) == int( port1 ) ):
3006 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04003007 else:
Jon Hall7eb38402015-01-08 17:19:54 -08003008 main.log.warn(
3009 'The port numbers do not match for ' +
3010 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08003011 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08003012 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07003013 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08003014 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07003015 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08003016 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04003017 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08003018 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07003019 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08003020 'ONOS does not have the link %s/%s -> %s/%s' %
3021 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003022 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07003023 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08003024 'ONOS does not have the link %s/%s -> %s/%s' %
3025 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003026 linkResults = linkResults and firstDir and secondDir
3027 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04003028
Jon Hallafa8a472015-06-12 14:02:42 -07003029 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003030 """
Jon Hallafa8a472015-06-12 14:02:42 -07003031 Compare mn and onos Hosts.
3032 Since Mininet hosts are quiet, ONOS will only know of them when they
3033 speak. For this reason, we will only check that the hosts in ONOS
3034 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003035
Jon Hallafa8a472015-06-12 14:02:42 -07003036 Arguments:
3037 hostsJson: parsed json object from the onos hosts api
3038 Returns:
3039 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003040 import json
3041 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08003042 for onosHost in hostsJson:
3043 onosMAC = onosHost[ 'mac' ].lower()
3044 match = False
Jon Halld80cc142015-07-06 13:36:05 -07003045 for mnHost, info in hosts.iteritems():
3046 for mnIntf in info[ 'interfaces' ]:
3047 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08003048 match = True
3049 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07003050 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08003051 pass # all is well
3052 else:
3053 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07003054 main.log.error( "ONOS host " +
3055 onosHost[ 'id' ] +
3056 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07003057 str( onosHost[ 'ipAddresses' ] ) +
3058 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07003059 str( ip ) +
3060 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08003061 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07003062 onosHost,
3063 sort_keys=True,
3064 indent=4,
3065 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08003066 main.log.info( output )
3067 hostResults = main.FALSE
3068 if not match:
3069 hostResults = main.FALSE
3070 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3071 "corresponding Mininet host." )
3072 output = json.dumps( onosHost,
3073 sort_keys=True,
3074 indent=4,
3075 separators=( ',', ': ' ) )
3076 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08003077 return hostResults
3078
Jon Hallafa8a472015-06-12 14:02:42 -07003079 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003080 """
3081 Returns a list of all hosts
3082 Don't ask questions just use it"""
3083 self.handle.sendline( "" )
3084 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003085
Jon Hall7eb38402015-01-08 17:19:54 -08003086 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3087 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003088
kelvin-onlabd3b64892015-01-20 13:26:24 -08003089 handlePy = self.handle.before
3090 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3091 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003092
Jon Hall7eb38402015-01-08 17:19:54 -08003093 self.handle.sendline( "" )
3094 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003095
kelvin-onlabd3b64892015-01-20 13:26:24 -08003096 hostStr = handlePy.replace( "]", "" )
3097 hostStr = hostStr.replace( "'", "" )
3098 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07003099 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003100 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003101
kelvin-onlabd3b64892015-01-20 13:26:24 -08003102 return hostList
adminbae64d82013-08-01 10:50:15 -07003103
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003104 def getSwitch( self ):
3105 """
3106 Returns a list of all switches
3107 Again, don't ask question just use it...
3108 """
3109 # get host list...
3110 hostList = self.getHosts()
3111 # Make host set
3112 hostSet = set( hostList )
3113
3114 # Getting all the nodes in mininet
3115 self.handle.sendline( "" )
3116 self.handle.expect( "mininet>" )
3117
3118 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3119 self.handle.expect( "mininet>" )
3120
3121 handlePy = self.handle.before
3122 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3123 handlePy = handlePy.rstrip()
3124
3125 self.handle.sendline( "" )
3126 self.handle.expect( "mininet>" )
3127
3128 nodesStr = handlePy.replace( "]", "" )
3129 nodesStr = nodesStr.replace( "'", "" )
3130 nodesStr = nodesStr.replace( "[", "" )
3131 nodesStr = nodesStr.replace( " ", "" )
3132 nodesList = nodesStr.split( "," )
3133
3134 nodesSet = set( nodesList )
3135 # discarding default controller(s) node
3136 nodesSet.discard( 'c0' )
3137 nodesSet.discard( 'c1' )
3138 nodesSet.discard( 'c2' )
3139
3140 switchSet = nodesSet - hostSet
3141 switchList = list( switchSet )
3142
3143 return switchList
3144
You Wangdb8cd0a2016-05-26 15:19:45 -07003145 def getGraphDict( self, timeout=60, useId=True, includeHost=False ):
3146 """
3147 Return a dictionary which describes the latest Mininet topology data as a
3148 graph.
3149 An example of the dictionary:
3150 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3151 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3152 Each vertex should at least have an 'edges' attribute which describes the
3153 adjacency information. The value of 'edges' attribute is also represented by
3154 a dictionary, which maps each edge (identified by the neighbor vertex) to a
3155 list of attributes.
3156 An example of the edges dictionary:
3157 'edges': { vertex2: { 'port': ..., 'weight': ... },
3158 vertex3: { 'port': ..., 'weight': ... } }
3159 If useId == True, dpid/mac will be used instead of names to identify
3160 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3161 topology.
3162 If includeHost == True, all hosts (and host-switch links) will be included
3163 in topology data.
3164 Note that link or switch that are brought down by 'link x x down' or 'switch
3165 x down' commands still show in the output of Mininet CLI commands such as
3166 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3167 recommended to use delLink() or delSwitch functions to simulate link/switch
3168 down, and addLink() or addSwitch to add them back.
3169 """
3170 graphDict = {}
3171 try:
3172 links = self.getLinks( timeout=timeout )
3173 portDict = {}
3174 if useId:
3175 switches = self.getSwitches()
3176 if includeHost:
3177 hosts = self.getHosts()
3178 for link in links:
3179 # FIXME: support 'includeHost' argument
3180 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3181 continue
3182 nodeName1 = link[ 'node1' ]
3183 nodeName2 = link[ 'node2' ]
3184 port1 = link[ 'port1' ]
3185 port2 = link[ 'port2' ]
3186 # Loop for two nodes
3187 for i in range( 2 ):
3188 # Get port index from OVS
3189 # The index extracted from port name may be inconsistent with ONOS
3190 portIndex = -1
3191 if not nodeName1 in portDict.keys():
3192 portList = self.getOVSPorts( nodeName1 )
3193 if len( portList ) == 0:
3194 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3195 return None
3196 portDict[ nodeName1 ] = portList
3197 for port in portDict[ nodeName1 ]:
3198 if port[ 'port' ] == port1:
3199 portIndex = port[ 'index' ]
3200 break
3201 if portIndex == -1:
3202 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3203 return None
3204 if useId:
3205 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3206 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3207 else:
3208 node1 = nodeName1
3209 node2 = nodeName2
3210 if not node1 in graphDict.keys():
3211 if useId:
3212 graphDict[ node1 ] = { 'edges':{},
3213 'dpid':switches[ nodeName1 ][ 'dpid' ],
3214 'name':nodeName1,
3215 'ports':switches[ nodeName1 ][ 'ports' ],
3216 'swClass':switches[ nodeName1 ][ 'swClass' ],
3217 'pid':switches[ nodeName1 ][ 'pid' ],
3218 'options':switches[ nodeName1 ][ 'options' ] }
3219 else:
3220 graphDict[ node1 ] = { 'edges':{} }
3221 else:
3222 # Assert node2 is not connected to any current links of node1
3223 assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
3224 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port':portIndex }
3225 # Swap two nodes/ports
3226 nodeName1, nodeName2 = nodeName2, nodeName1
3227 port1, port2 = port2, port1
3228 return graphDict
3229 except KeyError:
3230 main.log.exception( self.name + ": KeyError exception found" )
3231 return None
3232 except AssertionError:
3233 main.log.exception( self.name + ": AssertionError exception found" )
3234 return None
3235 except Exception:
3236 main.log.exception( self.name + ": Uncaught exception" )
3237 return None
3238
Jon Hall7eb38402015-01-08 17:19:54 -08003239 def update( self ):
3240 """
3241 updates the port address and status information for
3242 each port in mn"""
3243 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003244 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003245 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003246 self.handle.sendline( "" )
3247 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003248
Jon Hall7eb38402015-01-08 17:19:54 -08003249 self.handle.sendline( "update" )
3250 self.handle.expect( "update" )
3251 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003252
Jon Hall7eb38402015-01-08 17:19:54 -08003253 self.handle.sendline( "" )
3254 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003255
Jon Hallb1290e82014-11-18 16:17:48 -05003256 return main.TRUE
3257 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003258 main.log.error( self.name + ": EOF exception found" )
3259 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05003260 main.cleanup()
3261 main.exit()
3262
Jon Halld80cc142015-07-06 13:36:05 -07003263 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003264 """
3265 Add vlan tag to a host.
3266 Dependencies:
3267 This class depends on the "vlan" package
3268 $ sudo apt-get install vlan
3269 Configuration:
3270 Load the 8021q module into the kernel
3271 $sudo modprobe 8021q
3272
3273 To make this setup permanent:
3274 $ sudo su -c 'echo "8021q" >> /etc/modules'
3275 """
3276 if self.handle:
3277 try:
Jon Halld80cc142015-07-06 13:36:05 -07003278 # get the ip address of the host
3279 main.log.info( "Get the ip address of the host" )
3280 ipaddr = self.getIPAddress( host )
3281 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003282
Jon Halld80cc142015-07-06 13:36:05 -07003283 # remove IP from interface intf
3284 # Ex: h1 ifconfig h1-eth0 inet 0
3285 main.log.info( "Remove IP from interface " )
3286 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3287 self.handle.sendline( cmd2 )
3288 self.handle.expect( "mininet>" )
3289 response = self.handle.before
3290 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003291
Jon Halld80cc142015-07-06 13:36:05 -07003292 # create VLAN interface
3293 # Ex: h1 vconfig add h1-eth0 100
3294 main.log.info( "Create Vlan" )
3295 cmd3 = host + " vconfig add " + intf + " " + vlan
3296 self.handle.sendline( cmd3 )
3297 self.handle.expect( "mininet>" )
3298 response = self.handle.before
3299 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003300
Jon Halld80cc142015-07-06 13:36:05 -07003301 # assign the host's IP to the VLAN interface
3302 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3303 main.log.info( "Assign the host IP to the vlan interface" )
3304 vintf = intf + "." + vlan
3305 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3306 self.handle.sendline( cmd4 )
3307 self.handle.expect( "mininet>" )
3308 response = self.handle.before
3309 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003310
3311 return main.TRUE
3312 except pexpect.EOF:
3313 main.log.error( self.name + ": EOF exception found" )
3314 main.log.error( self.name + ": " + self.handle.before )
3315 return main.FALSE
3316
Jon Hall892818c2015-10-20 17:58:34 -07003317 def createHostComponent( self, name ):
3318 """
3319 Creates a new mininet cli component with the same parameters as self.
3320 This new component is intended to be used to login to the hosts created
3321 by mininet.
3322
3323 Arguments:
3324 name - The string of the name of this component. The new component
3325 will be assigned to main.<name> .
3326 In addition, main.<name>.name = str( name )
3327 """
3328 try:
3329 # look to see if this component already exists
3330 getattr( main, name )
3331 except AttributeError:
3332 # namespace is clear, creating component
3333 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
3334 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
3335 main.componentInit( name )
3336 except Exception:
3337 main.log.exception( self.name + ": Uncaught exception!" )
3338 main.cleanup()
3339 main.exit()
3340 else:
3341 # namespace is not clear!
3342 main.log.error( name + " component already exists!" )
3343 # FIXME: Should we exit here?
3344 main.cleanup()
3345 main.exit()
3346
3347 def removeHostComponent( self, name ):
3348 """
3349 Remove host component
3350 Arguments:
3351 name - The string of the name of the component to delete.
3352 """
3353 try:
3354 # Get host component
3355 component = getattr( main, name )
3356 except AttributeError:
3357 main.log.error( "Component " + name + " does not exist." )
3358 return
3359 try:
3360 # Disconnect from component
3361 component.disconnect()
3362 # Delete component
3363 delattr( main, name )
3364 # Delete component from ComponentDictionary
3365 del( main.componentDictionary[name] )
3366 except Exception:
3367 main.log.exception( self.name + ": Uncaught exception!" )
3368 main.cleanup()
3369 main.exit()
3370
3371 def startHostCli( self, host=None ):
3372 """
3373 Use the mininet m utility to connect to the host's cli
3374 """
3375 # These are fields that can be used by scapy packets. Initialized to None
3376 self.hostIp = None
3377 self.hostMac = None
3378 try:
3379 if not host:
3380 host = self.name
3381 self.handle.sendline( self.home + "/util/m " + host )
3382 self.handle.expect( self.hostPrompt )
3383 return main.TRUE
3384 except pexpect.TIMEOUT:
3385 main.log.exception( self.name + ": Command timed out" )
3386 return main.FALSE
3387 except pexpect.EOF:
3388 main.log.exception( self.name + ": connection closed." )
3389 main.cleanup()
3390 main.exit()
3391 except Exception:
3392 main.log.exception( self.name + ": Uncaught exception!" )
3393 main.cleanup()
3394 main.exit()
3395
Jon Hall892818c2015-10-20 17:58:34 -07003396
adminbae64d82013-08-01 10:50:15 -07003397if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07003398 sys.modules[ __name__ ] = MininetCliDriver()