blob: 59e1441a8a6e26e5824687c41bbf32cab6ce6648 [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
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004Copyright 2012 Open Networking Foundation (ONF)
adminbae64d82013-08-01 10:50:15 -07005
Jeremy Songsterae01bba2016-07-11 15:39:17 -07006Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
7the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
8or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
adminbae64d82013-08-01 10:50:15 -07009
Jon Hall7eb38402015-01-08 17:19:54 -080010TestON is free software: you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation, either version 2 of the License, or
13( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070014
Jon Hall7eb38402015-01-08 17:19:54 -080015TestON is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070019
Jon Hall7eb38402015-01-08 17:19:54 -080020You should have received a copy of the GNU General Public License
21along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070022
Jon Hallbe6dfc42015-01-12 17:37:25 -080023MininetCliDriver is the basic driver which will handle the Mininet functions
24
25Some functions rely on a modified version of Mininet. These functions
26should all be noted in the comments. To get this MN version run these commands
27from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080028 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080029 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080030 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080031 git pull
32
Jon Hall272a4db2015-01-12 17:43:48 -080033
34 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080035changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070036import pexpect
adminbae64d82013-08-01 10:50:15 -070037import re
38import sys
kelvin-onlabfa6ada82015-06-11 13:06:24 -070039import types
kelvin-onlaba4074292015-07-09 15:19:49 -070040import os
Devin Lima7cfdbd2017-09-29 15:02:22 -070041import time
Jon Hall1ccf82c2014-10-15 14:55:16 -040042from math import pow
adminbae64d82013-08-01 10:50:15 -070043from drivers.common.cli.emulatordriver import Emulator
You Wangdb8cd0a2016-05-26 15:19:45 -070044from core.graph import Graph
adminbae64d82013-08-01 10:50:15 -070045
Jon Hall7eb38402015-01-08 17:19:54 -080046
kelvin-onlab50907142015-04-01 13:37:45 -070047class MininetCliDriver( Emulator ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -070048
Jon Hall7eb38402015-01-08 17:19:54 -080049 """
50 MininetCliDriver is the basic driver which will handle
51 the Mininet functions"""
52 def __init__( self ):
Devin Limdc78e202017-06-09 18:30:07 -070053 super( MininetCliDriver, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070054 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080055 self.name = None
kelvin-onlabd9e23de2015-08-06 10:34:44 -070056 self.home = None
Jon Hall7eb38402015-01-08 17:19:54 -080057 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070058 self.flag = 0
Jon Hall892818c2015-10-20 17:58:34 -070059 # TODO: Refactor driver to use these everywhere
60 self.mnPrompt = "mininet>"
61 self.hostPrompt = "~#"
62 self.bashPrompt = "\$"
63 self.scapyPrompt = ">>>"
You Wangdb8cd0a2016-05-26 15:19:45 -070064 self.graph = Graph()
adminbae64d82013-08-01 10:50:15 -070065
Jon Hall7eb38402015-01-08 17:19:54 -080066 def connect( self, **connectargs ):
67 """
68 Here the main is the TestON instance after creating
69 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080070 try:
71 for key in connectargs:
72 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070073 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080074 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070075 for key in self.options:
76 if key == "home":
77 self.home = self.options[ 'home' ]
78 break
79 if self.home is None or self.home == "":
80 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070081
82 try:
Jon Hall892818c2015-10-20 17:58:34 -070083 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070084 self.ip_address = os.getenv( str( self.ip_address ) )
85 else:
86 main.log.info( self.name +
87 ": Trying to connect to " +
88 self.ip_address )
89
90 except KeyError:
91 main.log.info( "Invalid host name," +
92 " connecting to local host instead" )
93 self.ip_address = 'localhost'
94 except Exception as inst:
95 main.log.error( "Uncaught exception: " + str( inst ) )
96
kelvin-onlaba1484582015-02-02 15:46:20 -080097 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070098 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080099 self ).connect(
100 user_name=self.user_name,
101 ip_address=self.ip_address,
102 port=None,
103 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -0800104
kelvin-onlaba1484582015-02-02 15:46:20 -0800105 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -0800106 main.log.info( "Connection successful to the host " +
107 self.user_name +
108 "@" +
109 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800110 return main.TRUE
111 else:
112 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800113 self.user_name +
114 "@" +
115 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800116 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800117 return main.FALSE
118 except pexpect.EOF:
119 main.log.error( self.name + ": EOF exception found" )
120 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700121 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800122 except Exception:
123 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700124 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -0800125
kelvin-onlab10e8d392015-06-03 13:53:45 -0700126 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800127 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700128 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000129 Starts Mininet accepts a topology(.py) file and/or an optional
kelvin-onlabf512e942015-06-08 19:42:59 -0700130 argument, to start the mininet, as a parameter.
131 Can also send regular mininet command to load up desired topology.
alison12f34c32016-06-10 14:39:21 -0700132 Eg. Pass in a string 'mn --topo=tree,3,3' to mnCmd
kelvin-onlabf512e942015-06-08 19:42:59 -0700133 Options:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000134 topoFile = file path for topology file (.py)
kelvin-onlabf512e942015-06-08 19:42:59 -0700135 args = extra option added when starting the topology from the file
136 mnCmd = Mininet command use to start topology
137 Returns:
138 main.TRUE if the mininet starts successfully, main.FALSE
139 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800140 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700141 try:
142 if self.handle:
143 # make sure old networks are cleaned up
144 main.log.info( self.name +
145 ": Clearing any residual state or processes" )
146 self.handle.sendline( "sudo mn -c" )
147 i = self.handle.expect( [ 'password\sfor\s',
148 'Cleanup\scomplete',
Jon Hallefbd9792015-03-05 16:11:36 -0800149 pexpect.EOF,
150 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700151 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800152 if i == 0:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700153 # Sudo asking for password
154 main.log.info( self.name + ": Sending sudo password" )
155 self.handle.sendline( self.pwd )
Jon Hall173f2a02018-01-11 13:56:37 -0800156 i = self.handle.expect( [ '%s:' % self.user_name,
Devin Limdc78e202017-06-09 18:30:07 -0700157 self.prompt,
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700158 pexpect.EOF,
159 pexpect.TIMEOUT ],
160 timeout )
161 if i == 1:
162 main.log.info( self.name + ": Clean" )
Jon Hall689d8e42015-04-03 13:59:24 -0700163 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700164 main.log.error( self.name + ": Connection terminated" )
165 elif i == 3: # timeout
166 main.log.error( self.name + ": Something while cleaning " +
167 "Mininet took too long... " )
168 # Craft the string to start mininet
169 cmdString = "sudo "
170 if not mnCmd:
171 if topoFile is None or topoFile == '': # If no file is given
172 main.log.info( self.name + ": building fresh Mininet" )
173 cmdString += "mn "
174 if args is None or args == '':
175 # If no args given, use args from .topo file
176 args = self.options[ 'arg1' ] +\
177 " " + self.options[ 'arg2' ] +\
178 " --mac --controller " +\
179 self.options[ 'controller' ] + " " +\
180 self.options[ 'arg3' ]
181 else: # else only use given args
182 pass
183 # TODO: allow use of topo args and method args?
184 else: # Use given topology file
185 main.log.info(
186 "Starting Mininet from topo file " +
187 topoFile )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700188 cmdString += "-E python " + topoFile + " "
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700189 if args is None:
190 args = ''
191 # TODO: allow use of args from .topo file?
192 cmdString += args
193 else:
194 main.log.info( "Starting Mininet topology using '" + mnCmd +
195 "' command" )
196 cmdString += mnCmd
197 # Send the command and check if network started
198 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -0700199 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700200 main.log.info( "Sending '" + cmdString + "' to " + self.name )
201 self.handle.sendline( cmdString )
Devin Lima7cfdbd2017-09-29 15:02:22 -0700202 startTime = time.time()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700203 while True:
204 i = self.handle.expect( [ 'mininet>',
Jon Hallbc743112018-04-18 11:09:01 -0700205 'Exception|Error',
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700206 '\*\*\*',
207 pexpect.EOF,
Jon Hallab611372018-02-21 15:26:05 -0800208 pexpect.TIMEOUT,
209 "No such file or directory"],
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700210 timeout )
211 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -0700212 main.log.info( self.name + ": Mininet built\nTime Took : " + str( time.time() - startTime ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700213 return main.TRUE
214 elif i == 1:
215 response = str( self.handle.before +
216 self.handle.after )
Devin Limdc78e202017-06-09 18:30:07 -0700217 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700218 response += str( self.handle.before +
219 self.handle.after )
220 main.log.error(
221 self.name +
222 ": Launching Mininet failed: " + response )
223 return main.FALSE
224 elif i == 2:
225 self.handle.expect( [ "\n",
226 pexpect.EOF,
227 pexpect.TIMEOUT ],
228 timeout )
229 main.log.info( self.handle.before )
230 elif i == 3:
231 main.log.error( self.name + ": Connection timeout" )
232 return main.FALSE
233 elif i == 4: # timeout
234 main.log.error(
235 self.name +
236 ": Something took too long... " )
Jon Hallbc743112018-04-18 11:09:01 -0700237 main.log.debug( self.handle.before + self.handle.after )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700238 return main.FALSE
Jon Hallab611372018-02-21 15:26:05 -0800239 elif i == 5:
240 main.log.error( self.name + ": " + self.handle.before + self.handle.after )
241 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700242 # Why did we hit this part?
243 main.log.error( "startNet did not return correctly" )
244 return main.FASLE
245 else: # if no handle
246 main.log.error( self.name + ": Connection failed to the host " +
247 self.user_name + "@" + self.ip_address )
248 main.log.error( self.name + ": Failed to connect to the Mininet" )
249 return main.FALSE
250 except pexpect.TIMEOUT:
251 main.log.exception( self.name + ": TIMEOUT exception found while starting Mininet" )
252 main.log.error( self.name + ": " + self.handle.before )
adminbae64d82013-08-01 10:50:15 -0700253 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700254 except pexpect.EOF:
255 main.log.error( self.name + ": EOF exception found" )
256 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700257 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700258 except Exception:
259 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700260 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800261
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800262 def numSwitchesNlinks( self, topoType, depth, fanout ):
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700263 try:
264 if topoType == 'tree':
265 # In tree topology, if fanout arg is not given, by default it is 2
266 if fanout is None:
267 fanout = 2
268 k = 0
269 count = 0
270 while( k <= depth - 1 ):
271 count = count + pow( fanout, k )
272 k = k + 1
273 numSwitches = count
274 while( k <= depth - 2 ):
275 # depth-2 gives you only core links and not considering
276 # edge links as seen by ONOS. If all the links including
277 # edge links are required, do depth-1
278 count = count + pow( fanout, k )
279 k = k + 1
280 numLinks = count * fanout
281 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
282 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800283
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700284 elif topoType == 'linear':
285 # In linear topology, if fanout or numHostsPerSw is not given,
286 # by default it is 1
287 if fanout is None:
288 fanout = 1
289 numSwitches = depth
290 numHostsPerSw = fanout
291 totalNumHosts = numSwitches * numHostsPerSw
292 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hallab611372018-02-21 15:26:05 -0800293 main.log.debug( "num_switches for %s(%d,%d) = %d and links=%d" %
294 ( topoType, depth, fanout, numSwitches, numLinks ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700295 topoDict = { "num_switches": int( numSwitches ),
296 "num_corelinks": int( numLinks ) }
297 return topoDict
298 except Exception:
299 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700300 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400301
kelvin-onlabd3b64892015-01-20 13:26:24 -0800302 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700303 """
304 Calculate the number of switches and links in a topo."""
305 # TODO: combine this function and numSwitchesNlinks
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700306 try:
307 argList = self.options[ 'arg1' ].split( "," )
308 topoArgList = argList[ 0 ].split( " " )
309 argList = map( int, argList[ 1: ] )
310 topoArgList = topoArgList[ 1: ] + argList
Jon Hall689d8e42015-04-03 13:59:24 -0700311
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700312 topoDict = self.numSwitchesNlinks( *topoArgList )
313 return topoDict
314 except Exception:
315 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700316 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400317
GlennRCf07c44a2015-09-18 13:33:46 -0700318 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800319 """
320 Verifies the reachability of the hosts using pingall command.
321 Optional parameter timeout allows you to specify how long to
322 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700323 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700324 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700325 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700326 ping
327 acceptableFailed - Set the number of acceptable failed pings for the
328 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800329 Returns:
330 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700331 otherwise main.FALSE
332 """
333 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700334 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700335 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700336 if self.handle:
337 main.log.info(
338 self.name +
339 ": Checking reachabilty to the hosts using pingall" )
340 response = ""
341 failedPings = 0
342 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700343 cmd = "pingall"
344 if protocol == "IPv6":
345 cmd = "py net.pingAll6()"
346 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700347 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700348 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700349 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700350 pexpect.EOF,
351 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700352 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700353 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700354 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700355 response += self.handle.before
356 break
357 elif i == 1:
358 response += self.handle.before + self.handle.after
359 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700360 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700361 returnValue = main.FALSE
362 if shortCircuit:
363 main.log.error( self.name +
364 ": Aborting pingall - "
365 + str( failedPings ) +
366 " pings failed" )
367 break
Jon Hall390696c2015-05-05 17:13:41 -0700368 if ( time.time() - startTime ) > timeout:
369 returnValue = main.FALSE
370 main.log.error( self.name +
371 ": Aborting pingall - " +
372 "Function took too long " )
373 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700374 elif i == 2:
375 main.log.error( self.name +
376 ": EOF exception found" )
377 main.log.error( self.name + ": " +
378 self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700379 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700380 elif i == 3:
381 response += self.handle.before
382 main.log.error( self.name +
383 ": TIMEOUT exception found" )
384 main.log.error( self.name +
385 ": " +
386 str( response ) )
387 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800388 self.handle.send( "\x03" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700389 self.handle.expect( "Interrupt" )
390 self.handle.expect( "mininet>" )
391 break
392 pattern = "Results\:"
393 main.log.info( "Pingall output: " + str( response ) )
394 if re.search( pattern, response ):
395 main.log.info( self.name + ": Pingall finished with "
396 + str( failedPings ) + " failed pings" )
397 return returnValue
398 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700399 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800400 self.handle.send( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700401 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700402 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700403 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700404 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700405 main.log.error( self.name + ": Connection failed to the host" )
Devin Lim44075962017-08-11 10:56:37 -0700406 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700407 except pexpect.TIMEOUT:
408 if response:
409 main.log.info( "Pingall output: " + str( response ) )
410 main.log.error( self.name + ": pexpect.TIMEOUT found" )
411 return main.FALSE
412 except pexpect.EOF:
413 main.log.error( self.name + ": EOF exception found" )
414 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700415 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -0700416
Jon Hall7eb38402015-01-08 17:19:54 -0800417 def fpingHost( self, **pingParams ):
418 """
419 Uses the fping package for faster pinging...
420 *requires fping to be installed on machine running mininet"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700421 try:
422 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
423 command = args[ "SRC" ] + \
424 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
425 self.handle.sendline( command )
426 self.handle.expect(
427 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
428 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
429 response = self.handle.before
430 if re.search( ":\s-", response ):
431 main.log.info( self.name + ": Ping fail" )
432 return main.FALSE
433 elif re.search( ":\s\d{1,2}\.\d\d", response ):
434 main.log.info( self.name + ": Ping good!" )
435 return main.TRUE
436 main.log.info( self.name + ": Install fping on mininet machine... " )
437 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700438 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700439 except Exception:
440 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700441 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700442
Jon Hall3b489db2015-10-05 14:38:37 -0700443 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400444 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700445 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700446
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400447 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700448 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700449
450 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400451 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700452
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400453 Returns main.FALSE if one or more of hosts specified
454 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700455 wait = int( wait )
456 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400457
458 try:
459 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700460
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400461 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700462 pingResponse = "IPv4 ping across specified hosts\n"
463 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400464 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700465 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400466 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700467 pingList = hostList[ :listIndex ] + \
468 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700469
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700470 pingResponse += str( str( host ) + " -> " )
GlennRCd10d3cc2015-09-24 12:47:16 -0700471
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400472 for temp in pingList:
473 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700474 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700475 self.handle.sendline( pingCmd )
476 self.handle.expect( "mininet>", timeout=wait + 1 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400477 response = self.handle.before
478 if re.search( ',\s0\%\spacket\sloss', response ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700479 pingResponse += str( " h" + str( temp[ 1: ] ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400480 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700481 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400482 # One of the host to host pair is unreachable
483 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700484 failedPings += 1
You Wang11f9ead2018-03-21 14:34:59 -0700485 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
GlennRCd10d3cc2015-09-24 12:47:16 -0700486 pingResponse += "\n"
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700487 main.log.info( pingResponse + "Failed pings: " + str( failedPings ) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700488 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700489 except pexpect.TIMEOUT:
490 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800491 response = self.handle.before
492 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700493 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800494 self.handle.expect( "Interrupt" )
495 response += self.handle.before + self.handle.after
496 self.handle.expect( "mininet>" )
497 response += self.handle.before + self.handle.after
498 main.log.debug( response )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700499 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400500 except pexpect.EOF:
501 main.log.error( self.name + ": EOF exception found" )
502 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700503 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700504 except Exception:
505 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700506 main.cleanAndExit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400507
You Wangf19d9f42018-02-23 16:34:19 -0800508 def pingIpv6Hosts( self, hostList, wait=1, acceptableFailed=0 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700509 """
You Wangf19d9f42018-02-23 16:34:19 -0800510 IPv6 ping all hosts in hostList.
511
512 acceptableFailed: max number of acceptable failed pings
Hari Krishna9592fc82015-07-31 15:11:15 -0700513
Jon Hall3b489db2015-10-05 14:38:37 -0700514 Returns main.TRUE if all hosts specified can reach each other
Jon Hall3b489db2015-10-05 14:38:37 -0700515 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700516 """
517 try:
518 main.log.info( "Testing reachability between specified IPv6 hosts" )
519 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700520 wait = int( wait )
521 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700522 pingResponse = "IPv6 Pingall output:\n"
You Wangf19d9f42018-02-23 16:34:19 -0800523 failedPingsTotal = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700524 for host in hostList:
525 listIndex = hostList.index( host )
526 # List of hosts to ping other than itself
527 pingList = hostList[ :listIndex ] + \
528 hostList[ ( listIndex + 1 ): ]
529
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700530 pingResponse += str( str( host ) + " -> " )
GlennRC2cf7d952015-09-11 16:32:13 -0700531
Hari Krishna9592fc82015-07-31 15:11:15 -0700532 for temp in pingList:
533 # Current host pings all other hosts specified
You Wangf19d9f42018-02-23 16:34:19 -0800534 failedPings = 0
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700535 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
You Wangf19d9f42018-02-23 16:34:19 -0800536 while failedPings <= acceptableFailed:
537 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
538 self.handle.sendline( pingCmd )
539 self.handle.expect( "mininet>", timeout=wait + 1 )
540 response = self.handle.before
541 if re.search( ',\s0\%\spacket\sloss', response ):
You Wangba231e72018-03-01 13:18:21 -0800542 pingResponse += " " + str( temp )
543 break
544 else:
545 failedPings += 1
546 time.sleep(1)
547 if failedPings > acceptableFailed:
548 # One of the host to host pair is unreachable
549 pingResponse += " X"
550 isReachable = main.FALSE
551 failedPingsTotal += 1
You Wang11f9ead2018-03-21 14:34:59 -0700552 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
You Wangba231e72018-03-01 13:18:21 -0800553 pingResponse += "\n"
554 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
555 return isReachable
556
557 except pexpect.TIMEOUT:
558 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800559 response = self.handle.before
560 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700561 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800562 self.handle.expect( "Interrupt" )
563 response += self.handle.before + self.handle.after
564 self.handle.expect( "mininet>" )
565 response += self.handle.before + self.handle.after
566 main.log.debug( response )
You Wangba231e72018-03-01 13:18:21 -0800567 return main.FALSE
568 except pexpect.EOF:
569 main.log.error( self.name + ": EOF exception found" )
570 main.log.error( self.name + ": " + self.handle.before )
571 main.cleanAndExit()
572 except Exception:
573 main.log.exception( self.name + ": Uncaught exception!" )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700574
575 main.cleanAndExit()
576
You Wang48381752018-05-07 13:50:57 -0700577 def discoverHosts( self, hostList=[], wait=1, dstIp="6.6.6.6", dstIp6="1020::3fe" ):
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700578 '''
You Wang48381752018-05-07 13:50:57 -0700579 Hosts in hostList will do a single ping to a non-existent address for ONOS to
580 discover them. A host will use ping/ping6 to send echo requests depending on if
581 it has IPv4/IPv6 addresses configured.
582 Optional:
583 hostList: a list of names of the hosts that need to be discovered. If not
584 specified mininet will send ping from all the hosts
585 wait: timeout for IPv4/IPv6 echo requests
586 dstIp: destination address used by IPv4 hosts
587 dstIp6: destination address used by IPv6 hosts
588 Returns:
589 main.TRUE if all ping packets were successfully sent. Otherwise main.FALSE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700590 '''
591 try:
You Wang48381752018-05-07 13:50:57 -0700592 if not hostList:
593 hosts = self.getHosts( getInterfaces=False )
594 hostList = hosts.keys()
595 discoveryResult = main.TRUE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700596 for host in hostList:
You Wang48381752018-05-07 13:50:57 -0700597 cmd = ""
598 if self.getIPAddress( host ):
599 cmd = "{} ping -c 1 -i 1 -W {} {}".format( host, wait, dstIp )
600 main.log.debug( "Sending IPv4 probe ping from host {}".format( host ) )
601 elif self.getIPAddress( host, proto='IPV6' ):
602 cmd = "{} ping6 -c 1 -i 1 -W {} {}".format( host, wait, dstIp6 )
603 main.log.debug( "Sending IPv6 probe ping from host {}".format( host ) )
604 else:
605 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
606 discoveryResult = main.FALSE
607 if cmd:
608 self.handle.sendline( cmd )
609 self.handle.expect( "mininet>", timeout=wait + 1 )
610 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700611 except pexpect.TIMEOUT:
612 main.log.exception( self.name + ": TIMEOUT exception" )
613 response = self.handle.before
614 # NOTE: Send ctrl-c to make sure command is stopped
615 self.handle.send( "\x03" )
616 self.handle.expect( "Interrupt" )
617 response += self.handle.before + self.handle.after
618 self.handle.expect( "mininet>" )
619 response += self.handle.before + self.handle.after
620 main.log.debug( response )
621 return main.FALSE
622 except pexpect.EOF:
623 main.log.error( self.name + ": EOF exception found" )
624 main.log.error( self.name + ": " + self.handle.before )
625 main.cleanAndExit()
626 except Exception:
627 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800628 main.cleanAndExit()
629
630 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
631 """
632 Verify ping from each host in srcList to each host in dstList
633
634 acceptableFailed: max number of acceptable failed pings
635
636 Returns main.TRUE if all src hosts can reach all dst hosts
637 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
638 """
639 try:
640 main.log.info( "Verifying ping from each src host to each dst host" )
641 isReachable = main.TRUE
642 wait = int( wait )
643 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
644 pingResponse = "Ping output:\n"
645 failedPingsTotal = 0
646 for host in srcList:
647 pingResponse += str( str( host ) + " -> " )
648 for temp in dstList:
649 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700650 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
651 assert dstIP, "Not able to get IP address of host {}".format( temp )
652 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800653 while failedPings <= acceptableFailed:
654 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
655 self.handle.sendline( pingCmd )
656 self.handle.expect( "mininet>", timeout=wait + 1 )
657 response = self.handle.before
658 if re.search( ',\s0\%\spacket\sloss', response ):
659 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800660 break
661 else:
662 failedPings += 1
663 time.sleep(1)
664 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700665 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800666 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700667 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800668 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700669 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800670 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700671 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700672 except AssertionError:
673 main.log.exception( "" )
674 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700675 except pexpect.TIMEOUT:
676 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800677 response = self.handle.before
678 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700679 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800680 self.handle.expect( "Interrupt" )
681 response += self.handle.before + self.handle.after
682 self.handle.expect( "mininet>" )
683 response += self.handle.before + self.handle.after
684 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700685 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700686 except pexpect.EOF:
687 main.log.error( self.name + ": EOF exception found" )
688 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700689 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700690 except Exception:
691 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700692 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700693
Jon Hall7eb38402015-01-08 17:19:54 -0800694 def pingHost( self, **pingParams ):
695 """
Jon Hall3b489db2015-10-05 14:38:37 -0700696 Ping from one mininet host to another
697 Currently the only supported Params: SRC, TARGET, and WAIT
698 """
699 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700700 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700701 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800702 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700703 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700704 try:
Jon Hall61282e32015-03-19 11:34:11 -0700705 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800706 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700707 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
708 timeout=wait + 1 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700709 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800710 main.log.error(
711 self.name +
712 ": timeout when waiting for response from mininet" )
713 main.log.error( "response: " + str( self.handle.before ) )
714 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700715 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800716 main.log.error(
717 self.name +
718 ": timeout when waiting for response from mininet" )
719 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700720 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700721 if re.search( ',\s0\%\spacket\sloss', response ):
722 main.log.info( self.name + ": no packets lost, host is reachable" )
723 return main.TRUE
724 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800725 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700726 self.name +
727 ": PACKET LOST, HOST IS NOT REACHABLE" )
728 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800729 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800730 main.log.error( self.name + ": EOF exception found" )
731 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700732 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700733 except Exception:
734 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700735 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700736
737 def ping6pair( self, **pingParams ):
738 """
GlennRC2cf7d952015-09-11 16:32:13 -0700739 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700740 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000741 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700742 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
743 """
Jon Hall3b489db2015-10-05 14:38:37 -0700744 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700745 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700746 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530747 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700748 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700749 try:
750 main.log.info( "Sending: " + command )
751 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700752 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
753 timeout=wait + 1 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700754 if i == 1:
755 main.log.error(
756 self.name +
757 ": timeout when waiting for response from mininet" )
758 main.log.error( "response: " + str( self.handle.before ) )
759 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
760 if i == 1:
761 main.log.error(
762 self.name +
763 ": timeout when waiting for response from mininet" )
764 main.log.error( "response: " + str( self.handle.before ) )
765 response = self.handle.before
766 main.log.info( self.name + ": Ping Response: " + response )
767 if re.search( ',\s0\%\spacket\sloss', response ):
768 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700769 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700770 else:
alisone4121a92016-11-22 16:31:36 -0800771 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700772 self.name +
773 ": PACKET LOST, HOST IS NOT REACHABLE" )
774 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700775 except pexpect.EOF:
776 main.log.error( self.name + ": EOF exception found" )
777 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700778 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700779 except Exception:
780 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700781 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800782
You Wangdb927a52016-02-26 11:03:28 -0800783 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
784 """
785 Description:
786 Ping a set of destination host from host CLI.
787 Logging into a Mininet host CLI is required before calling this funtion.
788 Params:
789 dstIPList is a list of destination ip addresses
790 Returns:
791 main.TRUE if the destination host is reachable
792 main.FALSE otherwise
793 """
794 isReachable = main.TRUE
795 wait = int( wait )
796 cmd = "ping"
797 if IPv6:
798 cmd = cmd + "6"
799 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
800 try:
801 for dstIP in dstIPList:
802 pingCmd = cmd + " " + dstIP
803 self.handle.sendline( pingCmd )
804 i = self.handle.expect( [ self.hostPrompt,
805 '\*\*\* Unknown command: ' + pingCmd,
806 pexpect.TIMEOUT ],
807 timeout=wait + 1 )
You Wang5da39c82018-04-26 22:55:08 -0700808 # For some reason we need to send something
809 # Otherwise ping results won't be read by handle
810 self.handle.sendline( "" )
811 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800812 if i == 0:
813 response = self.handle.before
814 if not re.search( ',\s0\%\spacket\sloss', response ):
815 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
816 isReachable = main.FALSE
817 elif i == 1:
818 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700819 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800820 elif i == 2:
821 main.log.error( self.name + ": timeout when waiting for response" )
822 isReachable = main.FALSE
823 else:
824 main.log.error( self.name + ": unknown response: " + self.handle.before )
825 isReachable = main.FALSE
826 except pexpect.TIMEOUT:
827 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800828 response = self.handle.before
829 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700830 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800831 self.handle.expect( "Interrupt" )
832 response += self.handle.before + self.handle.after
833 self.handle.expect( "mininet>" )
834 response += self.handle.before + self.handle.after
835 main.log.debug( response )
You Wangdb927a52016-02-26 11:03:28 -0800836 isReachable = main.FALSE
837 except pexpect.EOF:
838 main.log.error( self.name + ": EOF exception found" )
839 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700840 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800841 except Exception:
842 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700843 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800844 return isReachable
845
Jon Hall7eb38402015-01-08 17:19:54 -0800846 def checkIP( self, host ):
847 """
848 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700849 try:
850 if self.handle:
851 try:
852 response = self.execute(
853 cmd=host +
854 " ifconfig",
855 prompt="mininet>",
856 timeout=10 )
857 except pexpect.EOF:
858 main.log.error( self.name + ": EOF exception found" )
859 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700860 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700861
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700862 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
863 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
864 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
865 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
866 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
867 "[0-9]|25[0-5]|[0-9]{1,2})"
868 # pattern = "inet addr:10.0.0.6"
869 if re.search( pattern, response ):
870 main.log.info( self.name + ": Host Ip configured properly" )
871 return main.TRUE
872 else:
873 main.log.error( self.name + ": Host IP not found" )
874 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700875 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700876 main.log.error( self.name + ": Connection failed to the host" )
877 except Exception:
878 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700879 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800880
Jon Hall7eb38402015-01-08 17:19:54 -0800881 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800882 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700883 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800884 response = self.execute(
885 cmd="h1 /usr/sbin/sshd -D&",
886 prompt="mininet>",
887 timeout=10 )
888 response = self.execute(
889 cmd="h4 /usr/sbin/sshd -D&",
890 prompt="mininet>",
891 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700892 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800893 vars( self )[ key ] = connectargs[ key ]
894 response = self.execute(
895 cmd="xterm h1 h4 ",
896 prompt="mininet>",
897 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800898 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800899 main.log.error( self.name + ": EOF exception found" )
900 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700901 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700902 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800903 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700904 if self.flag == 0:
905 self.flag = 1
906 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800907 else:
adminbae64d82013-08-01 10:50:15 -0700908 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800909
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700910 def moveHost( self, host, oldSw, newSw ):
Jon Hall53c5e662016-04-13 16:06:56 -0700911 """
912 Moves a host from one switch to another on the fly
913 Note: The intf between host and oldSw when detached
914 using detach(), will still show up in the 'net'
915 cmd, because switch.detach() doesn't affect switch.intfs[]
916 ( which is correct behavior since the interfaces
917 haven't moved ).
918 """
919 if self.handle:
920 try:
921 # Bring link between oldSw-host down
922 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
923 "'," + "'down')"
924 print "cmd1= ", cmd
925 response = self.execute( cmd=cmd,
926 prompt="mininet>",
927 timeout=10 )
928
929 # Determine hostintf and Oldswitchintf
930 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
931 ")[0]"
932 print "cmd2= ", cmd
933 self.handle.sendline( cmd )
934 self.handle.expect( "mininet>" )
935
936 # Determine ip and mac address of the host-oldSw interface
937 cmd = "px ipaddr = hintf.IP()"
938 print "cmd3= ", cmd
939 self.handle.sendline( cmd )
940 self.handle.expect( "mininet>" )
941
942 cmd = "px macaddr = hintf.MAC()"
943 print "cmd3= ", cmd
944 self.handle.sendline( cmd )
945 self.handle.expect( "mininet>" )
946
947 # Detach interface between oldSw-host
948 cmd = "px " + oldSw + ".detach( sintf )"
949 print "cmd4= ", cmd
950 self.handle.sendline( cmd )
951 self.handle.expect( "mininet>" )
952
953 # Add link between host-newSw
954 cmd = "py net.addLink(" + host + "," + newSw + ")"
955 print "cmd5= ", cmd
956 self.handle.sendline( cmd )
957 self.handle.expect( "mininet>" )
958
959 # Determine hostintf and Newswitchintf
960 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
961 ")[0]"
962 print "cmd6= ", cmd
963 self.handle.sendline( cmd )
964 self.handle.expect( "mininet>" )
965
966 # Attach interface between newSw-host
967 cmd = "px " + newSw + ".attach( sintf )"
968 print "cmd3= ", cmd
969 self.handle.sendline( cmd )
970 self.handle.expect( "mininet>" )
971
972 # Set ipaddress of the host-newSw interface
973 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
974 print "cmd7 = ", cmd
975 self.handle.sendline( cmd )
976 self.handle.expect( "mininet>" )
977
978 # Set macaddress of the host-newSw interface
979 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
980 print "cmd8 = ", cmd
981 self.handle.sendline( cmd )
982 self.handle.expect( "mininet>" )
983
984 cmd = "net"
985 print "cmd9 = ", cmd
986 self.handle.sendline( cmd )
987 self.handle.expect( "mininet>" )
988 print "output = ", self.handle.before
989
990 # Determine ipaddress of the host-newSw interface
991 cmd = host + " ifconfig"
992 print "cmd10= ", cmd
993 self.handle.sendline( cmd )
994 self.handle.expect( "mininet>" )
995 print "ifconfig o/p = ", self.handle.before
996
997 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700998
999 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001000 main.log.error( self.name + ": TIMEOUT exception found" )
1001 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001002 main.cleanAndExit()
Jon Hall53c5e662016-04-13 16:06:56 -07001003 except pexpect.EOF:
1004 main.log.error( self.name + ": EOF exception found" )
1005 main.log.error( self.name + ": " + self.handle.before )
1006 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001007 except Exception:
1008 main.log.exception( self.name + ": Uncaught exception!" )
1009 return main.FALSE
Jon Hall53c5e662016-04-13 16:06:56 -07001010
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001011 def moveHostv6( self, host, oldSw, newSw ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001012 """
1013 Moves a host from one switch to another on the fly
1014 Note: The intf between host and oldSw when detached
1015 using detach(), will still show up in the 'net'
1016 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -07001017 ( which is correct behavior since the interfaces
1018 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -08001019 """
1020 if self.handle:
1021 try:
Jon Hall439c8912016-04-15 02:22:03 -07001022 IP = str( self.getIPAddress( host, proto='IPV6' ) ) + "/64"
kelvin-onlaba1484582015-02-02 15:46:20 -08001023 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -07001024 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -08001025 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -08001026 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -08001027 response = self.execute( cmd=cmd,
1028 prompt="mininet>",
1029 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -07001030
kelvin-onlaba1484582015-02-02 15:46:20 -08001031 # Determine hostintf and Oldswitchintf
1032 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -08001033 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -08001034 print "cmd2= ", cmd
1035 self.handle.sendline( cmd )
1036 self.handle.expect( "mininet>" )
1037
shahshreya73537862015-02-11 15:15:24 -08001038 # Determine ip and mac address of the host-oldSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001039 cmd = "px ipaddr = " + str( IP )
kelvin-onlaba1484582015-02-02 15:46:20 -08001040 print "cmd3= ", cmd
1041 self.handle.sendline( cmd )
1042 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -08001043
1044 cmd = "px macaddr = hintf.MAC()"
1045 print "cmd3= ", cmd
1046 self.handle.sendline( cmd )
1047 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001048
kelvin-onlaba1484582015-02-02 15:46:20 -08001049 # Detach interface between oldSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001050 cmd = "px " + oldSw + ".detach(sintf)"
kelvin-onlaba1484582015-02-02 15:46:20 -08001051 print "cmd4= ", cmd
1052 self.handle.sendline( cmd )
1053 self.handle.expect( "mininet>" )
1054
1055 # Add link between host-newSw
1056 cmd = "py net.addLink(" + host + "," + newSw + ")"
1057 print "cmd5= ", cmd
1058 self.handle.sendline( cmd )
1059 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001060
kelvin-onlaba1484582015-02-02 15:46:20 -08001061 # Determine hostintf and Newswitchintf
1062 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -08001063 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -08001064 print "cmd6= ", cmd
1065 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -07001066 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001067
1068 # Attach interface between newSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001069 cmd = "px " + newSw + ".attach(sintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001070 print "cmd6= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001071 self.handle.sendline( cmd )
1072 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -08001073
1074 # Set macaddress of the host-newSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001075 cmd = "px " + host + ".setMAC(mac = macaddr, intf = hintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001076 print "cmd7 = ", cmd
1077 self.handle.sendline( cmd )
1078 self.handle.expect( "mininet>" )
1079
1080 # Set ipaddress of the host-newSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001081 cmd = "px " + host + ".setIP(ip = ipaddr, intf = hintf)"
shahshreya73537862015-02-11 15:15:24 -08001082 print "cmd8 = ", cmd
1083 self.handle.sendline( cmd )
1084 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001085
Jon Hall439c8912016-04-15 02:22:03 -07001086 cmd = host + " ifconfig"
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001087 print "cmd9 =", cmd
1088 response = self.execute( cmd = cmd, prompt="mininet>", timeout=10 )
Jon Hall439c8912016-04-15 02:22:03 -07001089 print response
1090 pattern = "h\d-eth([\w])"
Jeremyd9e4eb12016-04-13 12:09:06 -07001091 ipAddressSearch = re.search( pattern, response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001092 print ipAddressSearch.group( 1 )
1093 intf = host + "-eth" + str( ipAddressSearch.group( 1 ) )
Jon Hall439c8912016-04-15 02:22:03 -07001094 cmd = host + " ip -6 addr add %s dev %s" % ( IP, intf )
1095 print "cmd10 = ", cmd
1096 self.handle.sendline( cmd )
1097 self.handle.expect( "mininet>" )
1098
kelvin-onlaba1484582015-02-02 15:46:20 -08001099 cmd = "net"
Jon Hall439c8912016-04-15 02:22:03 -07001100 print "cmd11 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001101 self.handle.sendline( cmd )
1102 self.handle.expect( "mininet>" )
1103 print "output = ", self.handle.before
1104
1105 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -08001106 cmd = host + " ifconfig"
Jon Hall439c8912016-04-15 02:22:03 -07001107 print "cmd12= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001108 self.handle.sendline( cmd )
1109 self.handle.expect( "mininet>" )
1110 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -07001111
kelvin-onlaba1484582015-02-02 15:46:20 -08001112 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001113 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001114 main.log.error( self.name + ": TIMEOUT exception found" )
1115 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001116 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08001117 except pexpect.EOF:
1118 main.log.error( self.name + ": EOF exception found" )
1119 main.log.error( self.name + ": " + self.handle.before )
1120 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001121 except Exception:
1122 main.log.exception( self.name + ": Uncaught exception!" )
1123 return main.FALSE
kelvin-onlaba1484582015-02-02 15:46:20 -08001124
Jon Hall7eb38402015-01-08 17:19:54 -08001125 def changeIP( self, host, intf, newIP, newNetmask ):
1126 """
1127 Changes the ip address of a host on the fly
1128 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001129 if self.handle:
1130 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001131 cmd = host + " ifconfig " + intf + " " + \
1132 newIP + " " + 'netmask' + " " + newNetmask
1133 self.handle.sendline( cmd )
1134 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001135 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001136 main.log.info( "response = " + response )
1137 main.log.info(
1138 "Ip of host " +
1139 host +
1140 " changed to new IP " +
1141 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -08001142 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001143 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001144 main.log.error( self.name + ": TIMEOUT exception found" )
1145 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001146 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -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 )
shahshreyae6c7cf42014-11-26 16:39:01 -08001150 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001151 except Exception:
1152 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001153 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001154
Jon Hall7eb38402015-01-08 17:19:54 -08001155 def changeDefaultGateway( self, host, newGW ):
1156 """
1157 Changes the default gateway of a host
1158 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001159 if self.handle:
1160 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001161 cmd = host + " route add default gw " + newGW
1162 self.handle.sendline( cmd )
1163 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001164 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001165 main.log.info( "response = " + response )
1166 main.log.info(
1167 "Default gateway of host " +
1168 host +
1169 " changed to " +
1170 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -08001171 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001172 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001173 main.log.error( self.name + ": TIMEOUT exception found" )
1174 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001175 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001176 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001177 main.log.error( self.name + ": EOF exception found" )
1178 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001179 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001180 except Exception:
1181 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001182 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001183
You Wange24d6272018-03-27 21:18:50 -07001184 def addRoute( self, host, dstIP, interface, ipv6=False ):
1185 """
1186 Add a route to host
1187 Ex: h1 route add -host 224.2.0.1 h1-eth0
1188 """
1189 if self.handle:
1190 try:
1191 cmd = str( host )
1192 if ipv6:
1193 cmd += " route -A inet6 add "
1194 else:
1195 cmd += " route add -host "
1196 cmd += str( dstIP ) + " " + str( interface )
1197 self.handle.sendline( cmd )
1198 self.handle.expect( "mininet>" )
1199 response = self.handle.before
1200 main.log.debug( "response = " + response )
1201 return main.TRUE
1202 except pexpect.TIMEOUT:
1203 main.log.error( self.name + ": TIMEOUT exception found" )
1204 main.log.error( self.name + ": " + self.handle.before )
1205 main.cleanAndExit()
1206 except pexpect.EOF:
1207 main.log.error( self.name + ": EOF exception found" )
1208 main.log.error( self.name + ": " + self.handle.before )
1209 return main.FALSE
1210 except Exception:
1211 main.log.exception( self.name + ": Uncaught exception!" )
1212 main.cleanAndExit()
1213
Jon Hall7eb38402015-01-08 17:19:54 -08001214 def addStaticMACAddress( self, host, GW, macaddr ):
1215 """
Jon Hallefbd9792015-03-05 16:11:36 -08001216 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001217 if self.handle:
1218 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001219 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1220 cmd = host + " arp -s " + GW + " " + macaddr
1221 self.handle.sendline( cmd )
1222 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001223 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001224 main.log.info( "response = " + response )
1225 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001226 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001227 GW +
1228 " changed to " +
1229 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001230 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001231 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001232 main.log.error( self.name + ": TIMEOUT exception found" )
1233 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001234 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001235 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001236 main.log.error( self.name + ": EOF exception found" )
1237 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001238 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001239 except Exception:
1240 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001241 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001242
Jon Hall7eb38402015-01-08 17:19:54 -08001243 def verifyStaticGWandMAC( self, host ):
1244 """
1245 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001246 if self.handle:
1247 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001248 # h1 arp -an
1249 cmd = host + " arp -an "
1250 self.handle.sendline( cmd )
1251 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001252 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001253 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001254 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001255 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001256 main.log.error( self.name + ": TIMEOUT exception found" )
1257 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001258 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001259 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001260 main.log.error( self.name + ": EOF exception found" )
1261 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001262 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001263 except Exception:
1264 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001265 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001266
Jon Hall7eb38402015-01-08 17:19:54 -08001267 def getMacAddress( self, host ):
1268 """
1269 Verifies the host's ip configured or not."""
1270 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001271 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001272 response = self.execute(
1273 cmd=host +
1274 " ifconfig",
1275 prompt="mininet>",
1276 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001277 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001278 main.log.error( self.name + ": EOF exception found" )
1279 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001280 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001281 except Exception:
1282 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001283 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001284
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001285 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001286 macAddressSearch = re.search( pattern, response, re.I )
1287 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001288 main.log.info(
1289 self.name +
1290 ": Mac-Address of Host " +
1291 host +
1292 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001293 macAddress )
1294 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001295 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001296 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001297
Jon Hall7eb38402015-01-08 17:19:54 -08001298 def getInterfaceMACAddress( self, host, interface ):
1299 """
1300 Return the IP address of the interface on the given host"""
1301 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001302 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001303 response = self.execute( cmd=host + " ifconfig " + interface,
1304 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001305 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001306 main.log.error( self.name + ": EOF exception found" )
1307 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001308 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001309 except Exception:
1310 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001311 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001312
1313 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001314 macAddressSearch = re.search( pattern, response, re.I )
1315 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001316 main.log.info( "No mac address found in %s" % response )
1317 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001318 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001319 main.log.info(
1320 "Mac-Address of " +
1321 host +
1322 ":" +
1323 interface +
1324 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001325 macAddress )
1326 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001327 else:
1328 main.log.error( "Connection failed to the host" )
1329
You Wang5da39c82018-04-26 22:55:08 -07001330 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001331 """
1332 Verifies the host's ip configured or not."""
1333 if self.handle:
1334 try:
1335 response = self.execute(
1336 cmd=host +
1337 " ifconfig",
1338 prompt="mininet>",
1339 timeout=10 )
1340 except pexpect.EOF:
1341 main.log.error( self.name + ": EOF exception found" )
1342 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001343 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001344 except Exception:
1345 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001346 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001347
sathishmad953462015-12-03 17:42:07 +05301348 pattern = ''
1349 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001350 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301351 else:
Jon Hall439c8912016-04-15 02:22:03 -07001352 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001353 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001354 if not ipAddressSearch:
1355 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001356 main.log.info(
1357 self.name +
1358 ": IP-Address of Host " +
1359 host +
1360 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001361 ipAddressSearch.group( 1 ) )
1362 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001363 else:
1364 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001365
Jon Hall7eb38402015-01-08 17:19:54 -08001366 def getSwitchDPID( self, switch ):
1367 """
1368 return the datapath ID of the switch"""
1369 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001370 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001371 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001372 response = self.execute(
1373 cmd=cmd,
1374 prompt="mininet>",
1375 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001376 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001377 main.log.error( self.name + ": EOF exception found" )
1378 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001379 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001380 except Exception:
1381 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001382 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001383 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001384 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001385 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001386 main.log.info(
1387 "Couldn't find DPID for switch %s, found: %s" %
1388 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001389 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001390 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001391 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001392 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001393
Jon Hall7eb38402015-01-08 17:19:54 -08001394 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001395 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001396 self.handle.sendline( "" )
1397 self.expect( "mininet>" )
1398 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001399 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001400 response = self.execute(
1401 cmd=cmd,
1402 prompt="mininet>",
1403 timeout=10 )
1404 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001405 response = self.handle.before
1406 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001407 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001408 main.log.error( self.name + ": TIMEOUT exception found" )
1409 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001410 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001411 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001412 main.log.error( self.name + ": EOF exception found" )
1413 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001414 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001415 except Exception:
1416 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001417 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001418
Jon Hall7eb38402015-01-08 17:19:54 -08001419 def getInterfaces( self, node ):
1420 """
1421 return information dict about interfaces connected to the node"""
1422 if self.handle:
1423 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001424 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001425 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001426 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001427 response = self.execute(
1428 cmd=cmd,
1429 prompt="mininet>",
1430 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001431 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001432 main.log.error( self.name + ": EOF exception found" )
1433 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001434 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001435 except Exception:
1436 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001437 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001438 return response
1439 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001440 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001441
Jon Hall7eb38402015-01-08 17:19:54 -08001442 def dump( self ):
1443 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001444 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001445 response = self.execute(
1446 cmd='dump',
1447 prompt='mininet>',
1448 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001449 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001450 main.log.error( self.name + ": EOF exception found" )
1451 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001452 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001453 except Exception:
1454 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001455 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001456 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001457
Jon Hall7eb38402015-01-08 17:19:54 -08001458 def intfs( self ):
1459 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001460 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001461 response = self.execute(
1462 cmd='intfs',
1463 prompt='mininet>',
1464 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001465 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001466 main.log.error( self.name + ": EOF exception found" )
1467 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001468 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001469 except Exception:
1470 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001471 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001472 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001473
Jon Hall7eb38402015-01-08 17:19:54 -08001474 def net( self ):
1475 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001476 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001477 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001478 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001479 main.log.error( self.name + ": EOF exception found" )
1480 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001481 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001482 except Exception:
1483 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001484 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001485 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001486
Devin Lima7cfdbd2017-09-29 15:02:22 -07001487 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001488 main.log.info( self.name + ": List network links" )
1489 try:
1490 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001491 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001492 except pexpect.EOF:
1493 main.log.error( self.name + ": EOF exception found" )
1494 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001495 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001496 except Exception:
1497 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001498 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001499 return response
1500
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001501 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001502 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001503 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001504
kelvin-onlab7cce9382015-07-17 10:21:03 -07001505 @parm:
1506 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1507 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001508 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001509 try:
1510 for host1 in hosts:
1511 for host2 in hosts:
1512 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001513 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1514 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001515 except Exception:
1516 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001517 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001518
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001519 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001520 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001521 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1522 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001523
kelvin-onlab7cce9382015-07-17 10:21:03 -07001524 @parm:
1525 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1526 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001527 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001528 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1529 try:
1530 # Setup the mininet command
1531 cmd1 = 'iperf ' + host1 + " " + host2
1532 self.handle.sendline( cmd1 )
1533 outcome = self.handle.expect( "mininet>", timeout )
1534 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001535
kelvin-onlab7cce9382015-07-17 10:21:03 -07001536 # checks if there are results in the mininet response
1537 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001538 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001539 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001540 response = response.split( "\r\n" )
1541 response = response[ len( response )-2 ]
1542 response = response.split( ": " )
1543 response = response[ len( response )-1 ]
1544 response = response.replace( "[", "" )
1545 response = response.replace( "]", "" )
1546 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001547
kelvin-onlab7cce9382015-07-17 10:21:03 -07001548 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001549 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001550
kelvin-onlab7cce9382015-07-17 10:21:03 -07001551 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001552 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001553 if len( bandwidth ) == 2:
1554 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001555 return main.TRUE
1556 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001557 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001558 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001559 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001560 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001561 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001562 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001563 main.log.error( self.name + ": TIMEOUT exception found" )
1564 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001565 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001566 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001567 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001568 self.handle.expect( "Interrupt" )
1569 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001570 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001571 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001572 main.log.error( self.name + ": EOF exception found" )
1573 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001574 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001575 except Exception:
1576 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001577 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001578
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001579 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001580 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1581 try:
1582 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001583 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001584 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001585 outcome1 = self.handle.expect( "mininet>" )
1586 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001587 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001588 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001589 response1 = self.handle.before
1590 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001591 print response1, response2
1592 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001593 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001594 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001595 return main.TRUE
1596 else:
1597 main.log.error( self.name + ": iperf test failed" )
1598 return main.FALSE
1599 except pexpect.TIMEOUT:
1600 main.log.error( self.name + ": TIMEOUT exception found" )
1601 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001602 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001603 self.handle.expect( "Interrupt" )
1604 self.handle.expect( "mininet>" )
1605 return main.FALSE
1606 except pexpect.EOF:
1607 main.log.error( self.name + ": EOF exception found" )
1608 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001609 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001610 except Exception:
1611 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001612 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001613
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001614 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001615 '''
GlennRC61321f22015-07-16 13:36:54 -07001616 Runs the iperfudp function with a given set of hosts and specified
1617 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001618
GlennRC61321f22015-07-16 13:36:54 -07001619 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001620 bandwidth: the targeted bandwidth, in megabits ('M')
1621 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001622 try:
1623 for host1 in hosts:
1624 for host2 in hosts:
1625 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001626 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1627 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001628 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001629 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001630 return main.FALSE
1631 except Exception:
1632 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001633 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001634
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001635 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001636 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001637 Creates an iperf UDP test with a specific bandwidth.
1638 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001639
kelvin-onlab7cce9382015-07-17 10:21:03 -07001640 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001641 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1642 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001643 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001644 try:
1645 # setup the mininet command
1646 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001647 self.handle.sendline( cmd )
1648 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001649 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001650
kelvin-onlab7cce9382015-07-17 10:21:03 -07001651 # check if there are in results in the mininet response
1652 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001653 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001654 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001655 response = response.split( "\r\n" )
1656 response = response[ len( response )-2 ]
1657 response = response.split( ": " )
1658 response = response[ len( response )-1 ]
1659 response = response.replace( "[", "" )
1660 response = response.replace( "]", "" )
1661 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001662
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001663 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001664
kelvin-onlab7cce9382015-07-17 10:21:03 -07001665 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001666 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001667 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001668 # if one entry is blank then something is wrong
1669 for item in mnBandwidth:
1670 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001671 main.log.error( self.name + ": Could not parse iperf output" )
1672 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001673 return main.FALSE
1674 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001675 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001676 return main.TRUE
1677 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001678 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001679 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001680
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001681 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001682 main.log.error( self.name + ": TIMEOUT exception found" )
1683 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001684 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001685 except pexpect.EOF:
1686 main.log.error( self.name + ": EOF exception found" )
1687 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001688 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001689 except Exception:
1690 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001691 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001692
Jon Hall7eb38402015-01-08 17:19:54 -08001693 def nodes( self ):
1694 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001695 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001696 response = self.execute(
1697 cmd='nodes',
1698 prompt='mininet>',
1699 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001700 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001701 main.log.error( self.name + ": EOF exception found" )
1702 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001703 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001704 except Exception:
1705 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001706 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001707 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001708
Jon Hall7eb38402015-01-08 17:19:54 -08001709 def pingpair( self ):
1710 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001711 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001712 response = self.execute(
1713 cmd='pingpair',
1714 prompt='mininet>',
1715 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001716 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001717 main.log.error( self.name + ": EOF exception found" )
1718 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001719 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001720 except Exception:
1721 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001722 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001723
Jon Hall7eb38402015-01-08 17:19:54 -08001724 if re.search( ',\s0\%\spacket\sloss', response ):
1725 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001726 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001727 else:
alisone4121a92016-11-22 16:31:36 -08001728 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001729 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001730
Jon Hall7eb38402015-01-08 17:19:54 -08001731 def link( self, **linkargs ):
1732 """
GlennRCed771242016-01-13 17:02:47 -08001733 Bring link( s ) between two nodes up or down
1734 """
Jon Hall6094a362014-04-11 14:46:56 -07001735 try:
GlennRCed771242016-01-13 17:02:47 -08001736 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1737 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1738 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1739 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1740
1741 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1742 cmd = "link {} {} {}".format( end1, end2, option )
1743 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001744 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001745 response = self.handle.before
1746 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001747 if "not in network" in response:
1748 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1749 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001750 return main.TRUE
1751 except pexpect.TIMEOUT:
1752 main.log.exception( self.name + ": Command timed out" )
1753 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001754 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001755 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001756 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001757 except Exception:
1758 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001759 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001760
pingping-lin8244a3b2015-09-16 13:36:56 -07001761 def switch( self, **switchargs ):
1762 """
1763 start/stop a switch
1764 """
1765 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1766 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1767 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1768 command = "switch " + str( sw ) + " " + str( option )
1769 main.log.info( command )
1770 try:
1771 self.handle.sendline( command )
1772 self.handle.expect( "mininet>" )
1773 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001774 main.log.error( self.name + ": TIMEOUT exception found" )
1775 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001776 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001777 except pexpect.EOF:
1778 main.log.error( self.name + ": EOF exception found" )
1779 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001780 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001781 return main.TRUE
1782
pingping-lin5bb663b2015-09-24 11:47:50 -07001783 def node( self, nodeName, commandStr ):
1784 """
1785 Carry out a command line on a given node
1786 @parm:
1787 nodeName: the node name in Mininet testbed
1788 commandStr: the command line will be carried out on the node
1789 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1790 """
1791 command = str( nodeName ) + " " + str( commandStr )
1792 main.log.info( command )
1793
1794 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001795 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001796 if re.search( "Unknown command", response ):
1797 main.log.warn( response )
1798 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001799 if re.search( "Permission denied", response ):
1800 main.log.warn( response )
1801 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001802 except pexpect.EOF:
1803 main.log.error( self.name + ": EOF exception found" )
1804 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001805 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001806 main.log.info( " response is :" )
1807 main.log.info( response )
1808 return response
1809
Jon Hall7eb38402015-01-08 17:19:54 -08001810 def yank( self, **yankargs ):
1811 """
1812 yank a mininet switch interface to a host"""
1813 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001814 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001815 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1816 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001817 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001818 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001819 response = self.execute(
1820 cmd=command,
1821 prompt="mininet>",
1822 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001823 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001824 main.log.error( self.name + ": EOF exception found" )
1825 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001826 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001827 except Exception:
1828 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001829 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001830 return main.TRUE
1831
Jon Hall7eb38402015-01-08 17:19:54 -08001832 def plug( self, **plugargs ):
1833 """
1834 plug the yanked mininet switch interface to a switch"""
1835 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001836 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001837 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1838 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001839 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001840 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001841 response = self.execute(
1842 cmd=command,
1843 prompt="mininet>",
1844 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001845 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001846 main.log.error( self.name + ": EOF exception found" )
1847 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001848 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001849 except Exception:
1850 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001851 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001852 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001853
Jon Hall7eb38402015-01-08 17:19:54 -08001854 def dpctl( self, **dpctlargs ):
1855 """
1856 Run dpctl command on all switches."""
1857 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001858 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001859 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1860 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1861 command = "dpctl " + cmd + " " + str( cmdargs )
1862 try:
1863 response = self.execute(
1864 cmd=command,
1865 prompt="mininet>",
1866 timeout=10 )
1867 except pexpect.EOF:
1868 main.log.error( self.name + ": EOF exception found" )
1869 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001870 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001871 except Exception:
1872 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001873 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001874 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001875
kelvin-onlabd3b64892015-01-20 13:26:24 -08001876 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001877 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001878 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001879 try:
1880 fileInput = path + '/lib/Mininet/INSTALL'
1881 version = super( Mininet, self ).getVersion()
1882 pattern = 'Mininet\s\w\.\w\.\w\w*'
1883 for line in open( fileInput, 'r' ).readlines():
1884 result = re.match( pattern, line )
1885 if result:
1886 version = result.group( 0 )
1887 return version
1888 except Exception:
1889 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001890 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001891
kelvin-onlabd3b64892015-01-20 13:26:24 -08001892 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001893 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001894 Parameters:
1895 sw: The name of an OVS switch. Example "s1"
1896 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001897 The output of the command from the mininet cli
1898 or main.FALSE on timeout"""
1899 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001900 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001901 response = self.execute(
1902 cmd=command,
1903 prompt="mininet>",
1904 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001905 if response:
Jon Hallab611372018-02-21 15:26:05 -08001906 if "no bridge named" in response:
1907 main.log.error( self.name + ": Error in getSwController: " +
1908 self.handle.before )
1909 return main.FALSE
1910 else:
1911 return response
admin2a9548d2014-06-17 14:08:07 -07001912 else:
1913 return main.FALSE
1914 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001915 main.log.error( self.name + ": EOF exception found" )
1916 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001917 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001918 except Exception:
1919 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001920 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001921
Charles Chan029be652015-08-24 01:46:10 +08001922 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001923 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001924 Description:
1925 Assign switches to the controllers ( for ovs use only )
1926 Required:
1927 sw - Name of the switch. This can be a list or a string.
1928 ip - Ip addresses of controllers. This can be a list or a string.
1929 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001930 port - ONOS use port 6653, if no list of ports is passed, then
1931 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001932 ptcp - ptcp number, This can be a string or a list that has
1933 the same length as switch. This is optional and not required
1934 when using ovs switches.
1935 NOTE: If switches and ptcp are given in a list type they should have the
1936 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1937 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001938
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001939 Return:
1940 Returns main.TRUE if mininet correctly assigned switches to
1941 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001942 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001943 """
1944 assignResult = main.TRUE
1945 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001946 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001947 command = "sh ovs-vsctl set-controller "
1948 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001949 try:
1950 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001951 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001952 if isinstance( port, types.StringType ) or \
1953 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001954 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001955 elif isinstance( port, types.ListType ):
1956 main.log.error( self.name + ": Only one controller " +
1957 "assigned and a list of ports has" +
1958 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001959 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001960 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001961 main.log.error( self.name + ": Invalid controller port " +
1962 "number. Please specify correct " +
1963 "controller port" )
1964 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001965
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001966 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001967 if isinstance( port, types.StringType ) or \
1968 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001969 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001970 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1971 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001972 elif isinstance( port, types.ListType ):
1973 if ( len( ip ) != len( port ) ):
1974 main.log.error( self.name + ": Port list = " +
1975 str( len( port ) ) +
1976 "should be the same as controller" +
1977 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001978 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001979 else:
1980 onosIp = ""
1981 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001982 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1983 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001984 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001985 main.log.error( self.name + ": Invalid controller port " +
1986 "number. Please specify correct " +
1987 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001988 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001989 else:
1990 main.log.error( self.name + ": Invalid ip address" )
1991 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001992
1993 if isinstance( sw, types.StringType ):
1994 command += sw + " "
1995 if ptcp:
1996 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001997 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001998 elif isinstance( ptcp, types.ListType ):
1999 main.log.error( self.name + ": Only one switch is " +
2000 "being set and multiple PTCP is " +
2001 "being passed " )
2002 else:
2003 main.log.error( self.name + ": Invalid PTCP" )
2004 ptcp = ""
2005 command += onosIp
2006 commandList.append( command )
2007
2008 elif isinstance( sw, types.ListType ):
2009 if ptcp:
2010 if isinstance( ptcp, types.ListType ):
2011 if len( ptcp ) != len( sw ):
2012 main.log.error( self.name + ": PTCP length = " +
2013 str( len( ptcp ) ) +
2014 " is not the same as switch" +
2015 " length = " +
2016 str( len( sw ) ) )
2017 return main.FALSE
2018 else:
2019 for switch, ptcpNum in zip( sw, ptcp ):
2020 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07002021 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07002022 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002023 tempCmd += onosIp
2024 commandList.append( tempCmd )
2025 else:
2026 main.log.error( self.name + ": Invalid PTCP" )
2027 return main.FALSE
2028 else:
2029 for switch in sw:
2030 tempCmd = "sh ovs-vsctl set-controller "
2031 tempCmd += switch + " " + onosIp
2032 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002033 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002034 main.log.error( self.name + ": Invalid switch type " )
2035 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002036
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002037 for cmd in commandList:
2038 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002039 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08002040 if "no bridge named" in self.handle.before:
2041 main.log.error( self.name + ": Error in assignSwController: " +
2042 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002043 except pexpect.TIMEOUT:
2044 main.log.error( self.name + ": pexpect.TIMEOUT found" )
2045 return main.FALSE
2046 except pexpect.EOF:
2047 main.log.error( self.name + ": EOF exception found" )
2048 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002049 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002050 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002051 except pexpect.EOF:
2052 main.log.error( self.name + ": EOF exception found" )
2053 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002054 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002055 except Exception:
2056 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002057 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07002058
kelvin-onlabd3b64892015-01-20 13:26:24 -08002059 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08002060 """
2061 Removes the controller target from sw"""
2062 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07002063 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002064 response = self.execute(
2065 cmd=command,
2066 prompt="mininet>",
2067 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08002068 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002069 main.log.error( self.name + ": EOF exception found" )
2070 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002071 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002072 except Exception:
2073 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002074 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002075 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002076 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07002077
kelvin-onlabd3b64892015-01-20 13:26:24 -08002078 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002079 """
Jon Hallb1290e82014-11-18 16:17:48 -05002080 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002081 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002082 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002083 NOTE: cannot currently specify what type of switch
2084 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08002085 sw = name of the new switch as a string
2086 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05002087 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08002088 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002089 """
2090 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002091 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05002092 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002093 response = self.execute(
2094 cmd=command,
2095 prompt="mininet>",
2096 timeout=10 )
2097 if re.search( "already exists!", response ):
2098 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002099 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002100 elif re.search( "Error", response ):
2101 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002102 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002103 elif re.search( "usage:", response ):
2104 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002105 return main.FALSE
2106 else:
2107 return main.TRUE
2108 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002109 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07002110 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002111 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002112 except Exception:
2113 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002114 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002115
kelvin-onlabd3b64892015-01-20 13:26:24 -08002116 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08002117 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08002118 delete a switch from the mininet topology
2119 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002120 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08002121 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08002122 sw = name of the switch as a string
2123 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002124 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05002125 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002126 response = self.execute(
2127 cmd=command,
2128 prompt="mininet>",
2129 timeout=10 )
2130 if re.search( "no switch named", response ):
2131 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002132 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002133 elif re.search( "Error", response ):
2134 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002135 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002136 elif re.search( "usage:", response ):
2137 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002138 return main.FALSE
2139 else:
2140 return main.TRUE
2141 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002142 main.log.error( self.name + ": EOF exception found" )
2143 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002144 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002145 except Exception:
2146 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002147 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002148
You Wangdb8cd0a2016-05-26 15:19:45 -07002149 def getSwitchRandom( self, timeout=60, nonCut=True ):
2150 """
2151 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002152 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002153 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002154 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002155 it just randomly returns one switch from all current switches in
2156 Mininet.
2157 Returns the name of the chosen switch.
2158 """
2159 import random
2160 candidateSwitches = []
2161 try:
2162 if not nonCut:
2163 switches = self.getSwitches( timeout=timeout )
2164 assert len( switches ) != 0
2165 for switchName in switches.keys():
2166 candidateSwitches.append( switchName )
2167 else:
2168 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002169 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002170 return None
2171 self.graph.update( graphDict )
2172 candidateSwitches = self.graph.getNonCutVertices()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002173 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002174 return None
2175 elif len( candidateSwitches ) == 0:
2176 main.log.info( self.name + ": No candidate switch for deletion" )
2177 return None
2178 else:
2179 switch = random.sample( candidateSwitches, 1 )
2180 return switch[ 0 ]
2181 except KeyError:
2182 main.log.exception( self.name + ": KeyError exception found" )
2183 return None
2184 except AssertionError:
2185 main.log.exception( self.name + ": AssertionError exception found" )
2186 return None
2187 except Exception:
2188 main.log.exception( self.name + ": Uncaught exception" )
2189 return None
2190
2191 def delSwitchRandom( self, timeout=60, nonCut=True ):
2192 """
2193 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002194 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002195 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002196 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002197 otherwise it just randomly delete one switch from all current
2198 switches in Mininet.
2199 Returns the name of the deleted switch
2200 """
2201 try:
2202 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002203 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002204 return None
2205 else:
2206 deletionResult = self.delSwitch( switch )
2207 if deletionResult:
2208 return switch
2209 else:
2210 return None
2211 except Exception:
2212 main.log.exception( self.name + ": Uncaught exception" )
2213 return None
2214
kelvin-onlabd3b64892015-01-20 13:26:24 -08002215 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002216 """
2217 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002218 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002219 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002220 NOTE: cannot currently specify what type of link
2221 required params:
2222 node1 = the string node name of the first endpoint of the link
2223 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002224 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002225 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002226 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002227 response = self.execute(
2228 cmd=command,
2229 prompt="mininet>",
2230 timeout=10 )
2231 if re.search( "doesnt exist!", response ):
2232 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002233 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002234 elif re.search( "Error", response ):
2235 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002236 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002237 elif re.search( "usage:", response ):
2238 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002239 return main.FALSE
2240 else:
2241 return main.TRUE
2242 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002243 main.log.error( self.name + ": EOF exception found" )
2244 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002245 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002246 except Exception:
2247 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002248 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002249
kelvin-onlabd3b64892015-01-20 13:26:24 -08002250 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002251 """
2252 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002253 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002254 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002255 required params:
2256 node1 = the string node name of the first endpoint of the link
2257 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002258 returns: main.FALSE on an error, else main.TRUE
2259 """
Jon Hallffb386d2014-11-21 13:43:38 -08002260 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002261 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002262 response = self.execute(
2263 cmd=command,
2264 prompt="mininet>",
2265 timeout=10 )
2266 if re.search( "no node named", response ):
2267 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002268 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002269 elif re.search( "Error", response ):
2270 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002271 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002272 elif re.search( "usage:", response ):
2273 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002274 return main.FALSE
2275 else:
2276 return main.TRUE
2277 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002278 main.log.error( self.name + ": EOF exception found" )
2279 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002280 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002281 except Exception:
2282 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002283 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002284
You Wangdb8cd0a2016-05-26 15:19:45 -07002285 def getLinkRandom( self, timeout=60, nonCut=True ):
2286 """
2287 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002288 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002289 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002290 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002291 it just randomly returns one link from all current links in
2292 Mininet.
2293 Returns the link as a list, e.g. [ 's1', 's2' ]
2294 """
2295 import random
2296 candidateLinks = []
2297 try:
2298 if not nonCut:
2299 links = self.getLinks( timeout=timeout )
2300 assert len( links ) != 0
2301 for link in links:
2302 # Exclude host-switch link
2303 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2304 continue
2305 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2306 else:
2307 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002308 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002309 return None
2310 self.graph.update( graphDict )
2311 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002312 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002313 return None
2314 elif len( candidateLinks ) == 0:
2315 main.log.info( self.name + ": No candidate link for deletion" )
2316 return None
2317 else:
2318 link = random.sample( candidateLinks, 1 )
2319 return link[ 0 ]
2320 except KeyError:
2321 main.log.exception( self.name + ": KeyError exception found" )
2322 return None
2323 except AssertionError:
2324 main.log.exception( self.name + ": AssertionError exception found" )
2325 return None
2326 except Exception:
2327 main.log.exception( self.name + ": Uncaught exception" )
2328 return None
2329
2330 def delLinkRandom( self, timeout=60, nonCut=True ):
2331 """
2332 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002333 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002334 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002335 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002336 otherwise it just randomly delete one link from all current links
2337 in Mininet.
2338 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2339 """
2340 try:
2341 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002342 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002343 return None
2344 else:
2345 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2346 if deletionResult:
2347 return link
2348 else:
2349 return None
2350 except Exception:
2351 main.log.exception( self.name + ": Uncaught exception" )
2352 return None
2353
kelvin-onlabd3b64892015-01-20 13:26:24 -08002354 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002355 """
Jon Hallb1290e82014-11-18 16:17:48 -05002356 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002357 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002358 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002359 NOTE: cannot currently specify what type of host
2360 required params:
2361 hostname = the string hostname
2362 optional key-value params
2363 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002364 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002365 """
2366 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002367 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002368 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002369 response = self.execute(
2370 cmd=command,
2371 prompt="mininet>",
2372 timeout=10 )
2373 if re.search( "already exists!", response ):
2374 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002375 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002376 elif re.search( "doesnt exists!", response ):
2377 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002378 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002379 elif re.search( "Error", response ):
2380 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002381 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002382 elif re.search( "usage:", response ):
2383 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002384 return main.FALSE
2385 else:
2386 return main.TRUE
2387 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002388 main.log.error( self.name + ": EOF exception found" )
2389 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002390 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002391 except Exception:
2392 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002393 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002394
kelvin-onlabd3b64892015-01-20 13:26:24 -08002395 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002396 """
2397 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002398 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002399 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002400 NOTE: this uses a custom mn function
2401 required params:
2402 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002403 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002404 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002405 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002406 response = self.execute(
2407 cmd=command,
2408 prompt="mininet>",
2409 timeout=10 )
2410 if re.search( "no host named", response ):
2411 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002412 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002413 elif re.search( "Error", response ):
2414 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002415 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002416 elif re.search( "usage:", response ):
2417 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002418 return main.FALSE
2419 else:
2420 return main.TRUE
2421 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002422 main.log.error( self.name + ": EOF exception found" )
2423 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002424 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002425 except Exception:
2426 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002427 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002428
Jon Hall7eb38402015-01-08 17:19:54 -08002429 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002430 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002431 Called at the end of the test to stop the mininet and
2432 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002433 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002434 try:
2435 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002436 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002437 timeout=2 )
2438 response = main.TRUE
2439 if i == 0:
2440 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002441 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002442 return main.TRUE
2443 # print "Disconnecting Mininet"
2444 if self.handle:
2445 self.handle.sendline( "exit" )
2446 self.handle.expect( "exit" )
2447 self.handle.expect( "(.*)" )
2448 else:
2449 main.log.error( "Connection failed to the host" )
2450 return response
2451 except pexpect.EOF:
2452 main.log.error( self.name + ": EOF exception found" )
2453 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002454 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002455 except Exception:
2456 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002457 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002458
Devin Lima7cfdbd2017-09-29 15:02:22 -07002459 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002460 """
Jon Hall21270ac2015-02-16 17:59:55 -08002461 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002462 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002463 main.FALSE if the pexpect handle does not exist.
2464
Jon Halld61331b2015-02-17 16:35:47 -08002465 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002466 """
Jon Halld61331b2015-02-17 16:35:47 -08002467 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002468 response = ''
2469 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002470 try:
Jon Halld80cc142015-07-06 13:36:05 -07002471 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002472 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002473 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002474 pexpect.EOF,
2475 pexpect.TIMEOUT ],
2476 timeout )
2477 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002478 main.log.info( "Exiting mininet.." )
2479 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002480 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002481 prompt=self.prompt,
2482 timeout=exitTimeout )
2483 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002484 self.handle.sendline( "sudo mn -c" )
2485 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002486
Jeremyd9e4eb12016-04-13 12:09:06 -07002487 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002488 main.log.info( " Mininet trying to exit while not " +
2489 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002490 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002491 elif i == 2:
2492 main.log.error( "Something went wrong exiting mininet" )
2493 elif i == 3: # timeout
2494 main.log.error( "Something went wrong exiting mininet " +
2495 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002496
You Wang18db8592018-04-02 13:52:03 -07002497 self.handle.sendline( "" )
2498 self.handle.expect( self.prompt )
2499 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2500
Hari Krishnab35c6d02015-03-18 11:13:51 -07002501 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002502 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002503 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002504 self.handle.sendline(
2505 "sudo kill -9 \`ps -ef | grep \"" +
2506 fileName +
2507 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002508 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002509 main.log.error( self.name + ": TIMEOUT exception found" )
2510 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002511 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002512 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002513 main.log.error( self.name + ": EOF exception found" )
2514 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002515 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002516 except Exception:
2517 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002518 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002519 else:
2520 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002521 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002522 return response
2523
YPZhang26a139e2016-04-25 14:01:55 -07002524 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002525 """
2526 Description:
2527 Sends arp message from mininet host for hosts discovery
2528 Required:
2529 host - hosts name
2530 Optional:
2531 ip - ip address that does not exist in the network so there would
2532 be no reply.
2533 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002534 if ethDevice:
2535 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002536 cmd = srcHost + " arping -c1 "
2537 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002538 cmd += "-w10 " # If we don't want the actural arping result, set -w10, arping will exit after 10 ms.
YPZhang26a139e2016-04-25 14:01:55 -07002539 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002540 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002541 if output:
2542 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002543 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002544 i = self.handle.expect( [ "mininet>", "arping: " ] )
2545 if i == 0:
2546 return main.TRUE
2547 elif i == 1:
2548 response = self.handle.before + self.handle.after
2549 self.handle.expect( "mininet>" )
2550 response += self.handle.before + self.handle.after
2551 main.log.warn( "Error sending arping, output was: " +
2552 response )
2553 return main.FALSE
2554 except pexpect.TIMEOUT:
2555 main.log.error( self.name + ": TIMEOUT exception found" )
2556 main.log.warn( self.handle.before )
2557 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002558 except pexpect.EOF:
2559 main.log.error( self.name + ": EOF exception found" )
2560 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002561 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002562 except Exception:
2563 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002564 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002565
Jon Hall7eb38402015-01-08 17:19:54 -08002566 def decToHex( self, num ):
2567 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002568
Jon Hall7eb38402015-01-08 17:19:54 -08002569 def getSwitchFlowCount( self, switch ):
2570 """
2571 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002572 if self.handle:
2573 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2574 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002575 response = self.execute(
2576 cmd=cmd,
2577 prompt="mininet>",
2578 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002579 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002580 main.log.error( self.name + ": EOF exception found" )
2581 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002582 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002583 except Exception:
2584 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002585 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002586 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002587 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002588 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002589 main.log.info(
2590 "Couldn't find flows on switch %s, found: %s" %
2591 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002592 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002593 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002594 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002595 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002596
Jon Hall9ed8f372016-02-24 17:34:07 -08002597 def checkFlows( self, sw, dumpFormat=None ):
2598 if dumpFormat:
2599 command = "sh ovs-ofctl -F " + \
2600 dumpFormat + " dump-flows " + str( sw )
2601 else:
2602 command = "sh ovs-ofctl dump-flows " + str( sw )
2603 try:
2604 response = self.execute(
2605 cmd=command,
2606 prompt="mininet>",
2607 timeout=10 )
2608 return response
2609 except pexpect.EOF:
2610 main.log.error( self.name + ": EOF exception found" )
2611 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002612 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002613 except Exception:
2614 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002615 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002616
GlennRC68467eb2015-11-16 18:01:01 -08002617 def flowTableComp( self, flowTable1, flowTable2 ):
2618 # This function compares the selctors and treatments of each flow
2619 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002620 assert flowTable1, "flowTable1 is empty or None"
2621 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002622 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002623 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002624 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002625 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002626 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2627 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002628 for field in dFields:
2629 try:
2630 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002631 except KeyError:
2632 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002633 try:
2634 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002635 except KeyError:
2636 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002637 for i in range( len( flowTable1 ) ):
2638 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002639 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002640 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002641 returnValue = main.FALSE
2642 break
2643 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002644 except AssertionError:
2645 main.log.exception( "Nothing to compare" )
2646 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002647 except Exception:
2648 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002649 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002650
GlennRC528ad292015-11-12 10:38:18 -08002651 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002652 '''
GlennRC956ea742015-11-05 16:14:15 -08002653 Discription: Parses flows into json format.
2654 NOTE: this can parse any string thats separated with commas
2655 Arguments:
2656 Required:
2657 flows: a list of strings that represnt flows
2658 Optional:
2659 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2660 debug: prints out the final result
2661 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002662 '''
GlennRC528ad292015-11-12 10:38:18 -08002663 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002664 try:
2665 for flow in flowTable:
2666 jsonFlow = {}
2667 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002668 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002669 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002670 for i in range( len( parsedFlow ) ):
2671 item = parsedFlow[ i ]
2672 if item[ 0 ] == " ":
2673 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002674 # grab the selector and treatment from the parsed flow
2675 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002676 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002677 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002678 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002679 index = 0
2680 # parse the flags
2681 # NOTE: This only parses one flag
2682 flag = {}
2683 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002684 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002685 index += 1
2686 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002687 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002688 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002689 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002690 # the priority is stuck in the selecter so put it back
2691 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002692 if 'priority' in sel[0]:
2693 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002694 # parse selector
2695 criteria = []
2696 for item in sel:
2697 # this is the type of the packet e.g. "arp"
2698 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002699 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002700 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002701 field = item.split( "=" )
2702 criteria.append( { field[ 0 ]: field[ 1 ] } )
2703 selector = { "selector": { "criteria": sorted( criteria ) } }
2704 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002705 # get rid of the action part e.g. "action=output:2"
2706 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002707 treat = treat.split( "=" )
2708 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002709 # parse treatment
2710 action = []
2711 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002712 if ":" in item:
2713 field = item.split( ":" )
2714 action.append( { field[ 0 ]: field[ 1 ] } )
2715 else:
2716 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2717 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002718 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002719 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002720 # parse the rest of the flow
2721 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002722 field = item.split( "=" )
2723 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002724 # add the treatment and the selector to the json flow
2725 jsonFlow.update( selector )
2726 jsonFlow.update( treatment )
2727 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002728
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002729 if debug:
2730 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002731
You Wang91c37cf2016-05-23 09:39:42 -07002732 # add the json flow to the json flow table
2733 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002734
You Wang91c37cf2016-05-23 09:39:42 -07002735 return jsonFlowTable
2736
2737 except IndexError:
2738 main.log.exception( self.name + ": IndexError found" )
2739 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002740 except pexpect.EOF:
2741 main.log.error( self.name + ": EOF exception found" )
2742 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002743 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002744 except Exception:
2745 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002746 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002747
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002748 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002749 '''
2750 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002751 Each element is a flow.
2752 Arguments:
2753 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002754 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002755 a list of switches.
2756 Optional:
2757 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2758 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002759 '''
GlennRC956ea742015-11-05 16:14:15 -08002760 try:
2761 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002762 if isinstance( sw, list ):
2763 switches.extend( sw )
2764 else:
2765 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002766
2767 flows = []
2768 for s in switches:
2769 cmd = "sh ovs-ofctl dump-flows " + s
2770
GlennRC528ad292015-11-12 10:38:18 -08002771 if "1.0" == version:
2772 cmd += " -F OpenFlow10-table_id"
2773 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002774 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002775
2776 main.log.info( "Sending: " + cmd )
2777 self.handle.sendline( cmd )
2778 self.handle.expect( "mininet>" )
2779 response = self.handle.before
2780 response = response.split( "\r\n" )
2781 # dump the first two elements and the last
2782 # the first element is the command that was sent
2783 # the second is the table header
2784 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002785 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002786 flows.extend( response )
2787
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002788 if debug:
2789 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002790
GlennRC528ad292015-11-12 10:38:18 -08002791 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002792
GlennRC956ea742015-11-05 16:14:15 -08002793 except pexpect.EOF:
2794 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002795 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002796 except Exception:
2797 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002798 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002799
2800 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002801 '''
GlennRC956ea742015-11-05 16:14:15 -08002802 Discription: Checks whether the ID provided matches a flow ID in Mininet
2803 Arguments:
2804 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002805 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002806 a list of switches.
2807 flowId: the flow ID in hex format. Can also be a list of IDs
2808 Optional:
2809 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2810 debug: prints out the final result
2811 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2812 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002813 '''
GlennRC956ea742015-11-05 16:14:15 -08002814 try:
2815 main.log.info( "Getting flows from Mininet" )
2816 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002817 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002818 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002819
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002820 if debug:
2821 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002822
2823 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002824 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002825 result = False
2826 for f in flows:
2827 if flowId in f.get( 'cookie' ):
2828 result = True
2829 break
2830 # flowId is a list
2831 else:
2832 result = True
2833 # Get flow IDs from Mininet
2834 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2835 # Save the IDs that are not in Mininet
2836 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2837
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002838 if debug:
2839 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002840
2841 # Print out the IDs that are not in Mininet
2842 if absentIds:
2843 main.log.warn( "Absent ids: {}".format( absentIds ) )
2844 result = False
2845
2846 return main.TRUE if result else main.FALSE
2847
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002848 except pexpect.EOF:
2849 main.log.error( self.name + ": EOF exception found" )
2850 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002851 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002852 except Exception:
2853 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002854 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002855
Charles Chan029be652015-08-24 01:46:10 +08002856 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002857 """
Jon Hallefbd9792015-03-05 16:11:36 -08002858 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002859 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002860 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002861 self.handle.sendline( "" )
2862 self.handle.expect( "mininet>" )
2863 self.handle.sendline(
2864 "sh sudo tcpdump -n -i " +
2865 intf +
2866 " " +
2867 port +
2868 " -w " +
2869 filename.strip() +
2870 " &" )
2871 self.handle.sendline( "" )
2872 i = self.handle.expect( [ 'No\ssuch\device',
2873 'listening\son',
2874 pexpect.TIMEOUT,
2875 "mininet>" ],
2876 timeout=10 )
2877 main.log.warn( self.handle.before + self.handle.after )
2878 self.handle.sendline( "" )
2879 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002880 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002881 main.log.error(
2882 self.name +
2883 ": tcpdump - No such device exists. " +
2884 "tcpdump attempted on: " +
2885 intf )
admin2a9548d2014-06-17 14:08:07 -07002886 return main.FALSE
2887 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002888 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002889 return main.TRUE
2890 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002891 main.log.error(
2892 self.name +
2893 ": tcpdump command timed out! Check interface name," +
2894 " given interface was: " +
2895 intf )
admin2a9548d2014-06-17 14:08:07 -07002896 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002897 elif i == 3:
2898 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002899 return main.TRUE
2900 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002901 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002902 return main.FALSE
2903 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002904 main.log.error( self.name + ": EOF exception found" )
2905 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002906 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002907 except Exception:
2908 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002909 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002910
kelvin-onlabd3b64892015-01-20 13:26:24 -08002911 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002912 """
2913 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002914 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002915 self.handle.sendline( "sh sudo pkill tcpdump" )
2916 self.handle.expect( "mininet>" )
2917 self.handle.sendline( "" )
2918 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002919 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002920 main.log.error( self.name + ": TIMEOUT exception found" )
2921 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002922 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002923 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002924 main.log.error( self.name + ": EOF exception found" )
2925 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002926 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002927 except Exception:
2928 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002929 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002930
Jon Halld80cc142015-07-06 13:36:05 -07002931 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002932 """
2933 Read ports from a Mininet switch.
2934
2935 Returns a json structure containing information about the
2936 ports of the given switch.
2937 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002938 try:
2939 response = self.getInterfaces( nodeName )
2940 # TODO: Sanity check on response. log if no such switch exists
2941 ports = []
2942 for line in response.split( "\n" ):
2943 if not line.startswith( "name=" ):
2944 continue
2945 portVars = {}
2946 for var in line.split( "," ):
2947 key, value = var.split( "=" )
2948 portVars[ key ] = value
2949 isUp = portVars.pop( 'enabled', "True" )
2950 isUp = "True" in isUp
2951 if verbose:
2952 main.log.info( "Reading switch port %s(%s)" %
2953 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2954 mac = portVars[ 'mac' ]
2955 if mac == 'None':
2956 mac = None
2957 ips = []
2958 ip = portVars[ 'ip' ]
2959 if ip == 'None':
2960 ip = None
2961 ips.append( ip )
2962 name = portVars[ 'name' ]
2963 if name == 'None':
2964 name = None
2965 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2966 if name == 'lo':
2967 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2968 else:
2969 portNo = re.search( portRe, name ).group( 'port' )
2970 ports.append( { 'of_port': portNo,
2971 'mac': str( mac ).replace( '\'', '' ),
2972 'name': name,
2973 'ips': ips,
2974 'enabled': isUp } )
2975 return ports
2976 except pexpect.EOF:
2977 main.log.error( self.name + ": EOF exception found" )
2978 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002979 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002980 except Exception:
2981 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002982 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002983
You Wangdb8cd0a2016-05-26 15:19:45 -07002984 def getOVSPorts( self, nodeName ):
2985 """
2986 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2987
2988 Returns a list of dictionaries containing information about each
2989 port of the given switch.
2990 """
2991 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2992 try:
2993 response = self.execute(
2994 cmd=command,
2995 prompt="mininet>",
2996 timeout=10 )
2997 ports = []
2998 if response:
2999 for line in response.split( "\n" ):
3000 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
3001 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003002 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07003003 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
3004 result = re.search( pattern, line )
3005 if result:
3006 index = result.group( 'index' )
3007 name = result.group( 'name' )
3008 # This port number is extracted from port name
3009 port = result.group( 'port' )
3010 mac = result.group( 'mac' )
3011 ports.append( { 'index': index,
3012 'name': name,
3013 'port': port,
3014 'mac': mac } )
3015 return ports
3016 except pexpect.EOF:
3017 main.log.error( self.name + ": EOF exception found" )
3018 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003019 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003020 except Exception:
3021 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003022 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003023
Devin Lima7cfdbd2017-09-29 15:02:22 -07003024 def getSwitches( self, verbose=False, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07003025 """
3026 Read switches from Mininet.
3027
3028 Returns a dictionary whose keys are the switch names and the value is
3029 a dictionary containing information about the switch.
3030 """
Jon Halla22481b2015-07-28 17:46:01 -07003031 # NOTE: To support new Mininet switch classes, just append the new
3032 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07003033
Jon Halla22481b2015-07-28 17:46:01 -07003034 # Regex patterns to parse 'dump' output
3035 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07003036 # <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 -07003037 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07003038 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
3039 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
3040 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003041 try:
3042 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
3043 swRE = r"<(?P<class>" + switchClasses + r")" +\
3044 r"(?P<options>\{.*\})?\s" +\
3045 r"(?P<name>[^:]+)\:\s" +\
3046 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
3047 r"\spid=(?P<pid>(\d)+)"
3048 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07003049 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003050 output = {}
3051 dump = self.dump().split( "\n" )
3052 for line in dump:
3053 result = re.search( swRE, line, re.I )
3054 if result:
3055 name = result.group( 'name' )
3056 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
3057 pid = result.group( 'pid' )
3058 swClass = result.group( 'class' )
3059 options = result.group( 'options' )
3060 if verbose:
3061 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
3062 ports = self.getPorts( name )
3063 output[ name ] = { "dpid": dpid,
3064 "ports": ports,
3065 "swClass": swClass,
3066 "pid": pid,
3067 "options": options }
3068 return output
3069 except pexpect.EOF:
3070 main.log.error( self.name + ": EOF exception found" )
3071 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003072 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003073 except Exception:
3074 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003075 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003076
You Wangd66de192018-04-30 17:30:12 -07003077 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08003078 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
3079 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07003080 """
3081 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08003082 Optional:
3083 hostClass: it is used to match the class of the mininet host. It
3084 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07003085 Returns a dictionary whose keys are the host names and the value is
3086 a dictionary containing information about the host.
3087 """
3088 # Regex patterns to parse dump output
3089 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07003090 # <Host h1: pid=12725>
3091 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
3092 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
3093 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07003094 # NOTE: Does not correctly match hosts with multi-links
3095 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
3096 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003097 try:
You Wang53dba1e2018-02-02 17:45:44 -08003098 if not isinstance( hostClass, types.ListType ):
3099 hostClass = [ str( hostClass ) ]
3100 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08003101 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
3102 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
3103 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07003104 if update:
3105 # update mn port info
3106 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003107 # Get mininet dump
3108 dump = self.dump().split( "\n" )
3109 hosts = {}
3110 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08003111 result = re.search( hostRE, line )
3112 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003113 name = result.group( 'name' )
3114 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07003115 if getInterfaces:
3116 response = self.getInterfaces( name )
3117 # Populate interface info
3118 for line in response.split( "\n" ):
3119 if line.startswith( "name=" ):
3120 portVars = {}
3121 for var in line.split( "," ):
3122 key, value = var.split( "=" )
3123 portVars[ key ] = value
3124 isUp = portVars.pop( 'enabled', "True" )
3125 isUp = "True" in isUp
3126 if verbose:
3127 main.log.info( "Reading host port %s(%s)" %
3128 ( portVars[ 'name' ],
3129 portVars[ 'mac' ] ) )
3130 mac = portVars[ 'mac' ]
3131 if mac == 'None':
3132 mac = None
3133 ips = []
3134 ip = portVars[ 'ip' ]
3135 if ip == 'None':
3136 ip = None
3137 ips.append( ip )
3138 intfName = portVars[ 'name' ]
3139 if name == 'None':
3140 name = None
3141 interfaces.append( {
3142 "name": intfName,
3143 "ips": ips,
3144 "mac": str( mac ),
3145 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003146 hosts[ name ] = { "interfaces": interfaces }
3147 return hosts
3148 except pexpect.EOF:
3149 main.log.error( self.name + ": EOF exception found" )
3150 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003151 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003152 except Exception:
3153 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003154 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003155
Devin Lima7cfdbd2017-09-29 15:02:22 -07003156 def getLinks( self, timeout=20, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07003157 """
3158 Gathers information about current Mininet links. These links may not
3159 be up if one of the ports is down.
3160
3161 Returns a list of dictionaries with link endpoints.
3162
3163 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07003164 { 'node1': str( node1 name )
3165 'node2': str( node2 name )
3166 'port1': str( port1 of_port )
3167 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07003168 Note: The port number returned is the eth#, not necessarily the of_port
3169 number. In Mininet, for OVS switch, these should be the same. For
3170 hosts, this is just the eth#.
3171 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003172 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003173 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003174 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07003175
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003176 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003177 # s1-eth3<->s2-eth1 (OK OK)
3178 # s13-eth3<->h27-eth0 (OK OK)
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003179 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
3180 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
3181 links = []
3182 for line in response:
3183 match = re.search( linkRE, line )
3184 if match:
3185 node1 = match.group( 'node1' )
3186 node2 = match.group( 'node2' )
3187 port1 = match.group( 'port1' )
3188 port2 = match.group( 'port2' )
3189 links.append( { 'node1': node1,
3190 'node2': node2,
3191 'port1': port1,
3192 'port2': port2 } )
3193 return links
3194
3195 except pexpect.EOF:
3196 main.log.error( self.name + ": EOF exception found" )
3197 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003198 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003199 except Exception:
3200 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003201 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003202
3203 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003204 """
3205 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003206 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003207
Jon Hallafa8a472015-06-12 14:02:42 -07003208 Dependencies:
3209 1. numpy - "sudo pip install numpy"
3210 """
3211 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003212 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003213 try:
3214 mnDPIDs = []
3215 for swName, switch in switches.iteritems():
3216 mnDPIDs.append( switch[ 'dpid' ].lower() )
3217 mnDPIDs.sort()
3218 if switchesJson == "": # if rest call fails
3219 main.log.error(
3220 self.name +
3221 ".compareSwitches(): Empty JSON object given from ONOS" )
3222 return main.FALSE
3223 onos = switchesJson
3224 onosDPIDs = []
3225 for switch in onos:
3226 if switch[ 'available' ]:
3227 onosDPIDs.append(
3228 switch[ 'id' ].replace(
3229 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003230 '' ).replace(
3231 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003232 '' ).lower() )
3233 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003234
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003235 if mnDPIDs != onosDPIDs:
3236 switchResults = main.FALSE
3237 main.log.error( "Switches in MN but not in ONOS:" )
3238 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3239 main.log.error( str( list1 ) )
3240 main.log.error( "Switches in ONOS but not in MN:" )
3241 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3242 main.log.error( str( list2 ) )
3243 else: # list of dpid's match in onos and mn
3244 switchResults = main.TRUE
3245 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003246
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003247 # FIXME: this does not look for extra ports in ONOS, only checks that
3248 # ONOS has what is in MN
3249 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003250
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003251 # PORTS
3252 for name, mnSwitch in switches.iteritems():
3253 mnPorts = []
3254 onosPorts = []
3255 switchResult = main.TRUE
3256 for port in mnSwitch[ 'ports' ]:
3257 if port[ 'enabled' ]:
3258 mnPorts.append( int( port[ 'of_port' ] ) )
3259 for onosSwitch in portsJson:
3260 if onosSwitch[ 'device' ][ 'available' ]:
3261 if onosSwitch[ 'device' ][ 'id' ].replace(
3262 ':',
3263 '' ).replace(
3264 "of",
3265 '' ) == mnSwitch[ 'dpid' ]:
3266 for port in onosSwitch[ 'ports' ]:
3267 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003268 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003269 # onosPorts.append( 'local' )
3270 onosPorts.append( long( uint64( -2 ) ) )
3271 else:
3272 onosPorts.append( int( port[ 'port' ] ) )
3273 break
3274 mnPorts.sort( key=float )
3275 onosPorts.sort( key=float )
3276
3277 mnPortsLog = mnPorts
3278 onosPortsLog = onosPorts
3279 mnPorts = [ x for x in mnPorts ]
3280 onosPorts = [ x for x in onosPorts ]
3281
3282 # TODO: handle other reserved port numbers besides LOCAL
3283 # NOTE: Reserved ports
3284 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3285 # long( uint64( -2 ) )
3286 for mnPort in mnPortsLog:
3287 if mnPort in onosPorts:
3288 # don't set results to true here as this is just one of
3289 # many checks and it might override a failure
3290 mnPorts.remove( mnPort )
3291 onosPorts.remove( mnPort )
3292
3293 # NOTE: OVS reports this as down since there is no link
3294 # So ignoring these for now
3295 # TODO: Come up with a better way of handling these
3296 if 65534 in mnPorts:
3297 mnPorts.remove( 65534 )
3298 if long( uint64( -2 ) ) in onosPorts:
3299 onosPorts.remove( long( uint64( -2 ) ) )
3300 if len( mnPorts ): # the ports of this switch don't match
3301 switchResult = main.FALSE
3302 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3303 if len( onosPorts ): # the ports of this switch don't match
3304 switchResult = main.FALSE
3305 main.log.warn(
3306 "Ports in ONOS but not MN: " +
3307 str( onosPorts ) )
3308 if switchResult == main.FALSE:
3309 main.log.error(
3310 "The list of ports for switch %s(%s) does not match:" %
3311 ( name, mnSwitch[ 'dpid' ] ) )
3312 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3313 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3314 portsResults = portsResults and switchResult
3315 finalResults = finalResults and portsResults
3316 return finalResults
3317 except pexpect.EOF:
3318 main.log.error( self.name + ": EOF exception found" )
3319 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003320 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003321 except Exception:
3322 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003323 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003324
Jon Hallafa8a472015-06-12 14:02:42 -07003325 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003326 """
3327 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003328 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003329
Jon Hallafa8a472015-06-12 14:02:42 -07003330 """
Jon Hall7eb38402015-01-08 17:19:54 -08003331 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003332 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003333 try:
3334 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003335
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003336 mnLinks = []
3337 for l in links:
3338 try:
3339 node1 = switches[ l[ 'node1' ] ]
3340 node2 = switches[ l[ 'node2' ] ]
3341 enabled = True
3342 for port in node1[ 'ports' ]:
3343 if port[ 'of_port' ] == l[ 'port1' ]:
3344 enabled = enabled and port[ 'enabled' ]
3345 for port in node2[ 'ports' ]:
3346 if port[ 'of_port' ] == l[ 'port2' ]:
3347 enabled = enabled and port[ 'enabled' ]
3348 if enabled:
3349 mnLinks.append( l )
3350 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003351 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003352 if 2 * len( mnLinks ) == len( onos ):
3353 linkResults = main.TRUE
3354 else:
3355 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003356 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003357 "Mininet has " + str( len( mnLinks ) ) +
3358 " bidirectional links and ONOS has " +
3359 str( len( onos ) ) + " unidirectional links" )
3360
3361 # iterate through MN links and check if an ONOS link exists in
3362 # both directions
3363 for link in mnLinks:
3364 # TODO: Find a more efficient search method
3365 node1 = None
3366 port1 = None
3367 node2 = None
3368 port2 = None
3369 firstDir = main.FALSE
3370 secondDir = main.FALSE
3371 for swName, switch in switches.iteritems():
3372 if swName == link[ 'node1' ]:
3373 node1 = switch[ 'dpid' ]
3374 for port in switch[ 'ports' ]:
3375 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3376 port1 = port[ 'of_port' ]
3377 if node1 is not None and node2 is not None:
3378 break
3379 if swName == link[ 'node2' ]:
3380 node2 = switch[ 'dpid' ]
3381 for port in switch[ 'ports' ]:
3382 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3383 port2 = port[ 'of_port' ]
3384 if node1 is not None and node2 is not None:
3385 break
3386
3387 for onosLink in onos:
3388 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3389 ":", '' ).replace( "of", '' )
3390 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3391 ":", '' ).replace( "of", '' )
3392 onosPort1 = onosLink[ 'src' ][ 'port' ]
3393 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3394
3395 # check onos link from node1 to node2
3396 if str( onosNode1 ) == str( node1 ) and str(
3397 onosNode2 ) == str( node2 ):
3398 if int( onosPort1 ) == int( port1 ) and int(
3399 onosPort2 ) == int( port2 ):
3400 firstDir = main.TRUE
3401 else:
Jon Hallab611372018-02-21 15:26:05 -08003402 # The right switches, but wrong ports, could be
3403 # another link between these devices, or onos
3404 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003405 main.log.warn(
3406 'The port numbers do not match for ' +
3407 str( link ) +
3408 ' between ONOS and MN. When checking ONOS for ' +
3409 'link %s/%s -> %s/%s' %
3410 ( node1, port1, node2, port2 ) +
3411 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003412 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3413 '. This could be another link between these devices' +
3414 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003415
3416 # check onos link from node2 to node1
3417 elif ( str( onosNode1 ) == str( node2 ) and
3418 str( onosNode2 ) == str( node1 ) ):
3419 if ( int( onosPort1 ) == int( port2 )
3420 and int( onosPort2 ) == int( port1 ) ):
3421 secondDir = main.TRUE
3422 else:
Jon Hallab611372018-02-21 15:26:05 -08003423 # The right switches, but wrong ports, could be
3424 # another link between these devices, or onos
3425 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003426 main.log.warn(
3427 'The port numbers do not match for ' +
3428 str( link ) +
3429 ' between ONOS and MN. When checking ONOS for ' +
3430 'link %s/%s -> %s/%s' %
3431 ( node1, port1, node2, port2 ) +
3432 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003433 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3434 '. This could be another link between these devices' +
3435 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003436 else: # this is not the link you're looking for
3437 pass
3438 if not firstDir:
3439 main.log.error(
3440 'ONOS does not have the link %s/%s -> %s/%s' %
3441 ( node1, port1, node2, port2 ) )
3442 if not secondDir:
3443 main.log.error(
3444 'ONOS does not have the link %s/%s -> %s/%s' %
3445 ( node2, port2, node1, port1 ) )
3446 linkResults = linkResults and firstDir and secondDir
3447 return linkResults
3448 except pexpect.EOF:
3449 main.log.error( self.name + ": EOF exception found" )
3450 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003451 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003452 except Exception:
3453 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003454 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003455
Jon Hallafa8a472015-06-12 14:02:42 -07003456 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003457 """
Jon Hallafa8a472015-06-12 14:02:42 -07003458 Compare mn and onos Hosts.
3459 Since Mininet hosts are quiet, ONOS will only know of them when they
3460 speak. For this reason, we will only check that the hosts in ONOS
3461 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003462
Jon Hallafa8a472015-06-12 14:02:42 -07003463 Arguments:
3464 hostsJson: parsed json object from the onos hosts api
3465 Returns:
3466 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003467 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003468 try:
3469 hostResults = main.TRUE
3470 for onosHost in hostsJson:
3471 onosMAC = onosHost[ 'mac' ].lower()
3472 match = False
3473 for mnHost, info in hosts.iteritems():
3474 for mnIntf in info[ 'interfaces' ]:
3475 if onosMAC == mnIntf[ 'mac' ].lower():
3476 match = True
3477 for ip in mnIntf[ 'ips' ]:
3478 if ip in onosHost[ 'ipAddresses' ]:
3479 pass # all is well
3480 else:
3481 # misssing ip
3482 main.log.error( "ONOS host " +
3483 onosHost[ 'id' ] +
3484 " has a different IP(" +
3485 str( onosHost[ 'ipAddresses' ] ) +
3486 ") than the Mininet host(" +
3487 str( ip ) +
3488 ")." )
3489 output = json.dumps(
3490 onosHost,
3491 sort_keys=True,
3492 indent=4,
3493 separators=( ',', ': ' ) )
3494 main.log.info( output )
3495 hostResults = main.FALSE
3496 if not match:
3497 hostResults = main.FALSE
3498 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3499 "corresponding Mininet host." )
3500 output = json.dumps( onosHost,
3501 sort_keys=True,
3502 indent=4,
3503 separators=( ',', ': ' ) )
3504 main.log.info( output )
3505 return hostResults
3506 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003507 main.log.error( self.name + ": EOF exception found" )
3508 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003509 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003510 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003511 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003512 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003513
You Wangd66de192018-04-30 17:30:12 -07003514 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003515 """
3516 Description:
3517 Verify that all hosts have IP address assigned to them
3518 Optional:
3519 hostList: If specified, verifications only happen to the hosts
3520 in hostList
3521 prefix: at least one of the ip address assigned to the host
3522 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003523 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003524 Returns:
3525 main.TRUE if all hosts have specific IP address assigned;
3526 main.FALSE otherwise
3527 """
3528 try:
You Wangd66de192018-04-30 17:30:12 -07003529 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003530 if not hostList:
3531 hostList = hosts.keys()
3532 for hostName in hosts.keys():
3533 if hostName not in hostList:
3534 continue
3535 ipList = []
3536 self.handle.sendline( str( hostName ) + " ip a" )
3537 self.handle.expect( "mininet>" )
3538 ipa = self.handle.before
3539 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3540 ipList += re.findall( ipv4Pattern, ipa )
3541 # It's tricky to make regex for IPv6 addresses and this one is simplified
3542 ipv6Pattern = r'inet6 ((?:[0-9a-fA-F]{1,4})?(?:[:0-9a-fA-F]{1,4}){1,7}(?:::)?(?:[:0-9a-fA-F]{1,4}){1,7})/'
3543 ipList += re.findall( ipv6Pattern, ipa )
3544 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3545 if not ipList:
3546 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3547 else:
3548 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3549 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3550 else:
3551 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3552 hostList.remove( hostName )
3553 return main.FALSE if hostList else main.TRUE
3554 except KeyError:
3555 main.log.exception( self.name + ": host data not as expected: " + hosts )
3556 return None
3557 except pexpect.EOF:
3558 main.log.error( self.name + ": EOF exception found" )
3559 main.log.error( self.name + ": " + self.handle.before )
3560 main.cleanAndExit()
3561 except Exception:
3562 main.log.exception( self.name + ": Uncaught exception" )
3563 return None
3564
Jon Hallafa8a472015-06-12 14:02:42 -07003565 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003566 """
3567 Returns a list of all hosts
3568 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003569 try:
3570 self.handle.sendline( "" )
3571 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003572
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003573 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3574 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003575
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003576 handlePy = self.handle.before
3577 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3578 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003579
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003580 self.handle.sendline( "" )
3581 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003582
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003583 hostStr = handlePy.replace( "]", "" )
3584 hostStr = hostStr.replace( "'", "" )
3585 hostStr = hostStr.replace( "[", "" )
3586 hostStr = hostStr.replace( " ", "" )
3587 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003588
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003589 return hostList
3590 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003591 main.log.error( self.name + ": TIMEOUT exception found" )
3592 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003593 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003594 except pexpect.EOF:
3595 main.log.error( self.name + ": EOF exception found" )
3596 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003597 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003598 except Exception:
3599 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003600 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003601
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003602 def getSwitch( self ):
3603 """
3604 Returns a list of all switches
3605 Again, don't ask question just use it...
3606 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003607 try:
3608 # get host list...
3609 hostList = self.getHosts()
3610 # Make host set
3611 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003612
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003613 # Getting all the nodes in mininet
3614 self.handle.sendline( "" )
3615 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003616
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003617 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3618 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003619
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003620 handlePy = self.handle.before
3621 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3622 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003623
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003624 self.handle.sendline( "" )
3625 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003626
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003627 nodesStr = handlePy.replace( "]", "" )
3628 nodesStr = nodesStr.replace( "'", "" )
3629 nodesStr = nodesStr.replace( "[", "" )
3630 nodesStr = nodesStr.replace( " ", "" )
3631 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003632
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003633 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003634 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003635 nodesSet.discard( 'c0' )
3636 nodesSet.discard( 'c1' )
3637 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003638
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003639 switchSet = nodesSet - hostSet
3640 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003641
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003642 return switchList
3643 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003644 main.log.error( self.name + ": TIMEOUT exception found" )
3645 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003646 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003647 except pexpect.EOF:
3648 main.log.error( self.name + ": EOF exception found" )
3649 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003650 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003651 except Exception:
3652 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003653 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003654
You Wangdb8cd0a2016-05-26 15:19:45 -07003655 def getGraphDict( self, timeout=60, useId=True, includeHost=False ):
3656 """
3657 Return a dictionary which describes the latest Mininet topology data as a
3658 graph.
3659 An example of the dictionary:
3660 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3661 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3662 Each vertex should at least have an 'edges' attribute which describes the
3663 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003664 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003665 list of attributes.
3666 An example of the edges dictionary:
3667 'edges': { vertex2: { 'port': ..., 'weight': ... },
3668 vertex3: { 'port': ..., 'weight': ... } }
3669 If useId == True, dpid/mac will be used instead of names to identify
3670 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3671 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003672 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003673 in topology data.
3674 Note that link or switch that are brought down by 'link x x down' or 'switch
3675 x down' commands still show in the output of Mininet CLI commands such as
3676 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3677 recommended to use delLink() or delSwitch functions to simulate link/switch
3678 down, and addLink() or addSwitch to add them back.
3679 """
3680 graphDict = {}
3681 try:
3682 links = self.getLinks( timeout=timeout )
3683 portDict = {}
3684 if useId:
3685 switches = self.getSwitches()
3686 if includeHost:
3687 hosts = self.getHosts()
3688 for link in links:
3689 # FIXME: support 'includeHost' argument
3690 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3691 continue
3692 nodeName1 = link[ 'node1' ]
3693 nodeName2 = link[ 'node2' ]
3694 port1 = link[ 'port1' ]
3695 port2 = link[ 'port2' ]
3696 # Loop for two nodes
3697 for i in range( 2 ):
3698 # Get port index from OVS
3699 # The index extracted from port name may be inconsistent with ONOS
3700 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003701 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003702 portList = self.getOVSPorts( nodeName1 )
3703 if len( portList ) == 0:
3704 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3705 return None
3706 portDict[ nodeName1 ] = portList
3707 for port in portDict[ nodeName1 ]:
3708 if port[ 'port' ] == port1:
3709 portIndex = port[ 'index' ]
3710 break
3711 if portIndex == -1:
3712 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3713 return None
3714 if useId:
3715 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3716 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3717 else:
3718 node1 = nodeName1
3719 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003720 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003721 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003722 graphDict[ node1 ] = { 'edges': {},
3723 'dpid': switches[ nodeName1 ][ 'dpid' ],
3724 'name': nodeName1,
3725 'ports': switches[ nodeName1 ][ 'ports' ],
3726 'swClass': switches[ nodeName1 ][ 'swClass' ],
3727 'pid': switches[ nodeName1 ][ 'pid' ],
3728 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003729 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003730 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003731 else:
3732 # Assert node2 is not connected to any current links of node1
3733 assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003734 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
You Wangdb8cd0a2016-05-26 15:19:45 -07003735 # Swap two nodes/ports
3736 nodeName1, nodeName2 = nodeName2, nodeName1
3737 port1, port2 = port2, port1
3738 return graphDict
3739 except KeyError:
3740 main.log.exception( self.name + ": KeyError exception found" )
3741 return None
3742 except AssertionError:
3743 main.log.exception( self.name + ": AssertionError exception found" )
3744 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003745 except pexpect.EOF:
3746 main.log.error( self.name + ": EOF exception found" )
3747 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003748 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003749 except Exception:
3750 main.log.exception( self.name + ": Uncaught exception" )
3751 return None
3752
Devin Lima7cfdbd2017-09-29 15:02:22 -07003753 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003754 """
3755 updates the port address and status information for
3756 each port in mn"""
3757 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003758 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003759 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003760 self.handle.sendline( "" )
3761 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003762
Jon Hall7eb38402015-01-08 17:19:54 -08003763 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003764 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003765
Jon Hall7eb38402015-01-08 17:19:54 -08003766 self.handle.sendline( "" )
3767 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003768
Jon Hallb1290e82014-11-18 16:17:48 -05003769 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003770 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003771 main.log.error( self.name + ": TIMEOUT exception found" )
3772 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003773 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003774 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003775 main.log.error( self.name + ": EOF exception found" )
3776 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003777 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003778 except Exception:
3779 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003780 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003781
Jon Halld80cc142015-07-06 13:36:05 -07003782 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003783 """
3784 Add vlan tag to a host.
3785 Dependencies:
3786 This class depends on the "vlan" package
3787 $ sudo apt-get install vlan
3788 Configuration:
3789 Load the 8021q module into the kernel
3790 $sudo modprobe 8021q
3791
3792 To make this setup permanent:
3793 $ sudo su -c 'echo "8021q" >> /etc/modules'
3794 """
3795 if self.handle:
3796 try:
Jon Halld80cc142015-07-06 13:36:05 -07003797 # get the ip address of the host
3798 main.log.info( "Get the ip address of the host" )
3799 ipaddr = self.getIPAddress( host )
3800 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003801
Jon Halld80cc142015-07-06 13:36:05 -07003802 # remove IP from interface intf
3803 # Ex: h1 ifconfig h1-eth0 inet 0
3804 main.log.info( "Remove IP from interface " )
3805 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3806 self.handle.sendline( cmd2 )
3807 self.handle.expect( "mininet>" )
3808 response = self.handle.before
3809 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003810
Jon Halld80cc142015-07-06 13:36:05 -07003811 # create VLAN interface
3812 # Ex: h1 vconfig add h1-eth0 100
3813 main.log.info( "Create Vlan" )
3814 cmd3 = host + " vconfig add " + intf + " " + vlan
3815 self.handle.sendline( cmd3 )
3816 self.handle.expect( "mininet>" )
3817 response = self.handle.before
3818 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003819
Jon Halld80cc142015-07-06 13:36:05 -07003820 # assign the host's IP to the VLAN interface
3821 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3822 main.log.info( "Assign the host IP to the vlan interface" )
3823 vintf = intf + "." + vlan
3824 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3825 self.handle.sendline( cmd4 )
3826 self.handle.expect( "mininet>" )
3827 response = self.handle.before
3828 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003829
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003830 # update Mininet node variables
3831 main.log.info( "Update Mininet node variables" )
3832 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3833 self.handle.sendline( cmd5 )
3834 self.handle.expect( "mininet>" )
3835 response = self.handle.before
3836 main.log.info( "====> %s ", response )
3837
3838 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3839 self.handle.sendline( cmd6 )
3840 self.handle.expect( "mininet>" )
3841 response = self.handle.before
3842 main.log.info( "====> %s ", response )
3843
3844 return main.TRUE
3845 except pexpect.TIMEOUT:
3846 main.log.error( self.name + ": TIMEOUT exception found" )
3847 main.log.error( self.name + ": " + self.handle.before )
3848 main.cleanAndExit()
3849 except pexpect.EOF:
3850 main.log.error( self.name + ": EOF exception found" )
3851 main.log.error( self.name + ": " + self.handle.before )
3852 return main.FALSE
3853 except Exception:
3854 main.log.exception( self.name + ": Uncaught exception!" )
3855 return main.FALSE
3856
3857 def removeVLAN( self, host, intf ):
3858 """
3859 Remove vlan tag from a host.
3860 Dependencies:
3861 This class depends on the "vlan" package
3862 $ sudo apt-get install vlan
3863 Configuration:
3864 Load the 8021q module into the kernel
3865 $sudo modprobe 8021q
3866
3867 To make this setup permanent:
3868 $ sudo su -c 'echo "8021q" >> /etc/modules'
3869 """
3870 if self.handle:
3871 try:
3872 # get the ip address of the host
3873 main.log.info( "Get the ip address of the host" )
3874 ipaddr = self.getIPAddress( host )
3875
3876 # remove VLAN interface
3877 # Ex: h1 vconfig rem h1-eth0.100
3878 main.log.info( "Remove Vlan interface" )
3879 cmd2 = host + " vconfig rem " + intf
3880 self.handle.sendline( cmd2 )
3881 self.handle.expect( "mininet>" )
3882 response = self.handle.before
3883 main.log.info( "====> %s ", response )
3884
3885 # assign the host's IP to the original interface
3886 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3887 main.log.info( "Assign the host IP to the original interface" )
3888 original_intf = intf.split(".")[0]
3889 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3890 self.handle.sendline( cmd3 )
3891 self.handle.expect( "mininet>" )
3892 response = self.handle.before
3893 main.log.info( "====> %s ", response )
3894
3895 # update Mininet node variables
3896 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3897 self.handle.sendline( cmd4 )
3898 self.handle.expect( "mininet>" )
3899 response = self.handle.before
3900 main.log.info( "====> %s ", response )
3901
3902 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3903 self.handle.sendline( cmd5 )
3904 self.handle.expect( "mininet>" )
3905 response = self.handle.before
3906 main.log.info( "====> %s ", response )
3907
kaouthera3f13ca22015-05-05 15:01:41 -07003908 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003909 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003910 main.log.error( self.name + ": TIMEOUT exception found" )
3911 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003912 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003913 except pexpect.EOF:
3914 main.log.error( self.name + ": EOF exception found" )
3915 main.log.error( self.name + ": " + self.handle.before )
3916 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003917 except Exception:
3918 main.log.exception( self.name + ": Uncaught exception!" )
3919 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003920
Jon Hall892818c2015-10-20 17:58:34 -07003921 def createHostComponent( self, name ):
3922 """
3923 Creates a new mininet cli component with the same parameters as self.
3924 This new component is intended to be used to login to the hosts created
3925 by mininet.
3926
3927 Arguments:
3928 name - The string of the name of this component. The new component
3929 will be assigned to main.<name> .
3930 In addition, main.<name>.name = str( name )
3931 """
3932 try:
3933 # look to see if this component already exists
3934 getattr( main, name )
3935 except AttributeError:
3936 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003937 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3938 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003939 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003940 except pexpect.EOF:
3941 main.log.error( self.name + ": EOF exception found" )
3942 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003943 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003944 except Exception:
3945 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003946 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003947 else:
3948 # namespace is not clear!
3949 main.log.error( name + " component already exists!" )
3950 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003951 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003952
3953 def removeHostComponent( self, name ):
3954 """
3955 Remove host component
3956 Arguments:
3957 name - The string of the name of the component to delete.
3958 """
3959 try:
3960 # Get host component
3961 component = getattr( main, name )
3962 except AttributeError:
3963 main.log.error( "Component " + name + " does not exist." )
3964 return
3965 try:
3966 # Disconnect from component
3967 component.disconnect()
3968 # Delete component
3969 delattr( main, name )
3970 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003971 del( main.componentDictionary[ name ] )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003972 except pexpect.EOF:
3973 main.log.error( self.name + ": EOF exception found" )
3974 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003975 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003976 except Exception:
3977 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003978 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003979
3980 def startHostCli( self, host=None ):
3981 """
3982 Use the mininet m utility to connect to the host's cli
3983 """
3984 # These are fields that can be used by scapy packets. Initialized to None
3985 self.hostIp = None
3986 self.hostMac = None
3987 try:
3988 if not host:
3989 host = self.name
3990 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003991 self.handle.sendline( "cd" )
3992 self.handle.expect( self.hostPrompt )
3993 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003994 self.handle.expect( self.hostPrompt )
3995 return main.TRUE
3996 except pexpect.TIMEOUT:
3997 main.log.exception( self.name + ": Command timed out" )
3998 return main.FALSE
3999 except pexpect.EOF:
4000 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07004001 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07004002 except Exception:
4003 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004004 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07004005
YPZhang801d46d2016-08-08 13:26:28 -07004006 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004007 '''
4008
YPZhang801d46d2016-08-08 13:26:28 -07004009 Args:
4010 devicename: switch name
4011 intf: port name on switch
4012 status: up or down
4013
4014 Returns: boolean to show success change status
4015
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004016 '''
YPZhang801d46d2016-08-08 13:26:28 -07004017 if status == "down" or status == "up":
4018 try:
4019 cmd = devicename + " ifconfig " + intf + " " + status
4020 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004021 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07004022 return main.TRUE
4023 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004024 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07004025 return main.FALSE
4026 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004027 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07004028 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07004029 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004030 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07004031 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07004032 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004033 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004034 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07004035 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004036 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07004037 return main.FALSE
4038
4039
adminbae64d82013-08-01 10:50:15 -07004040if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004041 sys.modules[ __name__ ] = MininetCliDriver()