blob: 221fe821eba8e1387be27eafba27cfca15b3e421 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
Jon Hall7eb38402015-01-08 17:19:54 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
4
Jon Hallbe6dfc42015-01-12 17:37:25 -08005author: Anil Kumar ( anilkumar.s@paxterrasolutions.com )
adminbae64d82013-08-01 10:50:15 -07006
7
Jon Hall7eb38402015-01-08 17:19:54 -08008TestON is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 2 of the License, or
11( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070012
Jon Hall7eb38402015-01-08 17:19:54 -080013TestON is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070017
Jon Hall7eb38402015-01-08 17:19:54 -080018You should have received a copy of the GNU General Public License
19along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070020
Jon Hallbe6dfc42015-01-12 17:37:25 -080021MininetCliDriver is the basic driver which will handle the Mininet functions
22
23Some functions rely on a modified version of Mininet. These functions
24should all be noted in the comments. To get this MN version run these commands
25from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080026 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080027 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080028 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080029 git pull
30
Jon Hall272a4db2015-01-12 17:43:48 -080031
32 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080033changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070034import pexpect
adminbae64d82013-08-01 10:50:15 -070035import re
36import sys
kelvin-onlabfa6ada82015-06-11 13:06:24 -070037import types
kelvin-onlaba4074292015-07-09 15:19:49 -070038import os
Jon Hall1ccf82c2014-10-15 14:55:16 -040039from math import pow
adminbae64d82013-08-01 10:50:15 -070040from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070041
Jon Hall7eb38402015-01-08 17:19:54 -080042
kelvin-onlab50907142015-04-01 13:37:45 -070043class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080044
45 """
46 MininetCliDriver is the basic driver which will handle
47 the Mininet functions"""
48 def __init__( self ):
49 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070050 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080051 self.name = None
kelvin-onlabd9e23de2015-08-06 10:34:44 -070052 self.home = None
Jon Hall7eb38402015-01-08 17:19:54 -080053 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070054 self.flag = 0
Jon Hall892818c2015-10-20 17:58:34 -070055 # TODO: Refactor driver to use these everywhere
56 self.mnPrompt = "mininet>"
57 self.hostPrompt = "~#"
58 self.bashPrompt = "\$"
59 self.scapyPrompt = ">>>"
adminbae64d82013-08-01 10:50:15 -070060
Jon Hall7eb38402015-01-08 17:19:54 -080061 def connect( self, **connectargs ):
62 """
63 Here the main is the TestON instance after creating
64 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080065 try:
66 for key in connectargs:
67 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070068 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080069 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070070 for key in self.options:
71 if key == "home":
72 self.home = self.options[ 'home' ]
73 break
74 if self.home is None or self.home == "":
75 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070076
77 try:
Jon Hall892818c2015-10-20 17:58:34 -070078 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070079 self.ip_address = os.getenv( str( self.ip_address ) )
80 else:
81 main.log.info( self.name +
82 ": Trying to connect to " +
83 self.ip_address )
84
85 except KeyError:
86 main.log.info( "Invalid host name," +
87 " connecting to local host instead" )
88 self.ip_address = 'localhost'
89 except Exception as inst:
90 main.log.error( "Uncaught exception: " + str( inst ) )
91
kelvin-onlaba1484582015-02-02 15:46:20 -080092 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070093 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080094 self ).connect(
95 user_name=self.user_name,
96 ip_address=self.ip_address,
97 port=None,
98 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080099
kelvin-onlaba1484582015-02-02 15:46:20 -0800100 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -0800101 main.log.info( "Connection successful to the host " +
102 self.user_name +
103 "@" +
104 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800105 return main.TRUE
106 else:
107 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800108 self.user_name +
109 "@" +
110 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800111 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800112 return main.FALSE
113 except pexpect.EOF:
114 main.log.error( self.name + ": EOF exception found" )
115 main.log.error( self.name + ": " + self.handle.before )
116 main.cleanup()
117 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800118 except Exception:
119 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800120 main.cleanup()
121 main.exit()
122
kelvin-onlab10e8d392015-06-03 13:53:45 -0700123 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800124 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700125 Description:
126 Starts Mininet accepts a topology(.py) file and/or an optional
127 argument, to start the mininet, as a parameter.
128 Can also send regular mininet command to load up desired topology.
129 Eg. Pass in a string 'sudo mn --topo=tree,3,3' to mnCmd
130 Options:
131 topoFile = file path for topology file (.py)
132 args = extra option added when starting the topology from the file
133 mnCmd = Mininet command use to start topology
134 Returns:
135 main.TRUE if the mininet starts successfully, main.FALSE
136 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800137 """
Jon Hall7eb38402015-01-08 17:19:54 -0800138 if self.handle:
Jon Hall689d8e42015-04-03 13:59:24 -0700139 # make sure old networks are cleaned up
140 main.log.info( self.name +
141 ": Clearing any residual state or processes" )
Jon Hall7eb38402015-01-08 17:19:54 -0800142 self.handle.sendline( "sudo mn -c" )
143 i = self.handle.expect( [ 'password\sfor\s',
144 'Cleanup\scomplete',
145 pexpect.EOF,
146 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800147 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800148 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700149 # Sudo asking for password
Jon Hall7eb38402015-01-08 17:19:54 -0800150 main.log.info( self.name + ": Sending sudo password" )
151 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800152 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800153 '\$',
154 pexpect.EOF,
155 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800156 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800157 if i == 1:
158 main.log.info( self.name + ": Clean" )
159 elif i == 2:
160 main.log.error( self.name + ": Connection terminated" )
161 elif i == 3: # timeout
Jon Hall689d8e42015-04-03 13:59:24 -0700162 main.log.error( self.name + ": Something while cleaning " +
163 "Mininet took too long... " )
164 # Craft the string to start mininet
165 cmdString = "sudo "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700166 if not mnCmd:
167 if topoFile is None or topoFile == '': # If no file is given
168 main.log.info( self.name + ": building fresh Mininet" )
169 cmdString += "mn "
170 if args is None or args == '':
171 # If no args given, use args from .topo file
172 args = self.options[ 'arg1' ] +\
Jon Halld80cc142015-07-06 13:36:05 -0700173 " " + self.options[ 'arg2' ] +\
174 " --mac --controller " +\
175 self.options[ 'controller' ] + " " +\
176 self.options[ 'arg3' ]
kelvin-onlab10e8d392015-06-03 13:53:45 -0700177 else: # else only use given args
178 pass
179 # TODO: allow use of topo args and method args?
180 else: # Use given topology file
Jon Halld80cc142015-07-06 13:36:05 -0700181 main.log.info(
182 "Starting Mininet from topo file " +
183 topoFile )
Flavio Castrocc38a542016-03-03 13:15:46 -0800184 cmdString += "-E python " + topoFile + " "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700185 if args is None:
186 args = ''
187 # TODO: allow use of args from .topo file?
188 cmdString += args
189 else:
190 main.log.info( "Starting Mininet topology using '" + mnCmd +
191 "' command" )
192 cmdString += mnCmd
Jon Hall689d8e42015-04-03 13:59:24 -0700193 # Send the command and check if network started
194 self.handle.sendline( "" )
195 self.handle.expect( '\$' )
196 main.log.info( "Sending '" + cmdString + "' to " + self.name )
197 self.handle.sendline( cmdString )
198 while True:
Jon Hall7eb38402015-01-08 17:19:54 -0800199 i = self.handle.expect( [ 'mininet>',
Jon Hall689d8e42015-04-03 13:59:24 -0700200 'Exception',
201 '\*\*\*',
Jon Hallefbd9792015-03-05 16:11:36 -0800202 pexpect.EOF,
203 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700204 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800205 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700206 main.log.info( self.name + ": Mininet built" )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800207 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800208 elif i == 1:
Jon Hall689d8e42015-04-03 13:59:24 -0700209 response = str( self.handle.before +
210 self.handle.after )
211 self.handle.expect( '\$' )
212 response += str( self.handle.before +
Jon Halld80cc142015-07-06 13:36:05 -0700213 self.handle.after )
Jon Hall689d8e42015-04-03 13:59:24 -0700214 main.log.error(
215 self.name +
216 ": Launching Mininet failed: " + response )
217 return main.FALSE
218 elif i == 2:
219 self.handle.expect( [ "\n",
220 pexpect.EOF,
221 pexpect.TIMEOUT ],
222 timeout )
223 main.log.info( self.handle.before )
224 elif i == 3:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800225 main.log.error( self.name + ": Connection timeout" )
226 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700227 elif i == 4: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800228 main.log.error(
229 self.name +
230 ": Something took too long... " )
231 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700232 # Why did we hit this part?
233 main.log.error( "startNet did not return correctly" )
234 return main.FASLE
Jon Hall7eb38402015-01-08 17:19:54 -0800235 else: # if no handle
Jon Hall689d8e42015-04-03 13:59:24 -0700236 main.log.error( self.name + ": Connection failed to the host " +
237 self.user_name + "@" + self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800238 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700239 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800240
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800241 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400242 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800243 # In tree topology, if fanout arg is not given, by default it is 2
244 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400245 fanout = 2
246 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500247 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800248 while( k <= depth - 1 ):
249 count = count + pow( fanout, k )
250 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800251 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800252 while( k <= depth - 2 ):
253 # depth-2 gives you only core links and not considering
254 # edge links as seen by ONOS. If all the links including
255 # edge links are required, do depth-1
256 count = count + pow( fanout, k )
257 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800258 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800259 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800260 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800261
Jon Hall7eb38402015-01-08 17:19:54 -0800262 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800263 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800264 # by default it is 1
265 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400266 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800267 numSwitches = depth
268 numHostsPerSw = fanout
269 totalNumHosts = numSwitches * numHostsPerSw
270 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800271 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800272 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800273 topoDict = { "num_switches": int( numSwitches ),
274 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400275 return topoDict
276
kelvin-onlabd3b64892015-01-20 13:26:24 -0800277 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700278 """
279 Calculate the number of switches and links in a topo."""
280 # TODO: combine this function and numSwitchesNlinks
281 argList = self.options[ 'arg1' ].split( "," )
282 topoArgList = argList[ 0 ].split( " " )
283 argList = map( int, argList[ 1: ] )
284 topoArgList = topoArgList[ 1: ] + argList
285
286 topoDict = self.numSwitchesNlinks( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400287 return topoDict
288
GlennRCf07c44a2015-09-18 13:33:46 -0700289 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800290 """
291 Verifies the reachability of the hosts using pingall command.
292 Optional parameter timeout allows you to specify how long to
293 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700294 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700295 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700296 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700297 ping
298 acceptableFailed - Set the number of acceptable failed pings for the
299 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800300 Returns:
301 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700302 otherwise main.FALSE
303 """
304 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700305 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700306 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700307 if self.handle:
308 main.log.info(
309 self.name +
310 ": Checking reachabilty to the hosts using pingall" )
311 response = ""
312 failedPings = 0
313 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700314 cmd = "pingall"
315 if protocol == "IPv6":
316 cmd = "py net.pingAll6()"
317 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700318 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700319 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700320 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700321 pexpect.EOF,
322 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700323 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700324 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700325 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700326 response += self.handle.before
327 break
328 elif i == 1:
329 response += self.handle.before + self.handle.after
330 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700331 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700332 returnValue = main.FALSE
333 if shortCircuit:
334 main.log.error( self.name +
335 ": Aborting pingall - "
336 + str( failedPings ) +
337 " pings failed" )
338 break
Jon Hall390696c2015-05-05 17:13:41 -0700339 if ( time.time() - startTime ) > timeout:
340 returnValue = main.FALSE
341 main.log.error( self.name +
342 ": Aborting pingall - " +
343 "Function took too long " )
344 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700345 elif i == 2:
346 main.log.error( self.name +
347 ": EOF exception found" )
348 main.log.error( self.name + ": " +
349 self.handle.before )
350 main.cleanup()
351 main.exit()
352 elif i == 3:
353 response += self.handle.before
354 main.log.error( self.name +
355 ": TIMEOUT exception found" )
356 main.log.error( self.name +
357 ": " +
358 str( response ) )
359 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800360 self.handle.send( "\x03" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700361 self.handle.expect( "Interrupt" )
362 self.handle.expect( "mininet>" )
363 break
364 pattern = "Results\:"
365 main.log.info( "Pingall output: " + str( response ) )
366 if re.search( pattern, response ):
367 main.log.info( self.name + ": Pingall finished with "
368 + str( failedPings ) + " failed pings" )
369 return returnValue
370 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700371 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800372 self.handle.send( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700373 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700374 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700375 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700376 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700377 main.log.error( self.name + ": Connection failed to the host" )
378 main.cleanup()
379 main.exit()
380 except pexpect.TIMEOUT:
381 if response:
382 main.log.info( "Pingall output: " + str( response ) )
383 main.log.error( self.name + ": pexpect.TIMEOUT found" )
384 return main.FALSE
385 except pexpect.EOF:
386 main.log.error( self.name + ": EOF exception found" )
387 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500388 main.cleanup()
389 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700390
Jon Hall7eb38402015-01-08 17:19:54 -0800391 def fpingHost( self, **pingParams ):
392 """
393 Uses the fping package for faster pinging...
394 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800395 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800396 command = args[ "SRC" ] + \
397 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
398 self.handle.sendline( command )
399 self.handle.expect(
400 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
401 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
402 response = self.handle.before
403 if re.search( ":\s-", response ):
404 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700405 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800406 elif re.search( ":\s\d{1,2}\.\d\d", response ):
407 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700408 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800409 main.log.info( self.name + ": Install fping on mininet machine... " )
410 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700411 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800412
Jon Hall3b489db2015-10-05 14:38:37 -0700413 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400414 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700415 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700416
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400417 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700418 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700419
420 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400421 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700422
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400423 Returns main.FALSE if one or more of hosts specified
424 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700425 wait = int( wait )
426 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400427
428 try:
429 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700430
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400431 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700432 pingResponse = "IPv4 ping across specified hosts\n"
433 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400434 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700435 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400436 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700437 pingList = hostList[ :listIndex ] + \
438 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700439
440 pingResponse += str(str(host) + " -> ")
441
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400442 for temp in pingList:
443 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700444 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700445 self.handle.sendline( pingCmd )
446 self.handle.expect( "mininet>", timeout=wait + 1 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400447 response = self.handle.before
448 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRCd10d3cc2015-09-24 12:47:16 -0700449 pingResponse += str(" h" + str( temp[1:] ))
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400450 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700451 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400452 # One of the host to host pair is unreachable
453 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700454 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700455 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700456 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700457 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700458 except pexpect.TIMEOUT:
459 main.log.exception( self.name + ": TIMEOUT exception" )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700460 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400461 except pexpect.EOF:
462 main.log.error( self.name + ": EOF exception found" )
463 main.log.error( self.name + ": " + self.handle.before )
464 main.cleanup()
465 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700466 except Exception:
467 main.log.exception( self.name + ": Uncaught exception!" )
468 main.cleanup()
469 main.exit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400470
Jon Hall3b489db2015-10-05 14:38:37 -0700471 def pingIpv6Hosts( self, hostList, prefix='1000::', wait=1 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700472 """
Jon Hall3b489db2015-10-05 14:38:37 -0700473 IPv6 ping all hosts in hostList. If no prefix passed this will use
474 default prefix of 1000::
Hari Krishna9592fc82015-07-31 15:11:15 -0700475
Jon Hall3b489db2015-10-05 14:38:37 -0700476 Returns main.TRUE if all hosts specified can reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700477
Jon Hall3b489db2015-10-05 14:38:37 -0700478 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700479 """
480 try:
481 main.log.info( "Testing reachability between specified IPv6 hosts" )
482 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700483 wait = int( wait )
484 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700485 pingResponse = "IPv6 Pingall output:\n"
486 failedPings = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700487 for host in hostList:
488 listIndex = hostList.index( host )
489 # List of hosts to ping other than itself
490 pingList = hostList[ :listIndex ] + \
491 hostList[ ( listIndex + 1 ): ]
492
GlennRC2cf7d952015-09-11 16:32:13 -0700493 pingResponse += str(str(host) + " -> ")
494
Hari Krishna9592fc82015-07-31 15:11:15 -0700495 for temp in pingList:
496 # Current host pings all other hosts specified
Jon Hall439c8912016-04-15 02:22:03 -0700497 pingCmd = str( host ) + cmd + str( self.getIPAddress(temp,proto='IPv6') )
Jon Hall934576d2015-10-09 10:12:22 -0700498 self.handle.sendline( pingCmd )
499 self.handle.expect( "mininet>", timeout=wait + 1 )
Hari Krishna9592fc82015-07-31 15:11:15 -0700500 response = self.handle.before
501 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRC2cf7d952015-09-11 16:32:13 -0700502 pingResponse += str(" h" + str( temp[1:] ))
Hari Krishna9592fc82015-07-31 15:11:15 -0700503 else:
GlennRC2cf7d952015-09-11 16:32:13 -0700504 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700505 # One of the host to host pair is unreachable
506 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700507 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700508 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700509 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700510 return isReachable
511
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700512 except pexpect.TIMEOUT:
513 main.log.exception( self.name + ": TIMEOUT exception" )
514 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700515 except pexpect.EOF:
516 main.log.error( self.name + ": EOF exception found" )
517 main.log.error( self.name + ": " + self.handle.before )
518 main.cleanup()
519 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700520 except Exception:
521 main.log.exception( self.name + ": Uncaught exception!" )
522 main.cleanup()
523 main.exit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700524
Jon Hall7eb38402015-01-08 17:19:54 -0800525 def pingHost( self, **pingParams ):
526 """
Jon Hall3b489db2015-10-05 14:38:37 -0700527 Ping from one mininet host to another
528 Currently the only supported Params: SRC, TARGET, and WAIT
529 """
530 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
531 wait = args['WAIT']
532 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800533 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700534 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700535 try:
Jon Hall61282e32015-03-19 11:34:11 -0700536 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800537 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700538 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
539 timeout=wait + 1 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700540 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800541 main.log.error(
542 self.name +
543 ": timeout when waiting for response from mininet" )
544 main.log.error( "response: " + str( self.handle.before ) )
545 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700546 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800547 main.log.error(
548 self.name +
549 ": timeout when waiting for response from mininet" )
550 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700551 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700552 if re.search( ',\s0\%\spacket\sloss', response ):
553 main.log.info( self.name + ": no packets lost, host is reachable" )
554 return main.TRUE
555 else:
556 main.log.error(
557 self.name +
558 ": PACKET LOST, HOST IS NOT REACHABLE" )
559 return main.FALSE
560
Jon Hallfbc828e2015-01-06 17:30:19 -0800561 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800562 main.log.error( self.name + ": EOF exception found" )
563 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700564 main.cleanup()
565 main.exit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700566 except Exception:
567 main.log.exception( self.name + ": Uncaught exception!" )
568 main.cleanup()
569 main.exit()
570
571 def ping6pair( self, **pingParams ):
572 """
GlennRC2cf7d952015-09-11 16:32:13 -0700573 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700574 Currently the only supported Params are: SRC, TARGET, and WAIT
Hari Krishna012a1c12015-08-25 14:23:58 -0700575 FLOWLABEL and -I (src interface) will be added later after running some tests.
576 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
577 """
Jon Hall3b489db2015-10-05 14:38:37 -0700578 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
579 wait = args['WAIT']
580 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530581 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700582 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700583 try:
584 main.log.info( "Sending: " + command )
585 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700586 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
587 timeout=wait + 1 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700588 if i == 1:
589 main.log.error(
590 self.name +
591 ": timeout when waiting for response from mininet" )
592 main.log.error( "response: " + str( self.handle.before ) )
593 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
594 if i == 1:
595 main.log.error(
596 self.name +
597 ": timeout when waiting for response from mininet" )
598 main.log.error( "response: " + str( self.handle.before ) )
599 response = self.handle.before
600 main.log.info( self.name + ": Ping Response: " + response )
601 if re.search( ',\s0\%\spacket\sloss', response ):
602 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700603 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700604 else:
605 main.log.error(
606 self.name +
607 ": PACKET LOST, HOST IS NOT REACHABLE" )
608 return main.FALSE
609
610 except pexpect.EOF:
611 main.log.error( self.name + ": EOF exception found" )
612 main.log.error( self.name + ": " + self.handle.before )
613 main.cleanup()
614 main.exit()
615 except Exception:
616 main.log.exception( self.name + ": Uncaught exception!" )
617 main.cleanup()
618 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800619
Jon Hall7eb38402015-01-08 17:19:54 -0800620 def checkIP( self, host ):
621 """
622 Verifies the host's ip configured or not."""
623 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700624 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800625 response = self.execute(
626 cmd=host +
627 " ifconfig",
628 prompt="mininet>",
629 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800630 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800631 main.log.error( self.name + ": EOF exception found" )
632 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700633 main.cleanup()
634 main.exit()
adminbae64d82013-08-01 10:50:15 -0700635
Jon Hall7eb38402015-01-08 17:19:54 -0800636 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800637 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
638 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
639 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
640 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
641 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800642 # pattern = "inet addr:10.0.0.6"
643 if re.search( pattern, response ):
644 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700645 return main.TRUE
646 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800647 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700648 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800649 else:
650 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800651
Jon Hall7eb38402015-01-08 17:19:54 -0800652 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800653 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700654 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800655 response = self.execute(
656 cmd="h1 /usr/sbin/sshd -D&",
657 prompt="mininet>",
658 timeout=10 )
659 response = self.execute(
660 cmd="h4 /usr/sbin/sshd -D&",
661 prompt="mininet>",
662 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700663 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800664 vars( self )[ key ] = connectargs[ key ]
665 response = self.execute(
666 cmd="xterm h1 h4 ",
667 prompt="mininet>",
668 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800669 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800670 main.log.error( self.name + ": EOF exception found" )
671 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700672 main.cleanup()
673 main.exit()
adminbae64d82013-08-01 10:50:15 -0700674 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800675 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700676 if self.flag == 0:
677 self.flag = 1
678 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800679 else:
adminbae64d82013-08-01 10:50:15 -0700680 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800681
Jon Hall439c8912016-04-15 02:22:03 -0700682 def moveHostv6( self, host, oldSw, newSw, ):
kelvin-onlaba1484582015-02-02 15:46:20 -0800683 """
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:
Jon Hall439c8912016-04-15 02:22:03 -0700693 IP = str( self.getIPAddress( host, proto='IPV6' ) ) + "/64"
kelvin-onlaba1484582015-02-02 15:46:20 -0800694 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700695 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800696 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800697 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800698 response = self.execute( cmd=cmd,
699 prompt="mininet>",
700 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700701
kelvin-onlaba1484582015-02-02 15:46:20 -0800702 # Determine hostintf and Oldswitchintf
703 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800704 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800705 print "cmd2= ", cmd
706 self.handle.sendline( cmd )
707 self.handle.expect( "mininet>" )
708
shahshreya73537862015-02-11 15:15:24 -0800709 # Determine ip and mac address of the host-oldSw interface
Jon Hall439c8912016-04-15 02:22:03 -0700710 cmd = "px ipaddr = " + str(IP)
kelvin-onlaba1484582015-02-02 15:46:20 -0800711 print "cmd3= ", cmd
712 self.handle.sendline( cmd )
713 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800714
715 cmd = "px macaddr = hintf.MAC()"
716 print "cmd3= ", cmd
717 self.handle.sendline( cmd )
718 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700719
kelvin-onlaba1484582015-02-02 15:46:20 -0800720 # Detach interface between oldSw-host
721 cmd = "px " + oldSw + ".detach( sintf )"
722 print "cmd4= ", cmd
723 self.handle.sendline( cmd )
724 self.handle.expect( "mininet>" )
725
726 # Add link between host-newSw
727 cmd = "py net.addLink(" + host + "," + newSw + ")"
728 print "cmd5= ", cmd
729 self.handle.sendline( cmd )
730 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700731
kelvin-onlaba1484582015-02-02 15:46:20 -0800732 # Determine hostintf and Newswitchintf
733 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800734 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800735 print "cmd6= ", cmd
736 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700737 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800738
739 # Attach interface between newSw-host
740 cmd = "px " + newSw + ".attach( sintf )"
Jon Hall439c8912016-04-15 02:22:03 -0700741 print "cmd6= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800742 self.handle.sendline( cmd )
743 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800744
745 # Set macaddress of the host-newSw interface
746 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
Jon Hall439c8912016-04-15 02:22:03 -0700747 print "cmd7 = ", cmd
748 self.handle.sendline( cmd )
749 self.handle.expect( "mininet>" )
750
751 # Set ipaddress of the host-newSw interface
752 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
shahshreya73537862015-02-11 15:15:24 -0800753 print "cmd8 = ", cmd
754 self.handle.sendline( cmd )
755 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700756
Jon Hall439c8912016-04-15 02:22:03 -0700757 cmd = host + " ifconfig"
758 print "cmd9 =",cmd
759 response = self.execute( cmd = cmd, prompt="mininet>" ,timeout=10 )
760 print response
761 pattern = "h\d-eth([\w])"
762 ipAddressSearch = re.search( pattern, response )
763 print ipAddressSearch.group(1)
764 intf= host + "-eth" + str(ipAddressSearch.group(1))
765 cmd = host + " ip -6 addr add %s dev %s" % ( IP, intf )
766 print "cmd10 = ", cmd
767 self.handle.sendline( cmd )
768 self.handle.expect( "mininet>" )
769
kelvin-onlaba1484582015-02-02 15:46:20 -0800770 cmd = "net"
Jon Hall439c8912016-04-15 02:22:03 -0700771 print "cmd11 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800772 self.handle.sendline( cmd )
773 self.handle.expect( "mininet>" )
774 print "output = ", self.handle.before
775
776 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800777 cmd = host + " ifconfig"
Jon Hall439c8912016-04-15 02:22:03 -0700778 print "cmd12= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800779 self.handle.sendline( cmd )
780 self.handle.expect( "mininet>" )
781 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700782
kelvin-onlaba1484582015-02-02 15:46:20 -0800783 return main.TRUE
784 except pexpect.EOF:
785 main.log.error( self.name + ": EOF exception found" )
786 main.log.error( self.name + ": " + self.handle.before )
787 return main.FALSE
788
Jon Hall7eb38402015-01-08 17:19:54 -0800789 def changeIP( self, host, intf, newIP, newNetmask ):
790 """
791 Changes the ip address of a host on the fly
792 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800793 if self.handle:
794 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800795 cmd = host + " ifconfig " + intf + " " + \
796 newIP + " " + 'netmask' + " " + newNetmask
797 self.handle.sendline( cmd )
798 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800799 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800800 main.log.info( "response = " + response )
801 main.log.info(
802 "Ip of host " +
803 host +
804 " changed to new IP " +
805 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800806 return main.TRUE
807 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800808 main.log.error( self.name + ": EOF exception found" )
809 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800810 return main.FALSE
811
Jon Hall7eb38402015-01-08 17:19:54 -0800812 def changeDefaultGateway( self, host, newGW ):
813 """
814 Changes the default gateway of a host
815 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800816 if self.handle:
817 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800818 cmd = host + " route add default gw " + newGW
819 self.handle.sendline( cmd )
820 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800821 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800822 main.log.info( "response = " + response )
823 main.log.info(
824 "Default gateway of host " +
825 host +
826 " changed to " +
827 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800828 return main.TRUE
829 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800830 main.log.error( self.name + ": EOF exception found" )
831 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800832 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800833
Jon Hall7eb38402015-01-08 17:19:54 -0800834 def addStaticMACAddress( self, host, GW, macaddr ):
835 """
Jon Hallefbd9792015-03-05 16:11:36 -0800836 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800837 if self.handle:
838 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800839 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
840 cmd = host + " arp -s " + GW + " " + macaddr
841 self.handle.sendline( cmd )
842 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800843 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800844 main.log.info( "response = " + response )
845 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800846 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800847 GW +
848 " changed to " +
849 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800850 return main.TRUE
851 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800852 main.log.error( self.name + ": EOF exception found" )
853 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800854 return main.FALSE
855
Jon Hall7eb38402015-01-08 17:19:54 -0800856 def verifyStaticGWandMAC( self, host ):
857 """
858 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800859 if self.handle:
860 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800861 # h1 arp -an
862 cmd = host + " arp -an "
863 self.handle.sendline( cmd )
864 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800865 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800866 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800867 return main.TRUE
868 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800869 main.log.error( self.name + ": EOF exception found" )
870 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800871 return main.FALSE
872
Jon Hall7eb38402015-01-08 17:19:54 -0800873 def getMacAddress( self, host ):
874 """
875 Verifies the host's ip configured or not."""
876 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700877 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800878 response = self.execute(
879 cmd=host +
880 " ifconfig",
881 prompt="mininet>",
882 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800883 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800884 main.log.error( self.name + ": EOF exception found" )
885 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700886 main.cleanup()
887 main.exit()
adminbae64d82013-08-01 10:50:15 -0700888
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700889 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800890 macAddressSearch = re.search( pattern, response, re.I )
891 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800892 main.log.info(
893 self.name +
894 ": Mac-Address of Host " +
895 host +
896 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800897 macAddress )
898 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700899 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800900 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700901
Jon Hall7eb38402015-01-08 17:19:54 -0800902 def getInterfaceMACAddress( self, host, interface ):
903 """
904 Return the IP address of the interface on the given host"""
905 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700906 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800907 response = self.execute( cmd=host + " ifconfig " + interface,
908 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800909 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800910 main.log.error( self.name + ": EOF exception found" )
911 main.log.error( self.name + ": " + self.handle.before )
912 main.cleanup()
913 main.exit()
914
915 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800916 macAddressSearch = re.search( pattern, response, re.I )
917 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800918 main.log.info( "No mac address found in %s" % response )
919 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800920 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800921 main.log.info(
922 "Mac-Address of " +
923 host +
924 ":" +
925 interface +
926 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800927 macAddress )
928 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800929 else:
930 main.log.error( "Connection failed to the host" )
931
sathishmad953462015-12-03 17:42:07 +0530932 def getIPAddress( self, host , proto='IPV4'):
Jon Hall7eb38402015-01-08 17:19:54 -0800933 """
934 Verifies the host's ip configured or not."""
935 if self.handle:
936 try:
937 response = self.execute(
938 cmd=host +
939 " ifconfig",
940 prompt="mininet>",
941 timeout=10 )
942 except pexpect.EOF:
943 main.log.error( self.name + ": EOF exception found" )
944 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700945 main.cleanup()
946 main.exit()
adminbae64d82013-08-01 10:50:15 -0700947
sathishmad953462015-12-03 17:42:07 +0530948 pattern = ''
949 if proto == 'IPV4':
950 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
951 else:
Jon Hall439c8912016-04-15 02:22:03 -0700952 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800953 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800954 main.log.info(
955 self.name +
956 ": IP-Address of Host " +
957 host +
958 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800959 ipAddressSearch.group( 1 ) )
960 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800961 else:
962 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800963
Jon Hall7eb38402015-01-08 17:19:54 -0800964 def getSwitchDPID( self, switch ):
965 """
966 return the datapath ID of the switch"""
967 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700968 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700969 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800970 response = self.execute(
971 cmd=cmd,
972 prompt="mininet>",
973 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800974 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800975 main.log.error( self.name + ": EOF exception found" )
976 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700977 main.cleanup()
978 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800979 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800980 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700981 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800982 main.log.info(
983 "Couldn't find DPID for switch %s, found: %s" %
984 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700985 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800986 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700987 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800988 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700989
Jon Hall7eb38402015-01-08 17:19:54 -0800990 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700991 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800992 self.handle.sendline( "" )
993 self.expect( "mininet>" )
994 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700995 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800996 response = self.execute(
997 cmd=cmd,
998 prompt="mininet>",
999 timeout=10 )
1000 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001001 response = self.handle.before
1002 return response
1003 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001004 main.log.error( self.name + ": EOF exception found" )
1005 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -07001006 main.cleanup()
1007 main.exit()
1008
Jon Hall7eb38402015-01-08 17:19:54 -08001009 def getInterfaces( self, node ):
1010 """
1011 return information dict about interfaces connected to the node"""
1012 if self.handle:
1013 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001014 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001015 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001016 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001017 response = self.execute(
1018 cmd=cmd,
1019 prompt="mininet>",
1020 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001021 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001022 main.log.error( self.name + ": EOF exception found" )
1023 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001024 main.cleanup()
1025 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001026 return response
1027 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001028 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001029
Jon Hall7eb38402015-01-08 17:19:54 -08001030 def dump( self ):
1031 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001032 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001033 response = self.execute(
1034 cmd='dump',
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()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001042 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001043
Jon Hall7eb38402015-01-08 17:19:54 -08001044 def intfs( self ):
1045 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001046 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001047 response = self.execute(
1048 cmd='intfs',
1049 prompt='mininet>',
1050 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001051 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001052 main.log.error( self.name + ": EOF exception found" )
1053 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001054 main.cleanup()
1055 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001056 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001057
Jon Hall7eb38402015-01-08 17:19:54 -08001058 def net( self ):
1059 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001060 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001061 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001062 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001063 main.log.error( self.name + ": EOF exception found" )
1064 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001065 main.cleanup()
1066 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001067 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001068
Jon Hallafa8a472015-06-12 14:02:42 -07001069 def links( self ):
1070 main.log.info( self.name + ": List network links" )
1071 try:
1072 response = self.execute( cmd='links', prompt='mininet>',
Jon Hall3b489db2015-10-05 14:38:37 -07001073 timeout=20 )
Jon Hallafa8a472015-06-12 14:02:42 -07001074 except pexpect.EOF:
1075 main.log.error( self.name + ": EOF exception found" )
1076 main.log.error( self.name + ": " + self.handle.before )
1077 main.cleanup()
1078 main.exit()
1079 return response
1080
GlennRC61321f22015-07-16 13:36:54 -07001081 def iperftcpAll(self, hosts, timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001082 '''
1083 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001084
kelvin-onlab7cce9382015-07-17 10:21:03 -07001085 @parm:
1086 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1087 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1088 '''
1089 for host1 in hosts:
1090 for host2 in hosts:
1091 if host1 != host2:
1092 if self.iperftcp(host1, host2, timeout) == main.FALSE:
1093 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
GlennRC61321f22015-07-16 13:36:54 -07001094
1095 def iperftcp(self, host1="h1", host2="h2", timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001096 '''
1097 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1098 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001099
kelvin-onlab7cce9382015-07-17 10:21:03 -07001100 @parm:
1101 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1102 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1103 '''
1104 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1105 try:
1106 # Setup the mininet command
1107 cmd1 = 'iperf ' + host1 + " " + host2
1108 self.handle.sendline( cmd1 )
1109 outcome = self.handle.expect( "mininet>", timeout )
1110 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001111
kelvin-onlab7cce9382015-07-17 10:21:03 -07001112 # checks if there are results in the mininet response
1113 if "Results:" in response:
Jon Hall892818c2015-10-20 17:58:34 -07001114 main.log.report(self.name + ": iperf test completed")
kelvin-onlab7cce9382015-07-17 10:21:03 -07001115 # parse the mn results
1116 response = response.split("\r\n")
1117 response = response[len(response)-2]
1118 response = response.split(": ")
1119 response = response[len(response)-1]
1120 response = response.replace("[", "")
1121 response = response.replace("]", "")
1122 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001123
kelvin-onlab7cce9382015-07-17 10:21:03 -07001124 # this is the bandwith two and from the two hosts
1125 bandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001126
kelvin-onlab7cce9382015-07-17 10:21:03 -07001127 # there should be two elements in the bandwidth list
1128 # ['host1 to host2', 'host2 to host1"]
1129 if len(bandwidth) == 2:
1130 main.log.report(self.name + ": iperf test successful")
1131 return main.TRUE
1132 else:
1133 main.log.error(self.name + ": invalid iperf results")
1134 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001135 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001136 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001137 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001138 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001139 main.log.error( self.name + ": TIMEOUT exception found" )
1140 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001141 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001142 # NOTE: Send ctrl-c to make sure iperf is done
1143 self.handle.sendline( "\x03" )
1144 self.handle.expect( "Interrupt" )
1145 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001146 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001147 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001148 main.log.error( self.name + ": EOF exception found" )
1149 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001150 main.cleanup()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001151 main.exit()
GlennRC61321f22015-07-16 13:36:54 -07001152
Jon Hall439c8912016-04-15 02:22:03 -07001153 def iperftcpipv6(self, host1="h1", host2="h2", timeout=50):
1154 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1155 try:
1156 IP1 = self.getIPAddress( host1, proto='IPV6' )
1157 cmd1 = host1 +' iperf -V -sD -B '+ str(IP1)
1158 self.handle.sendline( cmd1 )
1159 outcome1 = self.handle.expect( "mininet>")
1160 cmd2 = host2 +' iperf -V -c '+ str(IP1) +' -t 5'
1161 self.handle.sendline( cmd2 )
1162 outcome2 = self.handle.expect( "mininet>")
1163 response1 = self.handle.before
1164 response2 = self.handle.after
1165 print response1,response2
1166 pattern = "connected with "+ str(IP1)
1167 if pattern in response1:
1168 main.log.report(self.name + ": iperf test completed")
1169 return main.TRUE
1170 else:
1171 main.log.error( self.name + ": iperf test failed" )
1172 return main.FALSE
1173 except pexpect.TIMEOUT:
1174 main.log.error( self.name + ": TIMEOUT exception found" )
1175 main.log.error( self.name + " response: " + repr( self.handle.before ) )
1176 self.handle.sendline( "\x03" )
1177 self.handle.expect( "Interrupt" )
1178 self.handle.expect( "mininet>" )
1179 return main.FALSE
1180 except pexpect.EOF:
1181 main.log.error( self.name + ": EOF exception found" )
1182 main.log.error( self.name + ": " + self.handle.before )
1183 main.cleanup()
1184 main.exit()
1185
GlennRC61321f22015-07-16 13:36:54 -07001186 def iperfudpAll(self, hosts, bandwidth="10M"):
1187 '''
1188 Runs the iperfudp function with a given set of hosts and specified
1189 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001190
GlennRC61321f22015-07-16 13:36:54 -07001191 @param:
1192 bandwidth: the targeted bandwidth, in megabits ('M')
1193 '''
1194 for host1 in hosts:
1195 for host2 in hosts:
1196 if host1 != host2:
1197 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1198 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1199
1200 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1201
kelvin-onlab7cce9382015-07-17 10:21:03 -07001202 '''
1203 Creates an iperf UDP test with a specific bandwidth.
1204 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001205
kelvin-onlab7cce9382015-07-17 10:21:03 -07001206 @param:
1207 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1208 '''
1209 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1210 try:
1211 # setup the mininet command
1212 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1213 self.handle.sendline(cmd)
1214 self.handle.expect("mininet>")
1215 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001216
kelvin-onlab7cce9382015-07-17 10:21:03 -07001217 # check if there are in results in the mininet response
1218 if "Results:" in response:
Jon Hall892818c2015-10-20 17:58:34 -07001219 main.log.report(self.name + ": iperfudp test completed")
kelvin-onlab7cce9382015-07-17 10:21:03 -07001220 # parse the results
1221 response = response.split("\r\n")
1222 response = response[len(response)-2]
1223 response = response.split(": ")
1224 response = response[len(response)-1]
1225 response = response.replace("[", "")
1226 response = response.replace("]", "")
1227 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001228
kelvin-onlab7cce9382015-07-17 10:21:03 -07001229 mnBandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001230
kelvin-onlab7cce9382015-07-17 10:21:03 -07001231 # check to see if there are at least three entries
1232 # ['bandwidth', 'host1 to host2', 'host2 to host1']
1233 if len(mnBandwidth) == 3:
1234 # if one entry is blank then something is wrong
1235 for item in mnBandwidth:
1236 if item == "":
1237 main.log.error(self.name + ": Could not parse iperf output")
1238 main.log.error(self.name + ": invalid iperfudp results")
1239 return main.FALSE
1240 # otherwise results are vaild
1241 main.log.report(self.name + ": iperfudp test successful")
1242 return main.TRUE
1243 else:
1244 main.log.error(self.name + ": invalid iperfudp results")
1245 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001246
kelvin-onlab7cce9382015-07-17 10:21:03 -07001247 except pexpect.EOF:
1248 main.log.error( self.name + ": EOF exception found" )
1249 main.log.error( self.name + ": " + self.handle.before )
1250 main.cleanup()
1251 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001252
Jon Hall7eb38402015-01-08 17:19:54 -08001253 def nodes( self ):
1254 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001255 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001256 response = self.execute(
1257 cmd='nodes',
1258 prompt='mininet>',
1259 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001260 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001261 main.log.error( self.name + ": EOF exception found" )
1262 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001263 main.cleanup()
1264 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001265 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001266
Jon Hall7eb38402015-01-08 17:19:54 -08001267 def pingpair( self ):
1268 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001269 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001270 response = self.execute(
1271 cmd='pingpair',
1272 prompt='mininet>',
1273 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001274 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001275 main.log.error( self.name + ": EOF exception found" )
1276 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001277 main.cleanup()
1278 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001279
Jon Hall7eb38402015-01-08 17:19:54 -08001280 if re.search( ',\s0\%\spacket\sloss', response ):
1281 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001282 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001283 else:
1284 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001285 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001286
Jon Hall7eb38402015-01-08 17:19:54 -08001287 def link( self, **linkargs ):
1288 """
GlennRCed771242016-01-13 17:02:47 -08001289 Bring link( s ) between two nodes up or down
1290 """
Jon Hall6094a362014-04-11 14:46:56 -07001291 try:
GlennRCed771242016-01-13 17:02:47 -08001292 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1293 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1294 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1295 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1296
1297 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1298 cmd = "link {} {} {}".format( end1, end2, option )
1299 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001300 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001301 response = self.handle.before
1302 main.log.info( response )
1303
1304 return main.TRUE
1305 except pexpect.TIMEOUT:
1306 main.log.exception( self.name + ": Command timed out" )
1307 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001308 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001309 main.log.exception( self.name + ": connection closed." )
Jon Hall6094a362014-04-11 14:46:56 -07001310 main.cleanup()
1311 main.exit()
GlennRCed771242016-01-13 17:02:47 -08001312 except Exception:
1313 main.log.exception( self.name + ": Uncaught exception!" )
1314 main.cleanup()
1315 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001316
pingping-lin8244a3b2015-09-16 13:36:56 -07001317 def switch( self, **switchargs ):
1318 """
1319 start/stop a switch
1320 """
1321 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1322 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1323 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1324 command = "switch " + str( sw ) + " " + str( option )
1325 main.log.info( command )
1326 try:
1327 self.handle.sendline( command )
1328 self.handle.expect( "mininet>" )
1329 except pexpect.TIMEOUT:
1330 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1331 main.cleanup()
1332 main.exit()
1333 except pexpect.EOF:
1334 main.log.error( self.name + ": EOF exception found" )
1335 main.log.error( self.name + ": " + self.handle.before )
1336 main.cleanup()
1337 main.exit()
1338 return main.TRUE
1339
pingping-lin5bb663b2015-09-24 11:47:50 -07001340 def node( self, nodeName, commandStr ):
1341 """
1342 Carry out a command line on a given node
1343 @parm:
1344 nodeName: the node name in Mininet testbed
1345 commandStr: the command line will be carried out on the node
1346 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1347 """
1348 command = str( nodeName ) + " " + str( commandStr )
1349 main.log.info( command )
1350
1351 try:
1352 response = self.execute( cmd = command, prompt = "mininet>" )
1353 if re.search( "Unknown command", response ):
1354 main.log.warn( response )
1355 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001356 if re.search( "Permission denied", response ):
1357 main.log.warn( response )
1358 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001359 except pexpect.TIMEOUT:
1360 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1361 main.cleanup()
1362 main.exit()
1363 except pexpect.EOF:
1364 main.log.error( self.name + ": EOF exception found" )
1365 main.log.error( self.name + ": " + self.handle.before )
1366 main.cleanup()
1367 main.exit()
1368 main.log.info( " response is :" )
1369 main.log.info( response )
1370 return response
1371
Jon Hall7eb38402015-01-08 17:19:54 -08001372 def yank( self, **yankargs ):
1373 """
1374 yank a mininet switch interface to a host"""
1375 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001376 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001377 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1378 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1379 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001380 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001381 response = self.execute(
1382 cmd=command,
1383 prompt="mininet>",
1384 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001385 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001386 main.log.error( self.name + ": EOF exception found" )
1387 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001388 main.cleanup()
1389 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001390 return main.TRUE
1391
Jon Hall7eb38402015-01-08 17:19:54 -08001392 def plug( self, **plugargs ):
1393 """
1394 plug the yanked mininet switch interface to a switch"""
1395 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001396 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001397 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1398 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1399 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001400 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001401 response = self.execute(
1402 cmd=command,
1403 prompt="mininet>",
1404 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001405 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001406 main.log.error( self.name + ": EOF exception found" )
1407 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001408 main.cleanup()
1409 main.exit()
adminbae64d82013-08-01 10:50:15 -07001410 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001411
Jon Hall7eb38402015-01-08 17:19:54 -08001412 def dpctl( self, **dpctlargs ):
1413 """
1414 Run dpctl command on all switches."""
1415 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001416 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001417 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1418 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1419 command = "dpctl " + cmd + " " + str( cmdargs )
1420 try:
1421 response = self.execute(
1422 cmd=command,
1423 prompt="mininet>",
1424 timeout=10 )
1425 except pexpect.EOF:
1426 main.log.error( self.name + ": EOF exception found" )
1427 main.log.error( self.name + ": " + self.handle.before )
1428 main.cleanup()
1429 main.exit()
1430 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001431
kelvin-onlabd3b64892015-01-20 13:26:24 -08001432 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001433 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001434 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001435 fileInput = path + '/lib/Mininet/INSTALL'
1436 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001437 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001438 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001439 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001440 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001441 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001442 return version
adminbae64d82013-08-01 10:50:15 -07001443
kelvin-onlabd3b64892015-01-20 13:26:24 -08001444 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001445 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001446 Parameters:
1447 sw: The name of an OVS switch. Example "s1"
1448 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001449 The output of the command from the mininet cli
1450 or main.FALSE on timeout"""
1451 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001452 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001453 response = self.execute(
1454 cmd=command,
1455 prompt="mininet>",
1456 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001457 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001458 return response
admin2a9548d2014-06-17 14:08:07 -07001459 else:
1460 return main.FALSE
1461 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001462 main.log.error( self.name + ": EOF exception found" )
1463 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001464 main.cleanup()
1465 main.exit()
adminbae64d82013-08-01 10:50:15 -07001466
Charles Chan029be652015-08-24 01:46:10 +08001467 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001468 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001469 Description:
1470 Assign switches to the controllers ( for ovs use only )
1471 Required:
1472 sw - Name of the switch. This can be a list or a string.
1473 ip - Ip addresses of controllers. This can be a list or a string.
1474 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001475 port - ONOS use port 6653, if no list of ports is passed, then
1476 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001477 ptcp - ptcp number, This can be a string or a list that has
1478 the same length as switch. This is optional and not required
1479 when using ovs switches.
1480 NOTE: If switches and ptcp are given in a list type they should have the
1481 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1482 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001483
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001484 Return:
1485 Returns main.TRUE if mininet correctly assigned switches to
1486 controllers, otherwise it will return main.FALSE or an appropriate
1487 exception(s)
1488 """
1489 assignResult = main.TRUE
1490 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001491 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001492 command = "sh ovs-vsctl set-controller "
1493 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001494 try:
1495 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001496 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001497 if isinstance( port, types.StringType ) or \
1498 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001499 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001500 elif isinstance( port, types.ListType ):
1501 main.log.error( self.name + ": Only one controller " +
1502 "assigned and a list of ports has" +
1503 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001504 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001505 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001506 main.log.error( self.name + ": Invalid controller port " +
1507 "number. Please specify correct " +
1508 "controller port" )
1509 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001510
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001511 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001512 if isinstance( port, types.StringType ) or \
1513 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001514 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001515 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1516 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001517 elif isinstance( port, types.ListType ):
1518 if ( len( ip ) != len( port ) ):
1519 main.log.error( self.name + ": Port list = " +
1520 str( len( port ) ) +
1521 "should be the same as controller" +
1522 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001523 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001524 else:
1525 onosIp = ""
1526 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001527 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1528 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001529 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001530 main.log.error( self.name + ": Invalid controller port " +
1531 "number. Please specify correct " +
1532 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001533 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001534 else:
1535 main.log.error( self.name + ": Invalid ip address" )
1536 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001537
1538 if isinstance( sw, types.StringType ):
1539 command += sw + " "
1540 if ptcp:
1541 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001542 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001543 elif isinstance( ptcp, types.ListType ):
1544 main.log.error( self.name + ": Only one switch is " +
1545 "being set and multiple PTCP is " +
1546 "being passed " )
1547 else:
1548 main.log.error( self.name + ": Invalid PTCP" )
1549 ptcp = ""
1550 command += onosIp
1551 commandList.append( command )
1552
1553 elif isinstance( sw, types.ListType ):
1554 if ptcp:
1555 if isinstance( ptcp, types.ListType ):
1556 if len( ptcp ) != len( sw ):
1557 main.log.error( self.name + ": PTCP length = " +
1558 str( len( ptcp ) ) +
1559 " is not the same as switch" +
1560 " length = " +
1561 str( len( sw ) ) )
1562 return main.FALSE
1563 else:
1564 for switch, ptcpNum in zip( sw, ptcp ):
1565 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001566 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001567 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001568 tempCmd += onosIp
1569 commandList.append( tempCmd )
1570 else:
1571 main.log.error( self.name + ": Invalid PTCP" )
1572 return main.FALSE
1573 else:
1574 for switch in sw:
1575 tempCmd = "sh ovs-vsctl set-controller "
1576 tempCmd += switch + " " + onosIp
1577 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001578 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001579 main.log.error( self.name + ": Invalid switch type " )
1580 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001581
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001582 for cmd in commandList:
1583 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001584 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001585 except pexpect.TIMEOUT:
1586 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1587 return main.FALSE
1588 except pexpect.EOF:
1589 main.log.error( self.name + ": EOF exception found" )
1590 main.log.error( self.name + ": " + self.handle.before )
1591 main.cleanup()
1592 main.exit()
1593 return main.TRUE
1594 except Exception:
1595 main.log.exception( self.name + ": Uncaught exception!" )
1596 main.cleanup()
1597 main.exit()
adminbae64d82013-08-01 10:50:15 -07001598
kelvin-onlabd3b64892015-01-20 13:26:24 -08001599 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001600 """
1601 Removes the controller target from sw"""
1602 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001603 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001604 response = self.execute(
1605 cmd=command,
1606 prompt="mininet>",
1607 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001608 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001609 main.log.error( self.name + ": EOF exception found" )
1610 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001611 main.cleanup()
1612 main.exit()
1613 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001614 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001615
kelvin-onlabd3b64892015-01-20 13:26:24 -08001616 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001617 """
Jon Hallb1290e82014-11-18 16:17:48 -05001618 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001619 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001620 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001621 NOTE: cannot currently specify what type of switch
1622 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001623 sw = name of the new switch as a string
1624 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001625 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001626 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001627 """
1628 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001629 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001630 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001631 response = self.execute(
1632 cmd=command,
1633 prompt="mininet>",
1634 timeout=10 )
1635 if re.search( "already exists!", response ):
1636 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001637 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001638 elif re.search( "Error", response ):
1639 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001640 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001641 elif re.search( "usage:", response ):
1642 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001643 return main.FALSE
1644 else:
1645 return main.TRUE
1646 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001647 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001648 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001649 main.cleanup()
1650 main.exit()
1651
kelvin-onlabd3b64892015-01-20 13:26:24 -08001652 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001653 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001654 delete a switch from the mininet topology
1655 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001656 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001657 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001658 sw = name of the switch as a string
1659 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001660 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001661 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001662 response = self.execute(
1663 cmd=command,
1664 prompt="mininet>",
1665 timeout=10 )
1666 if re.search( "no switch named", response ):
1667 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001668 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001669 elif re.search( "Error", response ):
1670 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001671 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001672 elif re.search( "usage:", response ):
1673 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001674 return main.FALSE
1675 else:
1676 return main.TRUE
1677 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001678 main.log.error( self.name + ": EOF exception found" )
1679 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001680 main.cleanup()
1681 main.exit()
1682
kelvin-onlabd3b64892015-01-20 13:26:24 -08001683 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001684 """
1685 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001686 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001687 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001688 NOTE: cannot currently specify what type of link
1689 required params:
1690 node1 = the string node name of the first endpoint of the link
1691 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001692 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001693 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001694 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001695 response = self.execute(
1696 cmd=command,
1697 prompt="mininet>",
1698 timeout=10 )
1699 if re.search( "doesnt exist!", response ):
1700 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001701 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001702 elif re.search( "Error", response ):
1703 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001704 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001705 elif re.search( "usage:", response ):
1706 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001707 return main.FALSE
1708 else:
1709 return main.TRUE
1710 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001711 main.log.error( self.name + ": EOF exception found" )
1712 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001713 main.cleanup()
1714 main.exit()
1715
kelvin-onlabd3b64892015-01-20 13:26:24 -08001716 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001717 """
1718 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001719 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001720 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001721 required params:
1722 node1 = the string node name of the first endpoint of the link
1723 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001724 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001725 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001726 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001727 response = self.execute(
1728 cmd=command,
1729 prompt="mininet>",
1730 timeout=10 )
1731 if re.search( "no node named", response ):
1732 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001733 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001734 elif re.search( "Error", response ):
1735 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001736 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001737 elif re.search( "usage:", response ):
1738 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001739 return main.FALSE
1740 else:
1741 return main.TRUE
1742 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001743 main.log.error( self.name + ": EOF exception found" )
1744 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001745 main.cleanup()
1746 main.exit()
1747
kelvin-onlabd3b64892015-01-20 13:26:24 -08001748 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001749 """
Jon Hallb1290e82014-11-18 16:17:48 -05001750 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001751 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001752 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001753 NOTE: cannot currently specify what type of host
1754 required params:
1755 hostname = the string hostname
1756 optional key-value params
1757 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001758 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001759 """
1760 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001761 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001762 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001763 response = self.execute(
1764 cmd=command,
1765 prompt="mininet>",
1766 timeout=10 )
1767 if re.search( "already exists!", response ):
1768 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001769 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001770 elif re.search( "doesnt exists!", response ):
1771 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001772 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001773 elif re.search( "Error", response ):
1774 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001775 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001776 elif re.search( "usage:", response ):
1777 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001778 return main.FALSE
1779 else:
1780 return main.TRUE
1781 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001782 main.log.error( self.name + ": EOF exception found" )
1783 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001784 main.cleanup()
1785 main.exit()
1786
kelvin-onlabd3b64892015-01-20 13:26:24 -08001787 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001788 """
1789 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001790 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001791 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001792 NOTE: this uses a custom mn function
1793 required params:
1794 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001795 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001796 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001797 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001798 response = self.execute(
1799 cmd=command,
1800 prompt="mininet>",
1801 timeout=10 )
1802 if re.search( "no host named", response ):
1803 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001804 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001805 elif re.search( "Error", response ):
1806 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001807 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001808 elif re.search( "usage:", response ):
1809 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001810 return main.FALSE
1811 else:
1812 return main.TRUE
1813 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001814 main.log.error( self.name + ": EOF exception found" )
1815 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001816 main.cleanup()
1817 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001818
Jon Hall7eb38402015-01-08 17:19:54 -08001819 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001820 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001821 Called at the end of the test to stop the mininet and
1822 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001823 """
Jon Halld80cc142015-07-06 13:36:05 -07001824 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001825 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001826 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001827 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001828 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001829 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001830 elif i == 1:
1831 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001832 # print "Disconnecting Mininet"
1833 if self.handle:
1834 self.handle.sendline( "exit" )
1835 self.handle.expect( "exit" )
1836 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001837 else:
1838 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001839 return response
1840
Jon Halld80cc142015-07-06 13:36:05 -07001841 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001842 """
Jon Hall21270ac2015-02-16 17:59:55 -08001843 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001844 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001845 main.FALSE if the pexpect handle does not exist.
1846
Jon Halld61331b2015-02-17 16:35:47 -08001847 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001848 """
Jon Halld61331b2015-02-17 16:35:47 -08001849 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001850 response = ''
1851 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001852 try:
Jon Halld80cc142015-07-06 13:36:05 -07001853 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08001854 i = self.handle.expect( [ 'mininet>',
1855 '\$',
1856 pexpect.EOF,
1857 pexpect.TIMEOUT ],
1858 timeout )
1859 if i == 0:
1860 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001861 response = self.execute(
1862 cmd="exit",
1863 prompt="(.*)",
1864 timeout=120 )
Jon Halld80cc142015-07-06 13:36:05 -07001865 main.log.info( self.name + ": Stopped" )
Jon Hall7eb38402015-01-08 17:19:54 -08001866 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001867 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001868
kelvin-onlab56a3f462015-02-06 14:04:43 -08001869 if i == 1:
1870 main.log.info( " Mininet trying to exit while not " +
1871 "in the mininet prompt" )
1872 elif i == 2:
1873 main.log.error( "Something went wrong exiting mininet" )
1874 elif i == 3: # timeout
1875 main.log.error( "Something went wrong exiting mininet " +
1876 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001877
Hari Krishnab35c6d02015-03-18 11:13:51 -07001878 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07001879 self.handle.sendline( "" )
1880 self.handle.expect( '\$' )
1881 self.handle.sendline(
1882 "sudo kill -9 \`ps -ef | grep \"" +
1883 fileName +
1884 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001885 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001886 main.log.error( self.name + ": EOF exception found" )
1887 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001888 main.cleanup()
1889 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001890 else:
1891 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001892 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001893 return response
1894
Jon Halla5cb3412015-08-18 14:08:22 -07001895 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001896 """
1897 Description:
1898 Sends arp message from mininet host for hosts discovery
1899 Required:
1900 host - hosts name
1901 Optional:
1902 ip - ip address that does not exist in the network so there would
1903 be no reply.
1904 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001905 if ethDevice:
1906 ethDevice = '-I ' + ethDevice + ' '
Jon Halla5cb3412015-08-18 14:08:22 -07001907 cmd = srcHost + " arping -c1 " + ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08001908 try:
Jon Halla5cb3412015-08-18 14:08:22 -07001909 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07001910 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07001911 i = self.handle.expect( [ "mininet>", "arping: " ] )
1912 if i == 0:
1913 return main.TRUE
1914 elif i == 1:
1915 response = self.handle.before + self.handle.after
1916 self.handle.expect( "mininet>" )
1917 response += self.handle.before + self.handle.after
1918 main.log.warn( "Error sending arping, output was: " +
1919 response )
1920 return main.FALSE
1921 except pexpect.TIMEOUT:
1922 main.log.error( self.name + ": TIMEOUT exception found" )
1923 main.log.warn( self.handle.before )
1924 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07001925 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()
admin07529932013-11-22 14:58:28 -08001930
Jon Hall7eb38402015-01-08 17:19:54 -08001931 def decToHex( self, num ):
1932 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001933
Jon Hall7eb38402015-01-08 17:19:54 -08001934 def getSwitchFlowCount( self, switch ):
1935 """
1936 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001937 if self.handle:
1938 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1939 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001940 response = self.execute(
1941 cmd=cmd,
1942 prompt="mininet>",
1943 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001944 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001945 main.log.error( self.name + ": EOF exception found" )
1946 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001947 main.cleanup()
1948 main.exit()
1949 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001950 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001951 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001952 main.log.info(
1953 "Couldn't find flows on switch %s, found: %s" %
1954 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001955 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001956 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001957 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001958 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001959
Jon Hall9ed8f372016-02-24 17:34:07 -08001960 def checkFlows( self, sw, dumpFormat=None ):
1961 if dumpFormat:
1962 command = "sh ovs-ofctl -F " + \
1963 dumpFormat + " dump-flows " + str( sw )
1964 else:
1965 command = "sh ovs-ofctl dump-flows " + str( sw )
1966 try:
1967 response = self.execute(
1968 cmd=command,
1969 prompt="mininet>",
1970 timeout=10 )
1971 return response
1972 except pexpect.EOF:
1973 main.log.error( self.name + ": EOF exception found" )
1974 main.log.error( self.name + ": " + self.handle.before )
1975 main.cleanup()
1976 main.exit()
1977
GlennRC68467eb2015-11-16 18:01:01 -08001978 def flowTableComp( self, flowTable1, flowTable2 ):
1979 # This function compares the selctors and treatments of each flow
1980 try:
Jon Hall41d39f12016-04-11 22:54:35 -07001981 returnValue = main.TRUE
GlennRC68467eb2015-11-16 18:01:01 -08001982 if len(flowTable1) != len(flowTable2):
1983 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07001984 returnValue = main.FALSE
GlennRCfa65fce2015-12-16 13:16:08 -08001985 dFields = ["n_bytes", "cookie", "n_packets", "duration"]
1986 for flow1, flow2 in zip(flowTable1, flowTable2):
Jon Hallacd1b182015-12-17 11:43:20 -08001987 for field in dFields:
1988 try:
1989 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07001990 except KeyError:
1991 pass
Jon Hallacd1b182015-12-17 11:43:20 -08001992 try:
1993 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07001994 except KeyError:
1995 pass
GlennRC68467eb2015-11-16 18:01:01 -08001996 for i in range( len(flowTable1) ):
GlennRC17bbcf52015-12-14 17:31:50 -08001997 if flowTable1[i] not in flowTable2:
1998 main.log.warn( "Flow tables do not match:" )
1999 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[i] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002000 returnValue = main.FALSE
2001 break
2002 return returnValue
GlennRC68467eb2015-11-16 18:01:01 -08002003 except Exception:
2004 main.log.exception( "Uncaught exception!" )
2005 main.cleanup()
2006 main.exit()
Jon Hall9043c902015-07-30 14:23:44 -07002007
GlennRC528ad292015-11-12 10:38:18 -08002008 def parseFlowTable( self, flowTable, version="", debug=True ):
GlennRC956ea742015-11-05 16:14:15 -08002009 '''
2010 Discription: Parses flows into json format.
2011 NOTE: this can parse any string thats separated with commas
2012 Arguments:
2013 Required:
2014 flows: a list of strings that represnt flows
2015 Optional:
2016 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2017 debug: prints out the final result
2018 returns: A list of flows in json format
2019 '''
GlennRC528ad292015-11-12 10:38:18 -08002020 jsonFlowTable = []
2021 for flow in flowTable:
GlennRC956ea742015-11-05 16:14:15 -08002022 jsonFlow = {}
GlennRC528ad292015-11-12 10:38:18 -08002023 # split up the fields of the flow
2024 parsedFlow = flow.split(", ")
2025 # get rid of any spaces in front of the field
2026 for i in range( len(parsedFlow) ):
2027 item = parsedFlow[i]
2028 if item[0] == " ":
2029 parsedFlow[i] = item[1:]
2030 # grab the selector and treatment from the parsed flow
2031 # the last element is the selector and the treatment
2032 temp = parsedFlow.pop(-1)
2033 # split up the selector and the treatment
2034 temp = temp.split(" ")
2035 index = 0
2036 # parse the flags
2037 # NOTE: This only parses one flag
2038 flag = {}
2039 if version == "1.3":
2040 flag = {"flag":[temp[index]]}
2041 index += 1
2042 # the first element is the selector and split it up
2043 sel = temp[index]
2044 index += 1
2045 sel = sel.split(",")
2046 # the priority is stuck in the selecter so put it back
2047 # in the flow
2048 parsedFlow.append(sel.pop(0))
2049 # parse selector
2050 criteria = []
2051 for item in sel:
2052 # this is the type of the packet e.g. "arp"
2053 if "=" not in item:
2054 criteria.append( {"type":item} )
2055 else:
2056 field = item.split("=")
2057 criteria.append( {field[0]:field[1]} )
GlennRC68467eb2015-11-16 18:01:01 -08002058 selector = {"selector": {"criteria":sorted(criteria)} }
GlennRC528ad292015-11-12 10:38:18 -08002059 treat = temp[index]
2060 # get rid of the action part e.g. "action=output:2"
2061 # we will add it back later
2062 treat = treat.split("=")
2063 treat.pop(0)
2064 # parse treatment
2065 action = []
2066 for item in treat:
2067 field = item.split(":")
2068 action.append( {field[0]:field[1]} )
2069 # create the treatment field and add the actions
GlennRC68467eb2015-11-16 18:01:01 -08002070 treatment = {"treatment": {"action":sorted(action)} }
GlennRC528ad292015-11-12 10:38:18 -08002071 # parse the rest of the flow
2072 for item in parsedFlow:
2073 field = item.split("=")
2074 jsonFlow.update( {field[0]:field[1]} )
2075 # add the treatment and the selector to the json flow
2076 jsonFlow.update( selector )
2077 jsonFlow.update( treatment )
2078 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002079
GlennRC528ad292015-11-12 10:38:18 -08002080 if debug: main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format(jsonFlow) )
GlennRC956ea742015-11-05 16:14:15 -08002081
GlennRC528ad292015-11-12 10:38:18 -08002082 # add the json flow to the json flow table
2083 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002084
GlennRC528ad292015-11-12 10:38:18 -08002085 return jsonFlowTable
2086
Jon Hall0a543792015-12-14 11:00:26 -08002087 def getFlowTable( self, sw, version="", debug=False):
GlennRC956ea742015-11-05 16:14:15 -08002088 '''
2089 Discription: Returns the flow table(s) on a switch or switches in a list.
2090 Each element is a flow.
2091 Arguments:
2092 Required:
2093 sw: The switch name ("s1") to retrive the flow table. Can also be
2094 a list of switches.
2095 Optional:
2096 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2097 debug: prints out the final result
2098 '''
2099 try:
2100 switches = []
2101 if type(sw) is list:
Jon Hallca7ac292015-11-11 09:28:12 -08002102 switches.extend(sw)
GlennRC956ea742015-11-05 16:14:15 -08002103 else: switches.append(sw)
2104
2105 flows = []
2106 for s in switches:
2107 cmd = "sh ovs-ofctl dump-flows " + s
2108
GlennRC528ad292015-11-12 10:38:18 -08002109 if "1.0" == version:
2110 cmd += " -F OpenFlow10-table_id"
2111 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002112 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002113
2114 main.log.info( "Sending: " + cmd )
2115 self.handle.sendline( cmd )
2116 self.handle.expect( "mininet>" )
2117 response = self.handle.before
2118 response = response.split( "\r\n" )
2119 # dump the first two elements and the last
2120 # the first element is the command that was sent
2121 # the second is the table header
2122 # the last element is empty
2123 response = response[2:-1]
2124 flows.extend( response )
2125
2126 if debug: print "Flows:\n{}\n\n".format(flows)
2127
GlennRC528ad292015-11-12 10:38:18 -08002128 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002129
2130 except pexpect.TIMEOUT:
2131 main.log.exception( self.name + ": Command timed out" )
2132 return None
2133 except pexpect.EOF:
2134 main.log.exception( self.name + ": connection closed." )
2135 main.cleanup()
2136 main.exit()
2137 except Exception:
2138 main.log.exception( self.name + ": Uncaught exception!" )
2139 main.cleanup()
2140 main.exit()
2141
2142 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
2143 '''
2144 Discription: Checks whether the ID provided matches a flow ID in Mininet
2145 Arguments:
2146 Required:
2147 sw: The switch name ("s1") to retrive the flow table. Can also be
2148 a list of switches.
2149 flowId: the flow ID in hex format. Can also be a list of IDs
2150 Optional:
2151 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2152 debug: prints out the final result
2153 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2154 NOTE: prints out IDs that are not present
2155 '''
2156 try:
2157 main.log.info( "Getting flows from Mininet" )
2158 flows = self.getFlowTable( sw, version, debug )
2159
2160 if debug: print "flow ids:\n{}\n\n".format(flowId)
2161
2162 # Check flowId is a list or a string
2163 if type( flowId ) is str:
2164 result = False
2165 for f in flows:
2166 if flowId in f.get( 'cookie' ):
2167 result = True
2168 break
2169 # flowId is a list
2170 else:
2171 result = True
2172 # Get flow IDs from Mininet
2173 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2174 # Save the IDs that are not in Mininet
2175 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2176
2177 if debug: print "mn flow ids:\n{}\n\n".format(mnFlowIds)
2178
2179 # Print out the IDs that are not in Mininet
2180 if absentIds:
2181 main.log.warn( "Absent ids: {}".format( absentIds ) )
2182 result = False
2183
2184 return main.TRUE if result else main.FALSE
2185
2186 except Exception:
2187 main.log.exception( self.name + ": Uncaught exception!" )
2188 main.cleanup()
2189 main.exit()
2190
2191
Charles Chan029be652015-08-24 01:46:10 +08002192 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002193 """
Jon Hallefbd9792015-03-05 16:11:36 -08002194 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002195 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002196 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002197 self.handle.sendline( "" )
2198 self.handle.expect( "mininet>" )
2199 self.handle.sendline(
2200 "sh sudo tcpdump -n -i " +
2201 intf +
2202 " " +
2203 port +
2204 " -w " +
2205 filename.strip() +
2206 " &" )
2207 self.handle.sendline( "" )
2208 i = self.handle.expect( [ 'No\ssuch\device',
2209 'listening\son',
2210 pexpect.TIMEOUT,
2211 "mininet>" ],
2212 timeout=10 )
2213 main.log.warn( self.handle.before + self.handle.after )
2214 self.handle.sendline( "" )
2215 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002216 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002217 main.log.error(
2218 self.name +
2219 ": tcpdump - No such device exists. " +
2220 "tcpdump attempted on: " +
2221 intf )
admin2a9548d2014-06-17 14:08:07 -07002222 return main.FALSE
2223 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002224 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002225 return main.TRUE
2226 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002227 main.log.error(
2228 self.name +
2229 ": tcpdump command timed out! Check interface name," +
2230 " given interface was: " +
2231 intf )
admin2a9548d2014-06-17 14:08:07 -07002232 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002233 elif i == 3:
2234 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002235 return main.TRUE
2236 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002237 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002238 return main.FALSE
2239 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002240 main.log.error( self.name + ": EOF exception found" )
2241 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002242 main.cleanup()
2243 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002244 except Exception:
2245 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002246 main.cleanup()
2247 main.exit()
2248
kelvin-onlabd3b64892015-01-20 13:26:24 -08002249 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002250 """
2251 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002252 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002253 self.handle.sendline( "sh sudo pkill tcpdump" )
2254 self.handle.expect( "mininet>" )
2255 self.handle.sendline( "" )
2256 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002257 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002258 main.log.error( self.name + ": EOF exception found" )
2259 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002260 main.cleanup()
2261 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002262 except Exception:
2263 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002264 main.cleanup()
2265 main.exit()
2266
Jon Halld80cc142015-07-06 13:36:05 -07002267 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002268 """
2269 Read ports from a Mininet switch.
2270
2271 Returns a json structure containing information about the
2272 ports of the given switch.
2273 """
2274 response = self.getInterfaces( nodeName )
2275 # TODO: Sanity check on response. log if no such switch exists
2276 ports = []
2277 for line in response.split( "\n" ):
2278 if not line.startswith( "name=" ):
2279 continue
2280 portVars = {}
2281 for var in line.split( "," ):
2282 key, value = var.split( "=" )
2283 portVars[ key ] = value
2284 isUp = portVars.pop( 'enabled', "True" )
2285 isUp = "True" in isUp
2286 if verbose:
2287 main.log.info( "Reading switch port %s(%s)" %
2288 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2289 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002290 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002291 mac = None
2292 ips = []
2293 ip = portVars[ 'ip' ]
2294 if ip == 'None':
2295 ip = None
2296 ips.append( ip )
2297 name = portVars[ 'name' ]
2298 if name == 'None':
2299 name = None
2300 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2301 if name == 'lo':
2302 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2303 else:
2304 portNo = re.search( portRe, name ).group( 'port' )
2305 ports.append( { 'of_port': portNo,
2306 'mac': str( mac ).replace( '\'', '' ),
2307 'name': name,
2308 'ips': ips,
2309 'enabled': isUp } )
2310 return ports
2311
Jon Halld80cc142015-07-06 13:36:05 -07002312 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002313 """
2314 Read switches from Mininet.
2315
2316 Returns a dictionary whose keys are the switch names and the value is
2317 a dictionary containing information about the switch.
2318 """
Jon Halla22481b2015-07-28 17:46:01 -07002319 # NOTE: To support new Mininet switch classes, just append the new
2320 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002321
Jon Halla22481b2015-07-28 17:46:01 -07002322 # Regex patterns to parse 'dump' output
2323 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002324 # <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 -07002325 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002326 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2327 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2328 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2329 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2330 swRE = r"<(?P<class>" + switchClasses + r")" +\
2331 r"(?P<options>\{.*\})?\s" +\
2332 r"(?P<name>[^:]+)\:\s" +\
2333 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2334 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002335 # Update mn port info
2336 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002337 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002338 dump = self.dump().split( "\n" )
2339 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002340 result = re.search( swRE, line, re.I )
2341 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002342 name = result.group( 'name' )
2343 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002344 pid = result.group( 'pid' )
2345 swClass = result.group( 'class' )
2346 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002347 if verbose:
2348 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2349 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002350 output[ name ] = { "dpid": dpid,
2351 "ports": ports,
2352 "swClass": swClass,
2353 "pid": pid,
2354 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002355 return output
2356
Jon Halld80cc142015-07-06 13:36:05 -07002357 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002358 """
2359 Read hosts from Mininet.
2360
2361 Returns a dictionary whose keys are the host names and the value is
2362 a dictionary containing information about the host.
2363 """
2364 # Regex patterns to parse dump output
2365 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002366 # <Host h1: pid=12725>
2367 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2368 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2369 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002370 # NOTE: Does not correctly match hosts with multi-links
2371 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2372 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002373 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002374 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002375 # update mn port info
2376 self.update()
2377 # Get mininet dump
2378 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002379 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002380 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002381 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002382 result = re.search( hostRE, line )
2383 name = result.group( 'name' )
2384 interfaces = []
2385 response = self.getInterfaces( name )
2386 # Populate interface info
2387 for line in response.split( "\n" ):
2388 if line.startswith( "name=" ):
2389 portVars = {}
2390 for var in line.split( "," ):
2391 key, value = var.split( "=" )
2392 portVars[ key ] = value
2393 isUp = portVars.pop( 'enabled', "True" )
2394 isUp = "True" in isUp
2395 if verbose:
2396 main.log.info( "Reading host port %s(%s)" %
2397 ( portVars[ 'name' ],
2398 portVars[ 'mac' ] ) )
2399 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002400 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002401 mac = None
2402 ips = []
2403 ip = portVars[ 'ip' ]
2404 if ip == 'None':
2405 ip = None
2406 ips.append( ip )
2407 intfName = portVars[ 'name' ]
2408 if name == 'None':
2409 name = None
2410 interfaces.append( {
2411 "name": intfName,
2412 "ips": ips,
2413 "mac": str( mac ),
2414 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002415 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002416 return hosts
2417
2418 def getLinks( self ):
2419 """
2420 Gathers information about current Mininet links. These links may not
2421 be up if one of the ports is down.
2422
2423 Returns a list of dictionaries with link endpoints.
2424
2425 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002426 { 'node1': str( node1 name )
2427 'node2': str( node2 name )
2428 'port1': str( port1 of_port )
2429 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002430 Note: The port number returned is the eth#, not necessarily the of_port
2431 number. In Mininet, for OVS switch, these should be the same. For
2432 hosts, this is just the eth#.
2433 """
2434 self.update()
2435 response = self.links().split( '\n' )
2436
2437 # Examples:
2438 # s1-eth3<->s2-eth1 (OK OK)
2439 # s13-eth3<->h27-eth0 (OK OK)
2440 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2441 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2442 links = []
2443 for line in response:
2444 match = re.search( linkRE, line )
2445 if match:
2446 node1 = match.group( 'node1' )
2447 node2 = match.group( 'node2' )
2448 port1 = match.group( 'port1' )
2449 port2 = match.group( 'port2' )
2450 links.append( { 'node1': node1,
2451 'node2': node2,
2452 'port1': port1,
2453 'port2': port2 } )
2454 return links
2455
2456 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002457 """
2458 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002459 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002460
Jon Hallafa8a472015-06-12 14:02:42 -07002461 Dependencies:
2462 1. numpy - "sudo pip install numpy"
2463 """
2464 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002465 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002466 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002467 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002468 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002469 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002470 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002471 main.log.error(
2472 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002473 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002474 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002475 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002476 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002477 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002478 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002479 onosDPIDs.append(
2480 switch[ 'id' ].replace(
2481 ":",
2482 '' ).replace(
2483 "of",
2484 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002485 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002486
Jon Hall7eb38402015-01-08 17:19:54 -08002487 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002488 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002489 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002490 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002491 main.log.error( str( list1 ) )
2492 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002493 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002494 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002495 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002496 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002497 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002498
Jon Hall7eb38402015-01-08 17:19:54 -08002499 # FIXME: this does not look for extra ports in ONOS, only checks that
2500 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002501 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002502
Jon Hall7eb38402015-01-08 17:19:54 -08002503 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002504 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002505 mnPorts = []
2506 onosPorts = []
2507 switchResult = main.TRUE
2508 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002509 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002510 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002511 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002512 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002513 if onosSwitch[ 'device' ][ 'id' ].replace(
2514 ':',
2515 '' ).replace(
2516 "of",
2517 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002518 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002519 if port[ 'isEnabled' ]:
2520 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002521 # onosPorts.append( 'local' )
2522 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002523 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002524 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002525 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002526 mnPorts.sort( key=float )
2527 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002528
kelvin-onlabd3b64892015-01-20 13:26:24 -08002529 mnPortsLog = mnPorts
2530 onosPortsLog = onosPorts
2531 mnPorts = [ x for x in mnPorts ]
2532 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002533
Jon Hall7eb38402015-01-08 17:19:54 -08002534 # TODO: handle other reserved port numbers besides LOCAL
2535 # NOTE: Reserved ports
2536 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2537 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002538 for mnPort in mnPortsLog:
2539 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002540 # don't set results to true here as this is just one of
2541 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002542 mnPorts.remove( mnPort )
2543 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002544
Jon Hall7eb38402015-01-08 17:19:54 -08002545 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002546 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002547 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002548 if 65534 in mnPorts:
2549 mnPorts.remove( 65534 )
2550 if long( uint64( -2 ) ) in onosPorts:
2551 onosPorts.remove( long( uint64( -2 ) ) )
2552 if len( mnPorts ): # the ports of this switch don't match
2553 switchResult = main.FALSE
2554 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2555 if len( onosPorts ): # the ports of this switch don't match
2556 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002557 main.log.warn(
2558 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002559 str( onosPorts ) )
2560 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002561 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002562 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002563 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002564 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2565 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2566 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002567 finalResults = finalResults and portsResults
2568 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002569
Jon Hallafa8a472015-06-12 14:02:42 -07002570 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002571 """
2572 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002573 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002574
Jon Hallafa8a472015-06-12 14:02:42 -07002575 """
Jon Hall7eb38402015-01-08 17:19:54 -08002576 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002577 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002578 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002579
Jon Halld80cc142015-07-06 13:36:05 -07002580 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002581 for l in links:
2582 try:
2583 node1 = switches[ l[ 'node1' ] ]
2584 node2 = switches[ l[ 'node2' ] ]
2585 enabled = True
2586 for port in node1[ 'ports' ]:
2587 if port[ 'of_port' ] == l[ 'port1' ]:
2588 enabled = enabled and port[ 'enabled' ]
2589 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002590 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002591 enabled = enabled and port[ 'enabled' ]
2592 if enabled:
2593 mnLinks.append( l )
2594 except KeyError:
2595 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002596 if 2 * len( mnLinks ) == len( onos ):
2597 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002598 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002599 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002600 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002601 "Mininet has " + str( len( mnLinks ) ) +
2602 " bidirectional links and ONOS has " +
2603 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002604
Jon Hall7eb38402015-01-08 17:19:54 -08002605 # iterate through MN links and check if an ONOS link exists in
2606 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002607 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002608 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002609 node1 = None
2610 port1 = None
2611 node2 = None
2612 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002613 firstDir = main.FALSE
2614 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002615 for swName, switch in switches.iteritems():
2616 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002617 node1 = switch[ 'dpid' ]
2618 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002619 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002620 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002621 if node1 is not None and node2 is not None:
2622 break
Jon Hallafa8a472015-06-12 14:02:42 -07002623 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002624 node2 = switch[ 'dpid' ]
2625 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002626 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002627 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002628 if node1 is not None and node2 is not None:
2629 break
2630
kelvin-onlabd3b64892015-01-20 13:26:24 -08002631 for onosLink in onos:
2632 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002633 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002634 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002635 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002636 onosPort1 = onosLink[ 'src' ][ 'port' ]
2637 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002638
Jon Hall72cf1dc2014-10-20 21:04:50 -04002639 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002640 if str( onosNode1 ) == str( node1 ) and str(
2641 onosNode2 ) == str( node2 ):
2642 if int( onosPort1 ) == int( port1 ) and int(
2643 onosPort2 ) == int( port2 ):
2644 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002645 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002646 main.log.warn(
2647 'The port numbers do not match for ' +
2648 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002649 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002650 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002651 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002652 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002653 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002654
2655 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002656 elif ( str( onosNode1 ) == str( node2 ) and
2657 str( onosNode2 ) == str( node1 ) ):
2658 if ( int( onosPort1 ) == int( port2 )
2659 and int( onosPort2 ) == int( port1 ) ):
2660 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002661 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002662 main.log.warn(
2663 'The port numbers do not match for ' +
2664 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002665 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002666 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002667 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002668 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002669 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002670 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002671 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002672 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002673 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002674 'ONOS does not have the link %s/%s -> %s/%s' %
2675 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002676 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002677 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002678 'ONOS does not have the link %s/%s -> %s/%s' %
2679 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002680 linkResults = linkResults and firstDir and secondDir
2681 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002682
Jon Hallafa8a472015-06-12 14:02:42 -07002683 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002684 """
Jon Hallafa8a472015-06-12 14:02:42 -07002685 Compare mn and onos Hosts.
2686 Since Mininet hosts are quiet, ONOS will only know of them when they
2687 speak. For this reason, we will only check that the hosts in ONOS
2688 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002689
Jon Hallafa8a472015-06-12 14:02:42 -07002690 Arguments:
2691 hostsJson: parsed json object from the onos hosts api
2692 Returns:
2693 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002694 import json
2695 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002696 for onosHost in hostsJson:
2697 onosMAC = onosHost[ 'mac' ].lower()
2698 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002699 for mnHost, info in hosts.iteritems():
2700 for mnIntf in info[ 'interfaces' ]:
2701 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002702 match = True
2703 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002704 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002705 pass # all is well
2706 else:
2707 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002708 main.log.error( "ONOS host " +
2709 onosHost[ 'id' ] +
2710 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002711 str( onosHost[ 'ipAddresses' ] ) +
2712 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002713 str( ip ) +
2714 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002715 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002716 onosHost,
2717 sort_keys=True,
2718 indent=4,
2719 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002720 main.log.info( output )
2721 hostResults = main.FALSE
2722 if not match:
2723 hostResults = main.FALSE
2724 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2725 "corresponding Mininet host." )
2726 output = json.dumps( onosHost,
2727 sort_keys=True,
2728 indent=4,
2729 separators=( ',', ': ' ) )
2730 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002731 return hostResults
2732
Jon Hallafa8a472015-06-12 14:02:42 -07002733 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002734 """
2735 Returns a list of all hosts
2736 Don't ask questions just use it"""
2737 self.handle.sendline( "" )
2738 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002739
Jon Hall7eb38402015-01-08 17:19:54 -08002740 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2741 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002742
kelvin-onlabd3b64892015-01-20 13:26:24 -08002743 handlePy = self.handle.before
2744 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2745 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002746
Jon Hall7eb38402015-01-08 17:19:54 -08002747 self.handle.sendline( "" )
2748 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002749
kelvin-onlabd3b64892015-01-20 13:26:24 -08002750 hostStr = handlePy.replace( "]", "" )
2751 hostStr = hostStr.replace( "'", "" )
2752 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002753 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002754 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002755
kelvin-onlabd3b64892015-01-20 13:26:24 -08002756 return hostList
adminbae64d82013-08-01 10:50:15 -07002757
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002758 def getSwitch( self ):
2759 """
2760 Returns a list of all switches
2761 Again, don't ask question just use it...
2762 """
2763 # get host list...
2764 hostList = self.getHosts()
2765 # Make host set
2766 hostSet = set( hostList )
2767
2768 # Getting all the nodes in mininet
2769 self.handle.sendline( "" )
2770 self.handle.expect( "mininet>" )
2771
2772 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2773 self.handle.expect( "mininet>" )
2774
2775 handlePy = self.handle.before
2776 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2777 handlePy = handlePy.rstrip()
2778
2779 self.handle.sendline( "" )
2780 self.handle.expect( "mininet>" )
2781
2782 nodesStr = handlePy.replace( "]", "" )
2783 nodesStr = nodesStr.replace( "'", "" )
2784 nodesStr = nodesStr.replace( "[", "" )
2785 nodesStr = nodesStr.replace( " ", "" )
2786 nodesList = nodesStr.split( "," )
2787
2788 nodesSet = set( nodesList )
2789 # discarding default controller(s) node
2790 nodesSet.discard( 'c0' )
2791 nodesSet.discard( 'c1' )
2792 nodesSet.discard( 'c2' )
2793
2794 switchSet = nodesSet - hostSet
2795 switchList = list( switchSet )
2796
2797 return switchList
2798
Jon Hall7eb38402015-01-08 17:19:54 -08002799 def update( self ):
2800 """
2801 updates the port address and status information for
2802 each port in mn"""
2803 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002804 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002805 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002806 self.handle.sendline( "" )
2807 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002808
Jon Hall7eb38402015-01-08 17:19:54 -08002809 self.handle.sendline( "update" )
2810 self.handle.expect( "update" )
2811 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002812
Jon Hall7eb38402015-01-08 17:19:54 -08002813 self.handle.sendline( "" )
2814 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002815
Jon Hallb1290e82014-11-18 16:17:48 -05002816 return main.TRUE
2817 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002818 main.log.error( self.name + ": EOF exception found" )
2819 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002820 main.cleanup()
2821 main.exit()
2822
Jon Halld80cc142015-07-06 13:36:05 -07002823 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002824 """
2825 Add vlan tag to a host.
2826 Dependencies:
2827 This class depends on the "vlan" package
2828 $ sudo apt-get install vlan
2829 Configuration:
2830 Load the 8021q module into the kernel
2831 $sudo modprobe 8021q
2832
2833 To make this setup permanent:
2834 $ sudo su -c 'echo "8021q" >> /etc/modules'
2835 """
2836 if self.handle:
2837 try:
Jon Halld80cc142015-07-06 13:36:05 -07002838 # get the ip address of the host
2839 main.log.info( "Get the ip address of the host" )
2840 ipaddr = self.getIPAddress( host )
2841 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002842
Jon Halld80cc142015-07-06 13:36:05 -07002843 # remove IP from interface intf
2844 # Ex: h1 ifconfig h1-eth0 inet 0
2845 main.log.info( "Remove IP from interface " )
2846 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2847 self.handle.sendline( cmd2 )
2848 self.handle.expect( "mininet>" )
2849 response = self.handle.before
2850 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002851
Jon Halld80cc142015-07-06 13:36:05 -07002852 # create VLAN interface
2853 # Ex: h1 vconfig add h1-eth0 100
2854 main.log.info( "Create Vlan" )
2855 cmd3 = host + " vconfig add " + intf + " " + vlan
2856 self.handle.sendline( cmd3 )
2857 self.handle.expect( "mininet>" )
2858 response = self.handle.before
2859 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002860
Jon Halld80cc142015-07-06 13:36:05 -07002861 # assign the host's IP to the VLAN interface
2862 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2863 main.log.info( "Assign the host IP to the vlan interface" )
2864 vintf = intf + "." + vlan
2865 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2866 self.handle.sendline( cmd4 )
2867 self.handle.expect( "mininet>" )
2868 response = self.handle.before
2869 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002870
2871 return main.TRUE
2872 except pexpect.EOF:
2873 main.log.error( self.name + ": EOF exception found" )
2874 main.log.error( self.name + ": " + self.handle.before )
2875 return main.FALSE
2876
Jon Hall892818c2015-10-20 17:58:34 -07002877 def createHostComponent( self, name ):
2878 """
2879 Creates a new mininet cli component with the same parameters as self.
2880 This new component is intended to be used to login to the hosts created
2881 by mininet.
2882
2883 Arguments:
2884 name - The string of the name of this component. The new component
2885 will be assigned to main.<name> .
2886 In addition, main.<name>.name = str( name )
2887 """
2888 try:
2889 # look to see if this component already exists
2890 getattr( main, name )
2891 except AttributeError:
2892 # namespace is clear, creating component
2893 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
2894 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
2895 main.componentInit( name )
2896 except Exception:
2897 main.log.exception( self.name + ": Uncaught exception!" )
2898 main.cleanup()
2899 main.exit()
2900 else:
2901 # namespace is not clear!
2902 main.log.error( name + " component already exists!" )
2903 # FIXME: Should we exit here?
2904 main.cleanup()
2905 main.exit()
2906
2907 def removeHostComponent( self, name ):
2908 """
2909 Remove host component
2910 Arguments:
2911 name - The string of the name of the component to delete.
2912 """
2913 try:
2914 # Get host component
2915 component = getattr( main, name )
2916 except AttributeError:
2917 main.log.error( "Component " + name + " does not exist." )
2918 return
2919 try:
2920 # Disconnect from component
2921 component.disconnect()
2922 # Delete component
2923 delattr( main, name )
2924 # Delete component from ComponentDictionary
2925 del( main.componentDictionary[name] )
2926 except Exception:
2927 main.log.exception( self.name + ": Uncaught exception!" )
2928 main.cleanup()
2929 main.exit()
2930
2931 def startHostCli( self, host=None ):
2932 """
2933 Use the mininet m utility to connect to the host's cli
2934 """
2935 # These are fields that can be used by scapy packets. Initialized to None
2936 self.hostIp = None
2937 self.hostMac = None
2938 try:
2939 if not host:
2940 host = self.name
2941 self.handle.sendline( self.home + "/util/m " + host )
2942 self.handle.expect( self.hostPrompt )
2943 return main.TRUE
2944 except pexpect.TIMEOUT:
2945 main.log.exception( self.name + ": Command timed out" )
2946 return main.FALSE
2947 except pexpect.EOF:
2948 main.log.exception( self.name + ": connection closed." )
2949 main.cleanup()
2950 main.exit()
2951 except Exception:
2952 main.log.exception( self.name + ": Uncaught exception!" )
2953 main.cleanup()
2954 main.exit()
2955
GlennRC956ea742015-11-05 16:14:15 -08002956 def startScapy( self, mplsPath="" ):
Jon Hall892818c2015-10-20 17:58:34 -07002957 """
2958 Start the Scapy cli
GlennRC956ea742015-11-05 16:14:15 -08002959 optional:
2960 mplsPath - The path where the MPLS class is located
2961 NOTE: This can be a relative path from the user's home dir
Jon Hall892818c2015-10-20 17:58:34 -07002962 """
GlennRC956ea742015-11-05 16:14:15 -08002963 mplsLines = ['import imp',
2964 'imp.load_source( "mplsClass", "{}mplsClass.py" )'.format(mplsPath),
2965 'from mplsClass import MPLS',
2966 'bind_layers(Ether, MPLS, type = 0x8847)',
2967 'bind_layers(MPLS, MPLS, bottom_of_label_stack = 0)',
2968 'bind_layers(MPLS, IP)']
2969
Jon Hall892818c2015-10-20 17:58:34 -07002970 try:
2971 self.handle.sendline( "scapy" )
2972 self.handle.expect( self.scapyPrompt )
2973 self.handle.sendline( "conf.color_theme = NoTheme()" )
2974 self.handle.expect( self.scapyPrompt )
GlennRC956ea742015-11-05 16:14:15 -08002975 if mplsPath:
2976 main.log.info( "Adding MPLS class" )
2977 main.log.info( "MPLS class path: " + mplsPath )
2978 for line in mplsLines:
2979 main.log.info( "sending line: " + line )
2980 self.handle.sendline( line )
2981 self.handle.expect( self.scapyPrompt )
Jon Hall892818c2015-10-20 17:58:34 -07002982 return main.TRUE
2983 except pexpect.TIMEOUT:
2984 main.log.exception( self.name + ": Command timed out" )
2985 return main.FALSE
2986 except pexpect.EOF:
2987 main.log.exception( self.name + ": connection closed." )
2988 main.cleanup()
2989 main.exit()
2990 except Exception:
2991 main.log.exception( self.name + ": Uncaught exception!" )
2992 main.cleanup()
2993 main.exit()
2994
2995 def stopScapy( self ):
2996 """
2997 Exit the Scapy cli
2998 """
2999 try:
3000 self.handle.sendline( "exit()" )
3001 self.handle.expect( self.hostPrompt )
3002 return main.TRUE
3003 except pexpect.TIMEOUT:
3004 main.log.exception( self.name + ": Command timed out" )
3005 return main.FALSE
3006 except pexpect.EOF:
3007 main.log.exception( self.name + ": connection closed." )
3008 main.cleanup()
3009 main.exit()
3010 except Exception:
3011 main.log.exception( self.name + ": Uncaught exception!" )
3012 main.cleanup()
3013 main.exit()
3014
3015 def buildEther( self, **kwargs ):
3016 """
3017 Build an Ethernet frame
3018
3019 Will create a frame class with the given options. If a field is
3020 left blank it will default to the below value unless it is
3021 overwritten by the next frame.
3022 Default frame:
3023 ###[ Ethernet ]###
3024 dst= ff:ff:ff:ff:ff:ff
3025 src= 00:00:00:00:00:00
3026 type= 0x800
3027
3028 Returns main.TRUE or main.FALSE on error
3029 """
3030 try:
3031 # Set the Ethernet frame
3032 cmd = 'ether = Ether( '
3033 options = []
3034 for key, value in kwargs.iteritems():
3035 if isinstance( value, str ):
3036 value = '"' + value + '"'
3037 options.append( str( key ) + "=" + str( value ) )
3038 cmd += ", ".join( options )
3039 cmd += ' )'
3040 self.handle.sendline( cmd )
3041 self.handle.expect( self.scapyPrompt )
3042 if "Traceback" in self.handle.before:
3043 # KeyError, SyntaxError, ...
3044 main.log.error( "Error in sending command: " + self.handle.before )
3045 return main.FALSE
3046 self.handle.sendline( "packet = ether" )
3047 self.handle.expect( self.scapyPrompt )
3048 if "Traceback" in self.handle.before:
3049 # KeyError, SyntaxError, ...
3050 main.log.error( "Error in sending command: " + self.handle.before )
3051 return main.FALSE
3052 return main.TRUE
3053 except pexpect.TIMEOUT:
3054 main.log.exception( self.name + ": Command timed out" )
3055 return main.FALSE
3056 except pexpect.EOF:
3057 main.log.exception( self.name + ": connection closed." )
3058 main.cleanup()
3059 main.exit()
3060 except Exception:
3061 main.log.exception( self.name + ": Uncaught exception!" )
3062 main.cleanup()
3063 main.exit()
3064
3065 def buildIP( self, **kwargs ):
3066 """
3067 Build an IP frame
3068
3069 Will create a frame class with the given options. If a field is
3070 left blank it will default to the below value unless it is
3071 overwritten by the next frame.
3072 Default frame:
3073 ###[ IP ]###
3074 version= 4
3075 ihl= None
3076 tos= 0x0
3077 len= None
3078 id= 1
3079 flags=
3080 frag= 0
3081 ttl= 64
3082 proto= hopopt
3083 chksum= None
3084 src= 127.0.0.1
3085 dst= 127.0.0.1
3086 \options\
3087
3088 Returns main.TRUE or main.FALSE on error
3089 """
3090 try:
3091 # Set the IP frame
3092 cmd = 'ip = IP( '
3093 options = []
3094 for key, value in kwargs.iteritems():
3095 if isinstance( value, str ):
3096 value = '"' + value + '"'
3097 options.append( str( key ) + "=" + str( value ) )
3098 cmd += ", ".join( options )
3099 cmd += ' )'
3100 self.handle.sendline( cmd )
3101 self.handle.expect( self.scapyPrompt )
3102 if "Traceback" in self.handle.before:
3103 # KeyError, SyntaxError, ...
3104 main.log.error( "Error in sending command: " + self.handle.before )
3105 return main.FALSE
3106 self.handle.sendline( "packet = ether/ip" )
3107 self.handle.expect( self.scapyPrompt )
3108 if "Traceback" in self.handle.before:
3109 # KeyError, SyntaxError, ...
3110 main.log.error( "Error in sending command: " + self.handle.before )
3111 return main.FALSE
3112 return main.TRUE
3113 except pexpect.TIMEOUT:
3114 main.log.exception( self.name + ": Command timed out" )
3115 return main.FALSE
3116 except pexpect.EOF:
3117 main.log.exception( self.name + ": connection closed." )
3118 main.cleanup()
3119 main.exit()
3120 except Exception:
3121 main.log.exception( self.name + ": Uncaught exception!" )
3122 main.cleanup()
3123 main.exit()
3124
3125 def buildIPv6( self, **kwargs ):
3126 """
3127 Build an IPv6 frame
3128
3129 Will create a frame class with the given options. If a field is
3130 left blank it will default to the below value unless it is
3131 overwritten by the next frame.
3132 Default frame:
3133 ###[ IPv6 ]###
3134 version= 6
3135 tc= 0
3136 fl= 0
3137 plen= None
3138 nh= No Next Header
3139 hlim= 64
3140 src= ::1
3141 dst= ::1
3142
3143 Returns main.TRUE or main.FALSE on error
3144 """
3145 try:
3146 # Set the IPv6 frame
3147 cmd = 'ipv6 = IPv6( '
3148 options = []
3149 for key, value in kwargs.iteritems():
3150 if isinstance( value, str ):
3151 value = '"' + value + '"'
3152 options.append( str( key ) + "=" + str( value ) )
3153 cmd += ", ".join( options )
3154 cmd += ' )'
3155 self.handle.sendline( cmd )
3156 self.handle.expect( self.scapyPrompt )
3157 if "Traceback" in self.handle.before:
3158 # KeyError, SyntaxError, ...
3159 main.log.error( "Error in sending command: " + self.handle.before )
3160 return main.FALSE
3161 self.handle.sendline( "packet = ether/ipv6" )
3162 self.handle.expect( self.scapyPrompt )
3163 if "Traceback" in self.handle.before:
3164 # KeyError, SyntaxError, ...
3165 main.log.error( "Error in sending command: " + self.handle.before )
3166 return main.FALSE
3167 return main.TRUE
3168 except pexpect.TIMEOUT:
3169 main.log.exception( self.name + ": Command timed out" )
3170 return main.FALSE
3171 except pexpect.EOF:
3172 main.log.exception( self.name + ": connection closed." )
3173 main.cleanup()
3174 main.exit()
3175 except Exception:
3176 main.log.exception( self.name + ": Uncaught exception!" )
3177 main.cleanup()
3178 main.exit()
3179
3180 def buildTCP( self, ipVersion=4, **kwargs ):
3181 """
3182 Build an TCP frame
3183
3184 Will create a frame class with the given options. If a field is
3185 left blank it will default to the below value unless it is
3186 overwritten by the next frame.
3187
GlennRC956ea742015-11-05 16:14:15 -08003188 NOTE: Some arguments require quotes around them. It's up to you to
3189 know which ones and to add them yourself. Arguments with an asterisk
3190 do not need quotes.
3191
Jon Hall892818c2015-10-20 17:58:34 -07003192 Options:
3193 ipVersion - Either 4 (default) or 6, indicates what Internet Protocol
3194 frame to use to encapsulate into
3195 Default frame:
3196 ###[ TCP ]###
GlennRC956ea742015-11-05 16:14:15 -08003197 sport= ftp_data *
3198 dport= http *
Jon Hall892818c2015-10-20 17:58:34 -07003199 seq= 0
3200 ack= 0
3201 dataofs= None
3202 reserved= 0
3203 flags= S
3204 window= 8192
3205 chksum= None
3206 urgptr= 0
3207 options= {}
3208
3209 Returns main.TRUE or main.FALSE on error
3210 """
3211 try:
3212 # Set the TCP frame
3213 cmd = 'tcp = TCP( '
3214 options = []
3215 for key, value in kwargs.iteritems():
Jon Hall892818c2015-10-20 17:58:34 -07003216 options.append( str( key ) + "=" + str( value ) )
3217 cmd += ", ".join( options )
3218 cmd += ' )'
3219 self.handle.sendline( cmd )
3220 self.handle.expect( self.scapyPrompt )
3221 if "Traceback" in self.handle.before:
3222 # KeyError, SyntaxError, ...
3223 main.log.error( "Error in sending command: " + self.handle.before )
3224 return main.FALSE
3225 if str( ipVersion ) is '4':
3226 self.handle.sendline( "packet = ether/ip/tcp" )
3227 elif str( ipVersion ) is '6':
3228 self.handle.sendline( "packet = ether/ipv6/tcp" )
3229 else:
3230 main.log.error( "Unrecognized option for ipVersion, given " +
3231 repr( ipVersion ) )
3232 return main.FALSE
3233 self.handle.expect( self.scapyPrompt )
3234 if "Traceback" in self.handle.before:
3235 # KeyError, SyntaxError, ...
3236 main.log.error( "Error in sending command: " + self.handle.before )
3237 return main.FALSE
3238 return main.TRUE
3239 except pexpect.TIMEOUT:
3240 main.log.exception( self.name + ": Command timed out" )
3241 return main.FALSE
3242 except pexpect.EOF:
3243 main.log.exception( self.name + ": connection closed." )
3244 main.cleanup()
3245 main.exit()
3246 except Exception:
3247 main.log.exception( self.name + ": Uncaught exception!" )
3248 main.cleanup()
3249 main.exit()
3250
3251 def buildUDP( self, ipVersion=4, **kwargs ):
3252 """
3253 Build an UDP frame
3254
3255 Will create a frame class with the given options. If a field is
3256 left blank it will default to the below value unless it is
3257 overwritten by the next frame.
3258
GlennRC956ea742015-11-05 16:14:15 -08003259 NOTE: Some arguments require quotes around them. It's up to you to
3260 know which ones and to add them yourself. Arguments with an asterisk
3261 do not need quotes.
3262
Jon Hall892818c2015-10-20 17:58:34 -07003263 Options:
3264 ipVersion - Either 4 (default) or 6, indicates what Internet Protocol
3265 frame to use to encapsulate into
3266 Default frame:
3267 ###[ UDP ]###
GlennRC956ea742015-11-05 16:14:15 -08003268 sport= domain *
3269 dport= domain *
Jon Hall892818c2015-10-20 17:58:34 -07003270 len= None
3271 chksum= None
3272
3273 Returns main.TRUE or main.FALSE on error
3274 """
3275 try:
3276 # Set the UDP frame
3277 cmd = 'udp = UDP( '
3278 options = []
3279 for key, value in kwargs.iteritems():
Jon Hall892818c2015-10-20 17:58:34 -07003280 options.append( str( key ) + "=" + str( value ) )
3281 cmd += ", ".join( options )
3282 cmd += ' )'
3283 self.handle.sendline( cmd )
3284 self.handle.expect( self.scapyPrompt )
3285 if "Traceback" in self.handle.before:
3286 # KeyError, SyntaxError, ...
3287 main.log.error( "Error in sending command: " + self.handle.before )
3288 return main.FALSE
3289 if str( ipVersion ) is '4':
3290 self.handle.sendline( "packet = ether/ip/udp" )
3291 elif str( ipVersion ) is '6':
3292 self.handle.sendline( "packet = ether/ipv6/udp" )
3293 else:
3294 main.log.error( "Unrecognized option for ipVersion, given " +
3295 repr( ipVersion ) )
3296 return main.FALSE
3297 self.handle.expect( self.scapyPrompt )
3298 if "Traceback" in self.handle.before:
3299 # KeyError, SyntaxError, ...
3300 main.log.error( "Error in sending command: " + self.handle.before )
3301 return main.FALSE
3302 return main.TRUE
3303 except pexpect.TIMEOUT:
3304 main.log.exception( self.name + ": Command timed out" )
3305 return main.FALSE
3306 except pexpect.EOF:
3307 main.log.exception( self.name + ": connection closed." )
3308 main.cleanup()
3309 main.exit()
3310 except Exception:
3311 main.log.exception( self.name + ": Uncaught exception!" )
3312 main.cleanup()
3313 main.exit()
3314
3315 def buildICMP( self, **kwargs ):
3316 """
3317 Build an ICMP frame
3318
3319 Will create a frame class with the given options. If a field is
3320 left blank it will default to the below value unless it is
3321 overwritten by the next frame.
3322 Default frame:
3323 ###[ ICMP ]###
3324 type= echo-request
3325 code= 0
3326 chksum= None
3327 id= 0x0
3328 seq= 0x0
3329
3330 Returns main.TRUE or main.FALSE on error
3331 """
3332 try:
3333 # Set the ICMP frame
3334 cmd = 'icmp = ICMP( '
3335 options = []
3336 for key, value in kwargs.iteritems():
3337 if isinstance( value, str ):
3338 value = '"' + value + '"'
3339 options.append( str( key ) + "=" + str( value ) )
3340 cmd += ", ".join( options )
3341 cmd += ' )'
3342 self.handle.sendline( cmd )
3343 self.handle.expect( self.scapyPrompt )
3344 if "Traceback" in self.handle.before:
3345 # KeyError, SyntaxError, ...
3346 main.log.error( "Error in sending command: " + self.handle.before )
3347 return main.FALSE
3348 self.handle.sendline( "packet = ether/ip/icmp" )
3349 self.handle.expect( self.scapyPrompt )
3350 if "Traceback" in self.handle.before:
3351 # KeyError, SyntaxError, ...
3352 main.log.error( "Error in sending command: " + self.handle.before )
3353 return main.FALSE
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
GlennRC073e8bc2015-10-27 17:11:28 -07003367 def sendPacket( self, iface=None, packet=None, timeout=1 ):
Jon Hall892818c2015-10-20 17:58:34 -07003368 """
3369 Send a packet with either the given scapy packet command, or use the
3370 packet saved in the variable 'packet'.
3371
3372 Examples of a valid string for packet:
3373
3374 Simple IP packet
3375 packet='Ether(dst="a6:d9:26:df:1d:4b")/IP(dst="10.0.0.2")'
3376
3377 A Ping with two vlan tags
3378 packet='Ether(dst='ff:ff:ff:ff:ff:ff')/Dot1Q(vlan=1)/Dot1Q(vlan=10)/
3379 IP(dst='255.255.255.255', src='192.168.0.1')/ICMP()'
3380
3381 Returns main.TRUE or main.FALSE on error
3382 """
3383 try:
3384 # TODO: add all params, or use kwargs
3385 sendCmd = 'srp( '
3386 if packet:
3387 sendCmd += packet
3388 else:
3389 sendCmd += "packet"
GlennRC073e8bc2015-10-27 17:11:28 -07003390 if iface:
3391 sendCmd += ", iface='{}'".format( iface )
3392
Jon Hall892818c2015-10-20 17:58:34 -07003393 sendCmd += ', timeout=' + str( timeout ) + ')'
3394 self.handle.sendline( sendCmd )
3395 self.handle.expect( self.scapyPrompt )
3396 if "Traceback" in self.handle.before:
3397 # KeyError, SyntaxError, ...
3398 main.log.error( "Error in sending command: " + self.handle.before )
3399 return main.FALSE
3400 # TODO: Check # of packets sent?
3401 return main.TRUE
3402 except pexpect.TIMEOUT:
3403 main.log.exception( self.name + ": Command timed out" )
3404 return main.FALSE
3405 except pexpect.EOF:
3406 main.log.exception( self.name + ": connection closed." )
3407 main.cleanup()
3408 main.exit()
3409 except Exception:
3410 main.log.exception( self.name + ": Uncaught exception!" )
3411 main.cleanup()
3412 main.exit()
3413
3414 def startFilter( self, ifaceName=None, sniffCount=1, pktFilter="ip" ):
3415 """
3416 Listen for packets using the given filters
3417
3418 Options:
3419 ifaceName - the name of the interface to listen on. If none is given,
3420 defaults to <host name>-eth0
3421 pktFilter - A string in Berkeley Packet Filter (BPF) format which
3422 specifies which packets to sniff
3423 sniffCount - The number of matching packets to capture before returning
3424
3425 Returns main.TRUE or main.FALSE on error
3426 """
3427 try:
3428 # TODO: add all params, or use kwargs
3429 ifaceName = str( ifaceName ) if ifaceName else self.name + "-eth0"
3430 # Set interface
3431 self.handle.sendline( ' conf.iface = "' + ifaceName + '"' )
3432 self.handle.expect( self.scapyPrompt )
3433 cmd = 'pkt = sniff(count = ' + str( sniffCount ) +\
3434 ', filter = "' + str( pktFilter ) + '")'
3435 self.handle.sendline( cmd )
3436 self.handle.expect( '"\)\r\n' )
3437 # TODO: parse this?
3438 return main.TRUE
3439 except pexpect.TIMEOUT:
3440 main.log.exception( self.name + ": Command timed out" )
3441 return main.FALSE
3442 except pexpect.EOF:
3443 main.log.exception( self.name + ": connection closed." )
3444 main.cleanup()
3445 main.exit()
3446 except Exception:
3447 main.log.exception( self.name + ": Uncaught exception!" )
3448 main.cleanup()
3449 main.exit()
3450
3451 def checkFilter( self ):
3452 """
3453 Check that a filter returned and returns the reponse
3454 """
3455 try:
3456 i = self.handle.expect( [ self.scapyPrompt, pexpect.TIMEOUT ] )
3457 if i == 0:
3458 return main.TRUE
3459 else:
3460 return main.FALSE
3461 except pexpect.EOF:
3462 main.log.exception( self.name + ": connection closed." )
3463 main.cleanup()
3464 main.exit()
3465 except Exception:
3466 main.log.exception( self.name + ": Uncaught exception!" )
3467 main.cleanup()
3468 main.exit()
3469
3470 def killFilter( self ):
3471 """
3472 Kill a scapy filter
3473 """
3474 try:
3475 self.handle.send( "\x03" ) # Send a ctrl-c to kill the filter
3476 self.handle.expect( self.scapyPrompt )
3477 return self.handle.before
3478 except pexpect.TIMEOUT:
3479 main.log.exception( self.name + ": Command timed out" )
3480 return None
3481 except pexpect.EOF:
3482 main.log.exception( self.name + ": connection closed." )
3483 main.cleanup()
3484 main.exit()
3485 except Exception:
3486 main.log.exception( self.name + ": Uncaught exception!" )
3487 main.cleanup()
3488 main.exit()
3489
3490 def readPackets( self ):
3491 """
3492 Read all the packets captured by the previous filter
3493 """
3494 try:
3495 self.handle.sendline( "for p in pkt: p \n")
3496 self.handle.expect( "for p in pkt: p \r\n... \r\n" )
3497 self.handle.expect( self.scapyPrompt )
3498 except pexpect.TIMEOUT:
3499 main.log.exception( self.name + ": Command timed out" )
3500 return None
3501 except pexpect.EOF:
3502 main.log.exception( self.name + ": connection closed." )
3503 main.cleanup()
3504 main.exit()
3505 except Exception:
3506 main.log.exception( self.name + ": Uncaught exception!" )
3507 main.cleanup()
3508 main.exit()
3509 return self.handle.before
3510
3511 def updateSelf( self ):
3512 """
3513 Updates local MAC and IP fields
3514 """
3515 self.hostMac = self.getMac()
3516 self.hostIp = self.getIp()
3517
3518 def getMac( self, ifaceName=None ):
3519 """
3520 Save host's MAC address
3521 """
3522 try:
3523 ifaceName = str( ifaceName ) if ifaceName else self.name + "-eth0"
3524 cmd = 'get_if_hwaddr("' + str( ifaceName ) + '")'
3525 self.handle.sendline( cmd )
3526 self.handle.expect( self.scapyPrompt )
3527 pattern = r'(([0-9a-f]{2}[:-]){5}([0-9a-f]{2}))'
3528 match = re.search( pattern, self.handle.before )
3529 if match:
3530 return match.group()
3531 else:
3532 # the command will have an exception if iface doesn't exist
3533 return None
3534 except pexpect.TIMEOUT:
3535 main.log.exception( self.name + ": Command timed out" )
3536 return None
3537 except pexpect.EOF:
3538 main.log.exception( self.name + ": connection closed." )
3539 main.cleanup()
3540 main.exit()
3541 except Exception:
3542 main.log.exception( self.name + ": Uncaught exception!" )
3543 main.cleanup()
3544 main.exit()
3545
3546 def getIp( self, ifaceName=None ):
3547 """
3548 Save host's IP address
3549 """
3550 try:
3551 ifaceName = ifaceName if ifaceName else self.name + "-eth0"
3552 cmd = 'get_if_addr("' + str( ifaceName ) + '")'
3553 self.handle.sendline( cmd )
3554 self.handle.expect( self.scapyPrompt )
3555
3556 pattern = r'(((2[0-5]|1[0-9]|[0-9])?[0-9]\.){3}((2[0-5]|1[0-9]|[0-9])?[0-9]))'
3557 match = re.search( pattern, self.handle.before )
3558 if match:
3559 # NOTE: The command will return 0.0.0.0 if the iface doesn't exist
3560 return match.group()
3561 else:
3562 return None
3563 except pexpect.TIMEOUT:
3564 main.log.exception( self.name + ": Command timed out" )
3565 return None
3566 except pexpect.EOF:
3567 main.log.exception( self.name + ": connection closed." )
3568 main.cleanup()
3569 main.exit()
3570 except Exception:
3571 main.log.exception( self.name + ": Uncaught exception!" )
3572 main.cleanup()
3573 main.exit()
3574
adminbae64d82013-08-01 10:50:15 -07003575if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07003576 sys.modules[ __name__ ] = MininetCliDriver()