blob: 5a165a2e8cb26d9a9331200317d64055991c23e7 [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
Jon Hall7eb38402015-01-08 17:19:54 -0800620 def checkIP( self, host ):
621 """
622 Verifies the host's ip configured or not."""
623 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700624 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800625 response = self.execute(
626 cmd=host +
627 " ifconfig",
628 prompt="mininet>",
629 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800630 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800631 main.log.error( self.name + ": EOF exception found" )
632 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700633 main.cleanup()
634 main.exit()
adminbae64d82013-08-01 10:50:15 -0700635
Jon Hall7eb38402015-01-08 17:19:54 -0800636 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800637 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
638 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
639 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
640 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
641 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800642 # pattern = "inet addr:10.0.0.6"
643 if re.search( pattern, response ):
644 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700645 return main.TRUE
646 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800647 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700648 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800649 else:
650 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800651
Jon Hall7eb38402015-01-08 17:19:54 -0800652 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800653 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700654 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800655 response = self.execute(
656 cmd="h1 /usr/sbin/sshd -D&",
657 prompt="mininet>",
658 timeout=10 )
659 response = self.execute(
660 cmd="h4 /usr/sbin/sshd -D&",
661 prompt="mininet>",
662 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700663 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800664 vars( self )[ key ] = connectargs[ key ]
665 response = self.execute(
666 cmd="xterm h1 h4 ",
667 prompt="mininet>",
668 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800669 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800670 main.log.error( self.name + ": EOF exception found" )
671 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700672 main.cleanup()
673 main.exit()
adminbae64d82013-08-01 10:50:15 -0700674 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800675 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700676 if self.flag == 0:
677 self.flag = 1
678 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800679 else:
adminbae64d82013-08-01 10:50:15 -0700680 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800681
Jon Hall53c5e662016-04-13 16:06:56 -0700682 def moveHost( self, host, oldSw, newSw, ):
683 """
684 Moves a host from one switch to another on the fly
685 Note: The intf between host and oldSw when detached
686 using detach(), will still show up in the 'net'
687 cmd, because switch.detach() doesn't affect switch.intfs[]
688 ( which is correct behavior since the interfaces
689 haven't moved ).
690 """
691 if self.handle:
692 try:
693 # Bring link between oldSw-host down
694 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
695 "'," + "'down')"
696 print "cmd1= ", cmd
697 response = self.execute( cmd=cmd,
698 prompt="mininet>",
699 timeout=10 )
700
701 # Determine hostintf and Oldswitchintf
702 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
703 ")[0]"
704 print "cmd2= ", cmd
705 self.handle.sendline( cmd )
706 self.handle.expect( "mininet>" )
707
708 # Determine ip and mac address of the host-oldSw interface
709 cmd = "px ipaddr = hintf.IP()"
710 print "cmd3= ", cmd
711 self.handle.sendline( cmd )
712 self.handle.expect( "mininet>" )
713
714 cmd = "px macaddr = hintf.MAC()"
715 print "cmd3= ", cmd
716 self.handle.sendline( cmd )
717 self.handle.expect( "mininet>" )
718
719 # Detach interface between oldSw-host
720 cmd = "px " + oldSw + ".detach( sintf )"
721 print "cmd4= ", cmd
722 self.handle.sendline( cmd )
723 self.handle.expect( "mininet>" )
724
725 # Add link between host-newSw
726 cmd = "py net.addLink(" + host + "," + newSw + ")"
727 print "cmd5= ", cmd
728 self.handle.sendline( cmd )
729 self.handle.expect( "mininet>" )
730
731 # Determine hostintf and Newswitchintf
732 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
733 ")[0]"
734 print "cmd6= ", cmd
735 self.handle.sendline( cmd )
736 self.handle.expect( "mininet>" )
737
738 # Attach interface between newSw-host
739 cmd = "px " + newSw + ".attach( sintf )"
740 print "cmd3= ", cmd
741 self.handle.sendline( cmd )
742 self.handle.expect( "mininet>" )
743
744 # Set ipaddress of the host-newSw interface
745 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
746 print "cmd7 = ", cmd
747 self.handle.sendline( cmd )
748 self.handle.expect( "mininet>" )
749
750 # Set macaddress of the host-newSw interface
751 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
752 print "cmd8 = ", cmd
753 self.handle.sendline( cmd )
754 self.handle.expect( "mininet>" )
755
756 cmd = "net"
757 print "cmd9 = ", cmd
758 self.handle.sendline( cmd )
759 self.handle.expect( "mininet>" )
760 print "output = ", self.handle.before
761
762 # Determine ipaddress of the host-newSw interface
763 cmd = host + " ifconfig"
764 print "cmd10= ", cmd
765 self.handle.sendline( cmd )
766 self.handle.expect( "mininet>" )
767 print "ifconfig o/p = ", self.handle.before
768
769 return main.TRUE
770 except pexpect.EOF:
771 main.log.error( self.name + ": EOF exception found" )
772 main.log.error( self.name + ": " + self.handle.before )
773 return main.FALSE
774
Jon Hall439c8912016-04-15 02:22:03 -0700775 def moveHostv6( self, host, oldSw, newSw, ):
kelvin-onlaba1484582015-02-02 15:46:20 -0800776 """
777 Moves a host from one switch to another on the fly
778 Note: The intf between host and oldSw when detached
779 using detach(), will still show up in the 'net'
780 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700781 ( which is correct behavior since the interfaces
782 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800783 """
784 if self.handle:
785 try:
Jon Hall439c8912016-04-15 02:22:03 -0700786 IP = str( self.getIPAddress( host, proto='IPV6' ) ) + "/64"
kelvin-onlaba1484582015-02-02 15:46:20 -0800787 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700788 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800789 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800790 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800791 response = self.execute( cmd=cmd,
792 prompt="mininet>",
793 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700794
kelvin-onlaba1484582015-02-02 15:46:20 -0800795 # Determine hostintf and Oldswitchintf
796 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800797 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800798 print "cmd2= ", cmd
799 self.handle.sendline( cmd )
800 self.handle.expect( "mininet>" )
801
shahshreya73537862015-02-11 15:15:24 -0800802 # Determine ip and mac address of the host-oldSw interface
Jon Hall439c8912016-04-15 02:22:03 -0700803 cmd = "px ipaddr = " + str(IP)
kelvin-onlaba1484582015-02-02 15:46:20 -0800804 print "cmd3= ", cmd
805 self.handle.sendline( cmd )
806 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800807
808 cmd = "px macaddr = hintf.MAC()"
809 print "cmd3= ", cmd
810 self.handle.sendline( cmd )
811 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700812
kelvin-onlaba1484582015-02-02 15:46:20 -0800813 # Detach interface between oldSw-host
814 cmd = "px " + oldSw + ".detach( sintf )"
815 print "cmd4= ", cmd
816 self.handle.sendline( cmd )
817 self.handle.expect( "mininet>" )
818
819 # Add link between host-newSw
820 cmd = "py net.addLink(" + host + "," + newSw + ")"
821 print "cmd5= ", cmd
822 self.handle.sendline( cmd )
823 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700824
kelvin-onlaba1484582015-02-02 15:46:20 -0800825 # Determine hostintf and Newswitchintf
826 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800827 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800828 print "cmd6= ", cmd
829 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700830 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800831
832 # Attach interface between newSw-host
833 cmd = "px " + newSw + ".attach( sintf )"
Jon Hall439c8912016-04-15 02:22:03 -0700834 print "cmd6= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800835 self.handle.sendline( cmd )
836 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800837
838 # Set macaddress of the host-newSw interface
839 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
Jon Hall439c8912016-04-15 02:22:03 -0700840 print "cmd7 = ", cmd
841 self.handle.sendline( cmd )
842 self.handle.expect( "mininet>" )
843
844 # Set ipaddress of the host-newSw interface
845 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
shahshreya73537862015-02-11 15:15:24 -0800846 print "cmd8 = ", cmd
847 self.handle.sendline( cmd )
848 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700849
Jon Hall439c8912016-04-15 02:22:03 -0700850 cmd = host + " ifconfig"
851 print "cmd9 =",cmd
852 response = self.execute( cmd = cmd, prompt="mininet>" ,timeout=10 )
853 print response
854 pattern = "h\d-eth([\w])"
Jeremyd9e4eb12016-04-13 12:09:06 -0700855 ipAddressSearch = re.search( pattern, response )
Jon Hall439c8912016-04-15 02:22:03 -0700856 print ipAddressSearch.group(1)
857 intf= host + "-eth" + str(ipAddressSearch.group(1))
858 cmd = host + " ip -6 addr add %s dev %s" % ( IP, intf )
859 print "cmd10 = ", cmd
860 self.handle.sendline( cmd )
861 self.handle.expect( "mininet>" )
862
kelvin-onlaba1484582015-02-02 15:46:20 -0800863 cmd = "net"
Jon Hall439c8912016-04-15 02:22:03 -0700864 print "cmd11 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800865 self.handle.sendline( cmd )
866 self.handle.expect( "mininet>" )
867 print "output = ", self.handle.before
868
869 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800870 cmd = host + " ifconfig"
Jon Hall439c8912016-04-15 02:22:03 -0700871 print "cmd12= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800872 self.handle.sendline( cmd )
873 self.handle.expect( "mininet>" )
874 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700875
kelvin-onlaba1484582015-02-02 15:46:20 -0800876 return main.TRUE
877 except pexpect.EOF:
878 main.log.error( self.name + ": EOF exception found" )
879 main.log.error( self.name + ": " + self.handle.before )
880 return main.FALSE
881
Jon Hall7eb38402015-01-08 17:19:54 -0800882 def changeIP( self, host, intf, newIP, newNetmask ):
883 """
884 Changes the ip address of a host on the fly
885 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800886 if self.handle:
887 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800888 cmd = host + " ifconfig " + intf + " " + \
889 newIP + " " + 'netmask' + " " + newNetmask
890 self.handle.sendline( cmd )
891 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800892 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800893 main.log.info( "response = " + response )
894 main.log.info(
895 "Ip of host " +
896 host +
897 " changed to new IP " +
898 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800899 return main.TRUE
900 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800901 main.log.error( self.name + ": EOF exception found" )
902 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800903 return main.FALSE
904
Jon Hall7eb38402015-01-08 17:19:54 -0800905 def changeDefaultGateway( self, host, newGW ):
906 """
907 Changes the default gateway of a host
908 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800909 if self.handle:
910 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800911 cmd = host + " route add default gw " + newGW
912 self.handle.sendline( cmd )
913 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800914 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800915 main.log.info( "response = " + response )
916 main.log.info(
917 "Default gateway of host " +
918 host +
919 " changed to " +
920 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800921 return main.TRUE
922 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800923 main.log.error( self.name + ": EOF exception found" )
924 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800925 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800926
Jon Hall7eb38402015-01-08 17:19:54 -0800927 def addStaticMACAddress( self, host, GW, macaddr ):
928 """
Jon Hallefbd9792015-03-05 16:11:36 -0800929 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800930 if self.handle:
931 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800932 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
933 cmd = host + " arp -s " + GW + " " + macaddr
934 self.handle.sendline( cmd )
935 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800936 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800937 main.log.info( "response = " + response )
938 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800939 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800940 GW +
941 " changed to " +
942 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800943 return main.TRUE
944 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800945 main.log.error( self.name + ": EOF exception found" )
946 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800947 return main.FALSE
948
Jon Hall7eb38402015-01-08 17:19:54 -0800949 def verifyStaticGWandMAC( self, host ):
950 """
951 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800952 if self.handle:
953 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800954 # h1 arp -an
955 cmd = host + " arp -an "
956 self.handle.sendline( cmd )
957 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800958 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800959 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800960 return main.TRUE
961 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800962 main.log.error( self.name + ": EOF exception found" )
963 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800964 return main.FALSE
965
Jon Hall7eb38402015-01-08 17:19:54 -0800966 def getMacAddress( self, host ):
967 """
968 Verifies the host's ip configured or not."""
969 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700970 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800971 response = self.execute(
972 cmd=host +
973 " ifconfig",
974 prompt="mininet>",
975 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800976 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 )
Jon Hall6094a362014-04-11 14:46:56 -0700979 main.cleanup()
980 main.exit()
adminbae64d82013-08-01 10:50:15 -0700981
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700982 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800983 macAddressSearch = re.search( pattern, response, re.I )
984 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800985 main.log.info(
986 self.name +
987 ": Mac-Address of Host " +
988 host +
989 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800990 macAddress )
991 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700992 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800993 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700994
Jon Hall7eb38402015-01-08 17:19:54 -0800995 def getInterfaceMACAddress( self, host, interface ):
996 """
997 Return the IP address of the interface on the given host"""
998 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700999 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001000 response = self.execute( cmd=host + " ifconfig " + interface,
1001 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001002 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001003 main.log.error( self.name + ": EOF exception found" )
1004 main.log.error( self.name + ": " + self.handle.before )
1005 main.cleanup()
1006 main.exit()
1007
1008 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001009 macAddressSearch = re.search( pattern, response, re.I )
1010 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001011 main.log.info( "No mac address found in %s" % response )
1012 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001013 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001014 main.log.info(
1015 "Mac-Address of " +
1016 host +
1017 ":" +
1018 interface +
1019 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001020 macAddress )
1021 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001022 else:
1023 main.log.error( "Connection failed to the host" )
1024
sathishmad953462015-12-03 17:42:07 +05301025 def getIPAddress( self, host , proto='IPV4'):
Jon Hall7eb38402015-01-08 17:19:54 -08001026 """
1027 Verifies the host's ip configured or not."""
1028 if self.handle:
1029 try:
1030 response = self.execute(
1031 cmd=host +
1032 " ifconfig",
1033 prompt="mininet>",
1034 timeout=10 )
1035 except pexpect.EOF:
1036 main.log.error( self.name + ": EOF exception found" )
1037 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001038 main.cleanup()
1039 main.exit()
adminbae64d82013-08-01 10:50:15 -07001040
sathishmad953462015-12-03 17:42:07 +05301041 pattern = ''
1042 if proto == 'IPV4':
1043 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
1044 else:
Jon Hall439c8912016-04-15 02:22:03 -07001045 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001046 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -08001047 main.log.info(
1048 self.name +
1049 ": IP-Address of Host " +
1050 host +
1051 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001052 ipAddressSearch.group( 1 ) )
1053 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001054 else:
1055 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001056
Jon Hall7eb38402015-01-08 17:19:54 -08001057 def getSwitchDPID( self, switch ):
1058 """
1059 return the datapath ID of the switch"""
1060 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001061 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001062 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001063 response = self.execute(
1064 cmd=cmd,
1065 prompt="mininet>",
1066 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001067 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001068 main.log.error( self.name + ": EOF exception found" )
1069 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001070 main.cleanup()
1071 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001072 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001073 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001074 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001075 main.log.info(
1076 "Couldn't find DPID for switch %s, found: %s" %
1077 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001078 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001079 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001080 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001081 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001082
Jon Hall7eb38402015-01-08 17:19:54 -08001083 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001084 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001085 self.handle.sendline( "" )
1086 self.expect( "mininet>" )
1087 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001088 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001089 response = self.execute(
1090 cmd=cmd,
1091 prompt="mininet>",
1092 timeout=10 )
1093 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001094 response = self.handle.before
1095 return response
1096 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001097 main.log.error( self.name + ": EOF exception found" )
1098 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -07001099 main.cleanup()
1100 main.exit()
1101
Jon Hall7eb38402015-01-08 17:19:54 -08001102 def getInterfaces( self, node ):
1103 """
1104 return information dict about interfaces connected to the node"""
1105 if self.handle:
1106 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001107 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001108 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001109 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001110 response = self.execute(
1111 cmd=cmd,
1112 prompt="mininet>",
1113 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001114 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001115 main.log.error( self.name + ": EOF exception found" )
1116 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001117 main.cleanup()
1118 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001119 return response
1120 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001121 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001122
Jon Hall7eb38402015-01-08 17:19:54 -08001123 def dump( self ):
1124 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001125 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001126 response = self.execute(
1127 cmd='dump',
1128 prompt='mininet>',
1129 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001130 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001131 main.log.error( self.name + ": EOF exception found" )
1132 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001133 main.cleanup()
1134 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001135 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001136
Jon Hall7eb38402015-01-08 17:19:54 -08001137 def intfs( self ):
1138 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001139 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001140 response = self.execute(
1141 cmd='intfs',
1142 prompt='mininet>',
1143 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001144 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001145 main.log.error( self.name + ": EOF exception found" )
1146 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001147 main.cleanup()
1148 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001149 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001150
Jon Hall7eb38402015-01-08 17:19:54 -08001151 def net( self ):
1152 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001153 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001154 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001155 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001156 main.log.error( self.name + ": EOF exception found" )
1157 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001158 main.cleanup()
1159 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001160 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001161
YPZhang81a7d4e2016-04-18 13:10:17 -07001162 def links( self, timeout=20 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001163 main.log.info( self.name + ": List network links" )
1164 try:
1165 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001166 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001167 except pexpect.EOF:
1168 main.log.error( self.name + ": EOF exception found" )
1169 main.log.error( self.name + ": " + self.handle.before )
1170 main.cleanup()
1171 main.exit()
1172 return response
1173
GlennRC61321f22015-07-16 13:36:54 -07001174 def iperftcpAll(self, hosts, timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001175 '''
1176 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001177
kelvin-onlab7cce9382015-07-17 10:21:03 -07001178 @parm:
1179 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1180 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1181 '''
1182 for host1 in hosts:
1183 for host2 in hosts:
1184 if host1 != host2:
1185 if self.iperftcp(host1, host2, timeout) == main.FALSE:
1186 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
GlennRC61321f22015-07-16 13:36:54 -07001187
1188 def iperftcp(self, host1="h1", host2="h2", timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001189 '''
1190 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1191 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001192
kelvin-onlab7cce9382015-07-17 10:21:03 -07001193 @parm:
1194 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1195 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1196 '''
1197 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1198 try:
1199 # Setup the mininet command
1200 cmd1 = 'iperf ' + host1 + " " + host2
1201 self.handle.sendline( cmd1 )
1202 outcome = self.handle.expect( "mininet>", timeout )
1203 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001204
kelvin-onlab7cce9382015-07-17 10:21:03 -07001205 # checks if there are results in the mininet response
1206 if "Results:" in response:
Jon Hall892818c2015-10-20 17:58:34 -07001207 main.log.report(self.name + ": iperf test completed")
kelvin-onlab7cce9382015-07-17 10:21:03 -07001208 # parse the mn results
1209 response = response.split("\r\n")
1210 response = response[len(response)-2]
1211 response = response.split(": ")
1212 response = response[len(response)-1]
1213 response = response.replace("[", "")
1214 response = response.replace("]", "")
1215 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001216
kelvin-onlab7cce9382015-07-17 10:21:03 -07001217 # this is the bandwith two and from the two hosts
1218 bandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001219
kelvin-onlab7cce9382015-07-17 10:21:03 -07001220 # there should be two elements in the bandwidth list
1221 # ['host1 to host2', 'host2 to host1"]
1222 if len(bandwidth) == 2:
1223 main.log.report(self.name + ": iperf test successful")
1224 return main.TRUE
1225 else:
1226 main.log.error(self.name + ": invalid iperf results")
1227 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001228 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001229 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001230 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001231 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001232 main.log.error( self.name + ": TIMEOUT exception found" )
1233 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001234 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001235 # NOTE: Send ctrl-c to make sure iperf is done
1236 self.handle.sendline( "\x03" )
1237 self.handle.expect( "Interrupt" )
1238 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001239 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001240 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001241 main.log.error( self.name + ": EOF exception found" )
1242 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001243 main.cleanup()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001244 main.exit()
GlennRC61321f22015-07-16 13:36:54 -07001245
Jon Hall439c8912016-04-15 02:22:03 -07001246 def iperftcpipv6(self, host1="h1", host2="h2", timeout=50):
1247 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1248 try:
1249 IP1 = self.getIPAddress( host1, proto='IPV6' )
1250 cmd1 = host1 +' iperf -V -sD -B '+ str(IP1)
1251 self.handle.sendline( cmd1 )
1252 outcome1 = self.handle.expect( "mininet>")
1253 cmd2 = host2 +' iperf -V -c '+ str(IP1) +' -t 5'
1254 self.handle.sendline( cmd2 )
1255 outcome2 = self.handle.expect( "mininet>")
1256 response1 = self.handle.before
1257 response2 = self.handle.after
1258 print response1,response2
1259 pattern = "connected with "+ str(IP1)
1260 if pattern in response1:
1261 main.log.report(self.name + ": iperf test completed")
1262 return main.TRUE
1263 else:
1264 main.log.error( self.name + ": iperf test failed" )
1265 return main.FALSE
1266 except pexpect.TIMEOUT:
1267 main.log.error( self.name + ": TIMEOUT exception found" )
1268 main.log.error( self.name + " response: " + repr( self.handle.before ) )
1269 self.handle.sendline( "\x03" )
1270 self.handle.expect( "Interrupt" )
1271 self.handle.expect( "mininet>" )
1272 return main.FALSE
1273 except pexpect.EOF:
1274 main.log.error( self.name + ": EOF exception found" )
1275 main.log.error( self.name + ": " + self.handle.before )
1276 main.cleanup()
1277 main.exit()
1278
GlennRC61321f22015-07-16 13:36:54 -07001279 def iperfudpAll(self, hosts, bandwidth="10M"):
1280 '''
1281 Runs the iperfudp function with a given set of hosts and specified
1282 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001283
GlennRC61321f22015-07-16 13:36:54 -07001284 @param:
1285 bandwidth: the targeted bandwidth, in megabits ('M')
1286 '''
1287 for host1 in hosts:
1288 for host2 in hosts:
1289 if host1 != host2:
1290 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1291 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1292
1293 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1294
kelvin-onlab7cce9382015-07-17 10:21:03 -07001295 '''
1296 Creates an iperf UDP test with a specific bandwidth.
1297 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001298
kelvin-onlab7cce9382015-07-17 10:21:03 -07001299 @param:
1300 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1301 '''
1302 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1303 try:
1304 # setup the mininet command
1305 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1306 self.handle.sendline(cmd)
1307 self.handle.expect("mininet>")
1308 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001309
kelvin-onlab7cce9382015-07-17 10:21:03 -07001310 # check if there are in results in the mininet response
1311 if "Results:" in response:
Jon Hall892818c2015-10-20 17:58:34 -07001312 main.log.report(self.name + ": iperfudp test completed")
kelvin-onlab7cce9382015-07-17 10:21:03 -07001313 # parse the results
1314 response = response.split("\r\n")
1315 response = response[len(response)-2]
1316 response = response.split(": ")
1317 response = response[len(response)-1]
1318 response = response.replace("[", "")
1319 response = response.replace("]", "")
1320 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001321
kelvin-onlab7cce9382015-07-17 10:21:03 -07001322 mnBandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001323
kelvin-onlab7cce9382015-07-17 10:21:03 -07001324 # check to see if there are at least three entries
1325 # ['bandwidth', 'host1 to host2', 'host2 to host1']
1326 if len(mnBandwidth) == 3:
1327 # if one entry is blank then something is wrong
1328 for item in mnBandwidth:
1329 if item == "":
1330 main.log.error(self.name + ": Could not parse iperf output")
1331 main.log.error(self.name + ": invalid iperfudp results")
1332 return main.FALSE
1333 # otherwise results are vaild
1334 main.log.report(self.name + ": iperfudp test successful")
1335 return main.TRUE
1336 else:
1337 main.log.error(self.name + ": invalid iperfudp results")
1338 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001339
kelvin-onlab7cce9382015-07-17 10:21:03 -07001340 except pexpect.EOF:
1341 main.log.error( self.name + ": EOF exception found" )
1342 main.log.error( self.name + ": " + self.handle.before )
1343 main.cleanup()
1344 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001345
Jon Hall7eb38402015-01-08 17:19:54 -08001346 def nodes( self ):
1347 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001348 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001349 response = self.execute(
1350 cmd='nodes',
1351 prompt='mininet>',
1352 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001353 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001354 main.log.error( self.name + ": EOF exception found" )
1355 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001356 main.cleanup()
1357 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001358 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001359
Jon Hall7eb38402015-01-08 17:19:54 -08001360 def pingpair( self ):
1361 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001362 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001363 response = self.execute(
1364 cmd='pingpair',
1365 prompt='mininet>',
1366 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001367 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001368 main.log.error( self.name + ": EOF exception found" )
1369 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001370 main.cleanup()
1371 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001372
Jon Hall7eb38402015-01-08 17:19:54 -08001373 if re.search( ',\s0\%\spacket\sloss', response ):
1374 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001375 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001376 else:
1377 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001378 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001379
Jon Hall7eb38402015-01-08 17:19:54 -08001380 def link( self, **linkargs ):
1381 """
GlennRCed771242016-01-13 17:02:47 -08001382 Bring link( s ) between two nodes up or down
1383 """
Jon Hall6094a362014-04-11 14:46:56 -07001384 try:
GlennRCed771242016-01-13 17:02:47 -08001385 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1386 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1387 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1388 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1389
1390 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1391 cmd = "link {} {} {}".format( end1, end2, option )
1392 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001393 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001394 response = self.handle.before
1395 main.log.info( response )
1396
1397 return main.TRUE
1398 except pexpect.TIMEOUT:
1399 main.log.exception( self.name + ": Command timed out" )
1400 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001401 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001402 main.log.exception( self.name + ": connection closed." )
Jon Hall6094a362014-04-11 14:46:56 -07001403 main.cleanup()
1404 main.exit()
GlennRCed771242016-01-13 17:02:47 -08001405 except Exception:
1406 main.log.exception( self.name + ": Uncaught exception!" )
1407 main.cleanup()
1408 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001409
pingping-lin8244a3b2015-09-16 13:36:56 -07001410 def switch( self, **switchargs ):
1411 """
1412 start/stop a switch
1413 """
1414 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1415 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1416 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1417 command = "switch " + str( sw ) + " " + str( option )
1418 main.log.info( command )
1419 try:
1420 self.handle.sendline( command )
1421 self.handle.expect( "mininet>" )
1422 except pexpect.TIMEOUT:
1423 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1424 main.cleanup()
1425 main.exit()
1426 except pexpect.EOF:
1427 main.log.error( self.name + ": EOF exception found" )
1428 main.log.error( self.name + ": " + self.handle.before )
1429 main.cleanup()
1430 main.exit()
1431 return main.TRUE
1432
pingping-lin5bb663b2015-09-24 11:47:50 -07001433 def node( self, nodeName, commandStr ):
1434 """
1435 Carry out a command line on a given node
1436 @parm:
1437 nodeName: the node name in Mininet testbed
1438 commandStr: the command line will be carried out on the node
1439 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1440 """
1441 command = str( nodeName ) + " " + str( commandStr )
1442 main.log.info( command )
1443
1444 try:
1445 response = self.execute( cmd = command, prompt = "mininet>" )
1446 if re.search( "Unknown command", response ):
1447 main.log.warn( response )
1448 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001449 if re.search( "Permission denied", response ):
1450 main.log.warn( response )
1451 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001452 except pexpect.TIMEOUT:
1453 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1454 main.cleanup()
1455 main.exit()
1456 except pexpect.EOF:
1457 main.log.error( self.name + ": EOF exception found" )
1458 main.log.error( self.name + ": " + self.handle.before )
1459 main.cleanup()
1460 main.exit()
1461 main.log.info( " response is :" )
1462 main.log.info( response )
1463 return response
1464
Jon Hall7eb38402015-01-08 17:19:54 -08001465 def yank( self, **yankargs ):
1466 """
1467 yank a mininet switch interface to a host"""
1468 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001469 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001470 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1471 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1472 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001473 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001474 response = self.execute(
1475 cmd=command,
1476 prompt="mininet>",
1477 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001478 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001479 main.log.error( self.name + ": EOF exception found" )
1480 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001481 main.cleanup()
1482 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001483 return main.TRUE
1484
Jon Hall7eb38402015-01-08 17:19:54 -08001485 def plug( self, **plugargs ):
1486 """
1487 plug the yanked mininet switch interface to a switch"""
1488 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001489 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001490 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1491 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1492 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001493 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001494 response = self.execute(
1495 cmd=command,
1496 prompt="mininet>",
1497 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001498 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001499 main.log.error( self.name + ": EOF exception found" )
1500 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001501 main.cleanup()
1502 main.exit()
adminbae64d82013-08-01 10:50:15 -07001503 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001504
Jon Hall7eb38402015-01-08 17:19:54 -08001505 def dpctl( self, **dpctlargs ):
1506 """
1507 Run dpctl command on all switches."""
1508 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001509 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001510 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1511 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1512 command = "dpctl " + cmd + " " + str( cmdargs )
1513 try:
1514 response = self.execute(
1515 cmd=command,
1516 prompt="mininet>",
1517 timeout=10 )
1518 except pexpect.EOF:
1519 main.log.error( self.name + ": EOF exception found" )
1520 main.log.error( self.name + ": " + self.handle.before )
1521 main.cleanup()
1522 main.exit()
1523 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001524
kelvin-onlabd3b64892015-01-20 13:26:24 -08001525 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001526 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001527 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001528 fileInput = path + '/lib/Mininet/INSTALL'
1529 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001530 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001531 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001532 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001533 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001534 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001535 return version
adminbae64d82013-08-01 10:50:15 -07001536
kelvin-onlabd3b64892015-01-20 13:26:24 -08001537 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001538 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001539 Parameters:
1540 sw: The name of an OVS switch. Example "s1"
1541 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001542 The output of the command from the mininet cli
1543 or main.FALSE on timeout"""
1544 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001545 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001546 response = self.execute(
1547 cmd=command,
1548 prompt="mininet>",
1549 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001550 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001551 return response
admin2a9548d2014-06-17 14:08:07 -07001552 else:
1553 return main.FALSE
1554 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001555 main.log.error( self.name + ": EOF exception found" )
1556 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001557 main.cleanup()
1558 main.exit()
adminbae64d82013-08-01 10:50:15 -07001559
Charles Chan029be652015-08-24 01:46:10 +08001560 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001561 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001562 Description:
1563 Assign switches to the controllers ( for ovs use only )
1564 Required:
1565 sw - Name of the switch. This can be a list or a string.
1566 ip - Ip addresses of controllers. This can be a list or a string.
1567 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001568 port - ONOS use port 6653, if no list of ports is passed, then
1569 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001570 ptcp - ptcp number, This can be a string or a list that has
1571 the same length as switch. This is optional and not required
1572 when using ovs switches.
1573 NOTE: If switches and ptcp are given in a list type they should have the
1574 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1575 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001576
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001577 Return:
1578 Returns main.TRUE if mininet correctly assigned switches to
1579 controllers, otherwise it will return main.FALSE or an appropriate
1580 exception(s)
1581 """
1582 assignResult = main.TRUE
1583 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001584 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001585 command = "sh ovs-vsctl set-controller "
1586 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001587 try:
1588 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001589 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001590 if isinstance( port, types.StringType ) or \
1591 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001592 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001593 elif isinstance( port, types.ListType ):
1594 main.log.error( self.name + ": Only one controller " +
1595 "assigned and a list of ports has" +
1596 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001597 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001598 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001599 main.log.error( self.name + ": Invalid controller port " +
1600 "number. Please specify correct " +
1601 "controller port" )
1602 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001603
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001604 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001605 if isinstance( port, types.StringType ) or \
1606 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001607 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001608 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1609 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001610 elif isinstance( port, types.ListType ):
1611 if ( len( ip ) != len( port ) ):
1612 main.log.error( self.name + ": Port list = " +
1613 str( len( port ) ) +
1614 "should be the same as controller" +
1615 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001616 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001617 else:
1618 onosIp = ""
1619 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001620 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1621 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001622 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001623 main.log.error( self.name + ": Invalid controller port " +
1624 "number. Please specify correct " +
1625 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001626 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001627 else:
1628 main.log.error( self.name + ": Invalid ip address" )
1629 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001630
1631 if isinstance( sw, types.StringType ):
1632 command += sw + " "
1633 if ptcp:
1634 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001635 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001636 elif isinstance( ptcp, types.ListType ):
1637 main.log.error( self.name + ": Only one switch is " +
1638 "being set and multiple PTCP is " +
1639 "being passed " )
1640 else:
1641 main.log.error( self.name + ": Invalid PTCP" )
1642 ptcp = ""
1643 command += onosIp
1644 commandList.append( command )
1645
1646 elif isinstance( sw, types.ListType ):
1647 if ptcp:
1648 if isinstance( ptcp, types.ListType ):
1649 if len( ptcp ) != len( sw ):
1650 main.log.error( self.name + ": PTCP length = " +
1651 str( len( ptcp ) ) +
1652 " is not the same as switch" +
1653 " length = " +
1654 str( len( sw ) ) )
1655 return main.FALSE
1656 else:
1657 for switch, ptcpNum in zip( sw, ptcp ):
1658 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001659 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001660 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001661 tempCmd += onosIp
1662 commandList.append( tempCmd )
1663 else:
1664 main.log.error( self.name + ": Invalid PTCP" )
1665 return main.FALSE
1666 else:
1667 for switch in sw:
1668 tempCmd = "sh ovs-vsctl set-controller "
1669 tempCmd += switch + " " + onosIp
1670 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001671 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001672 main.log.error( self.name + ": Invalid switch type " )
1673 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001674
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001675 for cmd in commandList:
1676 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001677 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001678 except pexpect.TIMEOUT:
1679 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1680 return main.FALSE
1681 except pexpect.EOF:
1682 main.log.error( self.name + ": EOF exception found" )
1683 main.log.error( self.name + ": " + self.handle.before )
1684 main.cleanup()
1685 main.exit()
1686 return main.TRUE
1687 except Exception:
1688 main.log.exception( self.name + ": Uncaught exception!" )
1689 main.cleanup()
1690 main.exit()
adminbae64d82013-08-01 10:50:15 -07001691
kelvin-onlabd3b64892015-01-20 13:26:24 -08001692 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001693 """
1694 Removes the controller target from sw"""
1695 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001696 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001697 response = self.execute(
1698 cmd=command,
1699 prompt="mininet>",
1700 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001701 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001702 main.log.error( self.name + ": EOF exception found" )
1703 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001704 main.cleanup()
1705 main.exit()
1706 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001707 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001708
kelvin-onlabd3b64892015-01-20 13:26:24 -08001709 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001710 """
Jon Hallb1290e82014-11-18 16:17:48 -05001711 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001712 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001713 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001714 NOTE: cannot currently specify what type of switch
1715 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001716 sw = name of the new switch as a string
1717 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001718 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001719 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001720 """
1721 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001722 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001723 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001724 response = self.execute(
1725 cmd=command,
1726 prompt="mininet>",
1727 timeout=10 )
1728 if re.search( "already exists!", response ):
1729 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001730 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001731 elif re.search( "Error", response ):
1732 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001733 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001734 elif re.search( "usage:", response ):
1735 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001736 return main.FALSE
1737 else:
1738 return main.TRUE
1739 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001740 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001741 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001742 main.cleanup()
1743 main.exit()
1744
kelvin-onlabd3b64892015-01-20 13:26:24 -08001745 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001746 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001747 delete a switch from the mininet topology
1748 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001749 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001750 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001751 sw = name of the switch as a string
1752 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001753 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001754 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001755 response = self.execute(
1756 cmd=command,
1757 prompt="mininet>",
1758 timeout=10 )
1759 if re.search( "no switch named", response ):
1760 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001761 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001762 elif re.search( "Error", response ):
1763 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001764 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001765 elif re.search( "usage:", response ):
1766 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001767 return main.FALSE
1768 else:
1769 return main.TRUE
1770 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001771 main.log.error( self.name + ": EOF exception found" )
1772 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001773 main.cleanup()
1774 main.exit()
1775
kelvin-onlabd3b64892015-01-20 13:26:24 -08001776 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001777 """
1778 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001779 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001780 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001781 NOTE: cannot currently specify what type of link
1782 required params:
1783 node1 = the string node name of the first endpoint of the link
1784 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001785 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001786 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001787 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001788 response = self.execute(
1789 cmd=command,
1790 prompt="mininet>",
1791 timeout=10 )
1792 if re.search( "doesnt exist!", response ):
1793 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001794 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001795 elif re.search( "Error", response ):
1796 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001797 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001798 elif re.search( "usage:", response ):
1799 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001800 return main.FALSE
1801 else:
1802 return main.TRUE
1803 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001804 main.log.error( self.name + ": EOF exception found" )
1805 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001806 main.cleanup()
1807 main.exit()
1808
kelvin-onlabd3b64892015-01-20 13:26:24 -08001809 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001810 """
1811 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001812 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001813 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001814 required params:
1815 node1 = the string node name of the first endpoint of the link
1816 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001817 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001818 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001819 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001820 response = self.execute(
1821 cmd=command,
1822 prompt="mininet>",
1823 timeout=10 )
1824 if re.search( "no node named", response ):
1825 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001826 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001827 elif re.search( "Error", response ):
1828 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001829 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001830 elif re.search( "usage:", response ):
1831 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001832 return main.FALSE
1833 else:
1834 return main.TRUE
1835 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001836 main.log.error( self.name + ": EOF exception found" )
1837 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001838 main.cleanup()
1839 main.exit()
1840
kelvin-onlabd3b64892015-01-20 13:26:24 -08001841 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001842 """
Jon Hallb1290e82014-11-18 16:17:48 -05001843 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001844 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001845 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001846 NOTE: cannot currently specify what type of host
1847 required params:
1848 hostname = the string hostname
1849 optional key-value params
1850 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001851 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001852 """
1853 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001854 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001855 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001856 response = self.execute(
1857 cmd=command,
1858 prompt="mininet>",
1859 timeout=10 )
1860 if re.search( "already exists!", response ):
1861 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001862 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001863 elif re.search( "doesnt exists!", response ):
1864 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001865 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001866 elif re.search( "Error", response ):
1867 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001868 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001869 elif re.search( "usage:", response ):
1870 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001871 return main.FALSE
1872 else:
1873 return main.TRUE
1874 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001875 main.log.error( self.name + ": EOF exception found" )
1876 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001877 main.cleanup()
1878 main.exit()
1879
kelvin-onlabd3b64892015-01-20 13:26:24 -08001880 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001881 """
1882 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001883 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001884 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001885 NOTE: this uses a custom mn function
1886 required params:
1887 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001888 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001889 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001890 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001891 response = self.execute(
1892 cmd=command,
1893 prompt="mininet>",
1894 timeout=10 )
1895 if re.search( "no host named", response ):
1896 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001897 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001898 elif re.search( "Error", response ):
1899 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001900 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001901 elif re.search( "usage:", response ):
1902 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001903 return main.FALSE
1904 else:
1905 return main.TRUE
1906 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001907 main.log.error( self.name + ": EOF exception found" )
1908 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001909 main.cleanup()
1910 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001911
Jon Hall7eb38402015-01-08 17:19:54 -08001912 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001913 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001914 Called at the end of the test to stop the mininet and
1915 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001916 """
Jon Halld80cc142015-07-06 13:36:05 -07001917 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001918 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001919 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001920 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001921 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001922 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001923 elif i == 1:
1924 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001925 # print "Disconnecting Mininet"
1926 if self.handle:
1927 self.handle.sendline( "exit" )
1928 self.handle.expect( "exit" )
1929 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001930 else:
1931 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001932 return response
1933
Jon Halld80cc142015-07-06 13:36:05 -07001934 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001935 """
Jon Hall21270ac2015-02-16 17:59:55 -08001936 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001937 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001938 main.FALSE if the pexpect handle does not exist.
1939
Jon Halld61331b2015-02-17 16:35:47 -08001940 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001941 """
Jon Halld61331b2015-02-17 16:35:47 -08001942 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001943 response = ''
1944 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001945 try:
Jon Halld80cc142015-07-06 13:36:05 -07001946 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08001947 i = self.handle.expect( [ 'mininet>',
1948 '\$',
1949 pexpect.EOF,
1950 pexpect.TIMEOUT ],
1951 timeout )
1952 if i == 0:
1953 main.log.info( "Exiting mininet..." )
Jeremyd9e4eb12016-04-13 12:09:06 -07001954 response = self.execute( cmd="exit",
1955 prompt="(.*)",
1956 timeout=120 )
1957 main.log.info( self.name + ": Stopped" )
1958 self.handle.sendline( "sudo mn -c" )
1959 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001960
Jeremyd9e4eb12016-04-13 12:09:06 -07001961 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08001962 main.log.info( " Mininet trying to exit while not " +
1963 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07001964 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08001965 elif i == 2:
1966 main.log.error( "Something went wrong exiting mininet" )
1967 elif i == 3: # timeout
1968 main.log.error( "Something went wrong exiting mininet " +
1969 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001970
Hari Krishnab35c6d02015-03-18 11:13:51 -07001971 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07001972 self.handle.sendline( "" )
1973 self.handle.expect( '\$' )
1974 self.handle.sendline(
1975 "sudo kill -9 \`ps -ef | grep \"" +
1976 fileName +
1977 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001978 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001979 main.log.error( self.name + ": EOF exception found" )
1980 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001981 main.cleanup()
1982 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001983 else:
1984 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001985 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001986 return response
1987
YPZhang26a139e2016-04-25 14:01:55 -07001988 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001989 """
1990 Description:
1991 Sends arp message from mininet host for hosts discovery
1992 Required:
1993 host - hosts name
1994 Optional:
1995 ip - ip address that does not exist in the network so there would
1996 be no reply.
1997 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001998 if ethDevice:
1999 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002000 cmd = srcHost + " arping -c1 "
2001 if noResult:
2002 cmd += "-w10 " # If we don't want the actural arping result, set -w10, arping will exit after 10 ms.
2003 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002004 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002005 if output:
2006 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002007 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002008 i = self.handle.expect( [ "mininet>", "arping: " ] )
2009 if i == 0:
2010 return main.TRUE
2011 elif i == 1:
2012 response = self.handle.before + self.handle.after
2013 self.handle.expect( "mininet>" )
2014 response += self.handle.before + self.handle.after
2015 main.log.warn( "Error sending arping, output was: " +
2016 response )
2017 return main.FALSE
2018 except pexpect.TIMEOUT:
2019 main.log.error( self.name + ": TIMEOUT exception found" )
2020 main.log.warn( self.handle.before )
2021 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002022 except pexpect.EOF:
2023 main.log.error( self.name + ": EOF exception found" )
2024 main.log.error( self.name + ": " + self.handle.before )
2025 main.cleanup()
2026 main.exit()
admin07529932013-11-22 14:58:28 -08002027
Jon Hall7eb38402015-01-08 17:19:54 -08002028 def decToHex( self, num ):
2029 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002030
Jon Hall7eb38402015-01-08 17:19:54 -08002031 def getSwitchFlowCount( self, switch ):
2032 """
2033 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002034 if self.handle:
2035 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2036 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002037 response = self.execute(
2038 cmd=cmd,
2039 prompt="mininet>",
2040 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002041 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002042 main.log.error( self.name + ": EOF exception found" )
2043 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002044 main.cleanup()
2045 main.exit()
2046 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002047 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002048 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002049 main.log.info(
2050 "Couldn't find flows on switch %s, found: %s" %
2051 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002052 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002053 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002054 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002055 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002056
Jon Hall9ed8f372016-02-24 17:34:07 -08002057 def checkFlows( self, sw, dumpFormat=None ):
2058 if dumpFormat:
2059 command = "sh ovs-ofctl -F " + \
2060 dumpFormat + " dump-flows " + str( sw )
2061 else:
2062 command = "sh ovs-ofctl dump-flows " + str( sw )
2063 try:
2064 response = self.execute(
2065 cmd=command,
2066 prompt="mininet>",
2067 timeout=10 )
2068 return response
2069 except pexpect.EOF:
2070 main.log.error( self.name + ": EOF exception found" )
2071 main.log.error( self.name + ": " + self.handle.before )
2072 main.cleanup()
2073 main.exit()
2074
GlennRC68467eb2015-11-16 18:01:01 -08002075 def flowTableComp( self, flowTable1, flowTable2 ):
2076 # This function compares the selctors and treatments of each flow
2077 try:
Jon Hall41d39f12016-04-11 22:54:35 -07002078 returnValue = main.TRUE
GlennRC68467eb2015-11-16 18:01:01 -08002079 if len(flowTable1) != len(flowTable2):
2080 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002081 returnValue = main.FALSE
GlennRCfa65fce2015-12-16 13:16:08 -08002082 dFields = ["n_bytes", "cookie", "n_packets", "duration"]
2083 for flow1, flow2 in zip(flowTable1, flowTable2):
Jon Hallacd1b182015-12-17 11:43:20 -08002084 for field in dFields:
2085 try:
2086 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002087 except KeyError:
2088 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002089 try:
2090 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002091 except KeyError:
2092 pass
GlennRC68467eb2015-11-16 18:01:01 -08002093 for i in range( len(flowTable1) ):
GlennRC17bbcf52015-12-14 17:31:50 -08002094 if flowTable1[i] not in flowTable2:
2095 main.log.warn( "Flow tables do not match:" )
2096 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[i] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002097 returnValue = main.FALSE
2098 break
2099 return returnValue
GlennRC68467eb2015-11-16 18:01:01 -08002100 except Exception:
2101 main.log.exception( "Uncaught exception!" )
2102 main.cleanup()
2103 main.exit()
Jon Hall9043c902015-07-30 14:23:44 -07002104
GlennRC528ad292015-11-12 10:38:18 -08002105 def parseFlowTable( self, flowTable, version="", debug=True ):
GlennRC956ea742015-11-05 16:14:15 -08002106 '''
2107 Discription: Parses flows into json format.
2108 NOTE: this can parse any string thats separated with commas
2109 Arguments:
2110 Required:
2111 flows: a list of strings that represnt flows
2112 Optional:
2113 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2114 debug: prints out the final result
2115 returns: A list of flows in json format
2116 '''
GlennRC528ad292015-11-12 10:38:18 -08002117 jsonFlowTable = []
2118 for flow in flowTable:
GlennRC956ea742015-11-05 16:14:15 -08002119 jsonFlow = {}
GlennRC528ad292015-11-12 10:38:18 -08002120 # split up the fields of the flow
2121 parsedFlow = flow.split(", ")
2122 # get rid of any spaces in front of the field
2123 for i in range( len(parsedFlow) ):
2124 item = parsedFlow[i]
2125 if item[0] == " ":
2126 parsedFlow[i] = item[1:]
2127 # grab the selector and treatment from the parsed flow
2128 # the last element is the selector and the treatment
2129 temp = parsedFlow.pop(-1)
2130 # split up the selector and the treatment
2131 temp = temp.split(" ")
2132 index = 0
2133 # parse the flags
2134 # NOTE: This only parses one flag
2135 flag = {}
2136 if version == "1.3":
2137 flag = {"flag":[temp[index]]}
2138 index += 1
2139 # the first element is the selector and split it up
2140 sel = temp[index]
2141 index += 1
2142 sel = sel.split(",")
2143 # the priority is stuck in the selecter so put it back
2144 # in the flow
2145 parsedFlow.append(sel.pop(0))
2146 # parse selector
2147 criteria = []
2148 for item in sel:
2149 # this is the type of the packet e.g. "arp"
2150 if "=" not in item:
2151 criteria.append( {"type":item} )
2152 else:
2153 field = item.split("=")
2154 criteria.append( {field[0]:field[1]} )
GlennRC68467eb2015-11-16 18:01:01 -08002155 selector = {"selector": {"criteria":sorted(criteria)} }
GlennRC528ad292015-11-12 10:38:18 -08002156 treat = temp[index]
2157 # get rid of the action part e.g. "action=output:2"
2158 # we will add it back later
2159 treat = treat.split("=")
2160 treat.pop(0)
2161 # parse treatment
2162 action = []
2163 for item in treat:
2164 field = item.split(":")
2165 action.append( {field[0]:field[1]} )
2166 # create the treatment field and add the actions
GlennRC68467eb2015-11-16 18:01:01 -08002167 treatment = {"treatment": {"action":sorted(action)} }
GlennRC528ad292015-11-12 10:38:18 -08002168 # parse the rest of the flow
2169 for item in parsedFlow:
2170 field = item.split("=")
2171 jsonFlow.update( {field[0]:field[1]} )
2172 # add the treatment and the selector to the json flow
2173 jsonFlow.update( selector )
2174 jsonFlow.update( treatment )
2175 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002176
GlennRC528ad292015-11-12 10:38:18 -08002177 if debug: main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format(jsonFlow) )
GlennRC956ea742015-11-05 16:14:15 -08002178
GlennRC528ad292015-11-12 10:38:18 -08002179 # add the json flow to the json flow table
2180 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002181
GlennRC528ad292015-11-12 10:38:18 -08002182 return jsonFlowTable
2183
Jon Hall0a543792015-12-14 11:00:26 -08002184 def getFlowTable( self, sw, version="", debug=False):
GlennRC956ea742015-11-05 16:14:15 -08002185 '''
2186 Discription: Returns the flow table(s) on a switch or switches in a list.
2187 Each element is a flow.
2188 Arguments:
2189 Required:
2190 sw: The switch name ("s1") to retrive the flow table. Can also be
2191 a list of switches.
2192 Optional:
2193 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2194 debug: prints out the final result
2195 '''
2196 try:
2197 switches = []
2198 if type(sw) is list:
Jon Hallca7ac292015-11-11 09:28:12 -08002199 switches.extend(sw)
GlennRC956ea742015-11-05 16:14:15 -08002200 else: switches.append(sw)
2201
2202 flows = []
2203 for s in switches:
2204 cmd = "sh ovs-ofctl dump-flows " + s
2205
GlennRC528ad292015-11-12 10:38:18 -08002206 if "1.0" == version:
2207 cmd += " -F OpenFlow10-table_id"
2208 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002209 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002210
2211 main.log.info( "Sending: " + cmd )
2212 self.handle.sendline( cmd )
2213 self.handle.expect( "mininet>" )
2214 response = self.handle.before
2215 response = response.split( "\r\n" )
2216 # dump the first two elements and the last
2217 # the first element is the command that was sent
2218 # the second is the table header
2219 # the last element is empty
2220 response = response[2:-1]
2221 flows.extend( response )
2222
2223 if debug: print "Flows:\n{}\n\n".format(flows)
2224
GlennRC528ad292015-11-12 10:38:18 -08002225 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002226
2227 except pexpect.TIMEOUT:
2228 main.log.exception( self.name + ": Command timed out" )
2229 return None
2230 except pexpect.EOF:
2231 main.log.exception( self.name + ": connection closed." )
2232 main.cleanup()
2233 main.exit()
2234 except Exception:
2235 main.log.exception( self.name + ": Uncaught exception!" )
2236 main.cleanup()
2237 main.exit()
2238
2239 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
2240 '''
2241 Discription: Checks whether the ID provided matches a flow ID in Mininet
2242 Arguments:
2243 Required:
2244 sw: The switch name ("s1") to retrive the flow table. Can also be
2245 a list of switches.
2246 flowId: the flow ID in hex format. Can also be a list of IDs
2247 Optional:
2248 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2249 debug: prints out the final result
2250 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2251 NOTE: prints out IDs that are not present
2252 '''
2253 try:
2254 main.log.info( "Getting flows from Mininet" )
2255 flows = self.getFlowTable( sw, version, debug )
2256
2257 if debug: print "flow ids:\n{}\n\n".format(flowId)
2258
2259 # Check flowId is a list or a string
2260 if type( flowId ) is str:
2261 result = False
2262 for f in flows:
2263 if flowId in f.get( 'cookie' ):
2264 result = True
2265 break
2266 # flowId is a list
2267 else:
2268 result = True
2269 # Get flow IDs from Mininet
2270 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2271 # Save the IDs that are not in Mininet
2272 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2273
2274 if debug: print "mn flow ids:\n{}\n\n".format(mnFlowIds)
2275
2276 # Print out the IDs that are not in Mininet
2277 if absentIds:
2278 main.log.warn( "Absent ids: {}".format( absentIds ) )
2279 result = False
2280
2281 return main.TRUE if result else main.FALSE
2282
2283 except Exception:
2284 main.log.exception( self.name + ": Uncaught exception!" )
2285 main.cleanup()
2286 main.exit()
2287
2288
Charles Chan029be652015-08-24 01:46:10 +08002289 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002290 """
Jon Hallefbd9792015-03-05 16:11:36 -08002291 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002292 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002293 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002294 self.handle.sendline( "" )
2295 self.handle.expect( "mininet>" )
2296 self.handle.sendline(
2297 "sh sudo tcpdump -n -i " +
2298 intf +
2299 " " +
2300 port +
2301 " -w " +
2302 filename.strip() +
2303 " &" )
2304 self.handle.sendline( "" )
2305 i = self.handle.expect( [ 'No\ssuch\device',
2306 'listening\son',
2307 pexpect.TIMEOUT,
2308 "mininet>" ],
2309 timeout=10 )
2310 main.log.warn( self.handle.before + self.handle.after )
2311 self.handle.sendline( "" )
2312 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002313 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002314 main.log.error(
2315 self.name +
2316 ": tcpdump - No such device exists. " +
2317 "tcpdump attempted on: " +
2318 intf )
admin2a9548d2014-06-17 14:08:07 -07002319 return main.FALSE
2320 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002321 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002322 return main.TRUE
2323 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002324 main.log.error(
2325 self.name +
2326 ": tcpdump command timed out! Check interface name," +
2327 " given interface was: " +
2328 intf )
admin2a9548d2014-06-17 14:08:07 -07002329 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002330 elif i == 3:
2331 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002332 return main.TRUE
2333 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002334 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002335 return main.FALSE
2336 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002337 main.log.error( self.name + ": EOF exception found" )
2338 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002339 main.cleanup()
2340 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002341 except Exception:
2342 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002343 main.cleanup()
2344 main.exit()
2345
kelvin-onlabd3b64892015-01-20 13:26:24 -08002346 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002347 """
2348 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002349 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002350 self.handle.sendline( "sh sudo pkill tcpdump" )
2351 self.handle.expect( "mininet>" )
2352 self.handle.sendline( "" )
2353 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002354 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002355 main.log.error( self.name + ": EOF exception found" )
2356 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002357 main.cleanup()
2358 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002359 except Exception:
2360 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002361 main.cleanup()
2362 main.exit()
2363
Jon Halld80cc142015-07-06 13:36:05 -07002364 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002365 """
2366 Read ports from a Mininet switch.
2367
2368 Returns a json structure containing information about the
2369 ports of the given switch.
2370 """
2371 response = self.getInterfaces( nodeName )
2372 # TODO: Sanity check on response. log if no such switch exists
2373 ports = []
2374 for line in response.split( "\n" ):
2375 if not line.startswith( "name=" ):
2376 continue
2377 portVars = {}
2378 for var in line.split( "," ):
2379 key, value = var.split( "=" )
2380 portVars[ key ] = value
2381 isUp = portVars.pop( 'enabled', "True" )
2382 isUp = "True" in isUp
2383 if verbose:
2384 main.log.info( "Reading switch port %s(%s)" %
2385 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2386 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002387 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002388 mac = None
2389 ips = []
2390 ip = portVars[ 'ip' ]
2391 if ip == 'None':
2392 ip = None
2393 ips.append( ip )
2394 name = portVars[ 'name' ]
2395 if name == 'None':
2396 name = None
2397 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2398 if name == 'lo':
2399 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2400 else:
2401 portNo = re.search( portRe, name ).group( 'port' )
2402 ports.append( { 'of_port': portNo,
2403 'mac': str( mac ).replace( '\'', '' ),
2404 'name': name,
2405 'ips': ips,
2406 'enabled': isUp } )
2407 return ports
2408
Jon Halld80cc142015-07-06 13:36:05 -07002409 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002410 """
2411 Read switches from Mininet.
2412
2413 Returns a dictionary whose keys are the switch names and the value is
2414 a dictionary containing information about the switch.
2415 """
Jon Halla22481b2015-07-28 17:46:01 -07002416 # NOTE: To support new Mininet switch classes, just append the new
2417 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002418
Jon Halla22481b2015-07-28 17:46:01 -07002419 # Regex patterns to parse 'dump' output
2420 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002421 # <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 -07002422 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002423 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2424 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2425 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2426 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2427 swRE = r"<(?P<class>" + switchClasses + r")" +\
2428 r"(?P<options>\{.*\})?\s" +\
2429 r"(?P<name>[^:]+)\:\s" +\
2430 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2431 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002432 # Update mn port info
2433 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002434 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002435 dump = self.dump().split( "\n" )
2436 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002437 result = re.search( swRE, line, re.I )
2438 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002439 name = result.group( 'name' )
2440 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002441 pid = result.group( 'pid' )
2442 swClass = result.group( 'class' )
2443 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002444 if verbose:
2445 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2446 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002447 output[ name ] = { "dpid": dpid,
2448 "ports": ports,
2449 "swClass": swClass,
2450 "pid": pid,
2451 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002452 return output
2453
Jon Halld80cc142015-07-06 13:36:05 -07002454 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002455 """
2456 Read hosts from Mininet.
2457
2458 Returns a dictionary whose keys are the host names and the value is
2459 a dictionary containing information about the host.
2460 """
2461 # Regex patterns to parse dump output
2462 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002463 # <Host h1: pid=12725>
2464 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2465 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2466 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002467 # NOTE: Does not correctly match hosts with multi-links
2468 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2469 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002470 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002471 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002472 # update mn port info
2473 self.update()
2474 # Get mininet dump
2475 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002476 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002477 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002478 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002479 result = re.search( hostRE, line )
2480 name = result.group( 'name' )
2481 interfaces = []
2482 response = self.getInterfaces( name )
2483 # Populate interface info
2484 for line in response.split( "\n" ):
2485 if line.startswith( "name=" ):
2486 portVars = {}
2487 for var in line.split( "," ):
2488 key, value = var.split( "=" )
2489 portVars[ key ] = value
2490 isUp = portVars.pop( 'enabled', "True" )
2491 isUp = "True" in isUp
2492 if verbose:
2493 main.log.info( "Reading host port %s(%s)" %
2494 ( portVars[ 'name' ],
2495 portVars[ 'mac' ] ) )
2496 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002497 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002498 mac = None
2499 ips = []
2500 ip = portVars[ 'ip' ]
2501 if ip == 'None':
2502 ip = None
2503 ips.append( ip )
2504 intfName = portVars[ 'name' ]
2505 if name == 'None':
2506 name = None
2507 interfaces.append( {
2508 "name": intfName,
2509 "ips": ips,
2510 "mac": str( mac ),
2511 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002512 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002513 return hosts
2514
YPZhang81a7d4e2016-04-18 13:10:17 -07002515 def getLinks( self, timeout=20 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002516 """
2517 Gathers information about current Mininet links. These links may not
2518 be up if one of the ports is down.
2519
2520 Returns a list of dictionaries with link endpoints.
2521
2522 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002523 { 'node1': str( node1 name )
2524 'node2': str( node2 name )
2525 'port1': str( port1 of_port )
2526 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002527 Note: The port number returned is the eth#, not necessarily the of_port
2528 number. In Mininet, for OVS switch, these should be the same. For
2529 hosts, this is just the eth#.
2530 """
2531 self.update()
YPZhang81a7d4e2016-04-18 13:10:17 -07002532 response = self.links(timeout=timeout).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002533
2534 # Examples:
2535 # s1-eth3<->s2-eth1 (OK OK)
2536 # s13-eth3<->h27-eth0 (OK OK)
2537 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2538 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2539 links = []
2540 for line in response:
2541 match = re.search( linkRE, line )
2542 if match:
2543 node1 = match.group( 'node1' )
2544 node2 = match.group( 'node2' )
2545 port1 = match.group( 'port1' )
2546 port2 = match.group( 'port2' )
2547 links.append( { 'node1': node1,
2548 'node2': node2,
2549 'port1': port1,
2550 'port2': port2 } )
2551 return links
2552
2553 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002554 """
2555 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002556 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002557
Jon Hallafa8a472015-06-12 14:02:42 -07002558 Dependencies:
2559 1. numpy - "sudo pip install numpy"
2560 """
2561 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002562 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002563 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002564 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002565 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002566 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002567 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002568 main.log.error(
2569 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002570 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002571 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002572 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002573 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002574 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002575 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002576 onosDPIDs.append(
2577 switch[ 'id' ].replace(
2578 ":",
2579 '' ).replace(
2580 "of",
2581 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002582 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002583
Jon Hall7eb38402015-01-08 17:19:54 -08002584 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002585 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002586 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002587 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002588 main.log.error( str( list1 ) )
2589 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002590 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002591 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002592 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002593 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002594 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002595
Jon Hall7eb38402015-01-08 17:19:54 -08002596 # FIXME: this does not look for extra ports in ONOS, only checks that
2597 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002598 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002599
Jon Hall7eb38402015-01-08 17:19:54 -08002600 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002601 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002602 mnPorts = []
2603 onosPorts = []
2604 switchResult = main.TRUE
2605 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002606 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002607 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002608 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002609 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002610 if onosSwitch[ 'device' ][ 'id' ].replace(
2611 ':',
2612 '' ).replace(
2613 "of",
2614 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002615 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002616 if port[ 'isEnabled' ]:
2617 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002618 # onosPorts.append( 'local' )
2619 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002620 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002621 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002622 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002623 mnPorts.sort( key=float )
2624 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002625
kelvin-onlabd3b64892015-01-20 13:26:24 -08002626 mnPortsLog = mnPorts
2627 onosPortsLog = onosPorts
2628 mnPorts = [ x for x in mnPorts ]
2629 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002630
Jon Hall7eb38402015-01-08 17:19:54 -08002631 # TODO: handle other reserved port numbers besides LOCAL
2632 # NOTE: Reserved ports
2633 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2634 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002635 for mnPort in mnPortsLog:
2636 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002637 # don't set results to true here as this is just one of
2638 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002639 mnPorts.remove( mnPort )
2640 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002641
Jon Hall7eb38402015-01-08 17:19:54 -08002642 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002643 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002644 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002645 if 65534 in mnPorts:
2646 mnPorts.remove( 65534 )
2647 if long( uint64( -2 ) ) in onosPorts:
2648 onosPorts.remove( long( uint64( -2 ) ) )
2649 if len( mnPorts ): # the ports of this switch don't match
2650 switchResult = main.FALSE
2651 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2652 if len( onosPorts ): # the ports of this switch don't match
2653 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002654 main.log.warn(
2655 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002656 str( onosPorts ) )
2657 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002658 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002659 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002660 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002661 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2662 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2663 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002664 finalResults = finalResults and portsResults
2665 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002666
Jon Hallafa8a472015-06-12 14:02:42 -07002667 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002668 """
2669 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002670 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002671
Jon Hallafa8a472015-06-12 14:02:42 -07002672 """
Jon Hall7eb38402015-01-08 17:19:54 -08002673 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002674 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002675 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002676
Jon Halld80cc142015-07-06 13:36:05 -07002677 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002678 for l in links:
2679 try:
2680 node1 = switches[ l[ 'node1' ] ]
2681 node2 = switches[ l[ 'node2' ] ]
2682 enabled = True
2683 for port in node1[ 'ports' ]:
2684 if port[ 'of_port' ] == l[ 'port1' ]:
2685 enabled = enabled and port[ 'enabled' ]
2686 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002687 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002688 enabled = enabled and port[ 'enabled' ]
2689 if enabled:
2690 mnLinks.append( l )
2691 except KeyError:
2692 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002693 if 2 * len( mnLinks ) == len( onos ):
2694 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002695 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002696 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002697 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002698 "Mininet has " + str( len( mnLinks ) ) +
2699 " bidirectional links and ONOS has " +
2700 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002701
Jon Hall7eb38402015-01-08 17:19:54 -08002702 # iterate through MN links and check if an ONOS link exists in
2703 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002704 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002705 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002706 node1 = None
2707 port1 = None
2708 node2 = None
2709 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002710 firstDir = main.FALSE
2711 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002712 for swName, switch in switches.iteritems():
2713 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002714 node1 = switch[ 'dpid' ]
2715 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002716 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002717 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002718 if node1 is not None and node2 is not None:
2719 break
Jon Hallafa8a472015-06-12 14:02:42 -07002720 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002721 node2 = switch[ 'dpid' ]
2722 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002723 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002724 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002725 if node1 is not None and node2 is not None:
2726 break
2727
kelvin-onlabd3b64892015-01-20 13:26:24 -08002728 for onosLink in onos:
2729 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002730 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002731 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002732 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002733 onosPort1 = onosLink[ 'src' ][ 'port' ]
2734 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002735
Jon Hall72cf1dc2014-10-20 21:04:50 -04002736 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002737 if str( onosNode1 ) == str( node1 ) and str(
2738 onosNode2 ) == str( node2 ):
2739 if int( onosPort1 ) == int( port1 ) and int(
2740 onosPort2 ) == int( port2 ):
2741 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002742 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002743 main.log.warn(
2744 'The port numbers do not match for ' +
2745 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002746 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002747 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002748 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002749 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002750 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002751
2752 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002753 elif ( str( onosNode1 ) == str( node2 ) and
2754 str( onosNode2 ) == str( node1 ) ):
2755 if ( int( onosPort1 ) == int( port2 )
2756 and int( onosPort2 ) == int( port1 ) ):
2757 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002758 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002759 main.log.warn(
2760 'The port numbers do not match for ' +
2761 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002762 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002763 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002764 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002765 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002766 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002767 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002768 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002769 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002770 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002771 'ONOS does not have the link %s/%s -> %s/%s' %
2772 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002773 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002774 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002775 'ONOS does not have the link %s/%s -> %s/%s' %
2776 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002777 linkResults = linkResults and firstDir and secondDir
2778 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002779
Jon Hallafa8a472015-06-12 14:02:42 -07002780 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002781 """
Jon Hallafa8a472015-06-12 14:02:42 -07002782 Compare mn and onos Hosts.
2783 Since Mininet hosts are quiet, ONOS will only know of them when they
2784 speak. For this reason, we will only check that the hosts in ONOS
2785 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002786
Jon Hallafa8a472015-06-12 14:02:42 -07002787 Arguments:
2788 hostsJson: parsed json object from the onos hosts api
2789 Returns:
2790 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002791 import json
2792 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002793 for onosHost in hostsJson:
2794 onosMAC = onosHost[ 'mac' ].lower()
2795 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002796 for mnHost, info in hosts.iteritems():
2797 for mnIntf in info[ 'interfaces' ]:
2798 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002799 match = True
2800 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002801 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002802 pass # all is well
2803 else:
2804 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002805 main.log.error( "ONOS host " +
2806 onosHost[ 'id' ] +
2807 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002808 str( onosHost[ 'ipAddresses' ] ) +
2809 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002810 str( ip ) +
2811 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002812 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002813 onosHost,
2814 sort_keys=True,
2815 indent=4,
2816 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002817 main.log.info( output )
2818 hostResults = main.FALSE
2819 if not match:
2820 hostResults = main.FALSE
2821 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2822 "corresponding Mininet host." )
2823 output = json.dumps( onosHost,
2824 sort_keys=True,
2825 indent=4,
2826 separators=( ',', ': ' ) )
2827 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002828 return hostResults
2829
Jon Hallafa8a472015-06-12 14:02:42 -07002830 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002831 """
2832 Returns a list of all hosts
2833 Don't ask questions just use it"""
2834 self.handle.sendline( "" )
2835 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002836
Jon Hall7eb38402015-01-08 17:19:54 -08002837 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2838 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002839
kelvin-onlabd3b64892015-01-20 13:26:24 -08002840 handlePy = self.handle.before
2841 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2842 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002843
Jon Hall7eb38402015-01-08 17:19:54 -08002844 self.handle.sendline( "" )
2845 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002846
kelvin-onlabd3b64892015-01-20 13:26:24 -08002847 hostStr = handlePy.replace( "]", "" )
2848 hostStr = hostStr.replace( "'", "" )
2849 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002850 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002851 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002852
kelvin-onlabd3b64892015-01-20 13:26:24 -08002853 return hostList
adminbae64d82013-08-01 10:50:15 -07002854
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002855 def getSwitch( self ):
2856 """
2857 Returns a list of all switches
2858 Again, don't ask question just use it...
2859 """
2860 # get host list...
2861 hostList = self.getHosts()
2862 # Make host set
2863 hostSet = set( hostList )
2864
2865 # Getting all the nodes in mininet
2866 self.handle.sendline( "" )
2867 self.handle.expect( "mininet>" )
2868
2869 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2870 self.handle.expect( "mininet>" )
2871
2872 handlePy = self.handle.before
2873 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2874 handlePy = handlePy.rstrip()
2875
2876 self.handle.sendline( "" )
2877 self.handle.expect( "mininet>" )
2878
2879 nodesStr = handlePy.replace( "]", "" )
2880 nodesStr = nodesStr.replace( "'", "" )
2881 nodesStr = nodesStr.replace( "[", "" )
2882 nodesStr = nodesStr.replace( " ", "" )
2883 nodesList = nodesStr.split( "," )
2884
2885 nodesSet = set( nodesList )
2886 # discarding default controller(s) node
2887 nodesSet.discard( 'c0' )
2888 nodesSet.discard( 'c1' )
2889 nodesSet.discard( 'c2' )
2890
2891 switchSet = nodesSet - hostSet
2892 switchList = list( switchSet )
2893
2894 return switchList
2895
Jon Hall7eb38402015-01-08 17:19:54 -08002896 def update( self ):
2897 """
2898 updates the port address and status information for
2899 each port in mn"""
2900 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002901 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002902 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002903 self.handle.sendline( "" )
2904 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002905
Jon Hall7eb38402015-01-08 17:19:54 -08002906 self.handle.sendline( "update" )
2907 self.handle.expect( "update" )
2908 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002909
Jon Hall7eb38402015-01-08 17:19:54 -08002910 self.handle.sendline( "" )
2911 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002912
Jon Hallb1290e82014-11-18 16:17:48 -05002913 return main.TRUE
2914 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002915 main.log.error( self.name + ": EOF exception found" )
2916 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002917 main.cleanup()
2918 main.exit()
2919
Jon Halld80cc142015-07-06 13:36:05 -07002920 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002921 """
2922 Add vlan tag to a host.
2923 Dependencies:
2924 This class depends on the "vlan" package
2925 $ sudo apt-get install vlan
2926 Configuration:
2927 Load the 8021q module into the kernel
2928 $sudo modprobe 8021q
2929
2930 To make this setup permanent:
2931 $ sudo su -c 'echo "8021q" >> /etc/modules'
2932 """
2933 if self.handle:
2934 try:
Jon Halld80cc142015-07-06 13:36:05 -07002935 # get the ip address of the host
2936 main.log.info( "Get the ip address of the host" )
2937 ipaddr = self.getIPAddress( host )
2938 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002939
Jon Halld80cc142015-07-06 13:36:05 -07002940 # remove IP from interface intf
2941 # Ex: h1 ifconfig h1-eth0 inet 0
2942 main.log.info( "Remove IP from interface " )
2943 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2944 self.handle.sendline( cmd2 )
2945 self.handle.expect( "mininet>" )
2946 response = self.handle.before
2947 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002948
Jon Halld80cc142015-07-06 13:36:05 -07002949 # create VLAN interface
2950 # Ex: h1 vconfig add h1-eth0 100
2951 main.log.info( "Create Vlan" )
2952 cmd3 = host + " vconfig add " + intf + " " + vlan
2953 self.handle.sendline( cmd3 )
2954 self.handle.expect( "mininet>" )
2955 response = self.handle.before
2956 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002957
Jon Halld80cc142015-07-06 13:36:05 -07002958 # assign the host's IP to the VLAN interface
2959 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2960 main.log.info( "Assign the host IP to the vlan interface" )
2961 vintf = intf + "." + vlan
2962 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2963 self.handle.sendline( cmd4 )
2964 self.handle.expect( "mininet>" )
2965 response = self.handle.before
2966 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002967
2968 return main.TRUE
2969 except pexpect.EOF:
2970 main.log.error( self.name + ": EOF exception found" )
2971 main.log.error( self.name + ": " + self.handle.before )
2972 return main.FALSE
2973
Jon Hall892818c2015-10-20 17:58:34 -07002974 def createHostComponent( self, name ):
2975 """
2976 Creates a new mininet cli component with the same parameters as self.
2977 This new component is intended to be used to login to the hosts created
2978 by mininet.
2979
2980 Arguments:
2981 name - The string of the name of this component. The new component
2982 will be assigned to main.<name> .
2983 In addition, main.<name>.name = str( name )
2984 """
2985 try:
2986 # look to see if this component already exists
2987 getattr( main, name )
2988 except AttributeError:
2989 # namespace is clear, creating component
2990 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
2991 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
2992 main.componentInit( name )
2993 except Exception:
2994 main.log.exception( self.name + ": Uncaught exception!" )
2995 main.cleanup()
2996 main.exit()
2997 else:
2998 # namespace is not clear!
2999 main.log.error( name + " component already exists!" )
3000 # FIXME: Should we exit here?
3001 main.cleanup()
3002 main.exit()
3003
3004 def removeHostComponent( self, name ):
3005 """
3006 Remove host component
3007 Arguments:
3008 name - The string of the name of the component to delete.
3009 """
3010 try:
3011 # Get host component
3012 component = getattr( main, name )
3013 except AttributeError:
3014 main.log.error( "Component " + name + " does not exist." )
3015 return
3016 try:
3017 # Disconnect from component
3018 component.disconnect()
3019 # Delete component
3020 delattr( main, name )
3021 # Delete component from ComponentDictionary
3022 del( main.componentDictionary[name] )
3023 except Exception:
3024 main.log.exception( self.name + ": Uncaught exception!" )
3025 main.cleanup()
3026 main.exit()
3027
3028 def startHostCli( self, host=None ):
3029 """
3030 Use the mininet m utility to connect to the host's cli
3031 """
3032 # These are fields that can be used by scapy packets. Initialized to None
3033 self.hostIp = None
3034 self.hostMac = None
3035 try:
3036 if not host:
3037 host = self.name
3038 self.handle.sendline( self.home + "/util/m " + host )
3039 self.handle.expect( self.hostPrompt )
3040 return main.TRUE
3041 except pexpect.TIMEOUT:
3042 main.log.exception( self.name + ": Command timed out" )
3043 return main.FALSE
3044 except pexpect.EOF:
3045 main.log.exception( self.name + ": connection closed." )
3046 main.cleanup()
3047 main.exit()
3048 except Exception:
3049 main.log.exception( self.name + ": Uncaught exception!" )
3050 main.cleanup()
3051 main.exit()
3052
GlennRC956ea742015-11-05 16:14:15 -08003053 def startScapy( self, mplsPath="" ):
Jon Hall892818c2015-10-20 17:58:34 -07003054 """
3055 Start the Scapy cli
GlennRC956ea742015-11-05 16:14:15 -08003056 optional:
3057 mplsPath - The path where the MPLS class is located
3058 NOTE: This can be a relative path from the user's home dir
Jon Hall892818c2015-10-20 17:58:34 -07003059 """
GlennRC956ea742015-11-05 16:14:15 -08003060 mplsLines = ['import imp',
3061 'imp.load_source( "mplsClass", "{}mplsClass.py" )'.format(mplsPath),
3062 'from mplsClass import MPLS',
3063 'bind_layers(Ether, MPLS, type = 0x8847)',
3064 'bind_layers(MPLS, MPLS, bottom_of_label_stack = 0)',
3065 'bind_layers(MPLS, IP)']
3066
Jon Hall892818c2015-10-20 17:58:34 -07003067 try:
3068 self.handle.sendline( "scapy" )
3069 self.handle.expect( self.scapyPrompt )
3070 self.handle.sendline( "conf.color_theme = NoTheme()" )
3071 self.handle.expect( self.scapyPrompt )
GlennRC956ea742015-11-05 16:14:15 -08003072 if mplsPath:
3073 main.log.info( "Adding MPLS class" )
3074 main.log.info( "MPLS class path: " + mplsPath )
3075 for line in mplsLines:
3076 main.log.info( "sending line: " + line )
3077 self.handle.sendline( line )
3078 self.handle.expect( self.scapyPrompt )
Jon Hall892818c2015-10-20 17:58:34 -07003079 return main.TRUE
3080 except pexpect.TIMEOUT:
3081 main.log.exception( self.name + ": Command timed out" )
3082 return main.FALSE
3083 except pexpect.EOF:
3084 main.log.exception( self.name + ": connection closed." )
3085 main.cleanup()
3086 main.exit()
3087 except Exception:
3088 main.log.exception( self.name + ": Uncaught exception!" )
3089 main.cleanup()
3090 main.exit()
3091
3092 def stopScapy( self ):
3093 """
3094 Exit the Scapy cli
3095 """
3096 try:
3097 self.handle.sendline( "exit()" )
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
3112 def buildEther( self, **kwargs ):
3113 """
3114 Build an Ethernet frame
3115
3116 Will create a frame class with the given options. If a field is
3117 left blank it will default to the below value unless it is
3118 overwritten by the next frame.
3119 Default frame:
3120 ###[ Ethernet ]###
3121 dst= ff:ff:ff:ff:ff:ff
3122 src= 00:00:00:00:00:00
3123 type= 0x800
3124
3125 Returns main.TRUE or main.FALSE on error
3126 """
3127 try:
3128 # Set the Ethernet frame
3129 cmd = 'ether = Ether( '
3130 options = []
3131 for key, value in kwargs.iteritems():
3132 if isinstance( value, str ):
3133 value = '"' + value + '"'
3134 options.append( str( key ) + "=" + str( value ) )
3135 cmd += ", ".join( options )
3136 cmd += ' )'
3137 self.handle.sendline( cmd )
3138 self.handle.expect( self.scapyPrompt )
3139 if "Traceback" in self.handle.before:
3140 # KeyError, SyntaxError, ...
3141 main.log.error( "Error in sending command: " + self.handle.before )
3142 return main.FALSE
3143 self.handle.sendline( "packet = ether" )
3144 self.handle.expect( self.scapyPrompt )
3145 if "Traceback" in self.handle.before:
3146 # KeyError, SyntaxError, ...
3147 main.log.error( "Error in sending command: " + self.handle.before )
3148 return main.FALSE
3149 return main.TRUE
3150 except pexpect.TIMEOUT:
3151 main.log.exception( self.name + ": Command timed out" )
3152 return main.FALSE
3153 except pexpect.EOF:
3154 main.log.exception( self.name + ": connection closed." )
3155 main.cleanup()
3156 main.exit()
3157 except Exception:
3158 main.log.exception( self.name + ": Uncaught exception!" )
3159 main.cleanup()
3160 main.exit()
3161
3162 def buildIP( self, **kwargs ):
3163 """
3164 Build an IP frame
3165
3166 Will create a frame class with the given options. If a field is
3167 left blank it will default to the below value unless it is
3168 overwritten by the next frame.
3169 Default frame:
3170 ###[ IP ]###
3171 version= 4
3172 ihl= None
3173 tos= 0x0
3174 len= None
3175 id= 1
3176 flags=
3177 frag= 0
3178 ttl= 64
3179 proto= hopopt
3180 chksum= None
3181 src= 127.0.0.1
3182 dst= 127.0.0.1
3183 \options\
3184
3185 Returns main.TRUE or main.FALSE on error
3186 """
3187 try:
3188 # Set the IP frame
3189 cmd = 'ip = IP( '
3190 options = []
3191 for key, value in kwargs.iteritems():
3192 if isinstance( value, str ):
3193 value = '"' + value + '"'
3194 options.append( str( key ) + "=" + str( value ) )
3195 cmd += ", ".join( options )
3196 cmd += ' )'
3197 self.handle.sendline( cmd )
3198 self.handle.expect( self.scapyPrompt )
3199 if "Traceback" in self.handle.before:
3200 # KeyError, SyntaxError, ...
3201 main.log.error( "Error in sending command: " + self.handle.before )
3202 return main.FALSE
3203 self.handle.sendline( "packet = ether/ip" )
3204 self.handle.expect( self.scapyPrompt )
3205 if "Traceback" in self.handle.before:
3206 # KeyError, SyntaxError, ...
3207 main.log.error( "Error in sending command: " + self.handle.before )
3208 return main.FALSE
3209 return main.TRUE
3210 except pexpect.TIMEOUT:
3211 main.log.exception( self.name + ": Command timed out" )
3212 return main.FALSE
3213 except pexpect.EOF:
3214 main.log.exception( self.name + ": connection closed." )
3215 main.cleanup()
3216 main.exit()
3217 except Exception:
3218 main.log.exception( self.name + ": Uncaught exception!" )
3219 main.cleanup()
3220 main.exit()
3221
3222 def buildIPv6( self, **kwargs ):
3223 """
3224 Build an IPv6 frame
3225
3226 Will create a frame class with the given options. If a field is
3227 left blank it will default to the below value unless it is
3228 overwritten by the next frame.
3229 Default frame:
3230 ###[ IPv6 ]###
3231 version= 6
3232 tc= 0
3233 fl= 0
3234 plen= None
3235 nh= No Next Header
3236 hlim= 64
3237 src= ::1
3238 dst= ::1
3239
3240 Returns main.TRUE or main.FALSE on error
3241 """
3242 try:
3243 # Set the IPv6 frame
3244 cmd = 'ipv6 = IPv6( '
3245 options = []
3246 for key, value in kwargs.iteritems():
3247 if isinstance( value, str ):
3248 value = '"' + value + '"'
3249 options.append( str( key ) + "=" + str( value ) )
3250 cmd += ", ".join( options )
3251 cmd += ' )'
3252 self.handle.sendline( cmd )
3253 self.handle.expect( self.scapyPrompt )
3254 if "Traceback" in self.handle.before:
3255 # KeyError, SyntaxError, ...
3256 main.log.error( "Error in sending command: " + self.handle.before )
3257 return main.FALSE
3258 self.handle.sendline( "packet = ether/ipv6" )
3259 self.handle.expect( self.scapyPrompt )
3260 if "Traceback" in self.handle.before:
3261 # KeyError, SyntaxError, ...
3262 main.log.error( "Error in sending command: " + self.handle.before )
3263 return main.FALSE
3264 return main.TRUE
3265 except pexpect.TIMEOUT:
3266 main.log.exception( self.name + ": Command timed out" )
3267 return main.FALSE
3268 except pexpect.EOF:
3269 main.log.exception( self.name + ": connection closed." )
3270 main.cleanup()
3271 main.exit()
3272 except Exception:
3273 main.log.exception( self.name + ": Uncaught exception!" )
3274 main.cleanup()
3275 main.exit()
3276
3277 def buildTCP( self, ipVersion=4, **kwargs ):
3278 """
3279 Build an TCP frame
3280
3281 Will create a frame class with the given options. If a field is
3282 left blank it will default to the below value unless it is
3283 overwritten by the next frame.
3284
GlennRC956ea742015-11-05 16:14:15 -08003285 NOTE: Some arguments require quotes around them. It's up to you to
3286 know which ones and to add them yourself. Arguments with an asterisk
3287 do not need quotes.
3288
Jon Hall892818c2015-10-20 17:58:34 -07003289 Options:
3290 ipVersion - Either 4 (default) or 6, indicates what Internet Protocol
3291 frame to use to encapsulate into
3292 Default frame:
3293 ###[ TCP ]###
GlennRC956ea742015-11-05 16:14:15 -08003294 sport= ftp_data *
3295 dport= http *
Jon Hall892818c2015-10-20 17:58:34 -07003296 seq= 0
3297 ack= 0
3298 dataofs= None
3299 reserved= 0
3300 flags= S
3301 window= 8192
3302 chksum= None
3303 urgptr= 0
3304 options= {}
3305
3306 Returns main.TRUE or main.FALSE on error
3307 """
3308 try:
3309 # Set the TCP frame
3310 cmd = 'tcp = TCP( '
3311 options = []
3312 for key, value in kwargs.iteritems():
Jon Hall892818c2015-10-20 17:58:34 -07003313 options.append( str( key ) + "=" + str( value ) )
3314 cmd += ", ".join( options )
3315 cmd += ' )'
3316 self.handle.sendline( cmd )
3317 self.handle.expect( self.scapyPrompt )
3318 if "Traceback" in self.handle.before:
3319 # KeyError, SyntaxError, ...
3320 main.log.error( "Error in sending command: " + self.handle.before )
3321 return main.FALSE
3322 if str( ipVersion ) is '4':
3323 self.handle.sendline( "packet = ether/ip/tcp" )
3324 elif str( ipVersion ) is '6':
3325 self.handle.sendline( "packet = ether/ipv6/tcp" )
3326 else:
3327 main.log.error( "Unrecognized option for ipVersion, given " +
3328 repr( ipVersion ) )
3329 return main.FALSE
3330 self.handle.expect( self.scapyPrompt )
3331 if "Traceback" in self.handle.before:
3332 # KeyError, SyntaxError, ...
3333 main.log.error( "Error in sending command: " + self.handle.before )
3334 return main.FALSE
3335 return main.TRUE
3336 except pexpect.TIMEOUT:
3337 main.log.exception( self.name + ": Command timed out" )
3338 return main.FALSE
3339 except pexpect.EOF:
3340 main.log.exception( self.name + ": connection closed." )
3341 main.cleanup()
3342 main.exit()
3343 except Exception:
3344 main.log.exception( self.name + ": Uncaught exception!" )
3345 main.cleanup()
3346 main.exit()
3347
3348 def buildUDP( self, ipVersion=4, **kwargs ):
3349 """
3350 Build an UDP frame
3351
3352 Will create a frame class with the given options. If a field is
3353 left blank it will default to the below value unless it is
3354 overwritten by the next frame.
3355
GlennRC956ea742015-11-05 16:14:15 -08003356 NOTE: Some arguments require quotes around them. It's up to you to
3357 know which ones and to add them yourself. Arguments with an asterisk
3358 do not need quotes.
3359
Jon Hall892818c2015-10-20 17:58:34 -07003360 Options:
3361 ipVersion - Either 4 (default) or 6, indicates what Internet Protocol
3362 frame to use to encapsulate into
3363 Default frame:
3364 ###[ UDP ]###
GlennRC956ea742015-11-05 16:14:15 -08003365 sport= domain *
3366 dport= domain *
Jon Hall892818c2015-10-20 17:58:34 -07003367 len= None
3368 chksum= None
3369
3370 Returns main.TRUE or main.FALSE on error
3371 """
3372 try:
3373 # Set the UDP frame
3374 cmd = 'udp = UDP( '
3375 options = []
3376 for key, value in kwargs.iteritems():
Jon Hall892818c2015-10-20 17:58:34 -07003377 options.append( str( key ) + "=" + str( value ) )
3378 cmd += ", ".join( options )
3379 cmd += ' )'
3380 self.handle.sendline( cmd )
3381 self.handle.expect( self.scapyPrompt )
3382 if "Traceback" in self.handle.before:
3383 # KeyError, SyntaxError, ...
3384 main.log.error( "Error in sending command: " + self.handle.before )
3385 return main.FALSE
3386 if str( ipVersion ) is '4':
3387 self.handle.sendline( "packet = ether/ip/udp" )
3388 elif str( ipVersion ) is '6':
3389 self.handle.sendline( "packet = ether/ipv6/udp" )
3390 else:
3391 main.log.error( "Unrecognized option for ipVersion, given " +
3392 repr( ipVersion ) )
3393 return main.FALSE
3394 self.handle.expect( self.scapyPrompt )
3395 if "Traceback" in self.handle.before:
3396 # KeyError, SyntaxError, ...
3397 main.log.error( "Error in sending command: " + self.handle.before )
3398 return main.FALSE
3399 return main.TRUE
3400 except pexpect.TIMEOUT:
3401 main.log.exception( self.name + ": Command timed out" )
3402 return main.FALSE
3403 except pexpect.EOF:
3404 main.log.exception( self.name + ": connection closed." )
3405 main.cleanup()
3406 main.exit()
3407 except Exception:
3408 main.log.exception( self.name + ": Uncaught exception!" )
3409 main.cleanup()
3410 main.exit()
3411
3412 def buildICMP( self, **kwargs ):
3413 """
3414 Build an ICMP frame
3415
3416 Will create a frame class with the given options. If a field is
3417 left blank it will default to the below value unless it is
3418 overwritten by the next frame.
3419 Default frame:
3420 ###[ ICMP ]###
3421 type= echo-request
3422 code= 0
3423 chksum= None
3424 id= 0x0
3425 seq= 0x0
3426
3427 Returns main.TRUE or main.FALSE on error
3428 """
3429 try:
3430 # Set the ICMP frame
3431 cmd = 'icmp = ICMP( '
3432 options = []
3433 for key, value in kwargs.iteritems():
3434 if isinstance( value, str ):
3435 value = '"' + value + '"'
3436 options.append( str( key ) + "=" + str( value ) )
3437 cmd += ", ".join( options )
3438 cmd += ' )'
3439 self.handle.sendline( cmd )
3440 self.handle.expect( self.scapyPrompt )
3441 if "Traceback" in self.handle.before:
3442 # KeyError, SyntaxError, ...
3443 main.log.error( "Error in sending command: " + self.handle.before )
3444 return main.FALSE
3445 self.handle.sendline( "packet = ether/ip/icmp" )
3446 self.handle.expect( self.scapyPrompt )
3447 if "Traceback" in self.handle.before:
3448 # KeyError, SyntaxError, ...
3449 main.log.error( "Error in sending command: " + self.handle.before )
3450 return main.FALSE
3451 return main.TRUE
3452 except pexpect.TIMEOUT:
3453 main.log.exception( self.name + ": Command timed out" )
3454 return main.FALSE
3455 except pexpect.EOF:
3456 main.log.exception( self.name + ": connection closed." )
3457 main.cleanup()
3458 main.exit()
3459 except Exception:
3460 main.log.exception( self.name + ": Uncaught exception!" )
3461 main.cleanup()
3462 main.exit()
3463
GlennRC073e8bc2015-10-27 17:11:28 -07003464 def sendPacket( self, iface=None, packet=None, timeout=1 ):
Jon Hall892818c2015-10-20 17:58:34 -07003465 """
3466 Send a packet with either the given scapy packet command, or use the
3467 packet saved in the variable 'packet'.
3468
3469 Examples of a valid string for packet:
3470
3471 Simple IP packet
3472 packet='Ether(dst="a6:d9:26:df:1d:4b")/IP(dst="10.0.0.2")'
3473
3474 A Ping with two vlan tags
3475 packet='Ether(dst='ff:ff:ff:ff:ff:ff')/Dot1Q(vlan=1)/Dot1Q(vlan=10)/
3476 IP(dst='255.255.255.255', src='192.168.0.1')/ICMP()'
3477
3478 Returns main.TRUE or main.FALSE on error
3479 """
3480 try:
3481 # TODO: add all params, or use kwargs
3482 sendCmd = 'srp( '
3483 if packet:
3484 sendCmd += packet
3485 else:
3486 sendCmd += "packet"
GlennRC073e8bc2015-10-27 17:11:28 -07003487 if iface:
3488 sendCmd += ", iface='{}'".format( iface )
3489
Jon Hall892818c2015-10-20 17:58:34 -07003490 sendCmd += ', timeout=' + str( timeout ) + ')'
3491 self.handle.sendline( sendCmd )
3492 self.handle.expect( self.scapyPrompt )
3493 if "Traceback" in self.handle.before:
3494 # KeyError, SyntaxError, ...
3495 main.log.error( "Error in sending command: " + self.handle.before )
3496 return main.FALSE
3497 # TODO: Check # of packets sent?
3498 return main.TRUE
3499 except pexpect.TIMEOUT:
3500 main.log.exception( self.name + ": Command timed out" )
3501 return main.FALSE
3502 except pexpect.EOF:
3503 main.log.exception( self.name + ": connection closed." )
3504 main.cleanup()
3505 main.exit()
3506 except Exception:
3507 main.log.exception( self.name + ": Uncaught exception!" )
3508 main.cleanup()
3509 main.exit()
3510
3511 def startFilter( self, ifaceName=None, sniffCount=1, pktFilter="ip" ):
3512 """
3513 Listen for packets using the given filters
3514
3515 Options:
3516 ifaceName - the name of the interface to listen on. If none is given,
3517 defaults to <host name>-eth0
3518 pktFilter - A string in Berkeley Packet Filter (BPF) format which
3519 specifies which packets to sniff
3520 sniffCount - The number of matching packets to capture before returning
3521
3522 Returns main.TRUE or main.FALSE on error
3523 """
3524 try:
3525 # TODO: add all params, or use kwargs
3526 ifaceName = str( ifaceName ) if ifaceName else self.name + "-eth0"
3527 # Set interface
3528 self.handle.sendline( ' conf.iface = "' + ifaceName + '"' )
3529 self.handle.expect( self.scapyPrompt )
3530 cmd = 'pkt = sniff(count = ' + str( sniffCount ) +\
3531 ', filter = "' + str( pktFilter ) + '")'
3532 self.handle.sendline( cmd )
3533 self.handle.expect( '"\)\r\n' )
3534 # TODO: parse this?
3535 return main.TRUE
3536 except pexpect.TIMEOUT:
3537 main.log.exception( self.name + ": Command timed out" )
3538 return main.FALSE
3539 except pexpect.EOF:
3540 main.log.exception( self.name + ": connection closed." )
3541 main.cleanup()
3542 main.exit()
3543 except Exception:
3544 main.log.exception( self.name + ": Uncaught exception!" )
3545 main.cleanup()
3546 main.exit()
3547
3548 def checkFilter( self ):
3549 """
3550 Check that a filter returned and returns the reponse
3551 """
3552 try:
3553 i = self.handle.expect( [ self.scapyPrompt, pexpect.TIMEOUT ] )
3554 if i == 0:
3555 return main.TRUE
3556 else:
3557 return main.FALSE
3558 except pexpect.EOF:
3559 main.log.exception( self.name + ": connection closed." )
3560 main.cleanup()
3561 main.exit()
3562 except Exception:
3563 main.log.exception( self.name + ": Uncaught exception!" )
3564 main.cleanup()
3565 main.exit()
3566
3567 def killFilter( self ):
3568 """
3569 Kill a scapy filter
3570 """
3571 try:
3572 self.handle.send( "\x03" ) # Send a ctrl-c to kill the filter
3573 self.handle.expect( self.scapyPrompt )
3574 return self.handle.before
3575 except pexpect.TIMEOUT:
3576 main.log.exception( self.name + ": Command timed out" )
3577 return None
3578 except pexpect.EOF:
3579 main.log.exception( self.name + ": connection closed." )
3580 main.cleanup()
3581 main.exit()
3582 except Exception:
3583 main.log.exception( self.name + ": Uncaught exception!" )
3584 main.cleanup()
3585 main.exit()
3586
3587 def readPackets( self ):
3588 """
3589 Read all the packets captured by the previous filter
3590 """
3591 try:
3592 self.handle.sendline( "for p in pkt: p \n")
3593 self.handle.expect( "for p in pkt: p \r\n... \r\n" )
3594 self.handle.expect( self.scapyPrompt )
3595 except pexpect.TIMEOUT:
3596 main.log.exception( self.name + ": Command timed out" )
3597 return None
3598 except pexpect.EOF:
3599 main.log.exception( self.name + ": connection closed." )
3600 main.cleanup()
3601 main.exit()
3602 except Exception:
3603 main.log.exception( self.name + ": Uncaught exception!" )
3604 main.cleanup()
3605 main.exit()
3606 return self.handle.before
3607
3608 def updateSelf( self ):
3609 """
3610 Updates local MAC and IP fields
3611 """
3612 self.hostMac = self.getMac()
3613 self.hostIp = self.getIp()
3614
3615 def getMac( self, ifaceName=None ):
3616 """
3617 Save host's MAC address
3618 """
3619 try:
3620 ifaceName = str( ifaceName ) if ifaceName else self.name + "-eth0"
3621 cmd = 'get_if_hwaddr("' + str( ifaceName ) + '")'
3622 self.handle.sendline( cmd )
3623 self.handle.expect( self.scapyPrompt )
3624 pattern = r'(([0-9a-f]{2}[:-]){5}([0-9a-f]{2}))'
3625 match = re.search( pattern, self.handle.before )
3626 if match:
3627 return match.group()
3628 else:
3629 # the command will have an exception if iface doesn't exist
3630 return None
3631 except pexpect.TIMEOUT:
3632 main.log.exception( self.name + ": Command timed out" )
3633 return None
3634 except pexpect.EOF:
3635 main.log.exception( self.name + ": connection closed." )
3636 main.cleanup()
3637 main.exit()
3638 except Exception:
3639 main.log.exception( self.name + ": Uncaught exception!" )
3640 main.cleanup()
3641 main.exit()
3642
3643 def getIp( self, ifaceName=None ):
3644 """
3645 Save host's IP address
3646 """
3647 try:
3648 ifaceName = ifaceName if ifaceName else self.name + "-eth0"
3649 cmd = 'get_if_addr("' + str( ifaceName ) + '")'
3650 self.handle.sendline( cmd )
3651 self.handle.expect( self.scapyPrompt )
3652
3653 pattern = r'(((2[0-5]|1[0-9]|[0-9])?[0-9]\.){3}((2[0-5]|1[0-9]|[0-9])?[0-9]))'
3654 match = re.search( pattern, self.handle.before )
3655 if match:
3656 # NOTE: The command will return 0.0.0.0 if the iface doesn't exist
3657 return match.group()
3658 else:
3659 return None
3660 except pexpect.TIMEOUT:
3661 main.log.exception( self.name + ": Command timed out" )
3662 return None
3663 except pexpect.EOF:
3664 main.log.exception( self.name + ": connection closed." )
3665 main.cleanup()
3666 main.exit()
3667 except Exception:
3668 main.log.exception( self.name + ": Uncaught exception!" )
3669 main.cleanup()
3670 main.exit()
3671
adminbae64d82013-08-01 10:50:15 -07003672if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07003673 sys.modules[ __name__ ] = MininetCliDriver()