blob: 8165d3ab2762b8a6c3a5ff353830f2b2e7ff557d [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
adminbae64d82013-08-01 10:50:15 -070041
Jon Hall7eb38402015-01-08 17:19:54 -080042
kelvin-onlab50907142015-04-01 13:37:45 -070043class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080044
45 """
46 MininetCliDriver is the basic driver which will handle
47 the Mininet functions"""
48 def __init__( self ):
49 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070050 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080051 self.name = None
kelvin-onlabd9e23de2015-08-06 10:34:44 -070052 self.home = None
Jon Hall7eb38402015-01-08 17:19:54 -080053 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070054 self.flag = 0
Jon Hall892818c2015-10-20 17:58:34 -070055 # TODO: Refactor driver to use these everywhere
56 self.mnPrompt = "mininet>"
57 self.hostPrompt = "~#"
58 self.bashPrompt = "\$"
59 self.scapyPrompt = ">>>"
adminbae64d82013-08-01 10:50:15 -070060
Jon Hall7eb38402015-01-08 17:19:54 -080061 def connect( self, **connectargs ):
62 """
63 Here the main is the TestON instance after creating
64 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080065 try:
66 for key in connectargs:
67 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070068 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080069 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070070 for key in self.options:
71 if key == "home":
72 self.home = self.options[ 'home' ]
73 break
74 if self.home is None or self.home == "":
75 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070076
77 try:
Jon Hall892818c2015-10-20 17:58:34 -070078 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070079 self.ip_address = os.getenv( str( self.ip_address ) )
80 else:
81 main.log.info( self.name +
82 ": Trying to connect to " +
83 self.ip_address )
84
85 except KeyError:
86 main.log.info( "Invalid host name," +
87 " connecting to local host instead" )
88 self.ip_address = 'localhost'
89 except Exception as inst:
90 main.log.error( "Uncaught exception: " + str( inst ) )
91
kelvin-onlaba1484582015-02-02 15:46:20 -080092 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070093 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080094 self ).connect(
95 user_name=self.user_name,
96 ip_address=self.ip_address,
97 port=None,
98 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080099
kelvin-onlaba1484582015-02-02 15:46:20 -0800100 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -0800101 main.log.info( "Connection successful to the host " +
102 self.user_name +
103 "@" +
104 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800105 return main.TRUE
106 else:
107 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800108 self.user_name +
109 "@" +
110 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800111 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800112 return main.FALSE
113 except pexpect.EOF:
114 main.log.error( self.name + ": EOF exception found" )
115 main.log.error( self.name + ": " + self.handle.before )
116 main.cleanup()
117 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800118 except Exception:
119 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800120 main.cleanup()
121 main.exit()
122
kelvin-onlab10e8d392015-06-03 13:53:45 -0700123 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800124 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700125 Description:
126 Starts Mininet accepts a topology(.py) file and/or an optional
127 argument, to start the mininet, as a parameter.
128 Can also send regular mininet command to load up desired topology.
129 Eg. Pass in a string 'sudo mn --topo=tree,3,3' to mnCmd
130 Options:
131 topoFile = file path for topology file (.py)
132 args = extra option added when starting the topology from the file
133 mnCmd = Mininet command use to start topology
134 Returns:
135 main.TRUE if the mininet starts successfully, main.FALSE
136 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800137 """
Jon Hall7eb38402015-01-08 17:19:54 -0800138 if self.handle:
Jon Hall689d8e42015-04-03 13:59:24 -0700139 # make sure old networks are cleaned up
140 main.log.info( self.name +
141 ": Clearing any residual state or processes" )
Jon Hall7eb38402015-01-08 17:19:54 -0800142 self.handle.sendline( "sudo mn -c" )
143 i = self.handle.expect( [ 'password\sfor\s',
144 'Cleanup\scomplete',
145 pexpect.EOF,
146 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800147 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800148 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700149 # Sudo asking for password
Jon Hall7eb38402015-01-08 17:19:54 -0800150 main.log.info( self.name + ": Sending sudo password" )
151 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800152 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800153 '\$',
154 pexpect.EOF,
155 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800156 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800157 if i == 1:
158 main.log.info( self.name + ": Clean" )
159 elif i == 2:
160 main.log.error( self.name + ": Connection terminated" )
161 elif i == 3: # timeout
Jon Hall689d8e42015-04-03 13:59:24 -0700162 main.log.error( self.name + ": Something while cleaning " +
163 "Mininet took too long... " )
164 # Craft the string to start mininet
165 cmdString = "sudo "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700166 if not mnCmd:
167 if topoFile is None or topoFile == '': # If no file is given
168 main.log.info( self.name + ": building fresh Mininet" )
169 cmdString += "mn "
170 if args is None or args == '':
171 # If no args given, use args from .topo file
172 args = self.options[ 'arg1' ] +\
Jon Halld80cc142015-07-06 13:36:05 -0700173 " " + self.options[ 'arg2' ] +\
174 " --mac --controller " +\
175 self.options[ 'controller' ] + " " +\
176 self.options[ 'arg3' ]
kelvin-onlab10e8d392015-06-03 13:53:45 -0700177 else: # else only use given args
178 pass
179 # TODO: allow use of topo args and method args?
180 else: # Use given topology file
Jon Halld80cc142015-07-06 13:36:05 -0700181 main.log.info(
182 "Starting Mininet from topo file " +
183 topoFile )
Flavio Castrocc38a542016-03-03 13:15:46 -0800184 cmdString += "-E python " + topoFile + " "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700185 if args is None:
186 args = ''
187 # TODO: allow use of args from .topo file?
188 cmdString += args
189 else:
190 main.log.info( "Starting Mininet topology using '" + mnCmd +
191 "' command" )
192 cmdString += mnCmd
Jon Hall689d8e42015-04-03 13:59:24 -0700193 # Send the command and check if network started
194 self.handle.sendline( "" )
195 self.handle.expect( '\$' )
196 main.log.info( "Sending '" + cmdString + "' to " + self.name )
197 self.handle.sendline( cmdString )
198 while True:
Jon Hall7eb38402015-01-08 17:19:54 -0800199 i = self.handle.expect( [ 'mininet>',
Jon Hall689d8e42015-04-03 13:59:24 -0700200 'Exception',
201 '\*\*\*',
Jon Hallefbd9792015-03-05 16:11:36 -0800202 pexpect.EOF,
203 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700204 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800205 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700206 main.log.info( self.name + ": Mininet built" )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800207 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800208 elif i == 1:
Jon Hall689d8e42015-04-03 13:59:24 -0700209 response = str( self.handle.before +
210 self.handle.after )
211 self.handle.expect( '\$' )
212 response += str( self.handle.before +
Jon Halld80cc142015-07-06 13:36:05 -0700213 self.handle.after )
Jon Hall689d8e42015-04-03 13:59:24 -0700214 main.log.error(
215 self.name +
216 ": Launching Mininet failed: " + response )
217 return main.FALSE
218 elif i == 2:
219 self.handle.expect( [ "\n",
220 pexpect.EOF,
221 pexpect.TIMEOUT ],
222 timeout )
223 main.log.info( self.handle.before )
224 elif i == 3:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800225 main.log.error( self.name + ": Connection timeout" )
226 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700227 elif i == 4: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800228 main.log.error(
229 self.name +
230 ": Something took too long... " )
231 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700232 # Why did we hit this part?
233 main.log.error( "startNet did not return correctly" )
234 return main.FASLE
Jon Hall7eb38402015-01-08 17:19:54 -0800235 else: # if no handle
Jon Hall689d8e42015-04-03 13:59:24 -0700236 main.log.error( self.name + ": Connection failed to the host " +
237 self.user_name + "@" + self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800238 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700239 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800240
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800241 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400242 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800243 # In tree topology, if fanout arg is not given, by default it is 2
244 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400245 fanout = 2
246 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500247 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800248 while( k <= depth - 1 ):
249 count = count + pow( fanout, k )
250 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800251 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800252 while( k <= depth - 2 ):
253 # depth-2 gives you only core links and not considering
254 # edge links as seen by ONOS. If all the links including
255 # edge links are required, do depth-1
256 count = count + pow( fanout, k )
257 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800258 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800259 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800260 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800261
Jon Hall7eb38402015-01-08 17:19:54 -0800262 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800263 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800264 # by default it is 1
265 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400266 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800267 numSwitches = depth
268 numHostsPerSw = fanout
269 totalNumHosts = numSwitches * numHostsPerSw
270 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800271 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800272 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800273 topoDict = { "num_switches": int( numSwitches ),
274 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400275 return topoDict
276
kelvin-onlabd3b64892015-01-20 13:26:24 -0800277 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700278 """
279 Calculate the number of switches and links in a topo."""
280 # TODO: combine this function and numSwitchesNlinks
281 argList = self.options[ 'arg1' ].split( "," )
282 topoArgList = argList[ 0 ].split( " " )
283 argList = map( int, argList[ 1: ] )
284 topoArgList = topoArgList[ 1: ] + argList
285
286 topoDict = self.numSwitchesNlinks( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400287 return topoDict
288
GlennRCf07c44a2015-09-18 13:33:46 -0700289 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800290 """
291 Verifies the reachability of the hosts using pingall command.
292 Optional parameter timeout allows you to specify how long to
293 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700294 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700295 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700296 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700297 ping
298 acceptableFailed - Set the number of acceptable failed pings for the
299 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800300 Returns:
301 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700302 otherwise main.FALSE
303 """
304 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700305 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700306 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700307 if self.handle:
308 main.log.info(
309 self.name +
310 ": Checking reachabilty to the hosts using pingall" )
311 response = ""
312 failedPings = 0
313 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700314 cmd = "pingall"
315 if protocol == "IPv6":
316 cmd = "py net.pingAll6()"
317 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700318 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700319 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700320 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700321 pexpect.EOF,
322 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700323 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700324 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700325 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700326 response += self.handle.before
327 break
328 elif i == 1:
329 response += self.handle.before + self.handle.after
330 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700331 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700332 returnValue = main.FALSE
333 if shortCircuit:
334 main.log.error( self.name +
335 ": Aborting pingall - "
336 + str( failedPings ) +
337 " pings failed" )
338 break
Jon Hall390696c2015-05-05 17:13:41 -0700339 if ( time.time() - startTime ) > timeout:
340 returnValue = main.FALSE
341 main.log.error( self.name +
342 ": Aborting pingall - " +
343 "Function took too long " )
344 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700345 elif i == 2:
346 main.log.error( self.name +
347 ": EOF exception found" )
348 main.log.error( self.name + ": " +
349 self.handle.before )
350 main.cleanup()
351 main.exit()
352 elif i == 3:
353 response += self.handle.before
354 main.log.error( self.name +
355 ": TIMEOUT exception found" )
356 main.log.error( self.name +
357 ": " +
358 str( response ) )
359 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800360 self.handle.send( "\x03" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700361 self.handle.expect( "Interrupt" )
362 self.handle.expect( "mininet>" )
363 break
364 pattern = "Results\:"
365 main.log.info( "Pingall output: " + str( response ) )
366 if re.search( pattern, response ):
367 main.log.info( self.name + ": Pingall finished with "
368 + str( failedPings ) + " failed pings" )
369 return returnValue
370 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700371 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800372 self.handle.send( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700373 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700374 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700375 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700376 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700377 main.log.error( self.name + ": Connection failed to the host" )
378 main.cleanup()
379 main.exit()
380 except pexpect.TIMEOUT:
381 if response:
382 main.log.info( "Pingall output: " + str( response ) )
383 main.log.error( self.name + ": pexpect.TIMEOUT found" )
384 return main.FALSE
385 except pexpect.EOF:
386 main.log.error( self.name + ": EOF exception found" )
387 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500388 main.cleanup()
389 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700390
Jon Hall7eb38402015-01-08 17:19:54 -0800391 def fpingHost( self, **pingParams ):
392 """
393 Uses the fping package for faster pinging...
394 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800395 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800396 command = args[ "SRC" ] + \
397 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
398 self.handle.sendline( command )
399 self.handle.expect(
400 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
401 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
402 response = self.handle.before
403 if re.search( ":\s-", response ):
404 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700405 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800406 elif re.search( ":\s\d{1,2}\.\d\d", response ):
407 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700408 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800409 main.log.info( self.name + ": Install fping on mininet machine... " )
410 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700411 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800412
Jon Hall3b489db2015-10-05 14:38:37 -0700413 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400414 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700415 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700416
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400417 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700418 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700419
420 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400421 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700422
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400423 Returns main.FALSE if one or more of hosts specified
424 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700425 wait = int( wait )
426 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400427
428 try:
429 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700430
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400431 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700432 pingResponse = "IPv4 ping across specified hosts\n"
433 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400434 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700435 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400436 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700437 pingList = hostList[ :listIndex ] + \
438 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700439
440 pingResponse += str(str(host) + " -> ")
441
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400442 for temp in pingList:
443 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700444 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700445 self.handle.sendline( pingCmd )
446 self.handle.expect( "mininet>", timeout=wait + 1 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400447 response = self.handle.before
448 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRCd10d3cc2015-09-24 12:47:16 -0700449 pingResponse += str(" h" + str( temp[1:] ))
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400450 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700451 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400452 # One of the host to host pair is unreachable
453 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700454 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700455 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700456 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700457 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700458 except pexpect.TIMEOUT:
459 main.log.exception( self.name + ": TIMEOUT exception" )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700460 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400461 except pexpect.EOF:
462 main.log.error( self.name + ": EOF exception found" )
463 main.log.error( self.name + ": " + self.handle.before )
464 main.cleanup()
465 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700466 except Exception:
467 main.log.exception( self.name + ": Uncaught exception!" )
468 main.cleanup()
469 main.exit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400470
Jon Hall3b489db2015-10-05 14:38:37 -0700471 def pingIpv6Hosts( self, hostList, prefix='1000::', wait=1 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700472 """
Jon Hall3b489db2015-10-05 14:38:37 -0700473 IPv6 ping all hosts in hostList. If no prefix passed this will use
474 default prefix of 1000::
Hari Krishna9592fc82015-07-31 15:11:15 -0700475
Jon Hall3b489db2015-10-05 14:38:37 -0700476 Returns main.TRUE if all hosts specified can reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700477
Jon Hall3b489db2015-10-05 14:38:37 -0700478 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700479 """
480 try:
481 main.log.info( "Testing reachability between specified IPv6 hosts" )
482 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700483 wait = int( wait )
484 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700485 pingResponse = "IPv6 Pingall output:\n"
486 failedPings = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700487 for host in hostList:
488 listIndex = hostList.index( host )
489 # List of hosts to ping other than itself
490 pingList = hostList[ :listIndex ] + \
491 hostList[ ( listIndex + 1 ): ]
492
GlennRC2cf7d952015-09-11 16:32:13 -0700493 pingResponse += str(str(host) + " -> ")
494
Hari Krishna9592fc82015-07-31 15:11:15 -0700495 for temp in pingList:
496 # Current host pings all other hosts specified
Jon Hall439c8912016-04-15 02:22:03 -0700497 pingCmd = str( host ) + cmd + str( self.getIPAddress(temp,proto='IPv6') )
Jon Hall934576d2015-10-09 10:12:22 -0700498 self.handle.sendline( pingCmd )
499 self.handle.expect( "mininet>", timeout=wait + 1 )
Hari Krishna9592fc82015-07-31 15:11:15 -0700500 response = self.handle.before
501 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRC2cf7d952015-09-11 16:32:13 -0700502 pingResponse += str(" h" + str( temp[1:] ))
Hari Krishna9592fc82015-07-31 15:11:15 -0700503 else:
GlennRC2cf7d952015-09-11 16:32:13 -0700504 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700505 # One of the host to host pair is unreachable
506 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700507 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700508 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700509 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700510 return isReachable
511
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700512 except pexpect.TIMEOUT:
513 main.log.exception( self.name + ": TIMEOUT exception" )
514 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700515 except pexpect.EOF:
516 main.log.error( self.name + ": EOF exception found" )
517 main.log.error( self.name + ": " + self.handle.before )
518 main.cleanup()
519 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700520 except Exception:
521 main.log.exception( self.name + ": Uncaught exception!" )
522 main.cleanup()
523 main.exit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700524
Jon Hall7eb38402015-01-08 17:19:54 -0800525 def pingHost( self, **pingParams ):
526 """
Jon Hall3b489db2015-10-05 14:38:37 -0700527 Ping from one mininet host to another
528 Currently the only supported Params: SRC, TARGET, and WAIT
529 """
530 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
531 wait = args['WAIT']
532 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800533 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700534 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700535 try:
Jon Hall61282e32015-03-19 11:34:11 -0700536 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800537 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700538 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
539 timeout=wait + 1 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700540 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800541 main.log.error(
542 self.name +
543 ": timeout when waiting for response from mininet" )
544 main.log.error( "response: " + str( self.handle.before ) )
545 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700546 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800547 main.log.error(
548 self.name +
549 ": timeout when waiting for response from mininet" )
550 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700551 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700552 if re.search( ',\s0\%\spacket\sloss', response ):
553 main.log.info( self.name + ": no packets lost, host is reachable" )
554 return main.TRUE
555 else:
556 main.log.error(
557 self.name +
558 ": PACKET LOST, HOST IS NOT REACHABLE" )
559 return main.FALSE
560
Jon Hallfbc828e2015-01-06 17:30:19 -0800561 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800562 main.log.error( self.name + ": EOF exception found" )
563 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700564 main.cleanup()
565 main.exit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700566 except Exception:
567 main.log.exception( self.name + ": Uncaught exception!" )
568 main.cleanup()
569 main.exit()
570
571 def ping6pair( self, **pingParams ):
572 """
GlennRC2cf7d952015-09-11 16:32:13 -0700573 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700574 Currently the only supported Params are: SRC, TARGET, and WAIT
Hari Krishna012a1c12015-08-25 14:23:58 -0700575 FLOWLABEL and -I (src interface) will be added later after running some tests.
576 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
577 """
Jon Hall3b489db2015-10-05 14:38:37 -0700578 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
579 wait = args['WAIT']
580 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530581 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700582 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700583 try:
584 main.log.info( "Sending: " + command )
585 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700586 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
587 timeout=wait + 1 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700588 if i == 1:
589 main.log.error(
590 self.name +
591 ": timeout when waiting for response from mininet" )
592 main.log.error( "response: " + str( self.handle.before ) )
593 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
594 if i == 1:
595 main.log.error(
596 self.name +
597 ": timeout when waiting for response from mininet" )
598 main.log.error( "response: " + str( self.handle.before ) )
599 response = self.handle.before
600 main.log.info( self.name + ": Ping Response: " + response )
601 if re.search( ',\s0\%\spacket\sloss', response ):
602 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700603 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700604 else:
605 main.log.error(
606 self.name +
607 ": PACKET LOST, HOST IS NOT REACHABLE" )
608 return main.FALSE
609
610 except pexpect.EOF:
611 main.log.error( self.name + ": EOF exception found" )
612 main.log.error( self.name + ": " + self.handle.before )
613 main.cleanup()
614 main.exit()
615 except Exception:
616 main.log.exception( self.name + ": Uncaught exception!" )
617 main.cleanup()
618 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800619
You Wangdb927a52016-02-26 11:03:28 -0800620 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
621 """
622 Description:
623 Ping a set of destination host from host CLI.
624 Logging into a Mininet host CLI is required before calling this funtion.
625 Params:
626 dstIPList is a list of destination ip addresses
627 Returns:
628 main.TRUE if the destination host is reachable
629 main.FALSE otherwise
630 """
631 isReachable = main.TRUE
632 wait = int( wait )
633 cmd = "ping"
634 if IPv6:
635 cmd = cmd + "6"
636 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
637 try:
638 for dstIP in dstIPList:
639 pingCmd = cmd + " " + dstIP
640 self.handle.sendline( pingCmd )
641 i = self.handle.expect( [ self.hostPrompt,
642 '\*\*\* Unknown command: ' + pingCmd,
643 pexpect.TIMEOUT ],
644 timeout=wait + 1 )
645 if i == 0:
646 response = self.handle.before
647 if not re.search( ',\s0\%\spacket\sloss', response ):
648 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
649 isReachable = main.FALSE
650 elif i == 1:
651 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
652 main.cleanup()
653 main.exit()
654 elif i == 2:
655 main.log.error( self.name + ": timeout when waiting for response" )
656 isReachable = main.FALSE
657 else:
658 main.log.error( self.name + ": unknown response: " + self.handle.before )
659 isReachable = main.FALSE
660 except pexpect.TIMEOUT:
661 main.log.exception( self.name + ": TIMEOUT exception" )
662 isReachable = main.FALSE
663 except pexpect.EOF:
664 main.log.error( self.name + ": EOF exception found" )
665 main.log.error( self.name + ": " + self.handle.before )
666 main.cleanup()
667 main.exit()
668 except Exception:
669 main.log.exception( self.name + ": Uncaught exception!" )
670 main.cleanup()
671 main.exit()
672 return isReachable
673
Jon Hall7eb38402015-01-08 17:19:54 -0800674 def checkIP( self, host ):
675 """
676 Verifies the host's ip configured or not."""
677 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700678 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800679 response = self.execute(
680 cmd=host +
681 " ifconfig",
682 prompt="mininet>",
683 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800684 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800685 main.log.error( self.name + ": EOF exception found" )
686 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700687 main.cleanup()
688 main.exit()
adminbae64d82013-08-01 10:50:15 -0700689
Jon Hall7eb38402015-01-08 17:19:54 -0800690 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800691 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
692 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
693 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
694 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
695 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800696 # pattern = "inet addr:10.0.0.6"
697 if re.search( pattern, response ):
698 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700699 return main.TRUE
700 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800701 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700702 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800703 else:
704 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800705
Jon Hall7eb38402015-01-08 17:19:54 -0800706 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800707 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700708 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800709 response = self.execute(
710 cmd="h1 /usr/sbin/sshd -D&",
711 prompt="mininet>",
712 timeout=10 )
713 response = self.execute(
714 cmd="h4 /usr/sbin/sshd -D&",
715 prompt="mininet>",
716 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700717 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800718 vars( self )[ key ] = connectargs[ key ]
719 response = self.execute(
720 cmd="xterm h1 h4 ",
721 prompt="mininet>",
722 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800723 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800724 main.log.error( self.name + ": EOF exception found" )
725 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700726 main.cleanup()
727 main.exit()
adminbae64d82013-08-01 10:50:15 -0700728 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800729 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700730 if self.flag == 0:
731 self.flag = 1
732 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800733 else:
adminbae64d82013-08-01 10:50:15 -0700734 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800735
Jon Hall53c5e662016-04-13 16:06:56 -0700736 def moveHost( self, host, oldSw, newSw, ):
737 """
738 Moves a host from one switch to another on the fly
739 Note: The intf between host and oldSw when detached
740 using detach(), will still show up in the 'net'
741 cmd, because switch.detach() doesn't affect switch.intfs[]
742 ( which is correct behavior since the interfaces
743 haven't moved ).
744 """
745 if self.handle:
746 try:
747 # Bring link between oldSw-host down
748 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
749 "'," + "'down')"
750 print "cmd1= ", cmd
751 response = self.execute( cmd=cmd,
752 prompt="mininet>",
753 timeout=10 )
754
755 # Determine hostintf and Oldswitchintf
756 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
757 ")[0]"
758 print "cmd2= ", cmd
759 self.handle.sendline( cmd )
760 self.handle.expect( "mininet>" )
761
762 # Determine ip and mac address of the host-oldSw interface
763 cmd = "px ipaddr = hintf.IP()"
764 print "cmd3= ", cmd
765 self.handle.sendline( cmd )
766 self.handle.expect( "mininet>" )
767
768 cmd = "px macaddr = hintf.MAC()"
769 print "cmd3= ", cmd
770 self.handle.sendline( cmd )
771 self.handle.expect( "mininet>" )
772
773 # Detach interface between oldSw-host
774 cmd = "px " + oldSw + ".detach( sintf )"
775 print "cmd4= ", cmd
776 self.handle.sendline( cmd )
777 self.handle.expect( "mininet>" )
778
779 # Add link between host-newSw
780 cmd = "py net.addLink(" + host + "," + newSw + ")"
781 print "cmd5= ", cmd
782 self.handle.sendline( cmd )
783 self.handle.expect( "mininet>" )
784
785 # Determine hostintf and Newswitchintf
786 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
787 ")[0]"
788 print "cmd6= ", cmd
789 self.handle.sendline( cmd )
790 self.handle.expect( "mininet>" )
791
792 # Attach interface between newSw-host
793 cmd = "px " + newSw + ".attach( sintf )"
794 print "cmd3= ", cmd
795 self.handle.sendline( cmd )
796 self.handle.expect( "mininet>" )
797
798 # Set ipaddress of the host-newSw interface
799 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
800 print "cmd7 = ", cmd
801 self.handle.sendline( cmd )
802 self.handle.expect( "mininet>" )
803
804 # Set macaddress of the host-newSw interface
805 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
806 print "cmd8 = ", cmd
807 self.handle.sendline( cmd )
808 self.handle.expect( "mininet>" )
809
810 cmd = "net"
811 print "cmd9 = ", cmd
812 self.handle.sendline( cmd )
813 self.handle.expect( "mininet>" )
814 print "output = ", self.handle.before
815
816 # Determine ipaddress of the host-newSw interface
817 cmd = host + " ifconfig"
818 print "cmd10= ", cmd
819 self.handle.sendline( cmd )
820 self.handle.expect( "mininet>" )
821 print "ifconfig o/p = ", self.handle.before
822
823 return main.TRUE
824 except pexpect.EOF:
825 main.log.error( self.name + ": EOF exception found" )
826 main.log.error( self.name + ": " + self.handle.before )
827 return main.FALSE
828
Jon Hall439c8912016-04-15 02:22:03 -0700829 def moveHostv6( self, host, oldSw, newSw, ):
kelvin-onlaba1484582015-02-02 15:46:20 -0800830 """
831 Moves a host from one switch to another on the fly
832 Note: The intf between host and oldSw when detached
833 using detach(), will still show up in the 'net'
834 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700835 ( which is correct behavior since the interfaces
836 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800837 """
838 if self.handle:
839 try:
Jon Hall439c8912016-04-15 02:22:03 -0700840 IP = str( self.getIPAddress( host, proto='IPV6' ) ) + "/64"
kelvin-onlaba1484582015-02-02 15:46:20 -0800841 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700842 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800843 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800844 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800845 response = self.execute( cmd=cmd,
846 prompt="mininet>",
847 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700848
kelvin-onlaba1484582015-02-02 15:46:20 -0800849 # Determine hostintf and Oldswitchintf
850 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800851 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800852 print "cmd2= ", cmd
853 self.handle.sendline( cmd )
854 self.handle.expect( "mininet>" )
855
shahshreya73537862015-02-11 15:15:24 -0800856 # Determine ip and mac address of the host-oldSw interface
Jon Hall439c8912016-04-15 02:22:03 -0700857 cmd = "px ipaddr = " + str(IP)
kelvin-onlaba1484582015-02-02 15:46:20 -0800858 print "cmd3= ", cmd
859 self.handle.sendline( cmd )
860 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800861
862 cmd = "px macaddr = hintf.MAC()"
863 print "cmd3= ", cmd
864 self.handle.sendline( cmd )
865 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700866
kelvin-onlaba1484582015-02-02 15:46:20 -0800867 # Detach interface between oldSw-host
868 cmd = "px " + oldSw + ".detach( sintf )"
869 print "cmd4= ", cmd
870 self.handle.sendline( cmd )
871 self.handle.expect( "mininet>" )
872
873 # Add link between host-newSw
874 cmd = "py net.addLink(" + host + "," + newSw + ")"
875 print "cmd5= ", cmd
876 self.handle.sendline( cmd )
877 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700878
kelvin-onlaba1484582015-02-02 15:46:20 -0800879 # Determine hostintf and Newswitchintf
880 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800881 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800882 print "cmd6= ", cmd
883 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700884 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800885
886 # Attach interface between newSw-host
887 cmd = "px " + newSw + ".attach( sintf )"
Jon Hall439c8912016-04-15 02:22:03 -0700888 print "cmd6= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800889 self.handle.sendline( cmd )
890 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800891
892 # Set macaddress of the host-newSw interface
893 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
Jon Hall439c8912016-04-15 02:22:03 -0700894 print "cmd7 = ", cmd
895 self.handle.sendline( cmd )
896 self.handle.expect( "mininet>" )
897
898 # Set ipaddress of the host-newSw interface
899 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
shahshreya73537862015-02-11 15:15:24 -0800900 print "cmd8 = ", cmd
901 self.handle.sendline( cmd )
902 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700903
Jon Hall439c8912016-04-15 02:22:03 -0700904 cmd = host + " ifconfig"
905 print "cmd9 =",cmd
906 response = self.execute( cmd = cmd, prompt="mininet>" ,timeout=10 )
907 print response
908 pattern = "h\d-eth([\w])"
Jeremyd9e4eb12016-04-13 12:09:06 -0700909 ipAddressSearch = re.search( pattern, response )
Jon Hall439c8912016-04-15 02:22:03 -0700910 print ipAddressSearch.group(1)
911 intf= host + "-eth" + str(ipAddressSearch.group(1))
912 cmd = host + " ip -6 addr add %s dev %s" % ( IP, intf )
913 print "cmd10 = ", cmd
914 self.handle.sendline( cmd )
915 self.handle.expect( "mininet>" )
916
kelvin-onlaba1484582015-02-02 15:46:20 -0800917 cmd = "net"
Jon Hall439c8912016-04-15 02:22:03 -0700918 print "cmd11 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800919 self.handle.sendline( cmd )
920 self.handle.expect( "mininet>" )
921 print "output = ", self.handle.before
922
923 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800924 cmd = host + " ifconfig"
Jon Hall439c8912016-04-15 02:22:03 -0700925 print "cmd12= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800926 self.handle.sendline( cmd )
927 self.handle.expect( "mininet>" )
928 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700929
kelvin-onlaba1484582015-02-02 15:46:20 -0800930 return main.TRUE
931 except pexpect.EOF:
932 main.log.error( self.name + ": EOF exception found" )
933 main.log.error( self.name + ": " + self.handle.before )
934 return main.FALSE
935
Jon Hall7eb38402015-01-08 17:19:54 -0800936 def changeIP( self, host, intf, newIP, newNetmask ):
937 """
938 Changes the ip address of a host on the fly
939 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800940 if self.handle:
941 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800942 cmd = host + " ifconfig " + intf + " " + \
943 newIP + " " + 'netmask' + " " + newNetmask
944 self.handle.sendline( cmd )
945 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800946 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800947 main.log.info( "response = " + response )
948 main.log.info(
949 "Ip of host " +
950 host +
951 " changed to new IP " +
952 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800953 return main.TRUE
954 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800955 main.log.error( self.name + ": EOF exception found" )
956 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800957 return main.FALSE
958
Jon Hall7eb38402015-01-08 17:19:54 -0800959 def changeDefaultGateway( self, host, newGW ):
960 """
961 Changes the default gateway of a host
962 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800963 if self.handle:
964 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800965 cmd = host + " route add default gw " + newGW
966 self.handle.sendline( cmd )
967 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800968 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800969 main.log.info( "response = " + response )
970 main.log.info(
971 "Default gateway of host " +
972 host +
973 " changed to " +
974 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800975 return main.TRUE
976 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800977 main.log.error( self.name + ": EOF exception found" )
978 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800979 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800980
Jon Hall7eb38402015-01-08 17:19:54 -0800981 def addStaticMACAddress( self, host, GW, macaddr ):
982 """
Jon Hallefbd9792015-03-05 16:11:36 -0800983 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800984 if self.handle:
985 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800986 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
987 cmd = host + " arp -s " + GW + " " + macaddr
988 self.handle.sendline( cmd )
989 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800990 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800991 main.log.info( "response = " + response )
992 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800993 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800994 GW +
995 " changed to " +
996 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800997 return main.TRUE
998 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800999 main.log.error( self.name + ": EOF exception found" )
1000 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001001 return main.FALSE
1002
Jon Hall7eb38402015-01-08 17:19:54 -08001003 def verifyStaticGWandMAC( self, host ):
1004 """
1005 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001006 if self.handle:
1007 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001008 # h1 arp -an
1009 cmd = host + " arp -an "
1010 self.handle.sendline( cmd )
1011 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001012 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001013 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001014 return main.TRUE
1015 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001016 main.log.error( self.name + ": EOF exception found" )
1017 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001018 return main.FALSE
1019
Jon Hall7eb38402015-01-08 17:19:54 -08001020 def getMacAddress( self, host ):
1021 """
1022 Verifies the host's ip configured or not."""
1023 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001024 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001025 response = self.execute(
1026 cmd=host +
1027 " ifconfig",
1028 prompt="mininet>",
1029 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001030 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001031 main.log.error( self.name + ": EOF exception found" )
1032 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001033 main.cleanup()
1034 main.exit()
adminbae64d82013-08-01 10:50:15 -07001035
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001036 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001037 macAddressSearch = re.search( pattern, response, re.I )
1038 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001039 main.log.info(
1040 self.name +
1041 ": Mac-Address of Host " +
1042 host +
1043 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001044 macAddress )
1045 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001046 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001047 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001048
Jon Hall7eb38402015-01-08 17:19:54 -08001049 def getInterfaceMACAddress( self, host, interface ):
1050 """
1051 Return the IP address of the interface on the given host"""
1052 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001053 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001054 response = self.execute( cmd=host + " ifconfig " + interface,
1055 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001056 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001057 main.log.error( self.name + ": EOF exception found" )
1058 main.log.error( self.name + ": " + self.handle.before )
1059 main.cleanup()
1060 main.exit()
1061
1062 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001063 macAddressSearch = re.search( pattern, response, re.I )
1064 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001065 main.log.info( "No mac address found in %s" % response )
1066 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001067 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001068 main.log.info(
1069 "Mac-Address of " +
1070 host +
1071 ":" +
1072 interface +
1073 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001074 macAddress )
1075 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001076 else:
1077 main.log.error( "Connection failed to the host" )
1078
sathishmad953462015-12-03 17:42:07 +05301079 def getIPAddress( self, host , proto='IPV4'):
Jon Hall7eb38402015-01-08 17:19:54 -08001080 """
1081 Verifies the host's ip configured or not."""
1082 if self.handle:
1083 try:
1084 response = self.execute(
1085 cmd=host +
1086 " ifconfig",
1087 prompt="mininet>",
1088 timeout=10 )
1089 except pexpect.EOF:
1090 main.log.error( self.name + ": EOF exception found" )
1091 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001092 main.cleanup()
1093 main.exit()
adminbae64d82013-08-01 10:50:15 -07001094
sathishmad953462015-12-03 17:42:07 +05301095 pattern = ''
1096 if proto == 'IPV4':
1097 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
1098 else:
Jon Hall439c8912016-04-15 02:22:03 -07001099 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001100 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -08001101 main.log.info(
1102 self.name +
1103 ": IP-Address of Host " +
1104 host +
1105 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001106 ipAddressSearch.group( 1 ) )
1107 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001108 else:
1109 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001110
Jon Hall7eb38402015-01-08 17:19:54 -08001111 def getSwitchDPID( self, switch ):
1112 """
1113 return the datapath ID of the switch"""
1114 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001115 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001116 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001117 response = self.execute(
1118 cmd=cmd,
1119 prompt="mininet>",
1120 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001121 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001122 main.log.error( self.name + ": EOF exception found" )
1123 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001124 main.cleanup()
1125 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001126 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001127 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001128 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001129 main.log.info(
1130 "Couldn't find DPID for switch %s, found: %s" %
1131 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001132 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001133 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001134 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001135 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001136
Jon Hall7eb38402015-01-08 17:19:54 -08001137 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001138 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001139 self.handle.sendline( "" )
1140 self.expect( "mininet>" )
1141 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001142 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001143 response = self.execute(
1144 cmd=cmd,
1145 prompt="mininet>",
1146 timeout=10 )
1147 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001148 response = self.handle.before
1149 return response
1150 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001151 main.log.error( self.name + ": EOF exception found" )
1152 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -07001153 main.cleanup()
1154 main.exit()
1155
Jon Hall7eb38402015-01-08 17:19:54 -08001156 def getInterfaces( self, node ):
1157 """
1158 return information dict about interfaces connected to the node"""
1159 if self.handle:
1160 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001161 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001162 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001163 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001164 response = self.execute(
1165 cmd=cmd,
1166 prompt="mininet>",
1167 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001168 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001169 main.log.error( self.name + ": EOF exception found" )
1170 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001171 main.cleanup()
1172 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001173 return response
1174 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001175 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001176
Jon Hall7eb38402015-01-08 17:19:54 -08001177 def dump( self ):
1178 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001179 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001180 response = self.execute(
1181 cmd='dump',
1182 prompt='mininet>',
1183 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001184 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001185 main.log.error( self.name + ": EOF exception found" )
1186 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001187 main.cleanup()
1188 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001189 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001190
Jon Hall7eb38402015-01-08 17:19:54 -08001191 def intfs( self ):
1192 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001193 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001194 response = self.execute(
1195 cmd='intfs',
1196 prompt='mininet>',
1197 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001198 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001199 main.log.error( self.name + ": EOF exception found" )
1200 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001201 main.cleanup()
1202 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001203 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001204
Jon Hall7eb38402015-01-08 17:19:54 -08001205 def net( self ):
1206 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001207 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001208 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001209 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001210 main.log.error( self.name + ": EOF exception found" )
1211 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001212 main.cleanup()
1213 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001214 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001215
YPZhang81a7d4e2016-04-18 13:10:17 -07001216 def links( self, timeout=20 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001217 main.log.info( self.name + ": List network links" )
1218 try:
1219 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001220 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001221 except pexpect.EOF:
1222 main.log.error( self.name + ": EOF exception found" )
1223 main.log.error( self.name + ": " + self.handle.before )
1224 main.cleanup()
1225 main.exit()
1226 return response
1227
GlennRC61321f22015-07-16 13:36:54 -07001228 def iperftcpAll(self, hosts, timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001229 '''
1230 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001231
kelvin-onlab7cce9382015-07-17 10:21:03 -07001232 @parm:
1233 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1234 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1235 '''
1236 for host1 in hosts:
1237 for host2 in hosts:
1238 if host1 != host2:
1239 if self.iperftcp(host1, host2, timeout) == main.FALSE:
1240 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
GlennRC61321f22015-07-16 13:36:54 -07001241
1242 def iperftcp(self, host1="h1", host2="h2", timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001243 '''
1244 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1245 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001246
kelvin-onlab7cce9382015-07-17 10:21:03 -07001247 @parm:
1248 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1249 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1250 '''
1251 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1252 try:
1253 # Setup the mininet command
1254 cmd1 = 'iperf ' + host1 + " " + host2
1255 self.handle.sendline( cmd1 )
1256 outcome = self.handle.expect( "mininet>", timeout )
1257 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001258
kelvin-onlab7cce9382015-07-17 10:21:03 -07001259 # checks if there are results in the mininet response
1260 if "Results:" in response:
Jon Hall892818c2015-10-20 17:58:34 -07001261 main.log.report(self.name + ": iperf test completed")
kelvin-onlab7cce9382015-07-17 10:21:03 -07001262 # parse the mn results
1263 response = response.split("\r\n")
1264 response = response[len(response)-2]
1265 response = response.split(": ")
1266 response = response[len(response)-1]
1267 response = response.replace("[", "")
1268 response = response.replace("]", "")
1269 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001270
kelvin-onlab7cce9382015-07-17 10:21:03 -07001271 # this is the bandwith two and from the two hosts
1272 bandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001273
kelvin-onlab7cce9382015-07-17 10:21:03 -07001274 # there should be two elements in the bandwidth list
1275 # ['host1 to host2', 'host2 to host1"]
1276 if len(bandwidth) == 2:
1277 main.log.report(self.name + ": iperf test successful")
1278 return main.TRUE
1279 else:
1280 main.log.error(self.name + ": invalid iperf results")
1281 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001282 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001283 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001284 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001285 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001286 main.log.error( self.name + ": TIMEOUT exception found" )
1287 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001288 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001289 # NOTE: Send ctrl-c to make sure iperf is done
1290 self.handle.sendline( "\x03" )
1291 self.handle.expect( "Interrupt" )
1292 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001293 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001294 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001295 main.log.error( self.name + ": EOF exception found" )
1296 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001297 main.cleanup()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001298 main.exit()
GlennRC61321f22015-07-16 13:36:54 -07001299
Jon Hall439c8912016-04-15 02:22:03 -07001300 def iperftcpipv6(self, host1="h1", host2="h2", timeout=50):
1301 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1302 try:
1303 IP1 = self.getIPAddress( host1, proto='IPV6' )
1304 cmd1 = host1 +' iperf -V -sD -B '+ str(IP1)
1305 self.handle.sendline( cmd1 )
1306 outcome1 = self.handle.expect( "mininet>")
1307 cmd2 = host2 +' iperf -V -c '+ str(IP1) +' -t 5'
1308 self.handle.sendline( cmd2 )
1309 outcome2 = self.handle.expect( "mininet>")
1310 response1 = self.handle.before
1311 response2 = self.handle.after
1312 print response1,response2
1313 pattern = "connected with "+ str(IP1)
1314 if pattern in response1:
1315 main.log.report(self.name + ": iperf test completed")
1316 return main.TRUE
1317 else:
1318 main.log.error( self.name + ": iperf test failed" )
1319 return main.FALSE
1320 except pexpect.TIMEOUT:
1321 main.log.error( self.name + ": TIMEOUT exception found" )
1322 main.log.error( self.name + " response: " + repr( self.handle.before ) )
1323 self.handle.sendline( "\x03" )
1324 self.handle.expect( "Interrupt" )
1325 self.handle.expect( "mininet>" )
1326 return main.FALSE
1327 except pexpect.EOF:
1328 main.log.error( self.name + ": EOF exception found" )
1329 main.log.error( self.name + ": " + self.handle.before )
1330 main.cleanup()
1331 main.exit()
1332
GlennRC61321f22015-07-16 13:36:54 -07001333 def iperfudpAll(self, hosts, bandwidth="10M"):
1334 '''
1335 Runs the iperfudp function with a given set of hosts and specified
1336 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001337
GlennRC61321f22015-07-16 13:36:54 -07001338 @param:
1339 bandwidth: the targeted bandwidth, in megabits ('M')
1340 '''
1341 for host1 in hosts:
1342 for host2 in hosts:
1343 if host1 != host2:
1344 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1345 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1346
1347 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1348
kelvin-onlab7cce9382015-07-17 10:21:03 -07001349 '''
1350 Creates an iperf UDP test with a specific bandwidth.
1351 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001352
kelvin-onlab7cce9382015-07-17 10:21:03 -07001353 @param:
1354 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1355 '''
1356 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1357 try:
1358 # setup the mininet command
1359 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1360 self.handle.sendline(cmd)
1361 self.handle.expect("mininet>")
1362 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001363
kelvin-onlab7cce9382015-07-17 10:21:03 -07001364 # check if there are in results in the mininet response
1365 if "Results:" in response:
Jon Hall892818c2015-10-20 17:58:34 -07001366 main.log.report(self.name + ": iperfudp test completed")
kelvin-onlab7cce9382015-07-17 10:21:03 -07001367 # parse the results
1368 response = response.split("\r\n")
1369 response = response[len(response)-2]
1370 response = response.split(": ")
1371 response = response[len(response)-1]
1372 response = response.replace("[", "")
1373 response = response.replace("]", "")
1374 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001375
kelvin-onlab7cce9382015-07-17 10:21:03 -07001376 mnBandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001377
kelvin-onlab7cce9382015-07-17 10:21:03 -07001378 # check to see if there are at least three entries
1379 # ['bandwidth', 'host1 to host2', 'host2 to host1']
1380 if len(mnBandwidth) == 3:
1381 # if one entry is blank then something is wrong
1382 for item in mnBandwidth:
1383 if item == "":
1384 main.log.error(self.name + ": Could not parse iperf output")
1385 main.log.error(self.name + ": invalid iperfudp results")
1386 return main.FALSE
1387 # otherwise results are vaild
1388 main.log.report(self.name + ": iperfudp test successful")
1389 return main.TRUE
1390 else:
1391 main.log.error(self.name + ": invalid iperfudp results")
1392 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001393
kelvin-onlab7cce9382015-07-17 10:21:03 -07001394 except pexpect.EOF:
1395 main.log.error( self.name + ": EOF exception found" )
1396 main.log.error( self.name + ": " + self.handle.before )
1397 main.cleanup()
1398 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001399
Jon Hall7eb38402015-01-08 17:19:54 -08001400 def nodes( self ):
1401 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001402 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001403 response = self.execute(
1404 cmd='nodes',
1405 prompt='mininet>',
1406 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001407 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001408 main.log.error( self.name + ": EOF exception found" )
1409 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001410 main.cleanup()
1411 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001412 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001413
Jon Hall7eb38402015-01-08 17:19:54 -08001414 def pingpair( self ):
1415 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001416 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001417 response = self.execute(
1418 cmd='pingpair',
1419 prompt='mininet>',
1420 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001421 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001422 main.log.error( self.name + ": EOF exception found" )
1423 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001424 main.cleanup()
1425 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001426
Jon Hall7eb38402015-01-08 17:19:54 -08001427 if re.search( ',\s0\%\spacket\sloss', response ):
1428 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001429 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001430 else:
1431 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001432 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001433
Jon Hall7eb38402015-01-08 17:19:54 -08001434 def link( self, **linkargs ):
1435 """
GlennRCed771242016-01-13 17:02:47 -08001436 Bring link( s ) between two nodes up or down
1437 """
Jon Hall6094a362014-04-11 14:46:56 -07001438 try:
GlennRCed771242016-01-13 17:02:47 -08001439 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1440 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1441 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1442 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1443
1444 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1445 cmd = "link {} {} {}".format( end1, end2, option )
1446 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001447 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001448 response = self.handle.before
1449 main.log.info( response )
1450
1451 return main.TRUE
1452 except pexpect.TIMEOUT:
1453 main.log.exception( self.name + ": Command timed out" )
1454 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001455 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001456 main.log.exception( self.name + ": connection closed." )
Jon Hall6094a362014-04-11 14:46:56 -07001457 main.cleanup()
1458 main.exit()
GlennRCed771242016-01-13 17:02:47 -08001459 except Exception:
1460 main.log.exception( self.name + ": Uncaught exception!" )
1461 main.cleanup()
1462 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001463
pingping-lin8244a3b2015-09-16 13:36:56 -07001464 def switch( self, **switchargs ):
1465 """
1466 start/stop a switch
1467 """
1468 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1469 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1470 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1471 command = "switch " + str( sw ) + " " + str( option )
1472 main.log.info( command )
1473 try:
1474 self.handle.sendline( command )
1475 self.handle.expect( "mininet>" )
1476 except pexpect.TIMEOUT:
1477 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1478 main.cleanup()
1479 main.exit()
1480 except pexpect.EOF:
1481 main.log.error( self.name + ": EOF exception found" )
1482 main.log.error( self.name + ": " + self.handle.before )
1483 main.cleanup()
1484 main.exit()
1485 return main.TRUE
1486
pingping-lin5bb663b2015-09-24 11:47:50 -07001487 def node( self, nodeName, commandStr ):
1488 """
1489 Carry out a command line on a given node
1490 @parm:
1491 nodeName: the node name in Mininet testbed
1492 commandStr: the command line will be carried out on the node
1493 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1494 """
1495 command = str( nodeName ) + " " + str( commandStr )
1496 main.log.info( command )
1497
1498 try:
1499 response = self.execute( cmd = command, prompt = "mininet>" )
1500 if re.search( "Unknown command", response ):
1501 main.log.warn( response )
1502 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001503 if re.search( "Permission denied", response ):
1504 main.log.warn( response )
1505 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001506 except pexpect.TIMEOUT:
1507 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1508 main.cleanup()
1509 main.exit()
1510 except pexpect.EOF:
1511 main.log.error( self.name + ": EOF exception found" )
1512 main.log.error( self.name + ": " + self.handle.before )
1513 main.cleanup()
1514 main.exit()
1515 main.log.info( " response is :" )
1516 main.log.info( response )
1517 return response
1518
Jon Hall7eb38402015-01-08 17:19:54 -08001519 def yank( self, **yankargs ):
1520 """
1521 yank a mininet switch interface to a host"""
1522 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001523 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001524 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1525 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1526 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001527 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001528 response = self.execute(
1529 cmd=command,
1530 prompt="mininet>",
1531 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001532 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001533 main.log.error( self.name + ": EOF exception found" )
1534 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001535 main.cleanup()
1536 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001537 return main.TRUE
1538
Jon Hall7eb38402015-01-08 17:19:54 -08001539 def plug( self, **plugargs ):
1540 """
1541 plug the yanked mininet switch interface to a switch"""
1542 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001543 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001544 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1545 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1546 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001547 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001548 response = self.execute(
1549 cmd=command,
1550 prompt="mininet>",
1551 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001552 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001553 main.log.error( self.name + ": EOF exception found" )
1554 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001555 main.cleanup()
1556 main.exit()
adminbae64d82013-08-01 10:50:15 -07001557 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001558
Jon Hall7eb38402015-01-08 17:19:54 -08001559 def dpctl( self, **dpctlargs ):
1560 """
1561 Run dpctl command on all switches."""
1562 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001563 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001564 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1565 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1566 command = "dpctl " + cmd + " " + str( cmdargs )
1567 try:
1568 response = self.execute(
1569 cmd=command,
1570 prompt="mininet>",
1571 timeout=10 )
1572 except pexpect.EOF:
1573 main.log.error( self.name + ": EOF exception found" )
1574 main.log.error( self.name + ": " + self.handle.before )
1575 main.cleanup()
1576 main.exit()
1577 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001578
kelvin-onlabd3b64892015-01-20 13:26:24 -08001579 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001580 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001581 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001582 fileInput = path + '/lib/Mininet/INSTALL'
1583 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001584 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001585 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001586 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001587 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001588 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001589 return version
adminbae64d82013-08-01 10:50:15 -07001590
kelvin-onlabd3b64892015-01-20 13:26:24 -08001591 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001592 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001593 Parameters:
1594 sw: The name of an OVS switch. Example "s1"
1595 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001596 The output of the command from the mininet cli
1597 or main.FALSE on timeout"""
1598 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001599 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001600 response = self.execute(
1601 cmd=command,
1602 prompt="mininet>",
1603 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001604 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001605 return response
admin2a9548d2014-06-17 14:08:07 -07001606 else:
1607 return main.FALSE
1608 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001609 main.log.error( self.name + ": EOF exception found" )
1610 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001611 main.cleanup()
1612 main.exit()
adminbae64d82013-08-01 10:50:15 -07001613
Charles Chan029be652015-08-24 01:46:10 +08001614 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001615 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001616 Description:
1617 Assign switches to the controllers ( for ovs use only )
1618 Required:
1619 sw - Name of the switch. This can be a list or a string.
1620 ip - Ip addresses of controllers. This can be a list or a string.
1621 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001622 port - ONOS use port 6653, if no list of ports is passed, then
1623 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001624 ptcp - ptcp number, This can be a string or a list that has
1625 the same length as switch. This is optional and not required
1626 when using ovs switches.
1627 NOTE: If switches and ptcp are given in a list type they should have the
1628 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1629 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001630
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001631 Return:
1632 Returns main.TRUE if mininet correctly assigned switches to
1633 controllers, otherwise it will return main.FALSE or an appropriate
1634 exception(s)
1635 """
1636 assignResult = main.TRUE
1637 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001638 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001639 command = "sh ovs-vsctl set-controller "
1640 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001641 try:
1642 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001643 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001644 if isinstance( port, types.StringType ) or \
1645 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001646 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001647 elif isinstance( port, types.ListType ):
1648 main.log.error( self.name + ": Only one controller " +
1649 "assigned and a list of ports has" +
1650 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001651 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001652 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001653 main.log.error( self.name + ": Invalid controller port " +
1654 "number. Please specify correct " +
1655 "controller port" )
1656 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001657
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001658 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001659 if isinstance( port, types.StringType ) or \
1660 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001661 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001662 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1663 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001664 elif isinstance( port, types.ListType ):
1665 if ( len( ip ) != len( port ) ):
1666 main.log.error( self.name + ": Port list = " +
1667 str( len( port ) ) +
1668 "should be the same as controller" +
1669 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001670 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001671 else:
1672 onosIp = ""
1673 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001674 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1675 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001676 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001677 main.log.error( self.name + ": Invalid controller port " +
1678 "number. Please specify correct " +
1679 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001680 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001681 else:
1682 main.log.error( self.name + ": Invalid ip address" )
1683 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001684
1685 if isinstance( sw, types.StringType ):
1686 command += sw + " "
1687 if ptcp:
1688 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001689 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001690 elif isinstance( ptcp, types.ListType ):
1691 main.log.error( self.name + ": Only one switch is " +
1692 "being set and multiple PTCP is " +
1693 "being passed " )
1694 else:
1695 main.log.error( self.name + ": Invalid PTCP" )
1696 ptcp = ""
1697 command += onosIp
1698 commandList.append( command )
1699
1700 elif isinstance( sw, types.ListType ):
1701 if ptcp:
1702 if isinstance( ptcp, types.ListType ):
1703 if len( ptcp ) != len( sw ):
1704 main.log.error( self.name + ": PTCP length = " +
1705 str( len( ptcp ) ) +
1706 " is not the same as switch" +
1707 " length = " +
1708 str( len( sw ) ) )
1709 return main.FALSE
1710 else:
1711 for switch, ptcpNum in zip( sw, ptcp ):
1712 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001713 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001714 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001715 tempCmd += onosIp
1716 commandList.append( tempCmd )
1717 else:
1718 main.log.error( self.name + ": Invalid PTCP" )
1719 return main.FALSE
1720 else:
1721 for switch in sw:
1722 tempCmd = "sh ovs-vsctl set-controller "
1723 tempCmd += switch + " " + onosIp
1724 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001725 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001726 main.log.error( self.name + ": Invalid switch type " )
1727 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001728
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001729 for cmd in commandList:
1730 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001731 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001732 except pexpect.TIMEOUT:
1733 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1734 return main.FALSE
1735 except pexpect.EOF:
1736 main.log.error( self.name + ": EOF exception found" )
1737 main.log.error( self.name + ": " + self.handle.before )
1738 main.cleanup()
1739 main.exit()
1740 return main.TRUE
1741 except Exception:
1742 main.log.exception( self.name + ": Uncaught exception!" )
1743 main.cleanup()
1744 main.exit()
adminbae64d82013-08-01 10:50:15 -07001745
kelvin-onlabd3b64892015-01-20 13:26:24 -08001746 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001747 """
1748 Removes the controller target from sw"""
1749 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001750 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001751 response = self.execute(
1752 cmd=command,
1753 prompt="mininet>",
1754 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001755 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001756 main.log.error( self.name + ": EOF exception found" )
1757 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001758 main.cleanup()
1759 main.exit()
1760 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001761 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001762
kelvin-onlabd3b64892015-01-20 13:26:24 -08001763 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001764 """
Jon Hallb1290e82014-11-18 16:17:48 -05001765 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001766 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001767 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001768 NOTE: cannot currently specify what type of switch
1769 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001770 sw = name of the new switch as a string
1771 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001772 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001773 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001774 """
1775 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001776 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001777 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001778 response = self.execute(
1779 cmd=command,
1780 prompt="mininet>",
1781 timeout=10 )
1782 if re.search( "already exists!", response ):
1783 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001784 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001785 elif re.search( "Error", response ):
1786 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001787 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001788 elif re.search( "usage:", response ):
1789 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001790 return main.FALSE
1791 else:
1792 return main.TRUE
1793 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001794 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001795 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001796 main.cleanup()
1797 main.exit()
1798
kelvin-onlabd3b64892015-01-20 13:26:24 -08001799 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001800 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001801 delete a switch from the mininet topology
1802 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001803 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001804 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001805 sw = name of the switch as a string
1806 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001807 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001808 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001809 response = self.execute(
1810 cmd=command,
1811 prompt="mininet>",
1812 timeout=10 )
1813 if re.search( "no switch named", response ):
1814 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001815 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001816 elif re.search( "Error", response ):
1817 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001818 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001819 elif re.search( "usage:", response ):
1820 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001821 return main.FALSE
1822 else:
1823 return main.TRUE
1824 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001825 main.log.error( self.name + ": EOF exception found" )
1826 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001827 main.cleanup()
1828 main.exit()
1829
kelvin-onlabd3b64892015-01-20 13:26:24 -08001830 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001831 """
1832 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001833 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001834 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001835 NOTE: cannot currently specify what type of link
1836 required params:
1837 node1 = the string node name of the first endpoint of the link
1838 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001839 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001840 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001841 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001842 response = self.execute(
1843 cmd=command,
1844 prompt="mininet>",
1845 timeout=10 )
1846 if re.search( "doesnt exist!", response ):
1847 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001848 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001849 elif re.search( "Error", response ):
1850 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001851 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001852 elif re.search( "usage:", response ):
1853 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001854 return main.FALSE
1855 else:
1856 return main.TRUE
1857 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001858 main.log.error( self.name + ": EOF exception found" )
1859 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001860 main.cleanup()
1861 main.exit()
1862
kelvin-onlabd3b64892015-01-20 13:26:24 -08001863 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001864 """
1865 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001866 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001867 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001868 required params:
1869 node1 = the string node name of the first endpoint of the link
1870 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001871 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001872 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001873 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001874 response = self.execute(
1875 cmd=command,
1876 prompt="mininet>",
1877 timeout=10 )
1878 if re.search( "no node named", response ):
1879 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001880 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001881 elif re.search( "Error", response ):
1882 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001883 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001884 elif re.search( "usage:", response ):
1885 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001886 return main.FALSE
1887 else:
1888 return main.TRUE
1889 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001890 main.log.error( self.name + ": EOF exception found" )
1891 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001892 main.cleanup()
1893 main.exit()
1894
kelvin-onlabd3b64892015-01-20 13:26:24 -08001895 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001896 """
Jon Hallb1290e82014-11-18 16:17:48 -05001897 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001898 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001899 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001900 NOTE: cannot currently specify what type of host
1901 required params:
1902 hostname = the string hostname
1903 optional key-value params
1904 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001905 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001906 """
1907 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001908 command = "addhost " + str( hostname ) + " " + str( switch )
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( "already exists!", 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( "doesnt exists!", 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( "Error", response ):
1921 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001922 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001923 elif re.search( "usage:", response ):
1924 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001925 return main.FALSE
1926 else:
1927 return main.TRUE
1928 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001929 main.log.error( self.name + ": EOF exception found" )
1930 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001931 main.cleanup()
1932 main.exit()
1933
kelvin-onlabd3b64892015-01-20 13:26:24 -08001934 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001935 """
1936 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001937 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001938 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001939 NOTE: this uses a custom mn function
1940 required params:
1941 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001942 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001943 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001944 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001945 response = self.execute(
1946 cmd=command,
1947 prompt="mininet>",
1948 timeout=10 )
1949 if re.search( "no host named", 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( "Error", response ):
1953 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001954 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001955 elif re.search( "usage:", response ):
1956 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001957 return main.FALSE
1958 else:
1959 return main.TRUE
1960 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001961 main.log.error( self.name + ": EOF exception found" )
1962 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001963 main.cleanup()
1964 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001965
Jon Hall7eb38402015-01-08 17:19:54 -08001966 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001967 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001968 Called at the end of the test to stop the mininet and
1969 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001970 """
Jon Halld80cc142015-07-06 13:36:05 -07001971 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001972 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001973 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001974 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001975 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001976 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001977 elif i == 1:
1978 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001979 # print "Disconnecting Mininet"
1980 if self.handle:
1981 self.handle.sendline( "exit" )
1982 self.handle.expect( "exit" )
1983 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001984 else:
1985 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001986 return response
1987
Jon Halld80cc142015-07-06 13:36:05 -07001988 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001989 """
Jon Hall21270ac2015-02-16 17:59:55 -08001990 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001991 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001992 main.FALSE if the pexpect handle does not exist.
1993
Jon Halld61331b2015-02-17 16:35:47 -08001994 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001995 """
Jon Halld61331b2015-02-17 16:35:47 -08001996 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001997 response = ''
1998 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001999 try:
Jon Halld80cc142015-07-06 13:36:05 -07002000 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002001 i = self.handle.expect( [ 'mininet>',
2002 '\$',
2003 pexpect.EOF,
2004 pexpect.TIMEOUT ],
2005 timeout )
2006 if i == 0:
2007 main.log.info( "Exiting mininet..." )
Jeremyd9e4eb12016-04-13 12:09:06 -07002008 response = self.execute( cmd="exit",
2009 prompt="(.*)",
2010 timeout=120 )
2011 main.log.info( self.name + ": Stopped" )
2012 self.handle.sendline( "sudo mn -c" )
2013 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002014
Jeremyd9e4eb12016-04-13 12:09:06 -07002015 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002016 main.log.info( " Mininet trying to exit while not " +
2017 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002018 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002019 elif i == 2:
2020 main.log.error( "Something went wrong exiting mininet" )
2021 elif i == 3: # timeout
2022 main.log.error( "Something went wrong exiting mininet " +
2023 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002024
Hari Krishnab35c6d02015-03-18 11:13:51 -07002025 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002026 self.handle.sendline( "" )
2027 self.handle.expect( '\$' )
2028 self.handle.sendline(
2029 "sudo kill -9 \`ps -ef | grep \"" +
2030 fileName +
2031 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002032 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002033 main.log.error( self.name + ": EOF exception found" )
2034 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07002035 main.cleanup()
2036 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08002037 else:
2038 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002039 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002040 return response
2041
YPZhang26a139e2016-04-25 14:01:55 -07002042 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002043 """
2044 Description:
2045 Sends arp message from mininet host for hosts discovery
2046 Required:
2047 host - hosts name
2048 Optional:
2049 ip - ip address that does not exist in the network so there would
2050 be no reply.
2051 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002052 if ethDevice:
2053 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002054 cmd = srcHost + " arping -c1 "
2055 if noResult:
2056 cmd += "-w10 " # If we don't want the actural arping result, set -w10, arping will exit after 10 ms.
2057 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002058 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002059 if output:
2060 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002061 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002062 i = self.handle.expect( [ "mininet>", "arping: " ] )
2063 if i == 0:
2064 return main.TRUE
2065 elif i == 1:
2066 response = self.handle.before + self.handle.after
2067 self.handle.expect( "mininet>" )
2068 response += self.handle.before + self.handle.after
2069 main.log.warn( "Error sending arping, output was: " +
2070 response )
2071 return main.FALSE
2072 except pexpect.TIMEOUT:
2073 main.log.error( self.name + ": TIMEOUT exception found" )
2074 main.log.warn( self.handle.before )
2075 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002076 except pexpect.EOF:
2077 main.log.error( self.name + ": EOF exception found" )
2078 main.log.error( self.name + ": " + self.handle.before )
2079 main.cleanup()
2080 main.exit()
admin07529932013-11-22 14:58:28 -08002081
Jon Hall7eb38402015-01-08 17:19:54 -08002082 def decToHex( self, num ):
2083 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002084
Jon Hall7eb38402015-01-08 17:19:54 -08002085 def getSwitchFlowCount( self, switch ):
2086 """
2087 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002088 if self.handle:
2089 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2090 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002091 response = self.execute(
2092 cmd=cmd,
2093 prompt="mininet>",
2094 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002095 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002096 main.log.error( self.name + ": EOF exception found" )
2097 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002098 main.cleanup()
2099 main.exit()
2100 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002101 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002102 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002103 main.log.info(
2104 "Couldn't find flows on switch %s, found: %s" %
2105 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002106 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002107 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002108 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002109 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002110
Jon Hall9ed8f372016-02-24 17:34:07 -08002111 def checkFlows( self, sw, dumpFormat=None ):
2112 if dumpFormat:
2113 command = "sh ovs-ofctl -F " + \
2114 dumpFormat + " dump-flows " + str( sw )
2115 else:
2116 command = "sh ovs-ofctl dump-flows " + str( sw )
2117 try:
2118 response = self.execute(
2119 cmd=command,
2120 prompt="mininet>",
2121 timeout=10 )
2122 return response
2123 except pexpect.EOF:
2124 main.log.error( self.name + ": EOF exception found" )
2125 main.log.error( self.name + ": " + self.handle.before )
2126 main.cleanup()
2127 main.exit()
2128
GlennRC68467eb2015-11-16 18:01:01 -08002129 def flowTableComp( self, flowTable1, flowTable2 ):
2130 # This function compares the selctors and treatments of each flow
2131 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002132 assert flowTable1, "flowTable1 is empty or None"
2133 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002134 returnValue = main.TRUE
GlennRC68467eb2015-11-16 18:01:01 -08002135 if len(flowTable1) != len(flowTable2):
2136 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002137 returnValue = main.FALSE
GlennRCfa65fce2015-12-16 13:16:08 -08002138 dFields = ["n_bytes", "cookie", "n_packets", "duration"]
2139 for flow1, flow2 in zip(flowTable1, flowTable2):
Jon Hallacd1b182015-12-17 11:43:20 -08002140 for field in dFields:
2141 try:
2142 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002143 except KeyError:
2144 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002145 try:
2146 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002147 except KeyError:
2148 pass
GlennRC68467eb2015-11-16 18:01:01 -08002149 for i in range( len(flowTable1) ):
GlennRC17bbcf52015-12-14 17:31:50 -08002150 if flowTable1[i] not in flowTable2:
2151 main.log.warn( "Flow tables do not match:" )
2152 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[i] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002153 returnValue = main.FALSE
2154 break
2155 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002156 except AssertionError:
2157 main.log.exception( "Nothing to compare" )
2158 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002159 except Exception:
2160 main.log.exception( "Uncaught exception!" )
2161 main.cleanup()
2162 main.exit()
Jon Hall9043c902015-07-30 14:23:44 -07002163
GlennRC528ad292015-11-12 10:38:18 -08002164 def parseFlowTable( self, flowTable, version="", debug=True ):
GlennRC956ea742015-11-05 16:14:15 -08002165 '''
2166 Discription: Parses flows into json format.
2167 NOTE: this can parse any string thats separated with commas
2168 Arguments:
2169 Required:
2170 flows: a list of strings that represnt flows
2171 Optional:
2172 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2173 debug: prints out the final result
2174 returns: A list of flows in json format
2175 '''
GlennRC528ad292015-11-12 10:38:18 -08002176 jsonFlowTable = []
2177 for flow in flowTable:
GlennRC956ea742015-11-05 16:14:15 -08002178 jsonFlow = {}
GlennRC528ad292015-11-12 10:38:18 -08002179 # split up the fields of the flow
2180 parsedFlow = flow.split(", ")
2181 # get rid of any spaces in front of the field
2182 for i in range( len(parsedFlow) ):
2183 item = parsedFlow[i]
2184 if item[0] == " ":
2185 parsedFlow[i] = item[1:]
2186 # grab the selector and treatment from the parsed flow
2187 # the last element is the selector and the treatment
2188 temp = parsedFlow.pop(-1)
2189 # split up the selector and the treatment
2190 temp = temp.split(" ")
2191 index = 0
2192 # parse the flags
2193 # NOTE: This only parses one flag
2194 flag = {}
2195 if version == "1.3":
2196 flag = {"flag":[temp[index]]}
2197 index += 1
2198 # the first element is the selector and split it up
2199 sel = temp[index]
2200 index += 1
2201 sel = sel.split(",")
2202 # the priority is stuck in the selecter so put it back
2203 # in the flow
2204 parsedFlow.append(sel.pop(0))
2205 # parse selector
2206 criteria = []
2207 for item in sel:
2208 # this is the type of the packet e.g. "arp"
2209 if "=" not in item:
2210 criteria.append( {"type":item} )
2211 else:
2212 field = item.split("=")
2213 criteria.append( {field[0]:field[1]} )
GlennRC68467eb2015-11-16 18:01:01 -08002214 selector = {"selector": {"criteria":sorted(criteria)} }
GlennRC528ad292015-11-12 10:38:18 -08002215 treat = temp[index]
2216 # get rid of the action part e.g. "action=output:2"
2217 # we will add it back later
2218 treat = treat.split("=")
2219 treat.pop(0)
2220 # parse treatment
2221 action = []
2222 for item in treat:
2223 field = item.split(":")
2224 action.append( {field[0]:field[1]} )
2225 # create the treatment field and add the actions
GlennRC68467eb2015-11-16 18:01:01 -08002226 treatment = {"treatment": {"action":sorted(action)} }
GlennRC528ad292015-11-12 10:38:18 -08002227 # parse the rest of the flow
2228 for item in parsedFlow:
2229 field = item.split("=")
2230 jsonFlow.update( {field[0]:field[1]} )
2231 # add the treatment and the selector to the json flow
2232 jsonFlow.update( selector )
2233 jsonFlow.update( treatment )
2234 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002235
GlennRC528ad292015-11-12 10:38:18 -08002236 if debug: main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format(jsonFlow) )
GlennRC956ea742015-11-05 16:14:15 -08002237
GlennRC528ad292015-11-12 10:38:18 -08002238 # add the json flow to the json flow table
2239 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002240
GlennRC528ad292015-11-12 10:38:18 -08002241 return jsonFlowTable
2242
Jon Hall0a543792015-12-14 11:00:26 -08002243 def getFlowTable( self, sw, version="", debug=False):
GlennRC956ea742015-11-05 16:14:15 -08002244 '''
2245 Discription: Returns the flow table(s) on a switch or switches in a list.
2246 Each element is a flow.
2247 Arguments:
2248 Required:
2249 sw: The switch name ("s1") to retrive the flow table. Can also be
2250 a list of switches.
2251 Optional:
2252 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2253 debug: prints out the final result
2254 '''
2255 try:
2256 switches = []
2257 if type(sw) is list:
Jon Hallca7ac292015-11-11 09:28:12 -08002258 switches.extend(sw)
GlennRC956ea742015-11-05 16:14:15 -08002259 else: switches.append(sw)
2260
2261 flows = []
2262 for s in switches:
2263 cmd = "sh ovs-ofctl dump-flows " + s
2264
GlennRC528ad292015-11-12 10:38:18 -08002265 if "1.0" == version:
2266 cmd += " -F OpenFlow10-table_id"
2267 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002268 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002269
2270 main.log.info( "Sending: " + cmd )
2271 self.handle.sendline( cmd )
2272 self.handle.expect( "mininet>" )
2273 response = self.handle.before
2274 response = response.split( "\r\n" )
2275 # dump the first two elements and the last
2276 # the first element is the command that was sent
2277 # the second is the table header
2278 # the last element is empty
2279 response = response[2:-1]
2280 flows.extend( response )
2281
2282 if debug: print "Flows:\n{}\n\n".format(flows)
2283
GlennRC528ad292015-11-12 10:38:18 -08002284 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002285
2286 except pexpect.TIMEOUT:
2287 main.log.exception( self.name + ": Command timed out" )
2288 return None
2289 except pexpect.EOF:
2290 main.log.exception( self.name + ": connection closed." )
2291 main.cleanup()
2292 main.exit()
2293 except Exception:
2294 main.log.exception( self.name + ": Uncaught exception!" )
2295 main.cleanup()
2296 main.exit()
2297
2298 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
2299 '''
2300 Discription: Checks whether the ID provided matches a flow ID in Mininet
2301 Arguments:
2302 Required:
2303 sw: The switch name ("s1") to retrive the flow table. Can also be
2304 a list of switches.
2305 flowId: the flow ID in hex format. Can also be a list of IDs
2306 Optional:
2307 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2308 debug: prints out the final result
2309 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2310 NOTE: prints out IDs that are not present
2311 '''
2312 try:
2313 main.log.info( "Getting flows from Mininet" )
2314 flows = self.getFlowTable( sw, version, debug )
2315
2316 if debug: print "flow ids:\n{}\n\n".format(flowId)
2317
2318 # Check flowId is a list or a string
2319 if type( flowId ) is str:
2320 result = False
2321 for f in flows:
2322 if flowId in f.get( 'cookie' ):
2323 result = True
2324 break
2325 # flowId is a list
2326 else:
2327 result = True
2328 # Get flow IDs from Mininet
2329 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2330 # Save the IDs that are not in Mininet
2331 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2332
2333 if debug: print "mn flow ids:\n{}\n\n".format(mnFlowIds)
2334
2335 # Print out the IDs that are not in Mininet
2336 if absentIds:
2337 main.log.warn( "Absent ids: {}".format( absentIds ) )
2338 result = False
2339
2340 return main.TRUE if result else main.FALSE
2341
2342 except Exception:
2343 main.log.exception( self.name + ": Uncaught exception!" )
2344 main.cleanup()
2345 main.exit()
2346
2347
Charles Chan029be652015-08-24 01:46:10 +08002348 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002349 """
Jon Hallefbd9792015-03-05 16:11:36 -08002350 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002351 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002352 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002353 self.handle.sendline( "" )
2354 self.handle.expect( "mininet>" )
2355 self.handle.sendline(
2356 "sh sudo tcpdump -n -i " +
2357 intf +
2358 " " +
2359 port +
2360 " -w " +
2361 filename.strip() +
2362 " &" )
2363 self.handle.sendline( "" )
2364 i = self.handle.expect( [ 'No\ssuch\device',
2365 'listening\son',
2366 pexpect.TIMEOUT,
2367 "mininet>" ],
2368 timeout=10 )
2369 main.log.warn( self.handle.before + self.handle.after )
2370 self.handle.sendline( "" )
2371 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002372 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002373 main.log.error(
2374 self.name +
2375 ": tcpdump - No such device exists. " +
2376 "tcpdump attempted on: " +
2377 intf )
admin2a9548d2014-06-17 14:08:07 -07002378 return main.FALSE
2379 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002380 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002381 return main.TRUE
2382 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002383 main.log.error(
2384 self.name +
2385 ": tcpdump command timed out! Check interface name," +
2386 " given interface was: " +
2387 intf )
admin2a9548d2014-06-17 14:08:07 -07002388 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002389 elif i == 3:
2390 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002391 return main.TRUE
2392 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002393 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002394 return main.FALSE
2395 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002396 main.log.error( self.name + ": EOF exception found" )
2397 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002398 main.cleanup()
2399 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002400 except Exception:
2401 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002402 main.cleanup()
2403 main.exit()
2404
kelvin-onlabd3b64892015-01-20 13:26:24 -08002405 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002406 """
2407 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002408 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002409 self.handle.sendline( "sh sudo pkill tcpdump" )
2410 self.handle.expect( "mininet>" )
2411 self.handle.sendline( "" )
2412 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002413 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002414 main.log.error( self.name + ": EOF exception found" )
2415 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002416 main.cleanup()
2417 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002418 except Exception:
2419 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002420 main.cleanup()
2421 main.exit()
2422
Jon Halld80cc142015-07-06 13:36:05 -07002423 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002424 """
2425 Read ports from a Mininet switch.
2426
2427 Returns a json structure containing information about the
2428 ports of the given switch.
2429 """
2430 response = self.getInterfaces( nodeName )
2431 # TODO: Sanity check on response. log if no such switch exists
2432 ports = []
2433 for line in response.split( "\n" ):
2434 if not line.startswith( "name=" ):
2435 continue
2436 portVars = {}
2437 for var in line.split( "," ):
2438 key, value = var.split( "=" )
2439 portVars[ key ] = value
2440 isUp = portVars.pop( 'enabled', "True" )
2441 isUp = "True" in isUp
2442 if verbose:
2443 main.log.info( "Reading switch port %s(%s)" %
2444 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2445 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002446 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002447 mac = None
2448 ips = []
2449 ip = portVars[ 'ip' ]
2450 if ip == 'None':
2451 ip = None
2452 ips.append( ip )
2453 name = portVars[ 'name' ]
2454 if name == 'None':
2455 name = None
2456 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2457 if name == 'lo':
2458 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2459 else:
2460 portNo = re.search( portRe, name ).group( 'port' )
2461 ports.append( { 'of_port': portNo,
2462 'mac': str( mac ).replace( '\'', '' ),
2463 'name': name,
2464 'ips': ips,
2465 'enabled': isUp } )
2466 return ports
2467
Jon Halld80cc142015-07-06 13:36:05 -07002468 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002469 """
2470 Read switches from Mininet.
2471
2472 Returns a dictionary whose keys are the switch names and the value is
2473 a dictionary containing information about the switch.
2474 """
Jon Halla22481b2015-07-28 17:46:01 -07002475 # NOTE: To support new Mininet switch classes, just append the new
2476 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002477
Jon Halla22481b2015-07-28 17:46:01 -07002478 # Regex patterns to parse 'dump' output
2479 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002480 # <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 -07002481 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002482 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2483 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2484 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2485 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2486 swRE = r"<(?P<class>" + switchClasses + r")" +\
2487 r"(?P<options>\{.*\})?\s" +\
2488 r"(?P<name>[^:]+)\:\s" +\
2489 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2490 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002491 # Update mn port info
2492 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002493 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002494 dump = self.dump().split( "\n" )
2495 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002496 result = re.search( swRE, line, re.I )
2497 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002498 name = result.group( 'name' )
2499 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002500 pid = result.group( 'pid' )
2501 swClass = result.group( 'class' )
2502 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002503 if verbose:
2504 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2505 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002506 output[ name ] = { "dpid": dpid,
2507 "ports": ports,
2508 "swClass": swClass,
2509 "pid": pid,
2510 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002511 return output
2512
Jon Halld80cc142015-07-06 13:36:05 -07002513 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002514 """
2515 Read hosts from Mininet.
2516
2517 Returns a dictionary whose keys are the host names and the value is
2518 a dictionary containing information about the host.
2519 """
2520 # Regex patterns to parse dump output
2521 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002522 # <Host h1: pid=12725>
2523 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2524 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2525 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002526 # NOTE: Does not correctly match hosts with multi-links
2527 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2528 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002529 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002530 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002531 # update mn port info
2532 self.update()
2533 # Get mininet dump
2534 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002535 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002536 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002537 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002538 result = re.search( hostRE, line )
2539 name = result.group( 'name' )
2540 interfaces = []
2541 response = self.getInterfaces( name )
2542 # Populate interface info
2543 for line in response.split( "\n" ):
2544 if line.startswith( "name=" ):
2545 portVars = {}
2546 for var in line.split( "," ):
2547 key, value = var.split( "=" )
2548 portVars[ key ] = value
2549 isUp = portVars.pop( 'enabled', "True" )
2550 isUp = "True" in isUp
2551 if verbose:
2552 main.log.info( "Reading host port %s(%s)" %
2553 ( portVars[ 'name' ],
2554 portVars[ 'mac' ] ) )
2555 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002556 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002557 mac = None
2558 ips = []
2559 ip = portVars[ 'ip' ]
2560 if ip == 'None':
2561 ip = None
2562 ips.append( ip )
2563 intfName = portVars[ 'name' ]
2564 if name == 'None':
2565 name = None
2566 interfaces.append( {
2567 "name": intfName,
2568 "ips": ips,
2569 "mac": str( mac ),
2570 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002571 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002572 return hosts
2573
YPZhang81a7d4e2016-04-18 13:10:17 -07002574 def getLinks( self, timeout=20 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002575 """
2576 Gathers information about current Mininet links. These links may not
2577 be up if one of the ports is down.
2578
2579 Returns a list of dictionaries with link endpoints.
2580
2581 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002582 { 'node1': str( node1 name )
2583 'node2': str( node2 name )
2584 'port1': str( port1 of_port )
2585 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002586 Note: The port number returned is the eth#, not necessarily the of_port
2587 number. In Mininet, for OVS switch, these should be the same. For
2588 hosts, this is just the eth#.
2589 """
2590 self.update()
YPZhang81a7d4e2016-04-18 13:10:17 -07002591 response = self.links(timeout=timeout).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002592
2593 # Examples:
2594 # s1-eth3<->s2-eth1 (OK OK)
2595 # s13-eth3<->h27-eth0 (OK OK)
2596 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2597 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2598 links = []
2599 for line in response:
2600 match = re.search( linkRE, line )
2601 if match:
2602 node1 = match.group( 'node1' )
2603 node2 = match.group( 'node2' )
2604 port1 = match.group( 'port1' )
2605 port2 = match.group( 'port2' )
2606 links.append( { 'node1': node1,
2607 'node2': node2,
2608 'port1': port1,
2609 'port2': port2 } )
2610 return links
2611
2612 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002613 """
2614 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002615 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002616
Jon Hallafa8a472015-06-12 14:02:42 -07002617 Dependencies:
2618 1. numpy - "sudo pip install numpy"
2619 """
2620 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002621 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002622 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002623 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002624 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002625 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002626 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002627 main.log.error(
2628 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002629 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002630 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002631 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002632 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002633 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002634 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002635 onosDPIDs.append(
2636 switch[ 'id' ].replace(
2637 ":",
2638 '' ).replace(
2639 "of",
2640 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002641 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002642
Jon Hall7eb38402015-01-08 17:19:54 -08002643 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002644 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002645 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002646 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002647 main.log.error( str( list1 ) )
2648 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002649 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002650 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002651 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002652 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002653 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002654
Jon Hall7eb38402015-01-08 17:19:54 -08002655 # FIXME: this does not look for extra ports in ONOS, only checks that
2656 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002657 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002658
Jon Hall7eb38402015-01-08 17:19:54 -08002659 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002660 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002661 mnPorts = []
2662 onosPorts = []
2663 switchResult = main.TRUE
2664 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002665 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002666 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002667 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002668 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002669 if onosSwitch[ 'device' ][ 'id' ].replace(
2670 ':',
2671 '' ).replace(
2672 "of",
2673 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002674 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002675 if port[ 'isEnabled' ]:
2676 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002677 # onosPorts.append( 'local' )
2678 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002679 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002680 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002681 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002682 mnPorts.sort( key=float )
2683 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002684
kelvin-onlabd3b64892015-01-20 13:26:24 -08002685 mnPortsLog = mnPorts
2686 onosPortsLog = onosPorts
2687 mnPorts = [ x for x in mnPorts ]
2688 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002689
Jon Hall7eb38402015-01-08 17:19:54 -08002690 # TODO: handle other reserved port numbers besides LOCAL
2691 # NOTE: Reserved ports
2692 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2693 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002694 for mnPort in mnPortsLog:
2695 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002696 # don't set results to true here as this is just one of
2697 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002698 mnPorts.remove( mnPort )
2699 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002700
Jon Hall7eb38402015-01-08 17:19:54 -08002701 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002702 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002703 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002704 if 65534 in mnPorts:
2705 mnPorts.remove( 65534 )
2706 if long( uint64( -2 ) ) in onosPorts:
2707 onosPorts.remove( long( uint64( -2 ) ) )
2708 if len( mnPorts ): # the ports of this switch don't match
2709 switchResult = main.FALSE
2710 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2711 if len( onosPorts ): # the ports of this switch don't match
2712 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002713 main.log.warn(
2714 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002715 str( onosPorts ) )
2716 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002717 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002718 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002719 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002720 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2721 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2722 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002723 finalResults = finalResults and portsResults
2724 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002725
Jon Hallafa8a472015-06-12 14:02:42 -07002726 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002727 """
2728 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002729 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002730
Jon Hallafa8a472015-06-12 14:02:42 -07002731 """
Jon Hall7eb38402015-01-08 17:19:54 -08002732 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002733 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002734 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002735
Jon Halld80cc142015-07-06 13:36:05 -07002736 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002737 for l in links:
2738 try:
2739 node1 = switches[ l[ 'node1' ] ]
2740 node2 = switches[ l[ 'node2' ] ]
2741 enabled = True
2742 for port in node1[ 'ports' ]:
2743 if port[ 'of_port' ] == l[ 'port1' ]:
2744 enabled = enabled and port[ 'enabled' ]
2745 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002746 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002747 enabled = enabled and port[ 'enabled' ]
2748 if enabled:
2749 mnLinks.append( l )
2750 except KeyError:
2751 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002752 if 2 * len( mnLinks ) == len( onos ):
2753 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002754 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002755 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002756 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002757 "Mininet has " + str( len( mnLinks ) ) +
2758 " bidirectional links and ONOS has " +
2759 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002760
Jon Hall7eb38402015-01-08 17:19:54 -08002761 # iterate through MN links and check if an ONOS link exists in
2762 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002763 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002764 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002765 node1 = None
2766 port1 = None
2767 node2 = None
2768 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002769 firstDir = main.FALSE
2770 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002771 for swName, switch in switches.iteritems():
2772 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002773 node1 = switch[ 'dpid' ]
2774 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002775 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002776 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002777 if node1 is not None and node2 is not None:
2778 break
Jon Hallafa8a472015-06-12 14:02:42 -07002779 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002780 node2 = switch[ 'dpid' ]
2781 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002782 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002783 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002784 if node1 is not None and node2 is not None:
2785 break
2786
kelvin-onlabd3b64892015-01-20 13:26:24 -08002787 for onosLink in onos:
2788 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002789 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002790 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002791 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002792 onosPort1 = onosLink[ 'src' ][ 'port' ]
2793 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002794
Jon Hall72cf1dc2014-10-20 21:04:50 -04002795 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002796 if str( onosNode1 ) == str( node1 ) and str(
2797 onosNode2 ) == str( node2 ):
2798 if int( onosPort1 ) == int( port1 ) and int(
2799 onosPort2 ) == int( port2 ):
2800 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002801 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002802 main.log.warn(
2803 'The port numbers do not match for ' +
2804 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002805 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002806 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002807 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002808 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002809 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002810
2811 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002812 elif ( str( onosNode1 ) == str( node2 ) and
2813 str( onosNode2 ) == str( node1 ) ):
2814 if ( int( onosPort1 ) == int( port2 )
2815 and int( onosPort2 ) == int( port1 ) ):
2816 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002817 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002818 main.log.warn(
2819 'The port numbers do not match for ' +
2820 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002821 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002822 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002823 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002824 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002825 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002826 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002827 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002828 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002829 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002830 'ONOS does not have the link %s/%s -> %s/%s' %
2831 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002832 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002833 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002834 'ONOS does not have the link %s/%s -> %s/%s' %
2835 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002836 linkResults = linkResults and firstDir and secondDir
2837 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002838
Jon Hallafa8a472015-06-12 14:02:42 -07002839 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002840 """
Jon Hallafa8a472015-06-12 14:02:42 -07002841 Compare mn and onos Hosts.
2842 Since Mininet hosts are quiet, ONOS will only know of them when they
2843 speak. For this reason, we will only check that the hosts in ONOS
2844 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002845
Jon Hallafa8a472015-06-12 14:02:42 -07002846 Arguments:
2847 hostsJson: parsed json object from the onos hosts api
2848 Returns:
2849 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002850 import json
2851 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002852 for onosHost in hostsJson:
2853 onosMAC = onosHost[ 'mac' ].lower()
2854 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002855 for mnHost, info in hosts.iteritems():
2856 for mnIntf in info[ 'interfaces' ]:
2857 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002858 match = True
2859 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002860 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002861 pass # all is well
2862 else:
2863 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002864 main.log.error( "ONOS host " +
2865 onosHost[ 'id' ] +
2866 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002867 str( onosHost[ 'ipAddresses' ] ) +
2868 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002869 str( ip ) +
2870 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002871 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002872 onosHost,
2873 sort_keys=True,
2874 indent=4,
2875 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002876 main.log.info( output )
2877 hostResults = main.FALSE
2878 if not match:
2879 hostResults = main.FALSE
2880 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2881 "corresponding Mininet host." )
2882 output = json.dumps( onosHost,
2883 sort_keys=True,
2884 indent=4,
2885 separators=( ',', ': ' ) )
2886 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002887 return hostResults
2888
Jon Hallafa8a472015-06-12 14:02:42 -07002889 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002890 """
2891 Returns a list of all hosts
2892 Don't ask questions just use it"""
2893 self.handle.sendline( "" )
2894 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002895
Jon Hall7eb38402015-01-08 17:19:54 -08002896 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2897 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002898
kelvin-onlabd3b64892015-01-20 13:26:24 -08002899 handlePy = self.handle.before
2900 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2901 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002902
Jon Hall7eb38402015-01-08 17:19:54 -08002903 self.handle.sendline( "" )
2904 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002905
kelvin-onlabd3b64892015-01-20 13:26:24 -08002906 hostStr = handlePy.replace( "]", "" )
2907 hostStr = hostStr.replace( "'", "" )
2908 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002909 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002910 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002911
kelvin-onlabd3b64892015-01-20 13:26:24 -08002912 return hostList
adminbae64d82013-08-01 10:50:15 -07002913
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002914 def getSwitch( self ):
2915 """
2916 Returns a list of all switches
2917 Again, don't ask question just use it...
2918 """
2919 # get host list...
2920 hostList = self.getHosts()
2921 # Make host set
2922 hostSet = set( hostList )
2923
2924 # Getting all the nodes in mininet
2925 self.handle.sendline( "" )
2926 self.handle.expect( "mininet>" )
2927
2928 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2929 self.handle.expect( "mininet>" )
2930
2931 handlePy = self.handle.before
2932 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2933 handlePy = handlePy.rstrip()
2934
2935 self.handle.sendline( "" )
2936 self.handle.expect( "mininet>" )
2937
2938 nodesStr = handlePy.replace( "]", "" )
2939 nodesStr = nodesStr.replace( "'", "" )
2940 nodesStr = nodesStr.replace( "[", "" )
2941 nodesStr = nodesStr.replace( " ", "" )
2942 nodesList = nodesStr.split( "," )
2943
2944 nodesSet = set( nodesList )
2945 # discarding default controller(s) node
2946 nodesSet.discard( 'c0' )
2947 nodesSet.discard( 'c1' )
2948 nodesSet.discard( 'c2' )
2949
2950 switchSet = nodesSet - hostSet
2951 switchList = list( switchSet )
2952
2953 return switchList
2954
Jon Hall7eb38402015-01-08 17:19:54 -08002955 def update( self ):
2956 """
2957 updates the port address and status information for
2958 each port in mn"""
2959 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002960 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002961 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002962 self.handle.sendline( "" )
2963 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002964
Jon Hall7eb38402015-01-08 17:19:54 -08002965 self.handle.sendline( "update" )
2966 self.handle.expect( "update" )
2967 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002968
Jon Hall7eb38402015-01-08 17:19:54 -08002969 self.handle.sendline( "" )
2970 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002971
Jon Hallb1290e82014-11-18 16:17:48 -05002972 return main.TRUE
2973 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002974 main.log.error( self.name + ": EOF exception found" )
2975 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002976 main.cleanup()
2977 main.exit()
2978
Jon Halld80cc142015-07-06 13:36:05 -07002979 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002980 """
2981 Add vlan tag to a host.
2982 Dependencies:
2983 This class depends on the "vlan" package
2984 $ sudo apt-get install vlan
2985 Configuration:
2986 Load the 8021q module into the kernel
2987 $sudo modprobe 8021q
2988
2989 To make this setup permanent:
2990 $ sudo su -c 'echo "8021q" >> /etc/modules'
2991 """
2992 if self.handle:
2993 try:
Jon Halld80cc142015-07-06 13:36:05 -07002994 # get the ip address of the host
2995 main.log.info( "Get the ip address of the host" )
2996 ipaddr = self.getIPAddress( host )
2997 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002998
Jon Halld80cc142015-07-06 13:36:05 -07002999 # remove IP from interface intf
3000 # Ex: h1 ifconfig h1-eth0 inet 0
3001 main.log.info( "Remove IP from interface " )
3002 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3003 self.handle.sendline( cmd2 )
3004 self.handle.expect( "mininet>" )
3005 response = self.handle.before
3006 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003007
Jon Halld80cc142015-07-06 13:36:05 -07003008 # create VLAN interface
3009 # Ex: h1 vconfig add h1-eth0 100
3010 main.log.info( "Create Vlan" )
3011 cmd3 = host + " vconfig add " + intf + " " + vlan
3012 self.handle.sendline( cmd3 )
3013 self.handle.expect( "mininet>" )
3014 response = self.handle.before
3015 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003016
Jon Halld80cc142015-07-06 13:36:05 -07003017 # assign the host's IP to the VLAN interface
3018 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3019 main.log.info( "Assign the host IP to the vlan interface" )
3020 vintf = intf + "." + vlan
3021 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3022 self.handle.sendline( cmd4 )
3023 self.handle.expect( "mininet>" )
3024 response = self.handle.before
3025 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003026
3027 return main.TRUE
3028 except pexpect.EOF:
3029 main.log.error( self.name + ": EOF exception found" )
3030 main.log.error( self.name + ": " + self.handle.before )
3031 return main.FALSE
3032
Jon Hall892818c2015-10-20 17:58:34 -07003033 def createHostComponent( self, name ):
3034 """
3035 Creates a new mininet cli component with the same parameters as self.
3036 This new component is intended to be used to login to the hosts created
3037 by mininet.
3038
3039 Arguments:
3040 name - The string of the name of this component. The new component
3041 will be assigned to main.<name> .
3042 In addition, main.<name>.name = str( name )
3043 """
3044 try:
3045 # look to see if this component already exists
3046 getattr( main, name )
3047 except AttributeError:
3048 # namespace is clear, creating component
3049 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
3050 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
3051 main.componentInit( name )
3052 except Exception:
3053 main.log.exception( self.name + ": Uncaught exception!" )
3054 main.cleanup()
3055 main.exit()
3056 else:
3057 # namespace is not clear!
3058 main.log.error( name + " component already exists!" )
3059 # FIXME: Should we exit here?
3060 main.cleanup()
3061 main.exit()
3062
3063 def removeHostComponent( self, name ):
3064 """
3065 Remove host component
3066 Arguments:
3067 name - The string of the name of the component to delete.
3068 """
3069 try:
3070 # Get host component
3071 component = getattr( main, name )
3072 except AttributeError:
3073 main.log.error( "Component " + name + " does not exist." )
3074 return
3075 try:
3076 # Disconnect from component
3077 component.disconnect()
3078 # Delete component
3079 delattr( main, name )
3080 # Delete component from ComponentDictionary
3081 del( main.componentDictionary[name] )
3082 except Exception:
3083 main.log.exception( self.name + ": Uncaught exception!" )
3084 main.cleanup()
3085 main.exit()
3086
3087 def startHostCli( self, host=None ):
3088 """
3089 Use the mininet m utility to connect to the host's cli
3090 """
3091 # These are fields that can be used by scapy packets. Initialized to None
3092 self.hostIp = None
3093 self.hostMac = None
3094 try:
3095 if not host:
3096 host = self.name
3097 self.handle.sendline( self.home + "/util/m " + host )
3098 self.handle.expect( self.hostPrompt )
3099 return main.TRUE
3100 except pexpect.TIMEOUT:
3101 main.log.exception( self.name + ": Command timed out" )
3102 return main.FALSE
3103 except pexpect.EOF:
3104 main.log.exception( self.name + ": connection closed." )
3105 main.cleanup()
3106 main.exit()
3107 except Exception:
3108 main.log.exception( self.name + ": Uncaught exception!" )
3109 main.cleanup()
3110 main.exit()
3111
Jon Hall892818c2015-10-20 17:58:34 -07003112
adminbae64d82013-08-01 10:50:15 -07003113if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07003114 sys.modules[ __name__ ] = MininetCliDriver()