blob: 41670f72d7c6b09cecf50d3efda944c0e8ec5673 [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
497 pingCmd = str( host ) + cmd + prefix + str( temp[1:] )
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
kelvin-onlaba1484582015-02-02 15:46:20 -0800682 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[]
Jon Halld80cc142015-07-06 13:36:05 -0700688 ( which is correct behavior since the interfaces
689 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800690 """
691 if self.handle:
692 try:
693 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700694 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800695 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800696 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800697 response = self.execute( cmd=cmd,
698 prompt="mininet>",
699 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700700
kelvin-onlaba1484582015-02-02 15:46:20 -0800701 # Determine hostintf and Oldswitchintf
702 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800703 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800704 print "cmd2= ", cmd
705 self.handle.sendline( cmd )
706 self.handle.expect( "mininet>" )
707
shahshreya73537862015-02-11 15:15:24 -0800708 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800709 cmd = "px ipaddr = hintf.IP()"
710 print "cmd3= ", cmd
711 self.handle.sendline( cmd )
712 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800713
714 cmd = "px macaddr = hintf.MAC()"
715 print "cmd3= ", cmd
716 self.handle.sendline( cmd )
717 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700718
kelvin-onlaba1484582015-02-02 15:46:20 -0800719 # 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>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700730
kelvin-onlaba1484582015-02-02 15:46:20 -0800731 # Determine hostintf and Newswitchintf
732 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800733 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800734 print "cmd6= ", cmd
735 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700736 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800737
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>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700743
kelvin-onlaba1484582015-02-02 15:46:20 -0800744 # 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>" )
shahshreya73537862015-02-11 15:15:24 -0800749
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>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700755
kelvin-onlaba1484582015-02-02 15:46:20 -0800756 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800757 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800758 self.handle.sendline( cmd )
759 self.handle.expect( "mininet>" )
760 print "output = ", self.handle.before
761
762 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800763 cmd = host + " ifconfig"
764 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800765 self.handle.sendline( cmd )
766 self.handle.expect( "mininet>" )
767 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700768
kelvin-onlaba1484582015-02-02 15:46:20 -0800769 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 Hall7eb38402015-01-08 17:19:54 -0800775 def changeIP( self, host, intf, newIP, newNetmask ):
776 """
777 Changes the ip address of a host on the fly
778 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800779 if self.handle:
780 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800781 cmd = host + " ifconfig " + intf + " " + \
782 newIP + " " + 'netmask' + " " + newNetmask
783 self.handle.sendline( cmd )
784 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800785 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800786 main.log.info( "response = " + response )
787 main.log.info(
788 "Ip of host " +
789 host +
790 " changed to new IP " +
791 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800792 return main.TRUE
793 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800794 main.log.error( self.name + ": EOF exception found" )
795 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800796 return main.FALSE
797
Jon Hall7eb38402015-01-08 17:19:54 -0800798 def changeDefaultGateway( self, host, newGW ):
799 """
800 Changes the default gateway of a host
801 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800802 if self.handle:
803 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800804 cmd = host + " route add default gw " + newGW
805 self.handle.sendline( cmd )
806 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800807 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800808 main.log.info( "response = " + response )
809 main.log.info(
810 "Default gateway of host " +
811 host +
812 " changed to " +
813 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800814 return main.TRUE
815 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800816 main.log.error( self.name + ": EOF exception found" )
817 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800818 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800819
Jon Hall7eb38402015-01-08 17:19:54 -0800820 def addStaticMACAddress( self, host, GW, macaddr ):
821 """
Jon Hallefbd9792015-03-05 16:11:36 -0800822 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800823 if self.handle:
824 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800825 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
826 cmd = host + " arp -s " + GW + " " + macaddr
827 self.handle.sendline( cmd )
828 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800829 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800830 main.log.info( "response = " + response )
831 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800832 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800833 GW +
834 " changed to " +
835 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800836 return main.TRUE
837 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800838 main.log.error( self.name + ": EOF exception found" )
839 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800840 return main.FALSE
841
Jon Hall7eb38402015-01-08 17:19:54 -0800842 def verifyStaticGWandMAC( self, host ):
843 """
844 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800845 if self.handle:
846 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800847 # h1 arp -an
848 cmd = host + " arp -an "
849 self.handle.sendline( cmd )
850 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800851 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800852 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800853 return main.TRUE
854 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800855 main.log.error( self.name + ": EOF exception found" )
856 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800857 return main.FALSE
858
Jon Hall7eb38402015-01-08 17:19:54 -0800859 def getMacAddress( self, host ):
860 """
861 Verifies the host's ip configured or not."""
862 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700863 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800864 response = self.execute(
865 cmd=host +
866 " ifconfig",
867 prompt="mininet>",
868 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800869 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800870 main.log.error( self.name + ": EOF exception found" )
871 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700872 main.cleanup()
873 main.exit()
adminbae64d82013-08-01 10:50:15 -0700874
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700875 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800876 macAddressSearch = re.search( pattern, response, re.I )
877 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800878 main.log.info(
879 self.name +
880 ": Mac-Address of Host " +
881 host +
882 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800883 macAddress )
884 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700885 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800886 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700887
Jon Hall7eb38402015-01-08 17:19:54 -0800888 def getInterfaceMACAddress( self, host, interface ):
889 """
890 Return the IP address of the interface on the given host"""
891 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700892 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800893 response = self.execute( cmd=host + " ifconfig " + interface,
894 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800895 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800896 main.log.error( self.name + ": EOF exception found" )
897 main.log.error( self.name + ": " + self.handle.before )
898 main.cleanup()
899 main.exit()
900
901 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800902 macAddressSearch = re.search( pattern, response, re.I )
903 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800904 main.log.info( "No mac address found in %s" % response )
905 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800906 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800907 main.log.info(
908 "Mac-Address of " +
909 host +
910 ":" +
911 interface +
912 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800913 macAddress )
914 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800915 else:
916 main.log.error( "Connection failed to the host" )
917
sathishmad953462015-12-03 17:42:07 +0530918 def getIPAddress( self, host , proto='IPV4'):
Jon Hall7eb38402015-01-08 17:19:54 -0800919 """
920 Verifies the host's ip configured or not."""
921 if self.handle:
922 try:
923 response = self.execute(
924 cmd=host +
925 " ifconfig",
926 prompt="mininet>",
927 timeout=10 )
928 except pexpect.EOF:
929 main.log.error( self.name + ": EOF exception found" )
930 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700931 main.cleanup()
932 main.exit()
adminbae64d82013-08-01 10:50:15 -0700933
sathishmad953462015-12-03 17:42:07 +0530934 pattern = ''
935 if proto == 'IPV4':
936 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
937 else:
938 pattern = "inet6\saddr:\s([\w,:]*)/"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800939 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800940 main.log.info(
941 self.name +
942 ": IP-Address of Host " +
943 host +
944 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800945 ipAddressSearch.group( 1 ) )
946 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800947 else:
948 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800949
Jon Hall7eb38402015-01-08 17:19:54 -0800950 def getSwitchDPID( self, switch ):
951 """
952 return the datapath ID of the switch"""
953 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700954 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700955 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800956 response = self.execute(
957 cmd=cmd,
958 prompt="mininet>",
959 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800960 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800961 main.log.error( self.name + ": EOF exception found" )
962 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700963 main.cleanup()
964 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800965 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800966 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700967 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800968 main.log.info(
969 "Couldn't find DPID for switch %s, found: %s" %
970 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700971 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800972 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700973 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800974 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700975
Jon Hall7eb38402015-01-08 17:19:54 -0800976 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700977 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800978 self.handle.sendline( "" )
979 self.expect( "mininet>" )
980 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700981 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800982 response = self.execute(
983 cmd=cmd,
984 prompt="mininet>",
985 timeout=10 )
986 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700987 response = self.handle.before
988 return response
989 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800990 main.log.error( self.name + ": EOF exception found" )
991 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700992 main.cleanup()
993 main.exit()
994
Jon Hall7eb38402015-01-08 17:19:54 -0800995 def getInterfaces( self, node ):
996 """
997 return information dict about interfaces connected to the node"""
998 if self.handle:
999 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001000 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001001 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001002 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001003 response = self.execute(
1004 cmd=cmd,
1005 prompt="mininet>",
1006 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001007 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001008 main.log.error( self.name + ": EOF exception found" )
1009 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001010 main.cleanup()
1011 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001012 return response
1013 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001014 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001015
Jon Hall7eb38402015-01-08 17:19:54 -08001016 def dump( self ):
1017 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001018 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001019 response = self.execute(
1020 cmd='dump',
1021 prompt='mininet>',
1022 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001023 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001024 main.log.error( self.name + ": EOF exception found" )
1025 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001026 main.cleanup()
1027 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001028 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001029
Jon Hall7eb38402015-01-08 17:19:54 -08001030 def intfs( self ):
1031 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001032 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001033 response = self.execute(
1034 cmd='intfs',
1035 prompt='mininet>',
1036 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001037 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001038 main.log.error( self.name + ": EOF exception found" )
1039 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001040 main.cleanup()
1041 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001042 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001043
Jon Hall7eb38402015-01-08 17:19:54 -08001044 def net( self ):
1045 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001046 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001047 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001048 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001049 main.log.error( self.name + ": EOF exception found" )
1050 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001051 main.cleanup()
1052 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001053 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001054
Jon Hallafa8a472015-06-12 14:02:42 -07001055 def links( self ):
1056 main.log.info( self.name + ": List network links" )
1057 try:
1058 response = self.execute( cmd='links', prompt='mininet>',
Jon Hall3b489db2015-10-05 14:38:37 -07001059 timeout=20 )
Jon Hallafa8a472015-06-12 14:02:42 -07001060 except pexpect.EOF:
1061 main.log.error( self.name + ": EOF exception found" )
1062 main.log.error( self.name + ": " + self.handle.before )
1063 main.cleanup()
1064 main.exit()
1065 return response
1066
GlennRC61321f22015-07-16 13:36:54 -07001067 def iperftcpAll(self, hosts, timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001068 '''
1069 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001070
kelvin-onlab7cce9382015-07-17 10:21:03 -07001071 @parm:
1072 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1073 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1074 '''
1075 for host1 in hosts:
1076 for host2 in hosts:
1077 if host1 != host2:
1078 if self.iperftcp(host1, host2, timeout) == main.FALSE:
1079 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
GlennRC61321f22015-07-16 13:36:54 -07001080
1081 def iperftcp(self, host1="h1", host2="h2", timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001082 '''
1083 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1084 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001085
kelvin-onlab7cce9382015-07-17 10:21:03 -07001086 @parm:
1087 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1088 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1089 '''
1090 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1091 try:
1092 # Setup the mininet command
1093 cmd1 = 'iperf ' + host1 + " " + host2
1094 self.handle.sendline( cmd1 )
1095 outcome = self.handle.expect( "mininet>", timeout )
1096 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001097
kelvin-onlab7cce9382015-07-17 10:21:03 -07001098 # checks if there are results in the mininet response
1099 if "Results:" in response:
Jon Hall892818c2015-10-20 17:58:34 -07001100 main.log.report(self.name + ": iperf test completed")
kelvin-onlab7cce9382015-07-17 10:21:03 -07001101 # parse the mn results
1102 response = response.split("\r\n")
1103 response = response[len(response)-2]
1104 response = response.split(": ")
1105 response = response[len(response)-1]
1106 response = response.replace("[", "")
1107 response = response.replace("]", "")
1108 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001109
kelvin-onlab7cce9382015-07-17 10:21:03 -07001110 # this is the bandwith two and from the two hosts
1111 bandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001112
kelvin-onlab7cce9382015-07-17 10:21:03 -07001113 # there should be two elements in the bandwidth list
1114 # ['host1 to host2', 'host2 to host1"]
1115 if len(bandwidth) == 2:
1116 main.log.report(self.name + ": iperf test successful")
1117 return main.TRUE
1118 else:
1119 main.log.error(self.name + ": invalid iperf results")
1120 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001121 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001122 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001123 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001124 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001125 main.log.error( self.name + ": TIMEOUT exception found" )
1126 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001127 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001128 # NOTE: Send ctrl-c to make sure iperf is done
1129 self.handle.sendline( "\x03" )
1130 self.handle.expect( "Interrupt" )
1131 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001132 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001133 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001134 main.log.error( self.name + ": EOF exception found" )
1135 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001136 main.cleanup()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001137 main.exit()
GlennRC61321f22015-07-16 13:36:54 -07001138
1139 def iperfudpAll(self, hosts, bandwidth="10M"):
1140 '''
1141 Runs the iperfudp function with a given set of hosts and specified
1142 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001143
GlennRC61321f22015-07-16 13:36:54 -07001144 @param:
1145 bandwidth: the targeted bandwidth, in megabits ('M')
1146 '''
1147 for host1 in hosts:
1148 for host2 in hosts:
1149 if host1 != host2:
1150 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1151 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1152
1153 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1154
kelvin-onlab7cce9382015-07-17 10:21:03 -07001155 '''
1156 Creates an iperf UDP test with a specific bandwidth.
1157 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001158
kelvin-onlab7cce9382015-07-17 10:21:03 -07001159 @param:
1160 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1161 '''
1162 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1163 try:
1164 # setup the mininet command
1165 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1166 self.handle.sendline(cmd)
1167 self.handle.expect("mininet>")
1168 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001169
kelvin-onlab7cce9382015-07-17 10:21:03 -07001170 # check if there are in results in the mininet response
1171 if "Results:" in response:
Jon Hall892818c2015-10-20 17:58:34 -07001172 main.log.report(self.name + ": iperfudp test completed")
kelvin-onlab7cce9382015-07-17 10:21:03 -07001173 # parse the results
1174 response = response.split("\r\n")
1175 response = response[len(response)-2]
1176 response = response.split(": ")
1177 response = response[len(response)-1]
1178 response = response.replace("[", "")
1179 response = response.replace("]", "")
1180 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001181
kelvin-onlab7cce9382015-07-17 10:21:03 -07001182 mnBandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001183
kelvin-onlab7cce9382015-07-17 10:21:03 -07001184 # check to see if there are at least three entries
1185 # ['bandwidth', 'host1 to host2', 'host2 to host1']
1186 if len(mnBandwidth) == 3:
1187 # if one entry is blank then something is wrong
1188 for item in mnBandwidth:
1189 if item == "":
1190 main.log.error(self.name + ": Could not parse iperf output")
1191 main.log.error(self.name + ": invalid iperfudp results")
1192 return main.FALSE
1193 # otherwise results are vaild
1194 main.log.report(self.name + ": iperfudp test successful")
1195 return main.TRUE
1196 else:
1197 main.log.error(self.name + ": invalid iperfudp results")
1198 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001199
kelvin-onlab7cce9382015-07-17 10:21:03 -07001200 except pexpect.EOF:
1201 main.log.error( self.name + ": EOF exception found" )
1202 main.log.error( self.name + ": " + self.handle.before )
1203 main.cleanup()
1204 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001205
Jon Hall7eb38402015-01-08 17:19:54 -08001206 def nodes( self ):
1207 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001208 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001209 response = self.execute(
1210 cmd='nodes',
1211 prompt='mininet>',
1212 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001213 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001214 main.log.error( self.name + ": EOF exception found" )
1215 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001216 main.cleanup()
1217 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001218 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001219
Jon Hall7eb38402015-01-08 17:19:54 -08001220 def pingpair( self ):
1221 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001222 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001223 response = self.execute(
1224 cmd='pingpair',
1225 prompt='mininet>',
1226 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001227 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001228 main.log.error( self.name + ": EOF exception found" )
1229 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001230 main.cleanup()
1231 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001232
Jon Hall7eb38402015-01-08 17:19:54 -08001233 if re.search( ',\s0\%\spacket\sloss', response ):
1234 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001235 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001236 else:
1237 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001238 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001239
Jon Hall7eb38402015-01-08 17:19:54 -08001240 def link( self, **linkargs ):
1241 """
GlennRCed771242016-01-13 17:02:47 -08001242 Bring link( s ) between two nodes up or down
1243 """
Jon Hall6094a362014-04-11 14:46:56 -07001244 try:
GlennRCed771242016-01-13 17:02:47 -08001245 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1246 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1247 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1248 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1249
1250 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1251 cmd = "link {} {} {}".format( end1, end2, option )
1252 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001253 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001254 response = self.handle.before
1255 main.log.info( response )
1256
1257 return main.TRUE
1258 except pexpect.TIMEOUT:
1259 main.log.exception( self.name + ": Command timed out" )
1260 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001261 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001262 main.log.exception( self.name + ": connection closed." )
Jon Hall6094a362014-04-11 14:46:56 -07001263 main.cleanup()
1264 main.exit()
GlennRCed771242016-01-13 17:02:47 -08001265 except Exception:
1266 main.log.exception( self.name + ": Uncaught exception!" )
1267 main.cleanup()
1268 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001269
pingping-lin8244a3b2015-09-16 13:36:56 -07001270 def switch( self, **switchargs ):
1271 """
1272 start/stop a switch
1273 """
1274 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1275 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1276 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1277 command = "switch " + str( sw ) + " " + str( option )
1278 main.log.info( command )
1279 try:
1280 self.handle.sendline( command )
1281 self.handle.expect( "mininet>" )
1282 except pexpect.TIMEOUT:
1283 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1284 main.cleanup()
1285 main.exit()
1286 except pexpect.EOF:
1287 main.log.error( self.name + ": EOF exception found" )
1288 main.log.error( self.name + ": " + self.handle.before )
1289 main.cleanup()
1290 main.exit()
1291 return main.TRUE
1292
pingping-lin5bb663b2015-09-24 11:47:50 -07001293 def node( self, nodeName, commandStr ):
1294 """
1295 Carry out a command line on a given node
1296 @parm:
1297 nodeName: the node name in Mininet testbed
1298 commandStr: the command line will be carried out on the node
1299 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1300 """
1301 command = str( nodeName ) + " " + str( commandStr )
1302 main.log.info( command )
1303
1304 try:
1305 response = self.execute( cmd = command, prompt = "mininet>" )
1306 if re.search( "Unknown command", response ):
1307 main.log.warn( response )
1308 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001309 if re.search( "Permission denied", response ):
1310 main.log.warn( response )
1311 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001312 except pexpect.TIMEOUT:
1313 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1314 main.cleanup()
1315 main.exit()
1316 except pexpect.EOF:
1317 main.log.error( self.name + ": EOF exception found" )
1318 main.log.error( self.name + ": " + self.handle.before )
1319 main.cleanup()
1320 main.exit()
1321 main.log.info( " response is :" )
1322 main.log.info( response )
1323 return response
1324
Jon Hall7eb38402015-01-08 17:19:54 -08001325 def yank( self, **yankargs ):
1326 """
1327 yank a mininet switch interface to a host"""
1328 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001329 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001330 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1331 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1332 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001333 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001334 response = self.execute(
1335 cmd=command,
1336 prompt="mininet>",
1337 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001338 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001339 main.log.error( self.name + ": EOF exception found" )
1340 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001341 main.cleanup()
1342 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001343 return main.TRUE
1344
Jon Hall7eb38402015-01-08 17:19:54 -08001345 def plug( self, **plugargs ):
1346 """
1347 plug the yanked mininet switch interface to a switch"""
1348 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001349 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001350 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1351 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1352 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001353 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001354 response = self.execute(
1355 cmd=command,
1356 prompt="mininet>",
1357 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001358 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001359 main.log.error( self.name + ": EOF exception found" )
1360 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001361 main.cleanup()
1362 main.exit()
adminbae64d82013-08-01 10:50:15 -07001363 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001364
Jon Hall7eb38402015-01-08 17:19:54 -08001365 def dpctl( self, **dpctlargs ):
1366 """
1367 Run dpctl command on all switches."""
1368 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001369 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001370 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1371 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1372 command = "dpctl " + cmd + " " + str( cmdargs )
1373 try:
1374 response = self.execute(
1375 cmd=command,
1376 prompt="mininet>",
1377 timeout=10 )
1378 except pexpect.EOF:
1379 main.log.error( self.name + ": EOF exception found" )
1380 main.log.error( self.name + ": " + self.handle.before )
1381 main.cleanup()
1382 main.exit()
1383 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001384
kelvin-onlabd3b64892015-01-20 13:26:24 -08001385 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001386 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001387 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001388 fileInput = path + '/lib/Mininet/INSTALL'
1389 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001390 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001391 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001392 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001393 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001394 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001395 return version
adminbae64d82013-08-01 10:50:15 -07001396
kelvin-onlabd3b64892015-01-20 13:26:24 -08001397 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001398 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001399 Parameters:
1400 sw: The name of an OVS switch. Example "s1"
1401 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001402 The output of the command from the mininet cli
1403 or main.FALSE on timeout"""
1404 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001405 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001406 response = self.execute(
1407 cmd=command,
1408 prompt="mininet>",
1409 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001410 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001411 return response
admin2a9548d2014-06-17 14:08:07 -07001412 else:
1413 return main.FALSE
1414 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001415 main.log.error( self.name + ": EOF exception found" )
1416 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001417 main.cleanup()
1418 main.exit()
adminbae64d82013-08-01 10:50:15 -07001419
Charles Chan029be652015-08-24 01:46:10 +08001420 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001421 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001422 Description:
1423 Assign switches to the controllers ( for ovs use only )
1424 Required:
1425 sw - Name of the switch. This can be a list or a string.
1426 ip - Ip addresses of controllers. This can be a list or a string.
1427 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001428 port - ONOS use port 6653, if no list of ports is passed, then
1429 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001430 ptcp - ptcp number, This can be a string or a list that has
1431 the same length as switch. This is optional and not required
1432 when using ovs switches.
1433 NOTE: If switches and ptcp are given in a list type they should have the
1434 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1435 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001436
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001437 Return:
1438 Returns main.TRUE if mininet correctly assigned switches to
1439 controllers, otherwise it will return main.FALSE or an appropriate
1440 exception(s)
1441 """
1442 assignResult = main.TRUE
1443 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001444 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001445 command = "sh ovs-vsctl set-controller "
1446 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001447 try:
1448 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001449 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001450 if isinstance( port, types.StringType ) or \
1451 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001452 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001453 elif isinstance( port, types.ListType ):
1454 main.log.error( self.name + ": Only one controller " +
1455 "assigned and a list of ports has" +
1456 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001457 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001458 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001459 main.log.error( self.name + ": Invalid controller port " +
1460 "number. Please specify correct " +
1461 "controller port" )
1462 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001463
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001464 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001465 if isinstance( port, types.StringType ) or \
1466 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001467 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001468 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1469 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001470 elif isinstance( port, types.ListType ):
1471 if ( len( ip ) != len( port ) ):
1472 main.log.error( self.name + ": Port list = " +
1473 str( len( port ) ) +
1474 "should be the same as controller" +
1475 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001476 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001477 else:
1478 onosIp = ""
1479 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001480 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1481 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001482 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001483 main.log.error( self.name + ": Invalid controller port " +
1484 "number. Please specify correct " +
1485 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001486 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001487 else:
1488 main.log.error( self.name + ": Invalid ip address" )
1489 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001490
1491 if isinstance( sw, types.StringType ):
1492 command += sw + " "
1493 if ptcp:
1494 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001495 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001496 elif isinstance( ptcp, types.ListType ):
1497 main.log.error( self.name + ": Only one switch is " +
1498 "being set and multiple PTCP is " +
1499 "being passed " )
1500 else:
1501 main.log.error( self.name + ": Invalid PTCP" )
1502 ptcp = ""
1503 command += onosIp
1504 commandList.append( command )
1505
1506 elif isinstance( sw, types.ListType ):
1507 if ptcp:
1508 if isinstance( ptcp, types.ListType ):
1509 if len( ptcp ) != len( sw ):
1510 main.log.error( self.name + ": PTCP length = " +
1511 str( len( ptcp ) ) +
1512 " is not the same as switch" +
1513 " length = " +
1514 str( len( sw ) ) )
1515 return main.FALSE
1516 else:
1517 for switch, ptcpNum in zip( sw, ptcp ):
1518 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001519 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001520 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001521 tempCmd += onosIp
1522 commandList.append( tempCmd )
1523 else:
1524 main.log.error( self.name + ": Invalid PTCP" )
1525 return main.FALSE
1526 else:
1527 for switch in sw:
1528 tempCmd = "sh ovs-vsctl set-controller "
1529 tempCmd += switch + " " + onosIp
1530 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001531 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001532 main.log.error( self.name + ": Invalid switch type " )
1533 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001534
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001535 for cmd in commandList:
1536 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001537 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001538 except pexpect.TIMEOUT:
1539 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1540 return main.FALSE
1541 except pexpect.EOF:
1542 main.log.error( self.name + ": EOF exception found" )
1543 main.log.error( self.name + ": " + self.handle.before )
1544 main.cleanup()
1545 main.exit()
1546 return main.TRUE
1547 except Exception:
1548 main.log.exception( self.name + ": Uncaught exception!" )
1549 main.cleanup()
1550 main.exit()
adminbae64d82013-08-01 10:50:15 -07001551
kelvin-onlabd3b64892015-01-20 13:26:24 -08001552 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001553 """
1554 Removes the controller target from sw"""
1555 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001556 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001557 response = self.execute(
1558 cmd=command,
1559 prompt="mininet>",
1560 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001561 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001562 main.log.error( self.name + ": EOF exception found" )
1563 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001564 main.cleanup()
1565 main.exit()
1566 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001567 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001568
kelvin-onlabd3b64892015-01-20 13:26:24 -08001569 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001570 """
Jon Hallb1290e82014-11-18 16:17:48 -05001571 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001572 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001573 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001574 NOTE: cannot currently specify what type of switch
1575 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001576 sw = name of the new switch as a string
1577 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001578 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001579 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001580 """
1581 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001582 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001583 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001584 response = self.execute(
1585 cmd=command,
1586 prompt="mininet>",
1587 timeout=10 )
1588 if re.search( "already exists!", response ):
1589 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001590 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001591 elif re.search( "Error", response ):
1592 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001593 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001594 elif re.search( "usage:", response ):
1595 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001596 return main.FALSE
1597 else:
1598 return main.TRUE
1599 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001600 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001601 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001602 main.cleanup()
1603 main.exit()
1604
kelvin-onlabd3b64892015-01-20 13:26:24 -08001605 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001606 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001607 delete a switch from the mininet topology
1608 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001609 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001610 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001611 sw = name of the switch as a string
1612 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001613 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001614 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001615 response = self.execute(
1616 cmd=command,
1617 prompt="mininet>",
1618 timeout=10 )
1619 if re.search( "no switch named", response ):
1620 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001621 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001622 elif re.search( "Error", response ):
1623 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001624 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001625 elif re.search( "usage:", response ):
1626 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001627 return main.FALSE
1628 else:
1629 return main.TRUE
1630 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001631 main.log.error( self.name + ": EOF exception found" )
1632 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001633 main.cleanup()
1634 main.exit()
1635
kelvin-onlabd3b64892015-01-20 13:26:24 -08001636 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001637 """
1638 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001639 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001640 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001641 NOTE: cannot currently specify what type of link
1642 required params:
1643 node1 = the string node name of the first endpoint of the link
1644 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001645 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001646 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001647 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001648 response = self.execute(
1649 cmd=command,
1650 prompt="mininet>",
1651 timeout=10 )
1652 if re.search( "doesnt exist!", response ):
1653 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001654 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001655 elif re.search( "Error", response ):
1656 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001657 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001658 elif re.search( "usage:", response ):
1659 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001660 return main.FALSE
1661 else:
1662 return main.TRUE
1663 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001664 main.log.error( self.name + ": EOF exception found" )
1665 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001666 main.cleanup()
1667 main.exit()
1668
kelvin-onlabd3b64892015-01-20 13:26:24 -08001669 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001670 """
1671 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001672 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001673 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001674 required params:
1675 node1 = the string node name of the first endpoint of the link
1676 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001677 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001678 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001679 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001680 response = self.execute(
1681 cmd=command,
1682 prompt="mininet>",
1683 timeout=10 )
1684 if re.search( "no node named", response ):
1685 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001686 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001687 elif re.search( "Error", response ):
1688 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001689 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001690 elif re.search( "usage:", response ):
1691 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001692 return main.FALSE
1693 else:
1694 return main.TRUE
1695 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001696 main.log.error( self.name + ": EOF exception found" )
1697 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001698 main.cleanup()
1699 main.exit()
1700
kelvin-onlabd3b64892015-01-20 13:26:24 -08001701 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001702 """
Jon Hallb1290e82014-11-18 16:17:48 -05001703 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001704 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001705 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001706 NOTE: cannot currently specify what type of host
1707 required params:
1708 hostname = the string hostname
1709 optional key-value params
1710 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001711 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001712 """
1713 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001714 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001715 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001716 response = self.execute(
1717 cmd=command,
1718 prompt="mininet>",
1719 timeout=10 )
1720 if re.search( "already exists!", response ):
1721 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001722 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001723 elif re.search( "doesnt exists!", response ):
1724 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001725 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001726 elif re.search( "Error", response ):
1727 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001728 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001729 elif re.search( "usage:", response ):
1730 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001731 return main.FALSE
1732 else:
1733 return main.TRUE
1734 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001735 main.log.error( self.name + ": EOF exception found" )
1736 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001737 main.cleanup()
1738 main.exit()
1739
kelvin-onlabd3b64892015-01-20 13:26:24 -08001740 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001741 """
1742 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001743 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001744 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001745 NOTE: this uses a custom mn function
1746 required params:
1747 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001748 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001749 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001750 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001751 response = self.execute(
1752 cmd=command,
1753 prompt="mininet>",
1754 timeout=10 )
1755 if re.search( "no host named", response ):
1756 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001757 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001758 elif re.search( "Error", response ):
1759 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001760 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001761 elif re.search( "usage:", response ):
1762 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001763 return main.FALSE
1764 else:
1765 return main.TRUE
1766 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001767 main.log.error( self.name + ": EOF exception found" )
1768 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001769 main.cleanup()
1770 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001771
Jon Hall7eb38402015-01-08 17:19:54 -08001772 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001773 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001774 Called at the end of the test to stop the mininet and
1775 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001776 """
Jon Halld80cc142015-07-06 13:36:05 -07001777 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001778 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001779 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001780 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001781 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001782 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001783 elif i == 1:
1784 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001785 # print "Disconnecting Mininet"
1786 if self.handle:
1787 self.handle.sendline( "exit" )
1788 self.handle.expect( "exit" )
1789 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001790 else:
1791 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001792 return response
1793
Jon Halld80cc142015-07-06 13:36:05 -07001794 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001795 """
Jon Hall21270ac2015-02-16 17:59:55 -08001796 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001797 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001798 main.FALSE if the pexpect handle does not exist.
1799
Jon Halld61331b2015-02-17 16:35:47 -08001800 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001801 """
Jon Halld61331b2015-02-17 16:35:47 -08001802 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001803 response = ''
1804 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001805 try:
Jon Halld80cc142015-07-06 13:36:05 -07001806 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08001807 i = self.handle.expect( [ 'mininet>',
1808 '\$',
1809 pexpect.EOF,
1810 pexpect.TIMEOUT ],
1811 timeout )
1812 if i == 0:
1813 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001814 response = self.execute(
1815 cmd="exit",
1816 prompt="(.*)",
1817 timeout=120 )
Jon Halld80cc142015-07-06 13:36:05 -07001818 main.log.info( self.name + ": Stopped" )
Jon Hall7eb38402015-01-08 17:19:54 -08001819 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001820 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001821
kelvin-onlab56a3f462015-02-06 14:04:43 -08001822 if i == 1:
1823 main.log.info( " Mininet trying to exit while not " +
1824 "in the mininet prompt" )
1825 elif i == 2:
1826 main.log.error( "Something went wrong exiting mininet" )
1827 elif i == 3: # timeout
1828 main.log.error( "Something went wrong exiting mininet " +
1829 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001830
Hari Krishnab35c6d02015-03-18 11:13:51 -07001831 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07001832 self.handle.sendline( "" )
1833 self.handle.expect( '\$' )
1834 self.handle.sendline(
1835 "sudo kill -9 \`ps -ef | grep \"" +
1836 fileName +
1837 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001838 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001839 main.log.error( self.name + ": EOF exception found" )
1840 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001841 main.cleanup()
1842 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001843 else:
1844 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001845 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001846 return response
1847
Jon Halla5cb3412015-08-18 14:08:22 -07001848 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001849 """
1850 Description:
1851 Sends arp message from mininet host for hosts discovery
1852 Required:
1853 host - hosts name
1854 Optional:
1855 ip - ip address that does not exist in the network so there would
1856 be no reply.
1857 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001858 if ethDevice:
1859 ethDevice = '-I ' + ethDevice + ' '
Jon Halla5cb3412015-08-18 14:08:22 -07001860 cmd = srcHost + " arping -c1 " + ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08001861 try:
Jon Halla5cb3412015-08-18 14:08:22 -07001862 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07001863 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07001864 i = self.handle.expect( [ "mininet>", "arping: " ] )
1865 if i == 0:
1866 return main.TRUE
1867 elif i == 1:
1868 response = self.handle.before + self.handle.after
1869 self.handle.expect( "mininet>" )
1870 response += self.handle.before + self.handle.after
1871 main.log.warn( "Error sending arping, output was: " +
1872 response )
1873 return main.FALSE
1874 except pexpect.TIMEOUT:
1875 main.log.error( self.name + ": TIMEOUT exception found" )
1876 main.log.warn( self.handle.before )
1877 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07001878 except pexpect.EOF:
1879 main.log.error( self.name + ": EOF exception found" )
1880 main.log.error( self.name + ": " + self.handle.before )
1881 main.cleanup()
1882 main.exit()
admin07529932013-11-22 14:58:28 -08001883
Jon Hall7eb38402015-01-08 17:19:54 -08001884 def decToHex( self, num ):
1885 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001886
Jon Hall7eb38402015-01-08 17:19:54 -08001887 def getSwitchFlowCount( self, switch ):
1888 """
1889 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001890 if self.handle:
1891 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1892 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001893 response = self.execute(
1894 cmd=cmd,
1895 prompt="mininet>",
1896 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001897 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001898 main.log.error( self.name + ": EOF exception found" )
1899 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001900 main.cleanup()
1901 main.exit()
1902 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001903 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001904 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001905 main.log.info(
1906 "Couldn't find flows on switch %s, found: %s" %
1907 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001908 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001909 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001910 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001911 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001912
Jon Hall9ed8f372016-02-24 17:34:07 -08001913 def checkFlows( self, sw, dumpFormat=None ):
1914 if dumpFormat:
1915 command = "sh ovs-ofctl -F " + \
1916 dumpFormat + " dump-flows " + str( sw )
1917 else:
1918 command = "sh ovs-ofctl dump-flows " + str( sw )
1919 try:
1920 response = self.execute(
1921 cmd=command,
1922 prompt="mininet>",
1923 timeout=10 )
1924 return response
1925 except pexpect.EOF:
1926 main.log.error( self.name + ": EOF exception found" )
1927 main.log.error( self.name + ": " + self.handle.before )
1928 main.cleanup()
1929 main.exit()
1930
GlennRC68467eb2015-11-16 18:01:01 -08001931 def flowTableComp( self, flowTable1, flowTable2 ):
1932 # This function compares the selctors and treatments of each flow
1933 try:
Jon Hall41d39f12016-04-11 22:54:35 -07001934 returnValue = main.TRUE
GlennRC68467eb2015-11-16 18:01:01 -08001935 if len(flowTable1) != len(flowTable2):
1936 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07001937 returnValue = main.FALSE
GlennRCfa65fce2015-12-16 13:16:08 -08001938 dFields = ["n_bytes", "cookie", "n_packets", "duration"]
1939 for flow1, flow2 in zip(flowTable1, flowTable2):
Jon Hallacd1b182015-12-17 11:43:20 -08001940 for field in dFields:
1941 try:
1942 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07001943 except KeyError:
1944 pass
Jon Hallacd1b182015-12-17 11:43:20 -08001945 try:
1946 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07001947 except KeyError:
1948 pass
GlennRC68467eb2015-11-16 18:01:01 -08001949 for i in range( len(flowTable1) ):
GlennRC17bbcf52015-12-14 17:31:50 -08001950 if flowTable1[i] not in flowTable2:
1951 main.log.warn( "Flow tables do not match:" )
1952 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[i] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07001953 returnValue = main.FALSE
1954 break
1955 return returnValue
GlennRC68467eb2015-11-16 18:01:01 -08001956 except Exception:
1957 main.log.exception( "Uncaught exception!" )
1958 main.cleanup()
1959 main.exit()
Jon Hall9043c902015-07-30 14:23:44 -07001960
GlennRC528ad292015-11-12 10:38:18 -08001961 def parseFlowTable( self, flowTable, version="", debug=True ):
GlennRC956ea742015-11-05 16:14:15 -08001962 '''
1963 Discription: Parses flows into json format.
1964 NOTE: this can parse any string thats separated with commas
1965 Arguments:
1966 Required:
1967 flows: a list of strings that represnt flows
1968 Optional:
1969 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
1970 debug: prints out the final result
1971 returns: A list of flows in json format
1972 '''
GlennRC528ad292015-11-12 10:38:18 -08001973 jsonFlowTable = []
1974 for flow in flowTable:
GlennRC956ea742015-11-05 16:14:15 -08001975 jsonFlow = {}
GlennRC528ad292015-11-12 10:38:18 -08001976 # split up the fields of the flow
1977 parsedFlow = flow.split(", ")
1978 # get rid of any spaces in front of the field
1979 for i in range( len(parsedFlow) ):
1980 item = parsedFlow[i]
1981 if item[0] == " ":
1982 parsedFlow[i] = item[1:]
1983 # grab the selector and treatment from the parsed flow
1984 # the last element is the selector and the treatment
1985 temp = parsedFlow.pop(-1)
1986 # split up the selector and the treatment
1987 temp = temp.split(" ")
1988 index = 0
1989 # parse the flags
1990 # NOTE: This only parses one flag
1991 flag = {}
1992 if version == "1.3":
1993 flag = {"flag":[temp[index]]}
1994 index += 1
1995 # the first element is the selector and split it up
1996 sel = temp[index]
1997 index += 1
1998 sel = sel.split(",")
1999 # the priority is stuck in the selecter so put it back
2000 # in the flow
2001 parsedFlow.append(sel.pop(0))
2002 # parse selector
2003 criteria = []
2004 for item in sel:
2005 # this is the type of the packet e.g. "arp"
2006 if "=" not in item:
2007 criteria.append( {"type":item} )
2008 else:
2009 field = item.split("=")
2010 criteria.append( {field[0]:field[1]} )
GlennRC68467eb2015-11-16 18:01:01 -08002011 selector = {"selector": {"criteria":sorted(criteria)} }
GlennRC528ad292015-11-12 10:38:18 -08002012 treat = temp[index]
2013 # get rid of the action part e.g. "action=output:2"
2014 # we will add it back later
2015 treat = treat.split("=")
2016 treat.pop(0)
2017 # parse treatment
2018 action = []
2019 for item in treat:
2020 field = item.split(":")
2021 action.append( {field[0]:field[1]} )
2022 # create the treatment field and add the actions
GlennRC68467eb2015-11-16 18:01:01 -08002023 treatment = {"treatment": {"action":sorted(action)} }
GlennRC528ad292015-11-12 10:38:18 -08002024 # parse the rest of the flow
2025 for item in parsedFlow:
2026 field = item.split("=")
2027 jsonFlow.update( {field[0]:field[1]} )
2028 # add the treatment and the selector to the json flow
2029 jsonFlow.update( selector )
2030 jsonFlow.update( treatment )
2031 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002032
GlennRC528ad292015-11-12 10:38:18 -08002033 if debug: main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format(jsonFlow) )
GlennRC956ea742015-11-05 16:14:15 -08002034
GlennRC528ad292015-11-12 10:38:18 -08002035 # add the json flow to the json flow table
2036 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002037
GlennRC528ad292015-11-12 10:38:18 -08002038 return jsonFlowTable
2039
Jon Hall0a543792015-12-14 11:00:26 -08002040 def getFlowTable( self, sw, version="", debug=False):
GlennRC956ea742015-11-05 16:14:15 -08002041 '''
2042 Discription: Returns the flow table(s) on a switch or switches in a list.
2043 Each element is a flow.
2044 Arguments:
2045 Required:
2046 sw: The switch name ("s1") to retrive the flow table. Can also be
2047 a list of switches.
2048 Optional:
2049 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2050 debug: prints out the final result
2051 '''
2052 try:
2053 switches = []
2054 if type(sw) is list:
Jon Hallca7ac292015-11-11 09:28:12 -08002055 switches.extend(sw)
GlennRC956ea742015-11-05 16:14:15 -08002056 else: switches.append(sw)
2057
2058 flows = []
2059 for s in switches:
2060 cmd = "sh ovs-ofctl dump-flows " + s
2061
GlennRC528ad292015-11-12 10:38:18 -08002062 if "1.0" == version:
2063 cmd += " -F OpenFlow10-table_id"
2064 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002065 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002066
2067 main.log.info( "Sending: " + cmd )
2068 self.handle.sendline( cmd )
2069 self.handle.expect( "mininet>" )
2070 response = self.handle.before
2071 response = response.split( "\r\n" )
2072 # dump the first two elements and the last
2073 # the first element is the command that was sent
2074 # the second is the table header
2075 # the last element is empty
2076 response = response[2:-1]
2077 flows.extend( response )
2078
2079 if debug: print "Flows:\n{}\n\n".format(flows)
2080
GlennRC528ad292015-11-12 10:38:18 -08002081 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002082
2083 except pexpect.TIMEOUT:
2084 main.log.exception( self.name + ": Command timed out" )
2085 return None
2086 except pexpect.EOF:
2087 main.log.exception( self.name + ": connection closed." )
2088 main.cleanup()
2089 main.exit()
2090 except Exception:
2091 main.log.exception( self.name + ": Uncaught exception!" )
2092 main.cleanup()
2093 main.exit()
2094
2095 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
2096 '''
2097 Discription: Checks whether the ID provided matches a flow ID in Mininet
2098 Arguments:
2099 Required:
2100 sw: The switch name ("s1") to retrive the flow table. Can also be
2101 a list of switches.
2102 flowId: the flow ID in hex format. Can also be a list of IDs
2103 Optional:
2104 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2105 debug: prints out the final result
2106 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2107 NOTE: prints out IDs that are not present
2108 '''
2109 try:
2110 main.log.info( "Getting flows from Mininet" )
2111 flows = self.getFlowTable( sw, version, debug )
2112
2113 if debug: print "flow ids:\n{}\n\n".format(flowId)
2114
2115 # Check flowId is a list or a string
2116 if type( flowId ) is str:
2117 result = False
2118 for f in flows:
2119 if flowId in f.get( 'cookie' ):
2120 result = True
2121 break
2122 # flowId is a list
2123 else:
2124 result = True
2125 # Get flow IDs from Mininet
2126 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2127 # Save the IDs that are not in Mininet
2128 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2129
2130 if debug: print "mn flow ids:\n{}\n\n".format(mnFlowIds)
2131
2132 # Print out the IDs that are not in Mininet
2133 if absentIds:
2134 main.log.warn( "Absent ids: {}".format( absentIds ) )
2135 result = False
2136
2137 return main.TRUE if result else main.FALSE
2138
2139 except Exception:
2140 main.log.exception( self.name + ": Uncaught exception!" )
2141 main.cleanup()
2142 main.exit()
2143
2144
Charles Chan029be652015-08-24 01:46:10 +08002145 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002146 """
Jon Hallefbd9792015-03-05 16:11:36 -08002147 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002148 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002149 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002150 self.handle.sendline( "" )
2151 self.handle.expect( "mininet>" )
2152 self.handle.sendline(
2153 "sh sudo tcpdump -n -i " +
2154 intf +
2155 " " +
2156 port +
2157 " -w " +
2158 filename.strip() +
2159 " &" )
2160 self.handle.sendline( "" )
2161 i = self.handle.expect( [ 'No\ssuch\device',
2162 'listening\son',
2163 pexpect.TIMEOUT,
2164 "mininet>" ],
2165 timeout=10 )
2166 main.log.warn( self.handle.before + self.handle.after )
2167 self.handle.sendline( "" )
2168 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002169 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002170 main.log.error(
2171 self.name +
2172 ": tcpdump - No such device exists. " +
2173 "tcpdump attempted on: " +
2174 intf )
admin2a9548d2014-06-17 14:08:07 -07002175 return main.FALSE
2176 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002177 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002178 return main.TRUE
2179 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002180 main.log.error(
2181 self.name +
2182 ": tcpdump command timed out! Check interface name," +
2183 " given interface was: " +
2184 intf )
admin2a9548d2014-06-17 14:08:07 -07002185 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002186 elif i == 3:
2187 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002188 return main.TRUE
2189 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002190 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002191 return main.FALSE
2192 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002193 main.log.error( self.name + ": EOF exception found" )
2194 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002195 main.cleanup()
2196 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002197 except Exception:
2198 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002199 main.cleanup()
2200 main.exit()
2201
kelvin-onlabd3b64892015-01-20 13:26:24 -08002202 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002203 """
2204 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002205 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002206 self.handle.sendline( "sh sudo pkill tcpdump" )
2207 self.handle.expect( "mininet>" )
2208 self.handle.sendline( "" )
2209 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002210 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002211 main.log.error( self.name + ": EOF exception found" )
2212 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002213 main.cleanup()
2214 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002215 except Exception:
2216 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002217 main.cleanup()
2218 main.exit()
2219
Jon Halld80cc142015-07-06 13:36:05 -07002220 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002221 """
2222 Read ports from a Mininet switch.
2223
2224 Returns a json structure containing information about the
2225 ports of the given switch.
2226 """
2227 response = self.getInterfaces( nodeName )
2228 # TODO: Sanity check on response. log if no such switch exists
2229 ports = []
2230 for line in response.split( "\n" ):
2231 if not line.startswith( "name=" ):
2232 continue
2233 portVars = {}
2234 for var in line.split( "," ):
2235 key, value = var.split( "=" )
2236 portVars[ key ] = value
2237 isUp = portVars.pop( 'enabled', "True" )
2238 isUp = "True" in isUp
2239 if verbose:
2240 main.log.info( "Reading switch port %s(%s)" %
2241 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2242 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002243 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002244 mac = None
2245 ips = []
2246 ip = portVars[ 'ip' ]
2247 if ip == 'None':
2248 ip = None
2249 ips.append( ip )
2250 name = portVars[ 'name' ]
2251 if name == 'None':
2252 name = None
2253 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2254 if name == 'lo':
2255 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2256 else:
2257 portNo = re.search( portRe, name ).group( 'port' )
2258 ports.append( { 'of_port': portNo,
2259 'mac': str( mac ).replace( '\'', '' ),
2260 'name': name,
2261 'ips': ips,
2262 'enabled': isUp } )
2263 return ports
2264
Jon Halld80cc142015-07-06 13:36:05 -07002265 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002266 """
2267 Read switches from Mininet.
2268
2269 Returns a dictionary whose keys are the switch names and the value is
2270 a dictionary containing information about the switch.
2271 """
Jon Halla22481b2015-07-28 17:46:01 -07002272 # NOTE: To support new Mininet switch classes, just append the new
2273 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002274
Jon Halla22481b2015-07-28 17:46:01 -07002275 # Regex patterns to parse 'dump' output
2276 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002277 # <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 -07002278 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002279 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2280 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2281 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2282 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2283 swRE = r"<(?P<class>" + switchClasses + r")" +\
2284 r"(?P<options>\{.*\})?\s" +\
2285 r"(?P<name>[^:]+)\:\s" +\
2286 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2287 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002288 # Update mn port info
2289 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002290 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002291 dump = self.dump().split( "\n" )
2292 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002293 result = re.search( swRE, line, re.I )
2294 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002295 name = result.group( 'name' )
2296 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002297 pid = result.group( 'pid' )
2298 swClass = result.group( 'class' )
2299 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002300 if verbose:
2301 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2302 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002303 output[ name ] = { "dpid": dpid,
2304 "ports": ports,
2305 "swClass": swClass,
2306 "pid": pid,
2307 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002308 return output
2309
Jon Halld80cc142015-07-06 13:36:05 -07002310 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002311 """
2312 Read hosts from Mininet.
2313
2314 Returns a dictionary whose keys are the host names and the value is
2315 a dictionary containing information about the host.
2316 """
2317 # Regex patterns to parse dump output
2318 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002319 # <Host h1: pid=12725>
2320 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2321 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2322 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002323 # NOTE: Does not correctly match hosts with multi-links
2324 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2325 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002326 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002327 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002328 # update mn port info
2329 self.update()
2330 # Get mininet dump
2331 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002332 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002333 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002334 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002335 result = re.search( hostRE, line )
2336 name = result.group( 'name' )
2337 interfaces = []
2338 response = self.getInterfaces( name )
2339 # Populate interface info
2340 for line in response.split( "\n" ):
2341 if line.startswith( "name=" ):
2342 portVars = {}
2343 for var in line.split( "," ):
2344 key, value = var.split( "=" )
2345 portVars[ key ] = value
2346 isUp = portVars.pop( 'enabled', "True" )
2347 isUp = "True" in isUp
2348 if verbose:
2349 main.log.info( "Reading host port %s(%s)" %
2350 ( portVars[ 'name' ],
2351 portVars[ 'mac' ] ) )
2352 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002353 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002354 mac = None
2355 ips = []
2356 ip = portVars[ 'ip' ]
2357 if ip == 'None':
2358 ip = None
2359 ips.append( ip )
2360 intfName = portVars[ 'name' ]
2361 if name == 'None':
2362 name = None
2363 interfaces.append( {
2364 "name": intfName,
2365 "ips": ips,
2366 "mac": str( mac ),
2367 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002368 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002369 return hosts
2370
2371 def getLinks( self ):
2372 """
2373 Gathers information about current Mininet links. These links may not
2374 be up if one of the ports is down.
2375
2376 Returns a list of dictionaries with link endpoints.
2377
2378 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002379 { 'node1': str( node1 name )
2380 'node2': str( node2 name )
2381 'port1': str( port1 of_port )
2382 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002383 Note: The port number returned is the eth#, not necessarily the of_port
2384 number. In Mininet, for OVS switch, these should be the same. For
2385 hosts, this is just the eth#.
2386 """
2387 self.update()
2388 response = self.links().split( '\n' )
2389
2390 # Examples:
2391 # s1-eth3<->s2-eth1 (OK OK)
2392 # s13-eth3<->h27-eth0 (OK OK)
2393 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2394 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2395 links = []
2396 for line in response:
2397 match = re.search( linkRE, line )
2398 if match:
2399 node1 = match.group( 'node1' )
2400 node2 = match.group( 'node2' )
2401 port1 = match.group( 'port1' )
2402 port2 = match.group( 'port2' )
2403 links.append( { 'node1': node1,
2404 'node2': node2,
2405 'port1': port1,
2406 'port2': port2 } )
2407 return links
2408
2409 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002410 """
2411 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002412 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002413
Jon Hallafa8a472015-06-12 14:02:42 -07002414 Dependencies:
2415 1. numpy - "sudo pip install numpy"
2416 """
2417 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002418 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002419 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002420 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002421 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002422 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002423 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002424 main.log.error(
2425 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002426 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002427 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002428 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002429 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002430 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002431 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002432 onosDPIDs.append(
2433 switch[ 'id' ].replace(
2434 ":",
2435 '' ).replace(
2436 "of",
2437 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002438 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002439
Jon Hall7eb38402015-01-08 17:19:54 -08002440 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002441 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002442 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002443 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002444 main.log.error( str( list1 ) )
2445 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002446 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002447 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002448 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002449 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002450 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002451
Jon Hall7eb38402015-01-08 17:19:54 -08002452 # FIXME: this does not look for extra ports in ONOS, only checks that
2453 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002454 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002455
Jon Hall7eb38402015-01-08 17:19:54 -08002456 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002457 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002458 mnPorts = []
2459 onosPorts = []
2460 switchResult = main.TRUE
2461 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002462 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002463 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002464 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002465 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002466 if onosSwitch[ 'device' ][ 'id' ].replace(
2467 ':',
2468 '' ).replace(
2469 "of",
2470 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002471 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002472 if port[ 'isEnabled' ]:
2473 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002474 # onosPorts.append( 'local' )
2475 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002476 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002477 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002478 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002479 mnPorts.sort( key=float )
2480 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002481
kelvin-onlabd3b64892015-01-20 13:26:24 -08002482 mnPortsLog = mnPorts
2483 onosPortsLog = onosPorts
2484 mnPorts = [ x for x in mnPorts ]
2485 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002486
Jon Hall7eb38402015-01-08 17:19:54 -08002487 # TODO: handle other reserved port numbers besides LOCAL
2488 # NOTE: Reserved ports
2489 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2490 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002491 for mnPort in mnPortsLog:
2492 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002493 # don't set results to true here as this is just one of
2494 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002495 mnPorts.remove( mnPort )
2496 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002497
Jon Hall7eb38402015-01-08 17:19:54 -08002498 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002499 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002500 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002501 if 65534 in mnPorts:
2502 mnPorts.remove( 65534 )
2503 if long( uint64( -2 ) ) in onosPorts:
2504 onosPorts.remove( long( uint64( -2 ) ) )
2505 if len( mnPorts ): # the ports of this switch don't match
2506 switchResult = main.FALSE
2507 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2508 if len( onosPorts ): # the ports of this switch don't match
2509 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002510 main.log.warn(
2511 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002512 str( onosPorts ) )
2513 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002514 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002515 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002516 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002517 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2518 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2519 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002520 finalResults = finalResults and portsResults
2521 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002522
Jon Hallafa8a472015-06-12 14:02:42 -07002523 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002524 """
2525 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002526 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002527
Jon Hallafa8a472015-06-12 14:02:42 -07002528 """
Jon Hall7eb38402015-01-08 17:19:54 -08002529 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002530 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002531 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002532
Jon Halld80cc142015-07-06 13:36:05 -07002533 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002534 for l in links:
2535 try:
2536 node1 = switches[ l[ 'node1' ] ]
2537 node2 = switches[ l[ 'node2' ] ]
2538 enabled = True
2539 for port in node1[ 'ports' ]:
2540 if port[ 'of_port' ] == l[ 'port1' ]:
2541 enabled = enabled and port[ 'enabled' ]
2542 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002543 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002544 enabled = enabled and port[ 'enabled' ]
2545 if enabled:
2546 mnLinks.append( l )
2547 except KeyError:
2548 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002549 if 2 * len( mnLinks ) == len( onos ):
2550 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002551 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002552 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002553 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002554 "Mininet has " + str( len( mnLinks ) ) +
2555 " bidirectional links and ONOS has " +
2556 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002557
Jon Hall7eb38402015-01-08 17:19:54 -08002558 # iterate through MN links and check if an ONOS link exists in
2559 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002560 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002561 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002562 node1 = None
2563 port1 = None
2564 node2 = None
2565 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002566 firstDir = main.FALSE
2567 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002568 for swName, switch in switches.iteritems():
2569 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002570 node1 = switch[ 'dpid' ]
2571 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002572 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002573 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002574 if node1 is not None and node2 is not None:
2575 break
Jon Hallafa8a472015-06-12 14:02:42 -07002576 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002577 node2 = switch[ 'dpid' ]
2578 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002579 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002580 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002581 if node1 is not None and node2 is not None:
2582 break
2583
kelvin-onlabd3b64892015-01-20 13:26:24 -08002584 for onosLink in onos:
2585 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002586 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002587 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002588 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002589 onosPort1 = onosLink[ 'src' ][ 'port' ]
2590 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002591
Jon Hall72cf1dc2014-10-20 21:04:50 -04002592 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002593 if str( onosNode1 ) == str( node1 ) and str(
2594 onosNode2 ) == str( node2 ):
2595 if int( onosPort1 ) == int( port1 ) and int(
2596 onosPort2 ) == int( port2 ):
2597 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002598 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002599 main.log.warn(
2600 'The port numbers do not match for ' +
2601 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002602 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002603 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002604 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002605 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002606 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002607
2608 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002609 elif ( str( onosNode1 ) == str( node2 ) and
2610 str( onosNode2 ) == str( node1 ) ):
2611 if ( int( onosPort1 ) == int( port2 )
2612 and int( onosPort2 ) == int( port1 ) ):
2613 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002614 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002615 main.log.warn(
2616 'The port numbers do not match for ' +
2617 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002618 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002619 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002620 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002621 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002622 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002623 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002624 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002625 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002626 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002627 'ONOS does not have the link %s/%s -> %s/%s' %
2628 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002629 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002630 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002631 'ONOS does not have the link %s/%s -> %s/%s' %
2632 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002633 linkResults = linkResults and firstDir and secondDir
2634 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002635
Jon Hallafa8a472015-06-12 14:02:42 -07002636 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002637 """
Jon Hallafa8a472015-06-12 14:02:42 -07002638 Compare mn and onos Hosts.
2639 Since Mininet hosts are quiet, ONOS will only know of them when they
2640 speak. For this reason, we will only check that the hosts in ONOS
2641 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002642
Jon Hallafa8a472015-06-12 14:02:42 -07002643 Arguments:
2644 hostsJson: parsed json object from the onos hosts api
2645 Returns:
2646 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002647 import json
2648 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002649 for onosHost in hostsJson:
2650 onosMAC = onosHost[ 'mac' ].lower()
2651 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002652 for mnHost, info in hosts.iteritems():
2653 for mnIntf in info[ 'interfaces' ]:
2654 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002655 match = True
2656 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002657 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002658 pass # all is well
2659 else:
2660 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002661 main.log.error( "ONOS host " +
2662 onosHost[ 'id' ] +
2663 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002664 str( onosHost[ 'ipAddresses' ] ) +
2665 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002666 str( ip ) +
2667 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002668 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002669 onosHost,
2670 sort_keys=True,
2671 indent=4,
2672 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002673 main.log.info( output )
2674 hostResults = main.FALSE
2675 if not match:
2676 hostResults = main.FALSE
2677 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2678 "corresponding Mininet host." )
2679 output = json.dumps( onosHost,
2680 sort_keys=True,
2681 indent=4,
2682 separators=( ',', ': ' ) )
2683 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002684 return hostResults
2685
Jon Hallafa8a472015-06-12 14:02:42 -07002686 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002687 """
2688 Returns a list of all hosts
2689 Don't ask questions just use it"""
2690 self.handle.sendline( "" )
2691 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002692
Jon Hall7eb38402015-01-08 17:19:54 -08002693 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2694 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002695
kelvin-onlabd3b64892015-01-20 13:26:24 -08002696 handlePy = self.handle.before
2697 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2698 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002699
Jon Hall7eb38402015-01-08 17:19:54 -08002700 self.handle.sendline( "" )
2701 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002702
kelvin-onlabd3b64892015-01-20 13:26:24 -08002703 hostStr = handlePy.replace( "]", "" )
2704 hostStr = hostStr.replace( "'", "" )
2705 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002706 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002707 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002708
kelvin-onlabd3b64892015-01-20 13:26:24 -08002709 return hostList
adminbae64d82013-08-01 10:50:15 -07002710
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002711 def getSwitch( self ):
2712 """
2713 Returns a list of all switches
2714 Again, don't ask question just use it...
2715 """
2716 # get host list...
2717 hostList = self.getHosts()
2718 # Make host set
2719 hostSet = set( hostList )
2720
2721 # Getting all the nodes in mininet
2722 self.handle.sendline( "" )
2723 self.handle.expect( "mininet>" )
2724
2725 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2726 self.handle.expect( "mininet>" )
2727
2728 handlePy = self.handle.before
2729 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2730 handlePy = handlePy.rstrip()
2731
2732 self.handle.sendline( "" )
2733 self.handle.expect( "mininet>" )
2734
2735 nodesStr = handlePy.replace( "]", "" )
2736 nodesStr = nodesStr.replace( "'", "" )
2737 nodesStr = nodesStr.replace( "[", "" )
2738 nodesStr = nodesStr.replace( " ", "" )
2739 nodesList = nodesStr.split( "," )
2740
2741 nodesSet = set( nodesList )
2742 # discarding default controller(s) node
2743 nodesSet.discard( 'c0' )
2744 nodesSet.discard( 'c1' )
2745 nodesSet.discard( 'c2' )
2746
2747 switchSet = nodesSet - hostSet
2748 switchList = list( switchSet )
2749
2750 return switchList
2751
Jon Hall7eb38402015-01-08 17:19:54 -08002752 def update( self ):
2753 """
2754 updates the port address and status information for
2755 each port in mn"""
2756 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002757 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002758 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002759 self.handle.sendline( "" )
2760 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002761
Jon Hall7eb38402015-01-08 17:19:54 -08002762 self.handle.sendline( "update" )
2763 self.handle.expect( "update" )
2764 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002765
Jon Hall7eb38402015-01-08 17:19:54 -08002766 self.handle.sendline( "" )
2767 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002768
Jon Hallb1290e82014-11-18 16:17:48 -05002769 return main.TRUE
2770 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002771 main.log.error( self.name + ": EOF exception found" )
2772 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002773 main.cleanup()
2774 main.exit()
2775
Jon Halld80cc142015-07-06 13:36:05 -07002776 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002777 """
2778 Add vlan tag to a host.
2779 Dependencies:
2780 This class depends on the "vlan" package
2781 $ sudo apt-get install vlan
2782 Configuration:
2783 Load the 8021q module into the kernel
2784 $sudo modprobe 8021q
2785
2786 To make this setup permanent:
2787 $ sudo su -c 'echo "8021q" >> /etc/modules'
2788 """
2789 if self.handle:
2790 try:
Jon Halld80cc142015-07-06 13:36:05 -07002791 # get the ip address of the host
2792 main.log.info( "Get the ip address of the host" )
2793 ipaddr = self.getIPAddress( host )
2794 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002795
Jon Halld80cc142015-07-06 13:36:05 -07002796 # remove IP from interface intf
2797 # Ex: h1 ifconfig h1-eth0 inet 0
2798 main.log.info( "Remove IP from interface " )
2799 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2800 self.handle.sendline( cmd2 )
2801 self.handle.expect( "mininet>" )
2802 response = self.handle.before
2803 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002804
Jon Halld80cc142015-07-06 13:36:05 -07002805 # create VLAN interface
2806 # Ex: h1 vconfig add h1-eth0 100
2807 main.log.info( "Create Vlan" )
2808 cmd3 = host + " vconfig add " + intf + " " + vlan
2809 self.handle.sendline( cmd3 )
2810 self.handle.expect( "mininet>" )
2811 response = self.handle.before
2812 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002813
Jon Halld80cc142015-07-06 13:36:05 -07002814 # assign the host's IP to the VLAN interface
2815 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2816 main.log.info( "Assign the host IP to the vlan interface" )
2817 vintf = intf + "." + vlan
2818 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2819 self.handle.sendline( cmd4 )
2820 self.handle.expect( "mininet>" )
2821 response = self.handle.before
2822 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002823
2824 return main.TRUE
2825 except pexpect.EOF:
2826 main.log.error( self.name + ": EOF exception found" )
2827 main.log.error( self.name + ": " + self.handle.before )
2828 return main.FALSE
2829
Jon Hall892818c2015-10-20 17:58:34 -07002830 def createHostComponent( self, name ):
2831 """
2832 Creates a new mininet cli component with the same parameters as self.
2833 This new component is intended to be used to login to the hosts created
2834 by mininet.
2835
2836 Arguments:
2837 name - The string of the name of this component. The new component
2838 will be assigned to main.<name> .
2839 In addition, main.<name>.name = str( name )
2840 """
2841 try:
2842 # look to see if this component already exists
2843 getattr( main, name )
2844 except AttributeError:
2845 # namespace is clear, creating component
2846 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
2847 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
2848 main.componentInit( name )
2849 except Exception:
2850 main.log.exception( self.name + ": Uncaught exception!" )
2851 main.cleanup()
2852 main.exit()
2853 else:
2854 # namespace is not clear!
2855 main.log.error( name + " component already exists!" )
2856 # FIXME: Should we exit here?
2857 main.cleanup()
2858 main.exit()
2859
2860 def removeHostComponent( self, name ):
2861 """
2862 Remove host component
2863 Arguments:
2864 name - The string of the name of the component to delete.
2865 """
2866 try:
2867 # Get host component
2868 component = getattr( main, name )
2869 except AttributeError:
2870 main.log.error( "Component " + name + " does not exist." )
2871 return
2872 try:
2873 # Disconnect from component
2874 component.disconnect()
2875 # Delete component
2876 delattr( main, name )
2877 # Delete component from ComponentDictionary
2878 del( main.componentDictionary[name] )
2879 except Exception:
2880 main.log.exception( self.name + ": Uncaught exception!" )
2881 main.cleanup()
2882 main.exit()
2883
2884 def startHostCli( self, host=None ):
2885 """
2886 Use the mininet m utility to connect to the host's cli
2887 """
2888 # These are fields that can be used by scapy packets. Initialized to None
2889 self.hostIp = None
2890 self.hostMac = None
2891 try:
2892 if not host:
2893 host = self.name
2894 self.handle.sendline( self.home + "/util/m " + host )
2895 self.handle.expect( self.hostPrompt )
2896 return main.TRUE
2897 except pexpect.TIMEOUT:
2898 main.log.exception( self.name + ": Command timed out" )
2899 return main.FALSE
2900 except pexpect.EOF:
2901 main.log.exception( self.name + ": connection closed." )
2902 main.cleanup()
2903 main.exit()
2904 except Exception:
2905 main.log.exception( self.name + ": Uncaught exception!" )
2906 main.cleanup()
2907 main.exit()
2908
GlennRC956ea742015-11-05 16:14:15 -08002909 def startScapy( self, mplsPath="" ):
Jon Hall892818c2015-10-20 17:58:34 -07002910 """
2911 Start the Scapy cli
GlennRC956ea742015-11-05 16:14:15 -08002912 optional:
2913 mplsPath - The path where the MPLS class is located
2914 NOTE: This can be a relative path from the user's home dir
Jon Hall892818c2015-10-20 17:58:34 -07002915 """
GlennRC956ea742015-11-05 16:14:15 -08002916 mplsLines = ['import imp',
2917 'imp.load_source( "mplsClass", "{}mplsClass.py" )'.format(mplsPath),
2918 'from mplsClass import MPLS',
2919 'bind_layers(Ether, MPLS, type = 0x8847)',
2920 'bind_layers(MPLS, MPLS, bottom_of_label_stack = 0)',
2921 'bind_layers(MPLS, IP)']
2922
Jon Hall892818c2015-10-20 17:58:34 -07002923 try:
2924 self.handle.sendline( "scapy" )
2925 self.handle.expect( self.scapyPrompt )
2926 self.handle.sendline( "conf.color_theme = NoTheme()" )
2927 self.handle.expect( self.scapyPrompt )
GlennRC956ea742015-11-05 16:14:15 -08002928 if mplsPath:
2929 main.log.info( "Adding MPLS class" )
2930 main.log.info( "MPLS class path: " + mplsPath )
2931 for line in mplsLines:
2932 main.log.info( "sending line: " + line )
2933 self.handle.sendline( line )
2934 self.handle.expect( self.scapyPrompt )
Jon Hall892818c2015-10-20 17:58:34 -07002935 return main.TRUE
2936 except pexpect.TIMEOUT:
2937 main.log.exception( self.name + ": Command timed out" )
2938 return main.FALSE
2939 except pexpect.EOF:
2940 main.log.exception( self.name + ": connection closed." )
2941 main.cleanup()
2942 main.exit()
2943 except Exception:
2944 main.log.exception( self.name + ": Uncaught exception!" )
2945 main.cleanup()
2946 main.exit()
2947
2948 def stopScapy( self ):
2949 """
2950 Exit the Scapy cli
2951 """
2952 try:
2953 self.handle.sendline( "exit()" )
2954 self.handle.expect( self.hostPrompt )
2955 return main.TRUE
2956 except pexpect.TIMEOUT:
2957 main.log.exception( self.name + ": Command timed out" )
2958 return main.FALSE
2959 except pexpect.EOF:
2960 main.log.exception( self.name + ": connection closed." )
2961 main.cleanup()
2962 main.exit()
2963 except Exception:
2964 main.log.exception( self.name + ": Uncaught exception!" )
2965 main.cleanup()
2966 main.exit()
2967
2968 def buildEther( self, **kwargs ):
2969 """
2970 Build an Ethernet frame
2971
2972 Will create a frame class with the given options. If a field is
2973 left blank it will default to the below value unless it is
2974 overwritten by the next frame.
2975 Default frame:
2976 ###[ Ethernet ]###
2977 dst= ff:ff:ff:ff:ff:ff
2978 src= 00:00:00:00:00:00
2979 type= 0x800
2980
2981 Returns main.TRUE or main.FALSE on error
2982 """
2983 try:
2984 # Set the Ethernet frame
2985 cmd = 'ether = Ether( '
2986 options = []
2987 for key, value in kwargs.iteritems():
2988 if isinstance( value, str ):
2989 value = '"' + value + '"'
2990 options.append( str( key ) + "=" + str( value ) )
2991 cmd += ", ".join( options )
2992 cmd += ' )'
2993 self.handle.sendline( cmd )
2994 self.handle.expect( self.scapyPrompt )
2995 if "Traceback" in self.handle.before:
2996 # KeyError, SyntaxError, ...
2997 main.log.error( "Error in sending command: " + self.handle.before )
2998 return main.FALSE
2999 self.handle.sendline( "packet = ether" )
3000 self.handle.expect( self.scapyPrompt )
3001 if "Traceback" in self.handle.before:
3002 # KeyError, SyntaxError, ...
3003 main.log.error( "Error in sending command: " + self.handle.before )
3004 return main.FALSE
3005 return main.TRUE
3006 except pexpect.TIMEOUT:
3007 main.log.exception( self.name + ": Command timed out" )
3008 return main.FALSE
3009 except pexpect.EOF:
3010 main.log.exception( self.name + ": connection closed." )
3011 main.cleanup()
3012 main.exit()
3013 except Exception:
3014 main.log.exception( self.name + ": Uncaught exception!" )
3015 main.cleanup()
3016 main.exit()
3017
3018 def buildIP( self, **kwargs ):
3019 """
3020 Build an IP frame
3021
3022 Will create a frame class with the given options. If a field is
3023 left blank it will default to the below value unless it is
3024 overwritten by the next frame.
3025 Default frame:
3026 ###[ IP ]###
3027 version= 4
3028 ihl= None
3029 tos= 0x0
3030 len= None
3031 id= 1
3032 flags=
3033 frag= 0
3034 ttl= 64
3035 proto= hopopt
3036 chksum= None
3037 src= 127.0.0.1
3038 dst= 127.0.0.1
3039 \options\
3040
3041 Returns main.TRUE or main.FALSE on error
3042 """
3043 try:
3044 # Set the IP frame
3045 cmd = 'ip = IP( '
3046 options = []
3047 for key, value in kwargs.iteritems():
3048 if isinstance( value, str ):
3049 value = '"' + value + '"'
3050 options.append( str( key ) + "=" + str( value ) )
3051 cmd += ", ".join( options )
3052 cmd += ' )'
3053 self.handle.sendline( cmd )
3054 self.handle.expect( self.scapyPrompt )
3055 if "Traceback" in self.handle.before:
3056 # KeyError, SyntaxError, ...
3057 main.log.error( "Error in sending command: " + self.handle.before )
3058 return main.FALSE
3059 self.handle.sendline( "packet = ether/ip" )
3060 self.handle.expect( self.scapyPrompt )
3061 if "Traceback" in self.handle.before:
3062 # KeyError, SyntaxError, ...
3063 main.log.error( "Error in sending command: " + self.handle.before )
3064 return main.FALSE
3065 return main.TRUE
3066 except pexpect.TIMEOUT:
3067 main.log.exception( self.name + ": Command timed out" )
3068 return main.FALSE
3069 except pexpect.EOF:
3070 main.log.exception( self.name + ": connection closed." )
3071 main.cleanup()
3072 main.exit()
3073 except Exception:
3074 main.log.exception( self.name + ": Uncaught exception!" )
3075 main.cleanup()
3076 main.exit()
3077
3078 def buildIPv6( self, **kwargs ):
3079 """
3080 Build an IPv6 frame
3081
3082 Will create a frame class with the given options. If a field is
3083 left blank it will default to the below value unless it is
3084 overwritten by the next frame.
3085 Default frame:
3086 ###[ IPv6 ]###
3087 version= 6
3088 tc= 0
3089 fl= 0
3090 plen= None
3091 nh= No Next Header
3092 hlim= 64
3093 src= ::1
3094 dst= ::1
3095
3096 Returns main.TRUE or main.FALSE on error
3097 """
3098 try:
3099 # Set the IPv6 frame
3100 cmd = 'ipv6 = IPv6( '
3101 options = []
3102 for key, value in kwargs.iteritems():
3103 if isinstance( value, str ):
3104 value = '"' + value + '"'
3105 options.append( str( key ) + "=" + str( value ) )
3106 cmd += ", ".join( options )
3107 cmd += ' )'
3108 self.handle.sendline( cmd )
3109 self.handle.expect( self.scapyPrompt )
3110 if "Traceback" in self.handle.before:
3111 # KeyError, SyntaxError, ...
3112 main.log.error( "Error in sending command: " + self.handle.before )
3113 return main.FALSE
3114 self.handle.sendline( "packet = ether/ipv6" )
3115 self.handle.expect( self.scapyPrompt )
3116 if "Traceback" in self.handle.before:
3117 # KeyError, SyntaxError, ...
3118 main.log.error( "Error in sending command: " + self.handle.before )
3119 return main.FALSE
3120 return main.TRUE
3121 except pexpect.TIMEOUT:
3122 main.log.exception( self.name + ": Command timed out" )
3123 return main.FALSE
3124 except pexpect.EOF:
3125 main.log.exception( self.name + ": connection closed." )
3126 main.cleanup()
3127 main.exit()
3128 except Exception:
3129 main.log.exception( self.name + ": Uncaught exception!" )
3130 main.cleanup()
3131 main.exit()
3132
3133 def buildTCP( self, ipVersion=4, **kwargs ):
3134 """
3135 Build an TCP frame
3136
3137 Will create a frame class with the given options. If a field is
3138 left blank it will default to the below value unless it is
3139 overwritten by the next frame.
3140
GlennRC956ea742015-11-05 16:14:15 -08003141 NOTE: Some arguments require quotes around them. It's up to you to
3142 know which ones and to add them yourself. Arguments with an asterisk
3143 do not need quotes.
3144
Jon Hall892818c2015-10-20 17:58:34 -07003145 Options:
3146 ipVersion - Either 4 (default) or 6, indicates what Internet Protocol
3147 frame to use to encapsulate into
3148 Default frame:
3149 ###[ TCP ]###
GlennRC956ea742015-11-05 16:14:15 -08003150 sport= ftp_data *
3151 dport= http *
Jon Hall892818c2015-10-20 17:58:34 -07003152 seq= 0
3153 ack= 0
3154 dataofs= None
3155 reserved= 0
3156 flags= S
3157 window= 8192
3158 chksum= None
3159 urgptr= 0
3160 options= {}
3161
3162 Returns main.TRUE or main.FALSE on error
3163 """
3164 try:
3165 # Set the TCP frame
3166 cmd = 'tcp = TCP( '
3167 options = []
3168 for key, value in kwargs.iteritems():
Jon Hall892818c2015-10-20 17:58:34 -07003169 options.append( str( key ) + "=" + str( value ) )
3170 cmd += ", ".join( options )
3171 cmd += ' )'
3172 self.handle.sendline( cmd )
3173 self.handle.expect( self.scapyPrompt )
3174 if "Traceback" in self.handle.before:
3175 # KeyError, SyntaxError, ...
3176 main.log.error( "Error in sending command: " + self.handle.before )
3177 return main.FALSE
3178 if str( ipVersion ) is '4':
3179 self.handle.sendline( "packet = ether/ip/tcp" )
3180 elif str( ipVersion ) is '6':
3181 self.handle.sendline( "packet = ether/ipv6/tcp" )
3182 else:
3183 main.log.error( "Unrecognized option for ipVersion, given " +
3184 repr( ipVersion ) )
3185 return main.FALSE
3186 self.handle.expect( self.scapyPrompt )
3187 if "Traceback" in self.handle.before:
3188 # KeyError, SyntaxError, ...
3189 main.log.error( "Error in sending command: " + self.handle.before )
3190 return main.FALSE
3191 return main.TRUE
3192 except pexpect.TIMEOUT:
3193 main.log.exception( self.name + ": Command timed out" )
3194 return main.FALSE
3195 except pexpect.EOF:
3196 main.log.exception( self.name + ": connection closed." )
3197 main.cleanup()
3198 main.exit()
3199 except Exception:
3200 main.log.exception( self.name + ": Uncaught exception!" )
3201 main.cleanup()
3202 main.exit()
3203
3204 def buildUDP( self, ipVersion=4, **kwargs ):
3205 """
3206 Build an UDP frame
3207
3208 Will create a frame class with the given options. If a field is
3209 left blank it will default to the below value unless it is
3210 overwritten by the next frame.
3211
GlennRC956ea742015-11-05 16:14:15 -08003212 NOTE: Some arguments require quotes around them. It's up to you to
3213 know which ones and to add them yourself. Arguments with an asterisk
3214 do not need quotes.
3215
Jon Hall892818c2015-10-20 17:58:34 -07003216 Options:
3217 ipVersion - Either 4 (default) or 6, indicates what Internet Protocol
3218 frame to use to encapsulate into
3219 Default frame:
3220 ###[ UDP ]###
GlennRC956ea742015-11-05 16:14:15 -08003221 sport= domain *
3222 dport= domain *
Jon Hall892818c2015-10-20 17:58:34 -07003223 len= None
3224 chksum= None
3225
3226 Returns main.TRUE or main.FALSE on error
3227 """
3228 try:
3229 # Set the UDP frame
3230 cmd = 'udp = UDP( '
3231 options = []
3232 for key, value in kwargs.iteritems():
Jon Hall892818c2015-10-20 17:58:34 -07003233 options.append( str( key ) + "=" + str( value ) )
3234 cmd += ", ".join( options )
3235 cmd += ' )'
3236 self.handle.sendline( cmd )
3237 self.handle.expect( self.scapyPrompt )
3238 if "Traceback" in self.handle.before:
3239 # KeyError, SyntaxError, ...
3240 main.log.error( "Error in sending command: " + self.handle.before )
3241 return main.FALSE
3242 if str( ipVersion ) is '4':
3243 self.handle.sendline( "packet = ether/ip/udp" )
3244 elif str( ipVersion ) is '6':
3245 self.handle.sendline( "packet = ether/ipv6/udp" )
3246 else:
3247 main.log.error( "Unrecognized option for ipVersion, given " +
3248 repr( ipVersion ) )
3249 return main.FALSE
3250 self.handle.expect( self.scapyPrompt )
3251 if "Traceback" in self.handle.before:
3252 # KeyError, SyntaxError, ...
3253 main.log.error( "Error in sending command: " + self.handle.before )
3254 return main.FALSE
3255 return main.TRUE
3256 except pexpect.TIMEOUT:
3257 main.log.exception( self.name + ": Command timed out" )
3258 return main.FALSE
3259 except pexpect.EOF:
3260 main.log.exception( self.name + ": connection closed." )
3261 main.cleanup()
3262 main.exit()
3263 except Exception:
3264 main.log.exception( self.name + ": Uncaught exception!" )
3265 main.cleanup()
3266 main.exit()
3267
3268 def buildICMP( self, **kwargs ):
3269 """
3270 Build an ICMP frame
3271
3272 Will create a frame class with the given options. If a field is
3273 left blank it will default to the below value unless it is
3274 overwritten by the next frame.
3275 Default frame:
3276 ###[ ICMP ]###
3277 type= echo-request
3278 code= 0
3279 chksum= None
3280 id= 0x0
3281 seq= 0x0
3282
3283 Returns main.TRUE or main.FALSE on error
3284 """
3285 try:
3286 # Set the ICMP frame
3287 cmd = 'icmp = ICMP( '
3288 options = []
3289 for key, value in kwargs.iteritems():
3290 if isinstance( value, str ):
3291 value = '"' + value + '"'
3292 options.append( str( key ) + "=" + str( value ) )
3293 cmd += ", ".join( options )
3294 cmd += ' )'
3295 self.handle.sendline( cmd )
3296 self.handle.expect( self.scapyPrompt )
3297 if "Traceback" in self.handle.before:
3298 # KeyError, SyntaxError, ...
3299 main.log.error( "Error in sending command: " + self.handle.before )
3300 return main.FALSE
3301 self.handle.sendline( "packet = ether/ip/icmp" )
3302 self.handle.expect( self.scapyPrompt )
3303 if "Traceback" in self.handle.before:
3304 # KeyError, SyntaxError, ...
3305 main.log.error( "Error in sending command: " + self.handle.before )
3306 return main.FALSE
3307 return main.TRUE
3308 except pexpect.TIMEOUT:
3309 main.log.exception( self.name + ": Command timed out" )
3310 return main.FALSE
3311 except pexpect.EOF:
3312 main.log.exception( self.name + ": connection closed." )
3313 main.cleanup()
3314 main.exit()
3315 except Exception:
3316 main.log.exception( self.name + ": Uncaught exception!" )
3317 main.cleanup()
3318 main.exit()
3319
GlennRC073e8bc2015-10-27 17:11:28 -07003320 def sendPacket( self, iface=None, packet=None, timeout=1 ):
Jon Hall892818c2015-10-20 17:58:34 -07003321 """
3322 Send a packet with either the given scapy packet command, or use the
3323 packet saved in the variable 'packet'.
3324
3325 Examples of a valid string for packet:
3326
3327 Simple IP packet
3328 packet='Ether(dst="a6:d9:26:df:1d:4b")/IP(dst="10.0.0.2")'
3329
3330 A Ping with two vlan tags
3331 packet='Ether(dst='ff:ff:ff:ff:ff:ff')/Dot1Q(vlan=1)/Dot1Q(vlan=10)/
3332 IP(dst='255.255.255.255', src='192.168.0.1')/ICMP()'
3333
3334 Returns main.TRUE or main.FALSE on error
3335 """
3336 try:
3337 # TODO: add all params, or use kwargs
3338 sendCmd = 'srp( '
3339 if packet:
3340 sendCmd += packet
3341 else:
3342 sendCmd += "packet"
GlennRC073e8bc2015-10-27 17:11:28 -07003343 if iface:
3344 sendCmd += ", iface='{}'".format( iface )
3345
Jon Hall892818c2015-10-20 17:58:34 -07003346 sendCmd += ', timeout=' + str( timeout ) + ')'
3347 self.handle.sendline( sendCmd )
3348 self.handle.expect( self.scapyPrompt )
3349 if "Traceback" in self.handle.before:
3350 # KeyError, SyntaxError, ...
3351 main.log.error( "Error in sending command: " + self.handle.before )
3352 return main.FALSE
3353 # TODO: Check # of packets sent?
3354 return main.TRUE
3355 except pexpect.TIMEOUT:
3356 main.log.exception( self.name + ": Command timed out" )
3357 return main.FALSE
3358 except pexpect.EOF:
3359 main.log.exception( self.name + ": connection closed." )
3360 main.cleanup()
3361 main.exit()
3362 except Exception:
3363 main.log.exception( self.name + ": Uncaught exception!" )
3364 main.cleanup()
3365 main.exit()
3366
3367 def startFilter( self, ifaceName=None, sniffCount=1, pktFilter="ip" ):
3368 """
3369 Listen for packets using the given filters
3370
3371 Options:
3372 ifaceName - the name of the interface to listen on. If none is given,
3373 defaults to <host name>-eth0
3374 pktFilter - A string in Berkeley Packet Filter (BPF) format which
3375 specifies which packets to sniff
3376 sniffCount - The number of matching packets to capture before returning
3377
3378 Returns main.TRUE or main.FALSE on error
3379 """
3380 try:
3381 # TODO: add all params, or use kwargs
3382 ifaceName = str( ifaceName ) if ifaceName else self.name + "-eth0"
3383 # Set interface
3384 self.handle.sendline( ' conf.iface = "' + ifaceName + '"' )
3385 self.handle.expect( self.scapyPrompt )
3386 cmd = 'pkt = sniff(count = ' + str( sniffCount ) +\
3387 ', filter = "' + str( pktFilter ) + '")'
3388 self.handle.sendline( cmd )
3389 self.handle.expect( '"\)\r\n' )
3390 # TODO: parse this?
3391 return main.TRUE
3392 except pexpect.TIMEOUT:
3393 main.log.exception( self.name + ": Command timed out" )
3394 return main.FALSE
3395 except pexpect.EOF:
3396 main.log.exception( self.name + ": connection closed." )
3397 main.cleanup()
3398 main.exit()
3399 except Exception:
3400 main.log.exception( self.name + ": Uncaught exception!" )
3401 main.cleanup()
3402 main.exit()
3403
3404 def checkFilter( self ):
3405 """
3406 Check that a filter returned and returns the reponse
3407 """
3408 try:
3409 i = self.handle.expect( [ self.scapyPrompt, pexpect.TIMEOUT ] )
3410 if i == 0:
3411 return main.TRUE
3412 else:
3413 return main.FALSE
3414 except pexpect.EOF:
3415 main.log.exception( self.name + ": connection closed." )
3416 main.cleanup()
3417 main.exit()
3418 except Exception:
3419 main.log.exception( self.name + ": Uncaught exception!" )
3420 main.cleanup()
3421 main.exit()
3422
3423 def killFilter( self ):
3424 """
3425 Kill a scapy filter
3426 """
3427 try:
3428 self.handle.send( "\x03" ) # Send a ctrl-c to kill the filter
3429 self.handle.expect( self.scapyPrompt )
3430 return self.handle.before
3431 except pexpect.TIMEOUT:
3432 main.log.exception( self.name + ": Command timed out" )
3433 return None
3434 except pexpect.EOF:
3435 main.log.exception( self.name + ": connection closed." )
3436 main.cleanup()
3437 main.exit()
3438 except Exception:
3439 main.log.exception( self.name + ": Uncaught exception!" )
3440 main.cleanup()
3441 main.exit()
3442
3443 def readPackets( self ):
3444 """
3445 Read all the packets captured by the previous filter
3446 """
3447 try:
3448 self.handle.sendline( "for p in pkt: p \n")
3449 self.handle.expect( "for p in pkt: p \r\n... \r\n" )
3450 self.handle.expect( self.scapyPrompt )
3451 except pexpect.TIMEOUT:
3452 main.log.exception( self.name + ": Command timed out" )
3453 return None
3454 except pexpect.EOF:
3455 main.log.exception( self.name + ": connection closed." )
3456 main.cleanup()
3457 main.exit()
3458 except Exception:
3459 main.log.exception( self.name + ": Uncaught exception!" )
3460 main.cleanup()
3461 main.exit()
3462 return self.handle.before
3463
3464 def updateSelf( self ):
3465 """
3466 Updates local MAC and IP fields
3467 """
3468 self.hostMac = self.getMac()
3469 self.hostIp = self.getIp()
3470
3471 def getMac( self, ifaceName=None ):
3472 """
3473 Save host's MAC address
3474 """
3475 try:
3476 ifaceName = str( ifaceName ) if ifaceName else self.name + "-eth0"
3477 cmd = 'get_if_hwaddr("' + str( ifaceName ) + '")'
3478 self.handle.sendline( cmd )
3479 self.handle.expect( self.scapyPrompt )
3480 pattern = r'(([0-9a-f]{2}[:-]){5}([0-9a-f]{2}))'
3481 match = re.search( pattern, self.handle.before )
3482 if match:
3483 return match.group()
3484 else:
3485 # the command will have an exception if iface doesn't exist
3486 return None
3487 except pexpect.TIMEOUT:
3488 main.log.exception( self.name + ": Command timed out" )
3489 return None
3490 except pexpect.EOF:
3491 main.log.exception( self.name + ": connection closed." )
3492 main.cleanup()
3493 main.exit()
3494 except Exception:
3495 main.log.exception( self.name + ": Uncaught exception!" )
3496 main.cleanup()
3497 main.exit()
3498
3499 def getIp( self, ifaceName=None ):
3500 """
3501 Save host's IP address
3502 """
3503 try:
3504 ifaceName = ifaceName if ifaceName else self.name + "-eth0"
3505 cmd = 'get_if_addr("' + str( ifaceName ) + '")'
3506 self.handle.sendline( cmd )
3507 self.handle.expect( self.scapyPrompt )
3508
3509 pattern = r'(((2[0-5]|1[0-9]|[0-9])?[0-9]\.){3}((2[0-5]|1[0-9]|[0-9])?[0-9]))'
3510 match = re.search( pattern, self.handle.before )
3511 if match:
3512 # NOTE: The command will return 0.0.0.0 if the iface doesn't exist
3513 return match.group()
3514 else:
3515 return None
3516 except pexpect.TIMEOUT:
3517 main.log.exception( self.name + ": Command timed out" )
3518 return None
3519 except pexpect.EOF:
3520 main.log.exception( self.name + ": connection closed." )
3521 main.cleanup()
3522 main.exit()
3523 except Exception:
3524 main.log.exception( self.name + ": Uncaught exception!" )
3525 main.cleanup()
3526 main.exit()
3527
adminbae64d82013-08-01 10:50:15 -07003528if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07003529 sys.modules[ __name__ ] = MininetCliDriver()