blob: 8d474cbbf3096aea0adce862bf039fbe5708dc34 [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 )
Jon Halla604fd42018-05-04 14:27:27 -0700476 self.handle.expect( "mininet>", timeout=wait + 5 )
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 )
Jon Halla604fd42018-05-04 14:27:27 -0700539 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangf19d9f42018-02-23 16:34:19 -0800540 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 Wang32833172018-10-23 15:19:31 -0700577 def discoverHosts( self, hostList=[], wait=1000, dstIp="6.6.6.6", dstIp6="1020::3fe" ):
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700578 '''
You Wang32833172018-10-23 15:19:31 -0700579 Hosts in hostList will do a single ARP/ND to a non-existent address for ONOS to
580 discover them. A host will use arping/ndisc6 to send ARP/ND depending on if it
581 has IPv4/IPv6 addresses configured.
You Wang48381752018-05-07 13:50:57 -0700582 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
You Wang32833172018-10-23 15:19:31 -0700585 wait: timeout for ARP/ND in milliseconds
You Wang48381752018-05-07 13:50:57 -0700586 dstIp: destination address used by IPv4 hosts
587 dstIp6: destination address used by IPv6 hosts
588 Returns:
You Wang32833172018-10-23 15:19:31 -0700589 main.TRUE if all packets were successfully sent. Otherwise main.FALSE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700590 '''
591 try:
You Wang32833172018-10-23 15:19:31 -0700592 hosts = self.getHosts()
You Wang48381752018-05-07 13:50:57 -0700593 if not hostList:
You Wang48381752018-05-07 13:50:57 -0700594 hostList = hosts.keys()
595 discoveryResult = main.TRUE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700596 for host in hostList:
You Wang0b82aa52018-06-06 14:33:58 -0700597 flushCmd = ""
You Wang48381752018-05-07 13:50:57 -0700598 cmd = ""
599 if self.getIPAddress( host ):
You Wang0b82aa52018-06-06 14:33:58 -0700600 flushCmd = "{} ip neigh flush all".format( host )
You Wang32833172018-10-23 15:19:31 -0700601 cmd = "{} arping -c 1 -w {} {}".format( host, wait, dstIp )
602 main.log.debug( "Sending IPv4 arping from host {}".format( host ) )
You Wang48381752018-05-07 13:50:57 -0700603 elif self.getIPAddress( host, proto='IPV6' ):
You Wang0b82aa52018-06-06 14:33:58 -0700604 flushCmd = "{} ip -6 neigh flush all".format( host )
You Wang32833172018-10-23 15:19:31 -0700605 intf = hosts[host]['interfaces'][0]['name']
606 cmd = "{} ndisc6 -r 1 -w {} {} {}".format( host, wait, dstIp6, intf )
607 main.log.debug( "Sending IPv6 ND from host {}".format( host ) )
You Wang48381752018-05-07 13:50:57 -0700608 else:
609 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
610 discoveryResult = main.FALSE
611 if cmd:
You Wang0b82aa52018-06-06 14:33:58 -0700612 self.handle.sendline( flushCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700613 self.handle.expect( "mininet>" )
You Wang48381752018-05-07 13:50:57 -0700614 self.handle.sendline( cmd )
Jon Halla604fd42018-05-04 14:27:27 -0700615 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700616 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700617 except pexpect.TIMEOUT:
618 main.log.exception( self.name + ": TIMEOUT exception" )
619 response = self.handle.before
620 # NOTE: Send ctrl-c to make sure command is stopped
621 self.handle.send( "\x03" )
622 self.handle.expect( "Interrupt" )
623 response += self.handle.before + self.handle.after
624 self.handle.expect( "mininet>" )
625 response += self.handle.before + self.handle.after
626 main.log.debug( response )
627 return main.FALSE
628 except pexpect.EOF:
629 main.log.error( self.name + ": EOF exception found" )
630 main.log.error( self.name + ": " + self.handle.before )
631 main.cleanAndExit()
632 except Exception:
633 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800634 main.cleanAndExit()
635
636 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
637 """
638 Verify ping from each host in srcList to each host in dstList
639
640 acceptableFailed: max number of acceptable failed pings
641
642 Returns main.TRUE if all src hosts can reach all dst hosts
643 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
644 """
645 try:
646 main.log.info( "Verifying ping from each src host to each dst host" )
647 isReachable = main.TRUE
648 wait = int( wait )
649 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
650 pingResponse = "Ping output:\n"
651 failedPingsTotal = 0
652 for host in srcList:
653 pingResponse += str( str( host ) + " -> " )
654 for temp in dstList:
655 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700656 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
657 assert dstIP, "Not able to get IP address of host {}".format( temp )
658 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800659 while failedPings <= acceptableFailed:
660 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
661 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700662 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800663 response = self.handle.before
664 if re.search( ',\s0\%\spacket\sloss', response ):
665 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800666 break
667 else:
668 failedPings += 1
669 time.sleep(1)
670 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700671 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800672 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700673 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800674 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700675 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800676 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700677 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700678 except AssertionError:
679 main.log.exception( "" )
680 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700681 except pexpect.TIMEOUT:
682 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800683 response = self.handle.before
684 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700685 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800686 self.handle.expect( "Interrupt" )
687 response += self.handle.before + self.handle.after
688 self.handle.expect( "mininet>" )
689 response += self.handle.before + self.handle.after
690 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700691 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700692 except pexpect.EOF:
693 main.log.error( self.name + ": EOF exception found" )
694 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700695 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700696 except Exception:
697 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700698 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700699
Jon Hall7eb38402015-01-08 17:19:54 -0800700 def pingHost( self, **pingParams ):
701 """
Jon Hall3b489db2015-10-05 14:38:37 -0700702 Ping from one mininet host to another
703 Currently the only supported Params: SRC, TARGET, and WAIT
704 """
705 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700706 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700707 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800708 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700709 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700710 try:
Jon Hall61282e32015-03-19 11:34:11 -0700711 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800712 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700713 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700714 timeout=wait + 5 )
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 ) )
720 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700721 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800722 main.log.error(
723 self.name +
724 ": timeout when waiting for response from mininet" )
725 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700726 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700727 if re.search( ',\s0\%\spacket\sloss', response ):
728 main.log.info( self.name + ": no packets lost, host is reachable" )
729 return main.TRUE
730 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800731 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700732 self.name +
733 ": PACKET LOST, HOST IS NOT REACHABLE" )
734 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800735 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800736 main.log.error( self.name + ": EOF exception found" )
737 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700738 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700739 except Exception:
740 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700741 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700742
743 def ping6pair( self, **pingParams ):
744 """
GlennRC2cf7d952015-09-11 16:32:13 -0700745 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700746 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000747 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700748 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
749 """
Jon Hall3b489db2015-10-05 14:38:37 -0700750 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700751 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700752 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530753 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700754 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700755 try:
756 main.log.info( "Sending: " + command )
757 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700758 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700759 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700760 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 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
766 if i == 1:
767 main.log.error(
768 self.name +
769 ": timeout when waiting for response from mininet" )
770 main.log.error( "response: " + str( self.handle.before ) )
771 response = self.handle.before
772 main.log.info( self.name + ": Ping Response: " + response )
773 if re.search( ',\s0\%\spacket\sloss', response ):
774 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700775 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700776 else:
alisone4121a92016-11-22 16:31:36 -0800777 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700778 self.name +
779 ": PACKET LOST, HOST IS NOT REACHABLE" )
780 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700781 except pexpect.EOF:
782 main.log.error( self.name + ": EOF exception found" )
783 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700784 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700785 except Exception:
786 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700787 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800788
You Wangdb927a52016-02-26 11:03:28 -0800789 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
790 """
791 Description:
792 Ping a set of destination host from host CLI.
793 Logging into a Mininet host CLI is required before calling this funtion.
794 Params:
795 dstIPList is a list of destination ip addresses
796 Returns:
797 main.TRUE if the destination host is reachable
798 main.FALSE otherwise
799 """
800 isReachable = main.TRUE
801 wait = int( wait )
802 cmd = "ping"
803 if IPv6:
804 cmd = cmd + "6"
805 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
806 try:
807 for dstIP in dstIPList:
808 pingCmd = cmd + " " + dstIP
809 self.handle.sendline( pingCmd )
810 i = self.handle.expect( [ self.hostPrompt,
811 '\*\*\* Unknown command: ' + pingCmd,
812 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700813 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700814 # For some reason we need to send something
815 # Otherwise ping results won't be read by handle
816 self.handle.sendline( "" )
817 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800818 if i == 0:
819 response = self.handle.before
820 if not re.search( ',\s0\%\spacket\sloss', response ):
821 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
822 isReachable = main.FALSE
823 elif i == 1:
824 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700825 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800826 elif i == 2:
827 main.log.error( self.name + ": timeout when waiting for response" )
828 isReachable = main.FALSE
829 else:
830 main.log.error( self.name + ": unknown response: " + self.handle.before )
831 isReachable = main.FALSE
832 except pexpect.TIMEOUT:
833 main.log.exception( self.name + ": TIMEOUT exception" )
You Wangd4fae5c2018-08-22 13:56:49 -0700834 self.exitFromCmd( [ self.hostPrompt, self.bashPrompt ] )
You Wangdb927a52016-02-26 11:03:28 -0800835 isReachable = main.FALSE
836 except pexpect.EOF:
837 main.log.error( self.name + ": EOF exception found" )
838 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700839 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800840 except Exception:
841 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700842 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800843 return isReachable
844
Jon Hall7eb38402015-01-08 17:19:54 -0800845 def checkIP( self, host ):
846 """
847 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700848 try:
849 if self.handle:
850 try:
851 response = self.execute(
852 cmd=host +
853 " ifconfig",
854 prompt="mininet>",
855 timeout=10 )
856 except pexpect.EOF:
857 main.log.error( self.name + ": EOF exception found" )
858 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700859 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700860
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700861 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
862 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
863 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
864 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
865 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
866 "[0-9]|25[0-5]|[0-9]{1,2})"
867 # pattern = "inet addr:10.0.0.6"
868 if re.search( pattern, response ):
869 main.log.info( self.name + ": Host Ip configured properly" )
870 return main.TRUE
871 else:
872 main.log.error( self.name + ": Host IP not found" )
873 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700874 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700875 main.log.error( self.name + ": Connection failed to the host" )
876 except Exception:
877 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700878 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800879
Jon Hall7eb38402015-01-08 17:19:54 -0800880 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800881 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700882 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800883 response = self.execute(
884 cmd="h1 /usr/sbin/sshd -D&",
885 prompt="mininet>",
886 timeout=10 )
887 response = self.execute(
888 cmd="h4 /usr/sbin/sshd -D&",
889 prompt="mininet>",
890 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700891 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800892 vars( self )[ key ] = connectargs[ key ]
893 response = self.execute(
894 cmd="xterm h1 h4 ",
895 prompt="mininet>",
896 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800897 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800898 main.log.error( self.name + ": EOF exception found" )
899 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700900 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700901 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800902 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700903 if self.flag == 0:
904 self.flag = 1
905 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800906 else:
adminbae64d82013-08-01 10:50:15 -0700907 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800908
Jon Hall7eb38402015-01-08 17:19:54 -0800909 def changeIP( self, host, intf, newIP, newNetmask ):
910 """
911 Changes the ip address of a host on the fly
912 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800913 if self.handle:
914 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800915 cmd = host + " ifconfig " + intf + " " + \
916 newIP + " " + 'netmask' + " " + newNetmask
917 self.handle.sendline( cmd )
918 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800919 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800920 main.log.info( "response = " + response )
921 main.log.info(
922 "Ip of host " +
923 host +
924 " changed to new IP " +
925 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800926 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700927 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700928 main.log.error( self.name + ": TIMEOUT exception found" )
929 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700930 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800931 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800932 main.log.error( self.name + ": EOF exception found" )
933 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800934 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700935 except Exception:
936 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700937 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800938
Jon Hall7eb38402015-01-08 17:19:54 -0800939 def changeDefaultGateway( self, host, newGW ):
940 """
941 Changes the default gateway of a host
942 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800943 if self.handle:
944 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800945 cmd = host + " route add default gw " + newGW
946 self.handle.sendline( cmd )
947 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800948 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800949 main.log.info( "response = " + response )
950 main.log.info(
951 "Default gateway of host " +
952 host +
953 " changed to " +
954 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800955 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700956 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700957 main.log.error( self.name + ": TIMEOUT exception found" )
958 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700959 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800960 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800961 main.log.error( self.name + ": EOF exception found" )
962 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800963 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700964 except Exception:
965 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700966 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800967
You Wange24d6272018-03-27 21:18:50 -0700968 def addRoute( self, host, dstIP, interface, ipv6=False ):
969 """
970 Add a route to host
971 Ex: h1 route add -host 224.2.0.1 h1-eth0
972 """
973 if self.handle:
974 try:
975 cmd = str( host )
976 if ipv6:
977 cmd += " route -A inet6 add "
978 else:
979 cmd += " route add -host "
980 cmd += str( dstIP ) + " " + str( interface )
981 self.handle.sendline( cmd )
982 self.handle.expect( "mininet>" )
983 response = self.handle.before
984 main.log.debug( "response = " + response )
985 return main.TRUE
986 except pexpect.TIMEOUT:
987 main.log.error( self.name + ": TIMEOUT exception found" )
988 main.log.error( self.name + ": " + self.handle.before )
989 main.cleanAndExit()
990 except pexpect.EOF:
991 main.log.error( self.name + ": EOF exception found" )
992 main.log.error( self.name + ": " + self.handle.before )
993 return main.FALSE
994 except Exception:
995 main.log.exception( self.name + ": Uncaught exception!" )
996 main.cleanAndExit()
997
Jon Hall7eb38402015-01-08 17:19:54 -0800998 def addStaticMACAddress( self, host, GW, macaddr ):
999 """
Jon Hallefbd9792015-03-05 16:11:36 -08001000 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001001 if self.handle:
1002 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001003 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1004 cmd = host + " arp -s " + GW + " " + macaddr
1005 self.handle.sendline( cmd )
1006 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001007 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001008 main.log.info( "response = " + response )
1009 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001010 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001011 GW +
1012 " changed to " +
1013 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001014 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001015 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001016 main.log.error( self.name + ": TIMEOUT exception found" )
1017 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001018 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001019 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001020 main.log.error( self.name + ": EOF exception found" )
1021 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001022 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001023 except Exception:
1024 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001025 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001026
Jon Hall7eb38402015-01-08 17:19:54 -08001027 def verifyStaticGWandMAC( self, host ):
1028 """
1029 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001030 if self.handle:
1031 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001032 # h1 arp -an
1033 cmd = host + " arp -an "
1034 self.handle.sendline( cmd )
1035 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001036 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001037 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001038 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001039 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001040 main.log.error( self.name + ": TIMEOUT exception found" )
1041 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001042 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001043 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001044 main.log.error( self.name + ": EOF exception found" )
1045 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001046 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001047 except Exception:
1048 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001049 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001050
Jon Hall7eb38402015-01-08 17:19:54 -08001051 def getMacAddress( self, host ):
1052 """
1053 Verifies the host's ip configured or not."""
1054 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001055 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001056 response = self.execute(
1057 cmd=host +
1058 " ifconfig",
1059 prompt="mininet>",
1060 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001061 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001062 main.log.error( self.name + ": EOF exception found" )
1063 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001064 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001065 except Exception:
1066 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001067 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001068
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001069 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001070 macAddressSearch = re.search( pattern, response, re.I )
1071 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001072 main.log.info(
1073 self.name +
1074 ": Mac-Address of Host " +
1075 host +
1076 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001077 macAddress )
1078 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001079 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001080 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001081
Jon Hall7eb38402015-01-08 17:19:54 -08001082 def getInterfaceMACAddress( self, host, interface ):
1083 """
1084 Return the IP address of the interface on the given host"""
1085 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001086 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001087 response = self.execute( cmd=host + " ifconfig " + interface,
1088 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001089 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001090 main.log.error( self.name + ": EOF exception found" )
1091 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001092 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001093 except Exception:
1094 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001095 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001096
1097 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001098 macAddressSearch = re.search( pattern, response, re.I )
1099 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001100 main.log.info( "No mac address found in %s" % response )
1101 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001102 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001103 main.log.info(
1104 "Mac-Address of " +
1105 host +
1106 ":" +
1107 interface +
1108 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001109 macAddress )
1110 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001111 else:
1112 main.log.error( "Connection failed to the host" )
1113
You Wang5da39c82018-04-26 22:55:08 -07001114 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001115 """
1116 Verifies the host's ip configured or not."""
1117 if self.handle:
1118 try:
1119 response = self.execute(
1120 cmd=host +
1121 " ifconfig",
1122 prompt="mininet>",
1123 timeout=10 )
1124 except pexpect.EOF:
1125 main.log.error( self.name + ": EOF exception found" )
1126 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001127 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001128 except Exception:
1129 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001130 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001131
sathishmad953462015-12-03 17:42:07 +05301132 pattern = ''
1133 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001134 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301135 else:
Jon Hall439c8912016-04-15 02:22:03 -07001136 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001137 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001138 if not ipAddressSearch:
1139 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001140 main.log.info(
1141 self.name +
1142 ": IP-Address of Host " +
1143 host +
1144 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001145 ipAddressSearch.group( 1 ) )
1146 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001147 else:
1148 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001149
Jon Hall7eb38402015-01-08 17:19:54 -08001150 def getSwitchDPID( self, switch ):
1151 """
1152 return the datapath ID of the switch"""
1153 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001154 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001155 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001156 response = self.execute(
1157 cmd=cmd,
1158 prompt="mininet>",
1159 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001160 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001161 main.log.error( self.name + ": EOF exception found" )
1162 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001163 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001164 except Exception:
1165 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001166 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001167 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001168 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001169 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001170 main.log.info(
1171 "Couldn't find DPID for switch %s, found: %s" %
1172 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001173 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001174 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001175 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001176 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001177
Jon Hall7eb38402015-01-08 17:19:54 -08001178 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001179 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001180 self.handle.sendline( "" )
1181 self.expect( "mininet>" )
1182 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001183 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001184 response = self.execute(
1185 cmd=cmd,
1186 prompt="mininet>",
1187 timeout=10 )
1188 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001189 response = self.handle.before
1190 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001191 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001192 main.log.error( self.name + ": TIMEOUT exception found" )
1193 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001194 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001195 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001196 main.log.error( self.name + ": EOF exception found" )
1197 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001198 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001199 except Exception:
1200 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001201 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001202
Jon Hall7eb38402015-01-08 17:19:54 -08001203 def getInterfaces( self, node ):
1204 """
1205 return information dict about interfaces connected to the node"""
1206 if self.handle:
1207 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001208 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001209 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001210 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001211 response = self.execute(
1212 cmd=cmd,
1213 prompt="mininet>",
1214 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001215 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001216 main.log.error( self.name + ": EOF exception found" )
1217 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001218 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001219 except Exception:
1220 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001221 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001222 return response
1223 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001224 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001225
Jon Hall7eb38402015-01-08 17:19:54 -08001226 def dump( self ):
1227 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001228 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001229 response = self.execute(
1230 cmd='dump',
1231 prompt='mininet>',
1232 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001233 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001234 main.log.error( self.name + ": EOF exception found" )
1235 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001236 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001237 except Exception:
1238 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001239 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001240 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001241
Jon Hall7eb38402015-01-08 17:19:54 -08001242 def intfs( self ):
1243 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001244 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001245 response = self.execute(
1246 cmd='intfs',
1247 prompt='mininet>',
1248 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001249 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001250 main.log.error( self.name + ": EOF exception found" )
1251 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001252 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001253 except Exception:
1254 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001255 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001256 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001257
Jon Hall7eb38402015-01-08 17:19:54 -08001258 def net( self ):
1259 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001260 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001261 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001262 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001263 main.log.error( self.name + ": EOF exception found" )
1264 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001265 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001266 except Exception:
1267 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001268 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001269 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001270
Devin Lima7cfdbd2017-09-29 15:02:22 -07001271 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001272 main.log.info( self.name + ": List network links" )
1273 try:
1274 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001275 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001276 except pexpect.EOF:
1277 main.log.error( self.name + ": EOF exception found" )
1278 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001279 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001280 except Exception:
1281 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001282 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001283 return response
1284
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001285 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001286 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001287 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001288
kelvin-onlab7cce9382015-07-17 10:21:03 -07001289 @parm:
1290 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1291 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001292 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001293 try:
1294 for host1 in hosts:
1295 for host2 in hosts:
1296 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001297 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1298 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001299 except Exception:
1300 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001301 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001302
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001303 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001304 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001305 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1306 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001307
kelvin-onlab7cce9382015-07-17 10:21:03 -07001308 @parm:
1309 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1310 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001311 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001312 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1313 try:
1314 # Setup the mininet command
1315 cmd1 = 'iperf ' + host1 + " " + host2
1316 self.handle.sendline( cmd1 )
1317 outcome = self.handle.expect( "mininet>", timeout )
1318 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001319
kelvin-onlab7cce9382015-07-17 10:21:03 -07001320 # checks if there are results in the mininet response
1321 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001322 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001323 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001324 response = response.split( "\r\n" )
1325 response = response[ len( response )-2 ]
1326 response = response.split( ": " )
1327 response = response[ len( response )-1 ]
1328 response = response.replace( "[", "" )
1329 response = response.replace( "]", "" )
1330 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001331
kelvin-onlab7cce9382015-07-17 10:21:03 -07001332 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001333 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001334
kelvin-onlab7cce9382015-07-17 10:21:03 -07001335 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001336 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001337 if len( bandwidth ) == 2:
1338 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001339 return main.TRUE
1340 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001341 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001342 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001343 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001344 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001345 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001346 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001347 main.log.error( self.name + ": TIMEOUT exception found" )
1348 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001349 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001350 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001351 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001352 self.handle.expect( "Interrupt" )
1353 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001354 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001355 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001356 main.log.error( self.name + ": EOF exception found" )
1357 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001358 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001359 except Exception:
1360 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001361 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001362
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001363 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001364 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1365 try:
1366 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001367 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001368 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001369 outcome1 = self.handle.expect( "mininet>" )
1370 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001371 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001372 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001373 response1 = self.handle.before
1374 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001375 print response1, response2
1376 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001377 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001378 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001379 return main.TRUE
1380 else:
1381 main.log.error( self.name + ": iperf test failed" )
1382 return main.FALSE
1383 except pexpect.TIMEOUT:
1384 main.log.error( self.name + ": TIMEOUT exception found" )
1385 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001386 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001387 self.handle.expect( "Interrupt" )
1388 self.handle.expect( "mininet>" )
1389 return main.FALSE
1390 except pexpect.EOF:
1391 main.log.error( self.name + ": EOF exception found" )
1392 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001393 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001394 except Exception:
1395 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001396 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001397
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001398 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001399 '''
GlennRC61321f22015-07-16 13:36:54 -07001400 Runs the iperfudp function with a given set of hosts and specified
1401 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001402
GlennRC61321f22015-07-16 13:36:54 -07001403 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001404 bandwidth: the targeted bandwidth, in megabits ('M')
1405 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001406 try:
1407 for host1 in hosts:
1408 for host2 in hosts:
1409 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001410 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1411 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001412 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001413 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001414 return main.FALSE
1415 except Exception:
1416 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001417 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001418
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001419 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001420 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001421 Creates an iperf UDP test with a specific bandwidth.
1422 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001423
kelvin-onlab7cce9382015-07-17 10:21:03 -07001424 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001425 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1426 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001427 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001428 try:
1429 # setup the mininet command
1430 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001431 self.handle.sendline( cmd )
1432 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001433 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001434
kelvin-onlab7cce9382015-07-17 10:21:03 -07001435 # check if there are in results in the mininet response
1436 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001437 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001438 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001439 response = response.split( "\r\n" )
1440 response = response[ len( response )-2 ]
1441 response = response.split( ": " )
1442 response = response[ len( response )-1 ]
1443 response = response.replace( "[", "" )
1444 response = response.replace( "]", "" )
1445 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001446
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001447 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001448
kelvin-onlab7cce9382015-07-17 10:21:03 -07001449 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001450 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001451 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001452 # if one entry is blank then something is wrong
1453 for item in mnBandwidth:
1454 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001455 main.log.error( self.name + ": Could not parse iperf output" )
1456 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001457 return main.FALSE
1458 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001459 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001460 return main.TRUE
1461 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001462 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001463 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001464
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001465 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001466 main.log.error( self.name + ": TIMEOUT exception found" )
1467 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001468 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001469 except pexpect.EOF:
1470 main.log.error( self.name + ": EOF exception found" )
1471 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001472 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001473 except Exception:
1474 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001475 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001476
Jon Hall7eb38402015-01-08 17:19:54 -08001477 def nodes( self ):
1478 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001479 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001480 response = self.execute(
1481 cmd='nodes',
1482 prompt='mininet>',
1483 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001484 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001485 main.log.error( self.name + ": EOF exception found" )
1486 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001487 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001488 except Exception:
1489 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001490 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001491 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001492
Jon Hall7eb38402015-01-08 17:19:54 -08001493 def pingpair( self ):
1494 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001495 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001496 response = self.execute(
1497 cmd='pingpair',
1498 prompt='mininet>',
1499 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001500 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001501 main.log.error( self.name + ": EOF exception found" )
1502 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001503 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001504 except Exception:
1505 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001506 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001507
Jon Hall7eb38402015-01-08 17:19:54 -08001508 if re.search( ',\s0\%\spacket\sloss', response ):
1509 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001510 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001511 else:
alisone4121a92016-11-22 16:31:36 -08001512 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001513 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001514
Jon Hall7eb38402015-01-08 17:19:54 -08001515 def link( self, **linkargs ):
1516 """
GlennRCed771242016-01-13 17:02:47 -08001517 Bring link( s ) between two nodes up or down
1518 """
Jon Hall6094a362014-04-11 14:46:56 -07001519 try:
GlennRCed771242016-01-13 17:02:47 -08001520 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1521 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1522 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1523 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1524
1525 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1526 cmd = "link {} {} {}".format( end1, end2, option )
1527 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001528 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001529 response = self.handle.before
1530 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001531 if "not in network" in response:
1532 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1533 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001534 return main.TRUE
1535 except pexpect.TIMEOUT:
1536 main.log.exception( self.name + ": Command timed out" )
1537 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001538 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001539 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001540 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001541 except Exception:
1542 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001543 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001544
pingping-lin8244a3b2015-09-16 13:36:56 -07001545 def switch( self, **switchargs ):
1546 """
1547 start/stop a switch
1548 """
1549 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1550 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1551 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1552 command = "switch " + str( sw ) + " " + str( option )
1553 main.log.info( command )
1554 try:
1555 self.handle.sendline( command )
1556 self.handle.expect( "mininet>" )
1557 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001558 main.log.error( self.name + ": TIMEOUT exception found" )
1559 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001560 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001561 except pexpect.EOF:
1562 main.log.error( self.name + ": EOF exception found" )
1563 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001564 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001565 return main.TRUE
1566
pingping-lin5bb663b2015-09-24 11:47:50 -07001567 def node( self, nodeName, commandStr ):
1568 """
1569 Carry out a command line on a given node
1570 @parm:
1571 nodeName: the node name in Mininet testbed
1572 commandStr: the command line will be carried out on the node
1573 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1574 """
1575 command = str( nodeName ) + " " + str( commandStr )
1576 main.log.info( command )
1577
1578 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001579 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001580 if re.search( "Unknown command", response ):
1581 main.log.warn( response )
1582 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001583 if re.search( "Permission denied", response ):
1584 main.log.warn( response )
1585 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001586 except pexpect.EOF:
1587 main.log.error( self.name + ": EOF exception found" )
1588 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001589 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001590 main.log.info( " response is :" )
1591 main.log.info( response )
1592 return response
1593
Jon Hall7eb38402015-01-08 17:19:54 -08001594 def yank( self, **yankargs ):
1595 """
1596 yank a mininet switch interface to a host"""
1597 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001598 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001599 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1600 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001601 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001602 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001603 response = self.execute(
1604 cmd=command,
1605 prompt="mininet>",
1606 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001607 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001608 main.log.error( self.name + ": EOF exception found" )
1609 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001610 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001611 except Exception:
1612 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001613 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001614 return main.TRUE
1615
Jon Hall7eb38402015-01-08 17:19:54 -08001616 def plug( self, **plugargs ):
1617 """
1618 plug the yanked mininet switch interface to a switch"""
1619 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001620 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001621 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1622 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001623 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001624 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001625 response = self.execute(
1626 cmd=command,
1627 prompt="mininet>",
1628 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001629 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001630 main.log.error( self.name + ": EOF exception found" )
1631 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001632 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001633 except Exception:
1634 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001635 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001636 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001637
Jon Hall7eb38402015-01-08 17:19:54 -08001638 def dpctl( self, **dpctlargs ):
1639 """
1640 Run dpctl command on all switches."""
1641 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001642 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001643 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1644 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1645 command = "dpctl " + cmd + " " + str( cmdargs )
1646 try:
1647 response = self.execute(
1648 cmd=command,
1649 prompt="mininet>",
1650 timeout=10 )
1651 except pexpect.EOF:
1652 main.log.error( self.name + ": EOF exception found" )
1653 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001654 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001655 except Exception:
1656 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001657 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001658 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001659
kelvin-onlabd3b64892015-01-20 13:26:24 -08001660 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001661 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001662 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001663 try:
1664 fileInput = path + '/lib/Mininet/INSTALL'
1665 version = super( Mininet, self ).getVersion()
1666 pattern = 'Mininet\s\w\.\w\.\w\w*'
1667 for line in open( fileInput, 'r' ).readlines():
1668 result = re.match( pattern, line )
1669 if result:
1670 version = result.group( 0 )
1671 return version
1672 except Exception:
1673 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001674 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001675
kelvin-onlabd3b64892015-01-20 13:26:24 -08001676 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001677 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001678 Parameters:
1679 sw: The name of an OVS switch. Example "s1"
1680 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001681 The output of the command from the mininet cli
1682 or main.FALSE on timeout"""
1683 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001684 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001685 response = self.execute(
1686 cmd=command,
1687 prompt="mininet>",
1688 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001689 if response:
Jon Hallab611372018-02-21 15:26:05 -08001690 if "no bridge named" in response:
1691 main.log.error( self.name + ": Error in getSwController: " +
1692 self.handle.before )
1693 return main.FALSE
1694 else:
1695 return response
admin2a9548d2014-06-17 14:08:07 -07001696 else:
1697 return main.FALSE
1698 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001699 main.log.error( self.name + ": EOF exception found" )
1700 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001701 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001702 except Exception:
1703 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001704 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001705
Charles Chan029be652015-08-24 01:46:10 +08001706 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001707 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001708 Description:
1709 Assign switches to the controllers ( for ovs use only )
1710 Required:
1711 sw - Name of the switch. This can be a list or a string.
1712 ip - Ip addresses of controllers. This can be a list or a string.
1713 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001714 port - ONOS use port 6653, if no list of ports is passed, then
1715 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001716 ptcp - ptcp number, This can be a string or a list that has
1717 the same length as switch. This is optional and not required
1718 when using ovs switches.
1719 NOTE: If switches and ptcp are given in a list type they should have the
1720 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1721 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001722
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001723 Return:
1724 Returns main.TRUE if mininet correctly assigned switches to
1725 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001726 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001727 """
1728 assignResult = main.TRUE
1729 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001730 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001731 command = "sh ovs-vsctl set-controller "
1732 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001733 try:
1734 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001735 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001736 if isinstance( port, types.StringType ) or \
1737 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001738 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001739 elif isinstance( port, types.ListType ):
1740 main.log.error( self.name + ": Only one controller " +
1741 "assigned and a list of ports has" +
1742 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001743 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001744 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001745 main.log.error( self.name + ": Invalid controller port " +
1746 "number. Please specify correct " +
1747 "controller port" )
1748 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001749
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001750 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001751 if isinstance( port, types.StringType ) or \
1752 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001753 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001754 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1755 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001756 elif isinstance( port, types.ListType ):
1757 if ( len( ip ) != len( port ) ):
1758 main.log.error( self.name + ": Port list = " +
1759 str( len( port ) ) +
1760 "should be the same as controller" +
1761 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001762 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001763 else:
1764 onosIp = ""
1765 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001766 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1767 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001768 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001769 main.log.error( self.name + ": Invalid controller port " +
1770 "number. Please specify correct " +
1771 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001772 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001773 else:
1774 main.log.error( self.name + ": Invalid ip address" )
1775 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001776
1777 if isinstance( sw, types.StringType ):
1778 command += sw + " "
1779 if ptcp:
1780 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001781 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001782 elif isinstance( ptcp, types.ListType ):
1783 main.log.error( self.name + ": Only one switch is " +
1784 "being set and multiple PTCP is " +
1785 "being passed " )
1786 else:
1787 main.log.error( self.name + ": Invalid PTCP" )
1788 ptcp = ""
1789 command += onosIp
1790 commandList.append( command )
1791
1792 elif isinstance( sw, types.ListType ):
1793 if ptcp:
1794 if isinstance( ptcp, types.ListType ):
1795 if len( ptcp ) != len( sw ):
1796 main.log.error( self.name + ": PTCP length = " +
1797 str( len( ptcp ) ) +
1798 " is not the same as switch" +
1799 " length = " +
1800 str( len( sw ) ) )
1801 return main.FALSE
1802 else:
1803 for switch, ptcpNum in zip( sw, ptcp ):
1804 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001805 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001806 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001807 tempCmd += onosIp
1808 commandList.append( tempCmd )
1809 else:
1810 main.log.error( self.name + ": Invalid PTCP" )
1811 return main.FALSE
1812 else:
1813 for switch in sw:
1814 tempCmd = "sh ovs-vsctl set-controller "
1815 tempCmd += switch + " " + onosIp
1816 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001817 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001818 main.log.error( self.name + ": Invalid switch type " )
1819 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001820
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001821 for cmd in commandList:
1822 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001823 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08001824 if "no bridge named" in self.handle.before:
1825 main.log.error( self.name + ": Error in assignSwController: " +
1826 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001827 except pexpect.TIMEOUT:
1828 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1829 return main.FALSE
1830 except pexpect.EOF:
1831 main.log.error( self.name + ": EOF exception found" )
1832 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001833 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001834 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001835 except pexpect.EOF:
1836 main.log.error( self.name + ": EOF exception found" )
1837 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001838 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001839 except Exception:
1840 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001841 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001842
kelvin-onlabd3b64892015-01-20 13:26:24 -08001843 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001844 """
1845 Removes the controller target from sw"""
1846 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001847 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001848 response = self.execute(
1849 cmd=command,
1850 prompt="mininet>",
1851 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001852 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001853 main.log.error( self.name + ": EOF exception found" )
1854 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001855 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001856 except Exception:
1857 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001858 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001859 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001860 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001861
kelvin-onlabd3b64892015-01-20 13:26:24 -08001862 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001863 """
Jon Hallb1290e82014-11-18 16:17:48 -05001864 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001865 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001866 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001867 NOTE: cannot currently specify what type of switch
1868 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001869 sw = name of the new switch as a string
1870 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001871 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001872 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001873 """
1874 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001875 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001876 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001877 response = self.execute(
1878 cmd=command,
1879 prompt="mininet>",
1880 timeout=10 )
1881 if re.search( "already exists!", response ):
1882 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001883 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001884 elif re.search( "Error", response ):
1885 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001886 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001887 elif re.search( "usage:", response ):
1888 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001889 return main.FALSE
1890 else:
1891 return main.TRUE
1892 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001893 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001894 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001895 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001896 except Exception:
1897 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001898 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001899
kelvin-onlabd3b64892015-01-20 13:26:24 -08001900 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001901 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001902 delete a switch from the mininet topology
1903 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001904 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001905 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001906 sw = name of the switch as a string
1907 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001908 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001909 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001910 response = self.execute(
1911 cmd=command,
1912 prompt="mininet>",
1913 timeout=10 )
1914 if re.search( "no switch named", response ):
1915 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001916 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001917 elif re.search( "Error", response ):
1918 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001919 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001920 elif re.search( "usage:", response ):
1921 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001922 return main.FALSE
1923 else:
1924 return main.TRUE
1925 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001926 main.log.error( self.name + ": EOF exception found" )
1927 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001928 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001929 except Exception:
1930 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001931 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001932
You Wangdb8cd0a2016-05-26 15:19:45 -07001933 def getSwitchRandom( self, timeout=60, nonCut=True ):
1934 """
1935 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001936 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001937 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001938 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07001939 it just randomly returns one switch from all current switches in
1940 Mininet.
1941 Returns the name of the chosen switch.
1942 """
1943 import random
1944 candidateSwitches = []
1945 try:
1946 if not nonCut:
1947 switches = self.getSwitches( timeout=timeout )
1948 assert len( switches ) != 0
1949 for switchName in switches.keys():
1950 candidateSwitches.append( switchName )
1951 else:
1952 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001953 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001954 return None
1955 self.graph.update( graphDict )
1956 candidateSwitches = self.graph.getNonCutVertices()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001957 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001958 return None
1959 elif len( candidateSwitches ) == 0:
1960 main.log.info( self.name + ": No candidate switch for deletion" )
1961 return None
1962 else:
1963 switch = random.sample( candidateSwitches, 1 )
1964 return switch[ 0 ]
1965 except KeyError:
1966 main.log.exception( self.name + ": KeyError exception found" )
1967 return None
1968 except AssertionError:
1969 main.log.exception( self.name + ": AssertionError exception found" )
1970 return None
1971 except Exception:
1972 main.log.exception( self.name + ": Uncaught exception" )
1973 return None
1974
1975 def delSwitchRandom( self, timeout=60, nonCut=True ):
1976 """
1977 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001978 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001979 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001980 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07001981 otherwise it just randomly delete one switch from all current
1982 switches in Mininet.
1983 Returns the name of the deleted switch
1984 """
1985 try:
1986 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001987 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001988 return None
1989 else:
1990 deletionResult = self.delSwitch( switch )
1991 if deletionResult:
1992 return switch
1993 else:
1994 return None
1995 except Exception:
1996 main.log.exception( self.name + ": Uncaught exception" )
1997 return None
1998
kelvin-onlabd3b64892015-01-20 13:26:24 -08001999 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002000 """
2001 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002002 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002003 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002004 NOTE: cannot currently specify what type of link
2005 required params:
2006 node1 = the string node name of the first endpoint of the link
2007 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002008 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002009 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002010 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002011 response = self.execute(
2012 cmd=command,
2013 prompt="mininet>",
2014 timeout=10 )
2015 if re.search( "doesnt exist!", response ):
2016 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002017 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002018 elif re.search( "Error", response ):
2019 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002020 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002021 elif re.search( "usage:", response ):
2022 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002023 return main.FALSE
2024 else:
2025 return main.TRUE
2026 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002027 main.log.error( self.name + ": EOF exception found" )
2028 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002029 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002030 except Exception:
2031 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002032 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002033
kelvin-onlabd3b64892015-01-20 13:26:24 -08002034 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002035 """
2036 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002037 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002038 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002039 required params:
2040 node1 = the string node name of the first endpoint of the link
2041 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002042 returns: main.FALSE on an error, else main.TRUE
2043 """
Jon Hallffb386d2014-11-21 13:43:38 -08002044 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002045 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002046 response = self.execute(
2047 cmd=command,
2048 prompt="mininet>",
2049 timeout=10 )
2050 if re.search( "no node named", response ):
2051 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002052 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002053 elif re.search( "Error", response ):
2054 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002055 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002056 elif re.search( "usage:", response ):
2057 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002058 return main.FALSE
2059 else:
2060 return main.TRUE
2061 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002062 main.log.error( self.name + ": EOF exception found" )
2063 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002064 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002065 except Exception:
2066 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002067 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002068
You Wangdb8cd0a2016-05-26 15:19:45 -07002069 def getLinkRandom( self, timeout=60, nonCut=True ):
2070 """
2071 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002072 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002073 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002074 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002075 it just randomly returns one link from all current links in
2076 Mininet.
2077 Returns the link as a list, e.g. [ 's1', 's2' ]
2078 """
2079 import random
2080 candidateLinks = []
2081 try:
2082 if not nonCut:
2083 links = self.getLinks( timeout=timeout )
2084 assert len( links ) != 0
2085 for link in links:
2086 # Exclude host-switch link
2087 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2088 continue
2089 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2090 else:
2091 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002092 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002093 return None
2094 self.graph.update( graphDict )
2095 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002096 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002097 return None
2098 elif len( candidateLinks ) == 0:
2099 main.log.info( self.name + ": No candidate link for deletion" )
2100 return None
2101 else:
2102 link = random.sample( candidateLinks, 1 )
2103 return link[ 0 ]
2104 except KeyError:
2105 main.log.exception( self.name + ": KeyError exception found" )
2106 return None
2107 except AssertionError:
2108 main.log.exception( self.name + ": AssertionError exception found" )
2109 return None
2110 except Exception:
2111 main.log.exception( self.name + ": Uncaught exception" )
2112 return None
2113
2114 def delLinkRandom( self, timeout=60, nonCut=True ):
2115 """
2116 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002117 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002118 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002119 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002120 otherwise it just randomly delete one link from all current links
2121 in Mininet.
2122 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2123 """
2124 try:
2125 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002126 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002127 return None
2128 else:
2129 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2130 if deletionResult:
2131 return link
2132 else:
2133 return None
2134 except Exception:
2135 main.log.exception( self.name + ": Uncaught exception" )
2136 return None
2137
kelvin-onlabd3b64892015-01-20 13:26:24 -08002138 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002139 """
Jon Hallb1290e82014-11-18 16:17:48 -05002140 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002141 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002142 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002143 NOTE: cannot currently specify what type of host
2144 required params:
2145 hostname = the string hostname
2146 optional key-value params
2147 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002148 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002149 """
2150 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002151 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002152 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002153 response = self.execute(
2154 cmd=command,
2155 prompt="mininet>",
2156 timeout=10 )
2157 if re.search( "already exists!", response ):
2158 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002159 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002160 elif re.search( "doesnt exists!", response ):
2161 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002162 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002163 elif re.search( "Error", response ):
2164 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002165 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002166 elif re.search( "usage:", response ):
2167 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002168 return main.FALSE
2169 else:
2170 return main.TRUE
2171 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002172 main.log.error( self.name + ": EOF exception found" )
2173 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002174 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002175 except Exception:
2176 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002177 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002178
kelvin-onlabd3b64892015-01-20 13:26:24 -08002179 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002180 """
2181 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002182 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002183 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002184 NOTE: this uses a custom mn function
2185 required params:
2186 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002187 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002188 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002189 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002190 response = self.execute(
2191 cmd=command,
2192 prompt="mininet>",
2193 timeout=10 )
2194 if re.search( "no host named", response ):
2195 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002196 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002197 elif re.search( "Error", response ):
2198 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002199 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002200 elif re.search( "usage:", response ):
2201 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002202 return main.FALSE
2203 else:
2204 return main.TRUE
2205 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002206 main.log.error( self.name + ": EOF exception found" )
2207 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002208 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002209 except Exception:
2210 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002211 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002212
Jon Hall7eb38402015-01-08 17:19:54 -08002213 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002214 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002215 Called at the end of the test to stop the mininet and
2216 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002217 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002218 try:
2219 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002220 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002221 timeout=2 )
2222 response = main.TRUE
2223 if i == 0:
2224 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002225 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002226 return main.TRUE
2227 # print "Disconnecting Mininet"
2228 if self.handle:
2229 self.handle.sendline( "exit" )
2230 self.handle.expect( "exit" )
2231 self.handle.expect( "(.*)" )
2232 else:
2233 main.log.error( "Connection failed to the host" )
2234 return response
2235 except pexpect.EOF:
2236 main.log.error( self.name + ": EOF exception found" )
2237 main.log.error( self.name + ": " + self.handle.before )
You Wangd4fae5c2018-08-22 13:56:49 -07002238 # Do not exit the entire test when pexpect.EOF is caught
2239 # FIXME: We might need to do something else here
2240 return main.ERROR
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002241 except Exception:
2242 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002243 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002244
Devin Lima7cfdbd2017-09-29 15:02:22 -07002245 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002246 """
Jon Hall21270ac2015-02-16 17:59:55 -08002247 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002248 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002249 main.FALSE if the pexpect handle does not exist.
2250
Jon Halld61331b2015-02-17 16:35:47 -08002251 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002252 """
Jon Halld61331b2015-02-17 16:35:47 -08002253 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002254 response = ''
2255 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002256 try:
Jon Halld80cc142015-07-06 13:36:05 -07002257 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002258 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002259 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002260 pexpect.EOF,
2261 pexpect.TIMEOUT ],
2262 timeout )
2263 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002264 main.log.info( "Exiting mininet.." )
2265 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002266 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002267 prompt=self.prompt,
2268 timeout=exitTimeout )
2269 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002270 self.handle.sendline( "sudo mn -c" )
2271 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002272
Jeremyd9e4eb12016-04-13 12:09:06 -07002273 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002274 main.log.info( " Mininet trying to exit while not " +
2275 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002276 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002277 elif i == 2:
2278 main.log.error( "Something went wrong exiting mininet" )
2279 elif i == 3: # timeout
2280 main.log.error( "Something went wrong exiting mininet " +
2281 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002282
You Wang18db8592018-04-02 13:52:03 -07002283 self.handle.sendline( "" )
2284 self.handle.expect( self.prompt )
2285 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2286
Hari Krishnab35c6d02015-03-18 11:13:51 -07002287 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002288 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002289 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002290 self.handle.sendline(
2291 "sudo kill -9 \`ps -ef | grep \"" +
2292 fileName +
2293 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002294 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002295 main.log.error( self.name + ": TIMEOUT exception found" )
2296 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002297 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002298 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002299 main.log.error( self.name + ": EOF exception found" )
2300 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002301 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002302 except Exception:
2303 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002304 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002305 else:
2306 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002307 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002308 return response
2309
YPZhang26a139e2016-04-25 14:01:55 -07002310 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002311 """
2312 Description:
2313 Sends arp message from mininet host for hosts discovery
2314 Required:
2315 host - hosts name
2316 Optional:
2317 ip - ip address that does not exist in the network so there would
2318 be no reply.
2319 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002320 if ethDevice:
2321 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002322 cmd = srcHost + " arping -c1 "
2323 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002324 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 -07002325 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002326 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002327 if output:
2328 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002329 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002330 i = self.handle.expect( [ "mininet>", "arping: " ] )
2331 if i == 0:
2332 return main.TRUE
2333 elif i == 1:
2334 response = self.handle.before + self.handle.after
2335 self.handle.expect( "mininet>" )
2336 response += self.handle.before + self.handle.after
2337 main.log.warn( "Error sending arping, output was: " +
2338 response )
2339 return main.FALSE
2340 except pexpect.TIMEOUT:
2341 main.log.error( self.name + ": TIMEOUT exception found" )
2342 main.log.warn( self.handle.before )
2343 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002344 except pexpect.EOF:
2345 main.log.error( self.name + ": EOF exception found" )
2346 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002347 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002348 except Exception:
2349 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002350 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002351
Jon Hall7eb38402015-01-08 17:19:54 -08002352 def decToHex( self, num ):
2353 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002354
Jon Hall7eb38402015-01-08 17:19:54 -08002355 def getSwitchFlowCount( self, switch ):
2356 """
2357 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002358 if self.handle:
2359 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2360 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002361 response = self.execute(
2362 cmd=cmd,
2363 prompt="mininet>",
2364 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002365 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002366 main.log.error( self.name + ": EOF exception found" )
2367 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002368 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002369 except Exception:
2370 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002371 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002372 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002373 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002374 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002375 main.log.info(
2376 "Couldn't find flows on switch %s, found: %s" %
2377 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002378 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002379 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002380 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002381 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002382
Jon Hall9ed8f372016-02-24 17:34:07 -08002383 def checkFlows( self, sw, dumpFormat=None ):
2384 if dumpFormat:
2385 command = "sh ovs-ofctl -F " + \
2386 dumpFormat + " dump-flows " + str( sw )
2387 else:
2388 command = "sh ovs-ofctl dump-flows " + str( sw )
2389 try:
2390 response = self.execute(
2391 cmd=command,
2392 prompt="mininet>",
2393 timeout=10 )
2394 return response
2395 except pexpect.EOF:
2396 main.log.error( self.name + ": EOF exception found" )
2397 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002398 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002399 except Exception:
2400 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002401 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002402
GlennRC68467eb2015-11-16 18:01:01 -08002403 def flowTableComp( self, flowTable1, flowTable2 ):
2404 # This function compares the selctors and treatments of each flow
2405 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002406 assert flowTable1, "flowTable1 is empty or None"
2407 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002408 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002409 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002410 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002411 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002412 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2413 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002414 for field in dFields:
2415 try:
2416 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002417 except KeyError:
2418 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002419 try:
2420 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002421 except KeyError:
2422 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002423 for i in range( len( flowTable1 ) ):
2424 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002425 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002426 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002427 returnValue = main.FALSE
2428 break
2429 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002430 except AssertionError:
2431 main.log.exception( "Nothing to compare" )
2432 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002433 except Exception:
2434 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002435 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002436
GlennRC528ad292015-11-12 10:38:18 -08002437 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002438 '''
GlennRC956ea742015-11-05 16:14:15 -08002439 Discription: Parses flows into json format.
2440 NOTE: this can parse any string thats separated with commas
2441 Arguments:
2442 Required:
2443 flows: a list of strings that represnt flows
2444 Optional:
2445 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2446 debug: prints out the final result
2447 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002448 '''
GlennRC528ad292015-11-12 10:38:18 -08002449 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002450 try:
2451 for flow in flowTable:
2452 jsonFlow = {}
2453 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002454 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002455 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002456 for i in range( len( parsedFlow ) ):
2457 item = parsedFlow[ i ]
2458 if item[ 0 ] == " ":
2459 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002460 # grab the selector and treatment from the parsed flow
2461 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002462 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002463 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002464 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002465 index = 0
2466 # parse the flags
2467 # NOTE: This only parses one flag
2468 flag = {}
2469 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002470 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002471 index += 1
2472 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002473 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002474 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002475 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002476 # the priority is stuck in the selecter so put it back
2477 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002478 if 'priority' in sel[0]:
2479 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002480 # parse selector
2481 criteria = []
2482 for item in sel:
2483 # this is the type of the packet e.g. "arp"
2484 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002485 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002486 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002487 field = item.split( "=" )
2488 criteria.append( { field[ 0 ]: field[ 1 ] } )
2489 selector = { "selector": { "criteria": sorted( criteria ) } }
2490 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002491 # get rid of the action part e.g. "action=output:2"
2492 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002493 treat = treat.split( "=" )
2494 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002495 # parse treatment
2496 action = []
2497 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002498 if ":" in item:
2499 field = item.split( ":" )
2500 action.append( { field[ 0 ]: field[ 1 ] } )
2501 else:
2502 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2503 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002504 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002505 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002506 # parse the rest of the flow
2507 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002508 field = item.split( "=" )
2509 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002510 # add the treatment and the selector to the json flow
2511 jsonFlow.update( selector )
2512 jsonFlow.update( treatment )
2513 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002514
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002515 if debug:
2516 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002517
You Wang91c37cf2016-05-23 09:39:42 -07002518 # add the json flow to the json flow table
2519 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002520
You Wang91c37cf2016-05-23 09:39:42 -07002521 return jsonFlowTable
2522
2523 except IndexError:
2524 main.log.exception( self.name + ": IndexError found" )
2525 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002526 except pexpect.EOF:
2527 main.log.error( self.name + ": EOF exception found" )
2528 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002529 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002530 except Exception:
2531 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002532 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002533
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002534 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002535 '''
2536 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002537 Each element is a flow.
2538 Arguments:
2539 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002540 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002541 a list of switches.
2542 Optional:
2543 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2544 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002545 '''
GlennRC956ea742015-11-05 16:14:15 -08002546 try:
2547 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002548 if isinstance( sw, list ):
2549 switches.extend( sw )
2550 else:
2551 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002552
2553 flows = []
2554 for s in switches:
2555 cmd = "sh ovs-ofctl dump-flows " + s
2556
GlennRC528ad292015-11-12 10:38:18 -08002557 if "1.0" == version:
2558 cmd += " -F OpenFlow10-table_id"
2559 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002560 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002561
2562 main.log.info( "Sending: " + cmd )
2563 self.handle.sendline( cmd )
2564 self.handle.expect( "mininet>" )
2565 response = self.handle.before
2566 response = response.split( "\r\n" )
2567 # dump the first two elements and the last
2568 # the first element is the command that was sent
2569 # the second is the table header
2570 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002571 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002572 flows.extend( response )
2573
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002574 if debug:
2575 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002576
GlennRC528ad292015-11-12 10:38:18 -08002577 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002578
GlennRC956ea742015-11-05 16:14:15 -08002579 except pexpect.EOF:
2580 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002581 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002582 except Exception:
2583 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002584 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002585
2586 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002587 '''
GlennRC956ea742015-11-05 16:14:15 -08002588 Discription: Checks whether the ID provided matches a flow ID in Mininet
2589 Arguments:
2590 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002591 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002592 a list of switches.
2593 flowId: the flow ID in hex format. Can also be a list of IDs
2594 Optional:
2595 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2596 debug: prints out the final result
2597 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2598 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002599 '''
GlennRC956ea742015-11-05 16:14:15 -08002600 try:
2601 main.log.info( "Getting flows from Mininet" )
2602 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002603 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002604 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002605
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002606 if debug:
2607 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002608
2609 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002610 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002611 result = False
2612 for f in flows:
2613 if flowId in f.get( 'cookie' ):
2614 result = True
2615 break
2616 # flowId is a list
2617 else:
2618 result = True
2619 # Get flow IDs from Mininet
2620 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2621 # Save the IDs that are not in Mininet
2622 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2623
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002624 if debug:
2625 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002626
2627 # Print out the IDs that are not in Mininet
2628 if absentIds:
2629 main.log.warn( "Absent ids: {}".format( absentIds ) )
2630 result = False
2631
2632 return main.TRUE if result else main.FALSE
2633
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002634 except pexpect.EOF:
2635 main.log.error( self.name + ": EOF exception found" )
2636 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002637 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002638 except Exception:
2639 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002640 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002641
Charles Chan029be652015-08-24 01:46:10 +08002642 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002643 """
Jon Hallefbd9792015-03-05 16:11:36 -08002644 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002645 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002646 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002647 self.handle.sendline( "" )
2648 self.handle.expect( "mininet>" )
2649 self.handle.sendline(
2650 "sh sudo tcpdump -n -i " +
2651 intf +
2652 " " +
2653 port +
2654 " -w " +
2655 filename.strip() +
2656 " &" )
2657 self.handle.sendline( "" )
2658 i = self.handle.expect( [ 'No\ssuch\device',
2659 'listening\son',
2660 pexpect.TIMEOUT,
2661 "mininet>" ],
2662 timeout=10 )
2663 main.log.warn( self.handle.before + self.handle.after )
2664 self.handle.sendline( "" )
2665 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002666 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002667 main.log.error(
2668 self.name +
2669 ": tcpdump - No such device exists. " +
2670 "tcpdump attempted on: " +
2671 intf )
admin2a9548d2014-06-17 14:08:07 -07002672 return main.FALSE
2673 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002674 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002675 return main.TRUE
2676 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002677 main.log.error(
2678 self.name +
2679 ": tcpdump command timed out! Check interface name," +
2680 " given interface was: " +
2681 intf )
admin2a9548d2014-06-17 14:08:07 -07002682 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002683 elif i == 3:
2684 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002685 return main.TRUE
2686 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002687 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002688 return main.FALSE
2689 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002690 main.log.error( self.name + ": EOF exception found" )
2691 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002692 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002693 except Exception:
2694 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002695 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002696
kelvin-onlabd3b64892015-01-20 13:26:24 -08002697 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002698 """
2699 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002700 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002701 self.handle.sendline( "sh sudo pkill tcpdump" )
2702 self.handle.expect( "mininet>" )
2703 self.handle.sendline( "" )
2704 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002705 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002706 main.log.error( self.name + ": TIMEOUT exception found" )
2707 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002708 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002709 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002710 main.log.error( self.name + ": EOF exception found" )
2711 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002712 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002713 except Exception:
2714 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002715 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002716
Jon Halld80cc142015-07-06 13:36:05 -07002717 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002718 """
2719 Read ports from a Mininet switch.
2720
2721 Returns a json structure containing information about the
2722 ports of the given switch.
2723 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002724 try:
2725 response = self.getInterfaces( nodeName )
2726 # TODO: Sanity check on response. log if no such switch exists
2727 ports = []
2728 for line in response.split( "\n" ):
2729 if not line.startswith( "name=" ):
2730 continue
2731 portVars = {}
2732 for var in line.split( "," ):
2733 key, value = var.split( "=" )
2734 portVars[ key ] = value
2735 isUp = portVars.pop( 'enabled', "True" )
2736 isUp = "True" in isUp
2737 if verbose:
2738 main.log.info( "Reading switch port %s(%s)" %
2739 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2740 mac = portVars[ 'mac' ]
2741 if mac == 'None':
2742 mac = None
2743 ips = []
2744 ip = portVars[ 'ip' ]
2745 if ip == 'None':
2746 ip = None
2747 ips.append( ip )
2748 name = portVars[ 'name' ]
2749 if name == 'None':
2750 name = None
2751 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2752 if name == 'lo':
2753 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2754 else:
2755 portNo = re.search( portRe, name ).group( 'port' )
2756 ports.append( { 'of_port': portNo,
2757 'mac': str( mac ).replace( '\'', '' ),
2758 'name': name,
2759 'ips': ips,
2760 'enabled': isUp } )
2761 return ports
2762 except pexpect.EOF:
2763 main.log.error( self.name + ": EOF exception found" )
2764 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002765 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002766 except Exception:
2767 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002768 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002769
You Wangdb8cd0a2016-05-26 15:19:45 -07002770 def getOVSPorts( self, nodeName ):
2771 """
2772 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2773
2774 Returns a list of dictionaries containing information about each
2775 port of the given switch.
2776 """
2777 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2778 try:
2779 response = self.execute(
2780 cmd=command,
2781 prompt="mininet>",
2782 timeout=10 )
2783 ports = []
2784 if response:
2785 for line in response.split( "\n" ):
2786 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2787 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002788 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002789 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2790 result = re.search( pattern, line )
2791 if result:
2792 index = result.group( 'index' )
2793 name = result.group( 'name' )
2794 # This port number is extracted from port name
2795 port = result.group( 'port' )
2796 mac = result.group( 'mac' )
2797 ports.append( { 'index': index,
2798 'name': name,
2799 'port': port,
2800 'mac': mac } )
2801 return ports
2802 except pexpect.EOF:
2803 main.log.error( self.name + ": EOF exception found" )
2804 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002805 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002806 except Exception:
2807 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002808 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002809
Devin Lima7cfdbd2017-09-29 15:02:22 -07002810 def getSwitches( self, verbose=False, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002811 """
2812 Read switches from Mininet.
2813
2814 Returns a dictionary whose keys are the switch names and the value is
2815 a dictionary containing information about the switch.
2816 """
Jon Halla22481b2015-07-28 17:46:01 -07002817 # NOTE: To support new Mininet switch classes, just append the new
2818 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002819
Jon Halla22481b2015-07-28 17:46:01 -07002820 # Regex patterns to parse 'dump' output
2821 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002822 # <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 -07002823 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002824 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2825 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2826 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002827 try:
2828 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2829 swRE = r"<(?P<class>" + switchClasses + r")" +\
2830 r"(?P<options>\{.*\})?\s" +\
2831 r"(?P<name>[^:]+)\:\s" +\
2832 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2833 r"\spid=(?P<pid>(\d)+)"
2834 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002835 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002836 output = {}
2837 dump = self.dump().split( "\n" )
2838 for line in dump:
2839 result = re.search( swRE, line, re.I )
2840 if result:
2841 name = result.group( 'name' )
2842 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2843 pid = result.group( 'pid' )
2844 swClass = result.group( 'class' )
2845 options = result.group( 'options' )
2846 if verbose:
2847 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2848 ports = self.getPorts( name )
2849 output[ name ] = { "dpid": dpid,
2850 "ports": ports,
2851 "swClass": swClass,
2852 "pid": pid,
2853 "options": options }
2854 return output
2855 except pexpect.EOF:
2856 main.log.error( self.name + ": EOF exception found" )
2857 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002858 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002859 except Exception:
2860 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002861 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002862
You Wangd66de192018-04-30 17:30:12 -07002863 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002864 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2865 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002866 """
2867 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002868 Optional:
2869 hostClass: it is used to match the class of the mininet host. It
2870 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002871 Returns a dictionary whose keys are the host names and the value is
2872 a dictionary containing information about the host.
2873 """
2874 # Regex patterns to parse dump output
2875 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002876 # <Host h1: pid=12725>
2877 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2878 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2879 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002880 # NOTE: Does not correctly match hosts with multi-links
2881 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2882 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002883 try:
You Wang53dba1e2018-02-02 17:45:44 -08002884 if not isinstance( hostClass, types.ListType ):
2885 hostClass = [ str( hostClass ) ]
2886 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002887 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2888 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2889 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002890 if update:
2891 # update mn port info
2892 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002893 # Get mininet dump
2894 dump = self.dump().split( "\n" )
2895 hosts = {}
2896 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002897 result = re.search( hostRE, line )
2898 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002899 name = result.group( 'name' )
2900 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002901 if getInterfaces:
2902 response = self.getInterfaces( name )
2903 # Populate interface info
2904 for line in response.split( "\n" ):
2905 if line.startswith( "name=" ):
2906 portVars = {}
2907 for var in line.split( "," ):
2908 key, value = var.split( "=" )
2909 portVars[ key ] = value
2910 isUp = portVars.pop( 'enabled', "True" )
2911 isUp = "True" in isUp
2912 if verbose:
2913 main.log.info( "Reading host port %s(%s)" %
2914 ( portVars[ 'name' ],
2915 portVars[ 'mac' ] ) )
2916 mac = portVars[ 'mac' ]
2917 if mac == 'None':
2918 mac = None
2919 ips = []
2920 ip = portVars[ 'ip' ]
2921 if ip == 'None':
2922 ip = None
2923 ips.append( ip )
2924 intfName = portVars[ 'name' ]
2925 if name == 'None':
2926 name = None
2927 interfaces.append( {
2928 "name": intfName,
2929 "ips": ips,
2930 "mac": str( mac ),
2931 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002932 hosts[ name ] = { "interfaces": interfaces }
2933 return hosts
2934 except pexpect.EOF:
2935 main.log.error( self.name + ": EOF exception found" )
2936 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002937 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002938 except Exception:
2939 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002940 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002941
Devin Lima7cfdbd2017-09-29 15:02:22 -07002942 def getLinks( self, timeout=20, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002943 """
2944 Gathers information about current Mininet links. These links may not
2945 be up if one of the ports is down.
2946
2947 Returns a list of dictionaries with link endpoints.
2948
2949 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002950 { 'node1': str( node1 name )
2951 'node2': str( node2 name )
2952 'port1': str( port1 of_port )
2953 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002954 Note: The port number returned is the eth#, not necessarily the of_port
2955 number. In Mininet, for OVS switch, these should be the same. For
2956 hosts, this is just the eth#.
2957 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002958 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002959 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002960 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002961
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002962 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002963 # s1-eth3<->s2-eth1 (OK OK)
2964 # s13-eth3<->h27-eth0 (OK OK)
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002965 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2966 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2967 links = []
2968 for line in response:
2969 match = re.search( linkRE, line )
2970 if match:
2971 node1 = match.group( 'node1' )
2972 node2 = match.group( 'node2' )
2973 port1 = match.group( 'port1' )
2974 port2 = match.group( 'port2' )
2975 links.append( { 'node1': node1,
2976 'node2': node2,
2977 'port1': port1,
2978 'port2': port2 } )
2979 return links
2980
2981 except pexpect.EOF:
2982 main.log.error( self.name + ": EOF exception found" )
2983 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002984 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002985 except Exception:
2986 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002987 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002988
2989 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002990 """
2991 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002992 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002993
Jon Hallafa8a472015-06-12 14:02:42 -07002994 Dependencies:
2995 1. numpy - "sudo pip install numpy"
2996 """
2997 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002998 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002999 try:
3000 mnDPIDs = []
3001 for swName, switch in switches.iteritems():
3002 mnDPIDs.append( switch[ 'dpid' ].lower() )
3003 mnDPIDs.sort()
3004 if switchesJson == "": # if rest call fails
3005 main.log.error(
3006 self.name +
3007 ".compareSwitches(): Empty JSON object given from ONOS" )
3008 return main.FALSE
3009 onos = switchesJson
3010 onosDPIDs = []
3011 for switch in onos:
3012 if switch[ 'available' ]:
3013 onosDPIDs.append(
3014 switch[ 'id' ].replace(
3015 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003016 '' ).replace(
3017 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003018 '' ).lower() )
3019 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003020
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003021 if mnDPIDs != onosDPIDs:
3022 switchResults = main.FALSE
3023 main.log.error( "Switches in MN but not in ONOS:" )
3024 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3025 main.log.error( str( list1 ) )
3026 main.log.error( "Switches in ONOS but not in MN:" )
3027 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3028 main.log.error( str( list2 ) )
3029 else: # list of dpid's match in onos and mn
3030 switchResults = main.TRUE
3031 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003032
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003033 # FIXME: this does not look for extra ports in ONOS, only checks that
3034 # ONOS has what is in MN
3035 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003036
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003037 # PORTS
3038 for name, mnSwitch in switches.iteritems():
3039 mnPorts = []
3040 onosPorts = []
3041 switchResult = main.TRUE
3042 for port in mnSwitch[ 'ports' ]:
3043 if port[ 'enabled' ]:
3044 mnPorts.append( int( port[ 'of_port' ] ) )
3045 for onosSwitch in portsJson:
3046 if onosSwitch[ 'device' ][ 'available' ]:
3047 if onosSwitch[ 'device' ][ 'id' ].replace(
3048 ':',
3049 '' ).replace(
3050 "of",
3051 '' ) == mnSwitch[ 'dpid' ]:
3052 for port in onosSwitch[ 'ports' ]:
3053 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003054 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003055 # onosPorts.append( 'local' )
3056 onosPorts.append( long( uint64( -2 ) ) )
3057 else:
3058 onosPorts.append( int( port[ 'port' ] ) )
3059 break
3060 mnPorts.sort( key=float )
3061 onosPorts.sort( key=float )
3062
3063 mnPortsLog = mnPorts
3064 onosPortsLog = onosPorts
3065 mnPorts = [ x for x in mnPorts ]
3066 onosPorts = [ x for x in onosPorts ]
3067
3068 # TODO: handle other reserved port numbers besides LOCAL
3069 # NOTE: Reserved ports
3070 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3071 # long( uint64( -2 ) )
3072 for mnPort in mnPortsLog:
3073 if mnPort in onosPorts:
3074 # don't set results to true here as this is just one of
3075 # many checks and it might override a failure
3076 mnPorts.remove( mnPort )
3077 onosPorts.remove( mnPort )
3078
3079 # NOTE: OVS reports this as down since there is no link
3080 # So ignoring these for now
3081 # TODO: Come up with a better way of handling these
3082 if 65534 in mnPorts:
3083 mnPorts.remove( 65534 )
3084 if long( uint64( -2 ) ) in onosPorts:
3085 onosPorts.remove( long( uint64( -2 ) ) )
3086 if len( mnPorts ): # the ports of this switch don't match
3087 switchResult = main.FALSE
3088 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3089 if len( onosPorts ): # the ports of this switch don't match
3090 switchResult = main.FALSE
3091 main.log.warn(
3092 "Ports in ONOS but not MN: " +
3093 str( onosPorts ) )
3094 if switchResult == main.FALSE:
3095 main.log.error(
3096 "The list of ports for switch %s(%s) does not match:" %
3097 ( name, mnSwitch[ 'dpid' ] ) )
3098 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3099 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3100 portsResults = portsResults and switchResult
3101 finalResults = finalResults and portsResults
3102 return finalResults
3103 except pexpect.EOF:
3104 main.log.error( self.name + ": EOF exception found" )
3105 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003106 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003107 except Exception:
3108 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003109 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003110
Jon Hallafa8a472015-06-12 14:02:42 -07003111 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003112 """
3113 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003114 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003115
Jon Hallafa8a472015-06-12 14:02:42 -07003116 """
Jon Hall7eb38402015-01-08 17:19:54 -08003117 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003118 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003119 try:
3120 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003121
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003122 mnLinks = []
3123 for l in links:
3124 try:
3125 node1 = switches[ l[ 'node1' ] ]
3126 node2 = switches[ l[ 'node2' ] ]
3127 enabled = True
3128 for port in node1[ 'ports' ]:
3129 if port[ 'of_port' ] == l[ 'port1' ]:
3130 enabled = enabled and port[ 'enabled' ]
3131 for port in node2[ 'ports' ]:
3132 if port[ 'of_port' ] == l[ 'port2' ]:
3133 enabled = enabled and port[ 'enabled' ]
3134 if enabled:
3135 mnLinks.append( l )
3136 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003137 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003138 if 2 * len( mnLinks ) == len( onos ):
3139 linkResults = main.TRUE
3140 else:
3141 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003142 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003143 "Mininet has " + str( len( mnLinks ) ) +
3144 " bidirectional links and ONOS has " +
3145 str( len( onos ) ) + " unidirectional links" )
3146
3147 # iterate through MN links and check if an ONOS link exists in
3148 # both directions
3149 for link in mnLinks:
3150 # TODO: Find a more efficient search method
3151 node1 = None
3152 port1 = None
3153 node2 = None
3154 port2 = None
3155 firstDir = main.FALSE
3156 secondDir = main.FALSE
3157 for swName, switch in switches.iteritems():
3158 if swName == link[ 'node1' ]:
3159 node1 = switch[ 'dpid' ]
3160 for port in switch[ 'ports' ]:
3161 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3162 port1 = port[ 'of_port' ]
3163 if node1 is not None and node2 is not None:
3164 break
3165 if swName == link[ 'node2' ]:
3166 node2 = switch[ 'dpid' ]
3167 for port in switch[ 'ports' ]:
3168 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3169 port2 = port[ 'of_port' ]
3170 if node1 is not None and node2 is not None:
3171 break
3172
3173 for onosLink in onos:
3174 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3175 ":", '' ).replace( "of", '' )
3176 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3177 ":", '' ).replace( "of", '' )
3178 onosPort1 = onosLink[ 'src' ][ 'port' ]
3179 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3180
3181 # check onos link from node1 to node2
3182 if str( onosNode1 ) == str( node1 ) and str(
3183 onosNode2 ) == str( node2 ):
3184 if int( onosPort1 ) == int( port1 ) and int(
3185 onosPort2 ) == int( port2 ):
3186 firstDir = main.TRUE
3187 else:
Jon Hallab611372018-02-21 15:26:05 -08003188 # The right switches, but wrong ports, could be
3189 # another link between these devices, or onos
3190 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003191 main.log.warn(
3192 'The port numbers do not match for ' +
3193 str( link ) +
3194 ' between ONOS and MN. When checking ONOS for ' +
3195 'link %s/%s -> %s/%s' %
3196 ( node1, port1, node2, port2 ) +
3197 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003198 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3199 '. This could be another link between these devices' +
3200 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003201
3202 # check onos link from node2 to node1
3203 elif ( str( onosNode1 ) == str( node2 ) and
3204 str( onosNode2 ) == str( node1 ) ):
3205 if ( int( onosPort1 ) == int( port2 )
3206 and int( onosPort2 ) == int( port1 ) ):
3207 secondDir = main.TRUE
3208 else:
Jon Hallab611372018-02-21 15:26:05 -08003209 # The right switches, but wrong ports, could be
3210 # another link between these devices, or onos
3211 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003212 main.log.warn(
3213 'The port numbers do not match for ' +
3214 str( link ) +
3215 ' between ONOS and MN. When checking ONOS for ' +
3216 'link %s/%s -> %s/%s' %
3217 ( node1, port1, node2, port2 ) +
3218 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003219 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3220 '. This could be another link between these devices' +
3221 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003222 else: # this is not the link you're looking for
3223 pass
3224 if not firstDir:
3225 main.log.error(
3226 'ONOS does not have the link %s/%s -> %s/%s' %
3227 ( node1, port1, node2, port2 ) )
3228 if not secondDir:
3229 main.log.error(
3230 'ONOS does not have the link %s/%s -> %s/%s' %
3231 ( node2, port2, node1, port1 ) )
3232 linkResults = linkResults and firstDir and secondDir
3233 return linkResults
3234 except pexpect.EOF:
3235 main.log.error( self.name + ": EOF exception found" )
3236 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003237 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003238 except Exception:
3239 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003240 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003241
Jon Hallafa8a472015-06-12 14:02:42 -07003242 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003243 """
Jon Hallafa8a472015-06-12 14:02:42 -07003244 Compare mn and onos Hosts.
3245 Since Mininet hosts are quiet, ONOS will only know of them when they
3246 speak. For this reason, we will only check that the hosts in ONOS
3247 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003248
Jon Hallafa8a472015-06-12 14:02:42 -07003249 Arguments:
3250 hostsJson: parsed json object from the onos hosts api
3251 Returns:
3252 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003253 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003254 try:
3255 hostResults = main.TRUE
3256 for onosHost in hostsJson:
3257 onosMAC = onosHost[ 'mac' ].lower()
3258 match = False
3259 for mnHost, info in hosts.iteritems():
3260 for mnIntf in info[ 'interfaces' ]:
3261 if onosMAC == mnIntf[ 'mac' ].lower():
3262 match = True
3263 for ip in mnIntf[ 'ips' ]:
3264 if ip in onosHost[ 'ipAddresses' ]:
3265 pass # all is well
3266 else:
3267 # misssing ip
3268 main.log.error( "ONOS host " +
3269 onosHost[ 'id' ] +
3270 " has a different IP(" +
3271 str( onosHost[ 'ipAddresses' ] ) +
3272 ") than the Mininet host(" +
3273 str( ip ) +
3274 ")." )
3275 output = json.dumps(
3276 onosHost,
3277 sort_keys=True,
3278 indent=4,
3279 separators=( ',', ': ' ) )
3280 main.log.info( output )
3281 hostResults = main.FALSE
3282 if not match:
3283 hostResults = main.FALSE
3284 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3285 "corresponding Mininet host." )
3286 output = json.dumps( onosHost,
3287 sort_keys=True,
3288 indent=4,
3289 separators=( ',', ': ' ) )
3290 main.log.info( output )
3291 return hostResults
3292 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003293 main.log.error( self.name + ": EOF exception found" )
3294 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003295 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003296 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003297 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003298 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003299
You Wangd66de192018-04-30 17:30:12 -07003300 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003301 """
3302 Description:
3303 Verify that all hosts have IP address assigned to them
3304 Optional:
3305 hostList: If specified, verifications only happen to the hosts
3306 in hostList
3307 prefix: at least one of the ip address assigned to the host
3308 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003309 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003310 Returns:
3311 main.TRUE if all hosts have specific IP address assigned;
3312 main.FALSE otherwise
3313 """
3314 try:
You Wangd66de192018-04-30 17:30:12 -07003315 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003316 if not hostList:
3317 hostList = hosts.keys()
3318 for hostName in hosts.keys():
3319 if hostName not in hostList:
3320 continue
3321 ipList = []
3322 self.handle.sendline( str( hostName ) + " ip a" )
3323 self.handle.expect( "mininet>" )
3324 ipa = self.handle.before
3325 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3326 ipList += re.findall( ipv4Pattern, ipa )
3327 # It's tricky to make regex for IPv6 addresses and this one is simplified
3328 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})/'
3329 ipList += re.findall( ipv6Pattern, ipa )
3330 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3331 if not ipList:
3332 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3333 else:
3334 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3335 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3336 else:
3337 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3338 hostList.remove( hostName )
3339 return main.FALSE if hostList else main.TRUE
3340 except KeyError:
3341 main.log.exception( self.name + ": host data not as expected: " + hosts )
3342 return None
3343 except pexpect.EOF:
3344 main.log.error( self.name + ": EOF exception found" )
3345 main.log.error( self.name + ": " + self.handle.before )
3346 main.cleanAndExit()
3347 except Exception:
3348 main.log.exception( self.name + ": Uncaught exception" )
3349 return None
3350
Jon Hallafa8a472015-06-12 14:02:42 -07003351 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003352 """
3353 Returns a list of all hosts
3354 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003355 try:
3356 self.handle.sendline( "" )
3357 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003358
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003359 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3360 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003361
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003362 handlePy = self.handle.before
3363 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3364 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003365
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003366 self.handle.sendline( "" )
3367 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003368
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003369 hostStr = handlePy.replace( "]", "" )
3370 hostStr = hostStr.replace( "'", "" )
3371 hostStr = hostStr.replace( "[", "" )
3372 hostStr = hostStr.replace( " ", "" )
3373 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003374
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003375 return hostList
3376 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003377 main.log.error( self.name + ": TIMEOUT exception found" )
3378 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003379 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003380 except pexpect.EOF:
3381 main.log.error( self.name + ": EOF exception found" )
3382 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003383 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003384 except Exception:
3385 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003386 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003387
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003388 def getSwitch( self ):
3389 """
3390 Returns a list of all switches
3391 Again, don't ask question just use it...
3392 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003393 try:
3394 # get host list...
3395 hostList = self.getHosts()
3396 # Make host set
3397 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003398
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003399 # Getting all the nodes in mininet
3400 self.handle.sendline( "" )
3401 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003402
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003403 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3404 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003405
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003406 handlePy = self.handle.before
3407 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3408 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003409
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003410 self.handle.sendline( "" )
3411 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003412
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003413 nodesStr = handlePy.replace( "]", "" )
3414 nodesStr = nodesStr.replace( "'", "" )
3415 nodesStr = nodesStr.replace( "[", "" )
3416 nodesStr = nodesStr.replace( " ", "" )
3417 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003418
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003419 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003420 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003421 nodesSet.discard( 'c0' )
3422 nodesSet.discard( 'c1' )
3423 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003424
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003425 switchSet = nodesSet - hostSet
3426 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003427
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003428 return switchList
3429 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003430 main.log.error( self.name + ": TIMEOUT exception found" )
3431 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003432 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003433 except pexpect.EOF:
3434 main.log.error( self.name + ": EOF exception found" )
3435 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003436 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003437 except Exception:
3438 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003439 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003440
You Wangdb8cd0a2016-05-26 15:19:45 -07003441 def getGraphDict( self, timeout=60, useId=True, includeHost=False ):
3442 """
3443 Return a dictionary which describes the latest Mininet topology data as a
3444 graph.
3445 An example of the dictionary:
3446 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3447 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3448 Each vertex should at least have an 'edges' attribute which describes the
3449 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003450 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003451 list of attributes.
3452 An example of the edges dictionary:
3453 'edges': { vertex2: { 'port': ..., 'weight': ... },
3454 vertex3: { 'port': ..., 'weight': ... } }
3455 If useId == True, dpid/mac will be used instead of names to identify
3456 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3457 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003458 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003459 in topology data.
3460 Note that link or switch that are brought down by 'link x x down' or 'switch
3461 x down' commands still show in the output of Mininet CLI commands such as
3462 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3463 recommended to use delLink() or delSwitch functions to simulate link/switch
3464 down, and addLink() or addSwitch to add them back.
3465 """
3466 graphDict = {}
3467 try:
3468 links = self.getLinks( timeout=timeout )
3469 portDict = {}
3470 if useId:
3471 switches = self.getSwitches()
3472 if includeHost:
3473 hosts = self.getHosts()
3474 for link in links:
3475 # FIXME: support 'includeHost' argument
3476 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3477 continue
3478 nodeName1 = link[ 'node1' ]
3479 nodeName2 = link[ 'node2' ]
3480 port1 = link[ 'port1' ]
3481 port2 = link[ 'port2' ]
3482 # Loop for two nodes
3483 for i in range( 2 ):
3484 # Get port index from OVS
3485 # The index extracted from port name may be inconsistent with ONOS
3486 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003487 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003488 portList = self.getOVSPorts( nodeName1 )
3489 if len( portList ) == 0:
3490 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3491 return None
3492 portDict[ nodeName1 ] = portList
3493 for port in portDict[ nodeName1 ]:
3494 if port[ 'port' ] == port1:
3495 portIndex = port[ 'index' ]
3496 break
3497 if portIndex == -1:
3498 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3499 return None
3500 if useId:
3501 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3502 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3503 else:
3504 node1 = nodeName1
3505 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003506 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003507 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003508 graphDict[ node1 ] = { 'edges': {},
3509 'dpid': switches[ nodeName1 ][ 'dpid' ],
3510 'name': nodeName1,
3511 'ports': switches[ nodeName1 ][ 'ports' ],
3512 'swClass': switches[ nodeName1 ][ 'swClass' ],
3513 'pid': switches[ nodeName1 ][ 'pid' ],
3514 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003515 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003516 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003517 else:
3518 # Assert node2 is not connected to any current links of node1
3519 assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003520 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
You Wangdb8cd0a2016-05-26 15:19:45 -07003521 # Swap two nodes/ports
3522 nodeName1, nodeName2 = nodeName2, nodeName1
3523 port1, port2 = port2, port1
3524 return graphDict
3525 except KeyError:
3526 main.log.exception( self.name + ": KeyError exception found" )
3527 return None
3528 except AssertionError:
3529 main.log.exception( self.name + ": AssertionError exception found" )
3530 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003531 except pexpect.EOF:
3532 main.log.error( self.name + ": EOF exception found" )
3533 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003534 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003535 except Exception:
3536 main.log.exception( self.name + ": Uncaught exception" )
3537 return None
3538
Devin Lima7cfdbd2017-09-29 15:02:22 -07003539 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003540 """
3541 updates the port address and status information for
3542 each port in mn"""
3543 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003544 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003545 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003546 self.handle.sendline( "" )
3547 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003548
Jon Hall7eb38402015-01-08 17:19:54 -08003549 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003550 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003551
Jon Hall7eb38402015-01-08 17:19:54 -08003552 self.handle.sendline( "" )
3553 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003554
Jon Hallb1290e82014-11-18 16:17:48 -05003555 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003556 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003557 main.log.error( self.name + ": TIMEOUT exception found" )
3558 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003559 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003560 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003561 main.log.error( self.name + ": EOF exception found" )
3562 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003563 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003564 except Exception:
3565 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003566 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003567
Jon Halld80cc142015-07-06 13:36:05 -07003568 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003569 """
3570 Add vlan tag to a host.
3571 Dependencies:
3572 This class depends on the "vlan" package
3573 $ sudo apt-get install vlan
3574 Configuration:
3575 Load the 8021q module into the kernel
3576 $sudo modprobe 8021q
3577
3578 To make this setup permanent:
3579 $ sudo su -c 'echo "8021q" >> /etc/modules'
3580 """
3581 if self.handle:
3582 try:
Jon Halld80cc142015-07-06 13:36:05 -07003583 # get the ip address of the host
3584 main.log.info( "Get the ip address of the host" )
3585 ipaddr = self.getIPAddress( host )
3586 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003587
Jon Halld80cc142015-07-06 13:36:05 -07003588 # remove IP from interface intf
3589 # Ex: h1 ifconfig h1-eth0 inet 0
3590 main.log.info( "Remove IP from interface " )
3591 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3592 self.handle.sendline( cmd2 )
3593 self.handle.expect( "mininet>" )
3594 response = self.handle.before
3595 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003596
Jon Halld80cc142015-07-06 13:36:05 -07003597 # create VLAN interface
3598 # Ex: h1 vconfig add h1-eth0 100
3599 main.log.info( "Create Vlan" )
3600 cmd3 = host + " vconfig add " + intf + " " + vlan
3601 self.handle.sendline( cmd3 )
3602 self.handle.expect( "mininet>" )
3603 response = self.handle.before
3604 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003605
Jon Halld80cc142015-07-06 13:36:05 -07003606 # assign the host's IP to the VLAN interface
3607 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3608 main.log.info( "Assign the host IP to the vlan interface" )
3609 vintf = intf + "." + vlan
3610 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3611 self.handle.sendline( cmd4 )
3612 self.handle.expect( "mininet>" )
3613 response = self.handle.before
3614 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003615
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003616 # update Mininet node variables
3617 main.log.info( "Update Mininet node variables" )
3618 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3619 self.handle.sendline( cmd5 )
3620 self.handle.expect( "mininet>" )
3621 response = self.handle.before
3622 main.log.info( "====> %s ", response )
3623
3624 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3625 self.handle.sendline( cmd6 )
3626 self.handle.expect( "mininet>" )
3627 response = self.handle.before
3628 main.log.info( "====> %s ", response )
3629
3630 return main.TRUE
3631 except pexpect.TIMEOUT:
3632 main.log.error( self.name + ": TIMEOUT exception found" )
3633 main.log.error( self.name + ": " + self.handle.before )
3634 main.cleanAndExit()
3635 except pexpect.EOF:
3636 main.log.error( self.name + ": EOF exception found" )
3637 main.log.error( self.name + ": " + self.handle.before )
3638 return main.FALSE
3639 except Exception:
3640 main.log.exception( self.name + ": Uncaught exception!" )
3641 return main.FALSE
3642
3643 def removeVLAN( self, host, intf ):
3644 """
3645 Remove vlan tag from a host.
3646 Dependencies:
3647 This class depends on the "vlan" package
3648 $ sudo apt-get install vlan
3649 Configuration:
3650 Load the 8021q module into the kernel
3651 $sudo modprobe 8021q
3652
3653 To make this setup permanent:
3654 $ sudo su -c 'echo "8021q" >> /etc/modules'
3655 """
3656 if self.handle:
3657 try:
3658 # get the ip address of the host
3659 main.log.info( "Get the ip address of the host" )
3660 ipaddr = self.getIPAddress( host )
3661
3662 # remove VLAN interface
3663 # Ex: h1 vconfig rem h1-eth0.100
3664 main.log.info( "Remove Vlan interface" )
3665 cmd2 = host + " vconfig rem " + intf
3666 self.handle.sendline( cmd2 )
3667 self.handle.expect( "mininet>" )
3668 response = self.handle.before
3669 main.log.info( "====> %s ", response )
3670
3671 # assign the host's IP to the original interface
3672 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3673 main.log.info( "Assign the host IP to the original interface" )
3674 original_intf = intf.split(".")[0]
3675 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3676 self.handle.sendline( cmd3 )
3677 self.handle.expect( "mininet>" )
3678 response = self.handle.before
3679 main.log.info( "====> %s ", response )
3680
3681 # update Mininet node variables
3682 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3683 self.handle.sendline( cmd4 )
3684 self.handle.expect( "mininet>" )
3685 response = self.handle.before
3686 main.log.info( "====> %s ", response )
3687
3688 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3689 self.handle.sendline( cmd5 )
3690 self.handle.expect( "mininet>" )
3691 response = self.handle.before
3692 main.log.info( "====> %s ", response )
3693
kaouthera3f13ca22015-05-05 15:01:41 -07003694 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003695 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003696 main.log.error( self.name + ": TIMEOUT exception found" )
3697 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003698 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003699 except pexpect.EOF:
3700 main.log.error( self.name + ": EOF exception found" )
3701 main.log.error( self.name + ": " + self.handle.before )
3702 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003703 except Exception:
3704 main.log.exception( self.name + ": Uncaught exception!" )
3705 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003706
Jon Hall892818c2015-10-20 17:58:34 -07003707 def createHostComponent( self, name ):
3708 """
3709 Creates a new mininet cli component with the same parameters as self.
3710 This new component is intended to be used to login to the hosts created
3711 by mininet.
3712
3713 Arguments:
3714 name - The string of the name of this component. The new component
3715 will be assigned to main.<name> .
3716 In addition, main.<name>.name = str( name )
3717 """
3718 try:
3719 # look to see if this component already exists
3720 getattr( main, name )
3721 except AttributeError:
3722 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003723 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3724 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003725 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003726 except pexpect.EOF:
3727 main.log.error( self.name + ": EOF exception found" )
3728 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003729 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003730 except Exception:
3731 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003732 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003733 else:
3734 # namespace is not clear!
3735 main.log.error( name + " component already exists!" )
3736 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003737 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003738
3739 def removeHostComponent( self, name ):
3740 """
3741 Remove host component
3742 Arguments:
3743 name - The string of the name of the component to delete.
3744 """
3745 try:
3746 # Get host component
3747 component = getattr( main, name )
3748 except AttributeError:
3749 main.log.error( "Component " + name + " does not exist." )
3750 return
3751 try:
3752 # Disconnect from component
3753 component.disconnect()
You Wangf32c6ed2018-08-23 17:10:22 -07003754 component.close_log_handles()
Jon Hall892818c2015-10-20 17:58:34 -07003755 # Delete component
3756 delattr( main, name )
3757 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003758 del( main.componentDictionary[ name ] )
You Wangf32c6ed2018-08-23 17:10:22 -07003759 except StandardError:
3760 self.log.exception( "Exception while closing log files for " + name )
3761 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003762 except pexpect.EOF:
3763 main.log.error( self.name + ": EOF exception found" )
3764 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003765 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003766 except Exception:
3767 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003768 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003769
3770 def startHostCli( self, host=None ):
3771 """
3772 Use the mininet m utility to connect to the host's cli
3773 """
3774 # These are fields that can be used by scapy packets. Initialized to None
3775 self.hostIp = None
3776 self.hostMac = None
3777 try:
3778 if not host:
3779 host = self.name
3780 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003781 self.handle.sendline( "cd" )
3782 self.handle.expect( self.hostPrompt )
3783 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003784 self.handle.expect( self.hostPrompt )
3785 return main.TRUE
3786 except pexpect.TIMEOUT:
3787 main.log.exception( self.name + ": Command timed out" )
3788 return main.FALSE
3789 except pexpect.EOF:
3790 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003791 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003792 except Exception:
3793 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003794 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003795
YPZhang801d46d2016-08-08 13:26:28 -07003796 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003797 '''
3798
YPZhang801d46d2016-08-08 13:26:28 -07003799 Args:
3800 devicename: switch name
3801 intf: port name on switch
3802 status: up or down
3803
3804 Returns: boolean to show success change status
3805
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003806 '''
YPZhang801d46d2016-08-08 13:26:28 -07003807 if status == "down" or status == "up":
3808 try:
3809 cmd = devicename + " ifconfig " + intf + " " + status
3810 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003811 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07003812 return main.TRUE
3813 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003814 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003815 return main.FALSE
3816 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003817 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003818 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003819 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003820 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003821 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003822 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003823 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003824 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003825 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003826 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003827 return main.FALSE
3828
You Wang6e5b48e2018-07-23 16:17:38 -07003829 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003830 """
You Wang6e5b48e2018-07-23 16:17:38 -07003831 Moves a host from one switch to another on the fly
3832 Optional:
3833 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3834 prefixLen: length of the host IP prefix
3835 ipv6: move an IPv6 host if True
3836 intfSuffix: suffix of the new interface after host movement
3837 vlan: vlan ID of the host. Use None for non-vlan host
3838 Note: The intf between host and oldSw when detached
3839 using detach(), will still show up in the 'net'
3840 cmd, because switch.detach() doesn't affect switch.intfs[]
3841 ( which is correct behavior since the interfaces
3842 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003843 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003844 if self.handle:
3845 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003846 newIntf = "%s-%s" % ( host, intfSuffix )
3847 commands = [
3848 # Bring link between oldSw-host down
3849 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3850 # Determine hostintf and Oldswitchintf
3851 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
3852 ]
3853 # Determine ip address of the host-oldSw interface
3854 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3855 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3856 commands += [
3857 # Determine mac address of the host-oldSw interface
3858 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3859 # Detach interface between oldSw-host
3860 "px " + oldSw + ".detach( sintf )",
3861 # Add link between host-newSw
3862 "py net.addLink(" + host + "," + newSw + ")",
3863 # Determine hostintf and Newswitchintf
3864 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3865 # Attach interface between newSw-host
3866 "px " + newSw + ".attach( sintf )",
3867 ]
3868 if vlan:
3869 vlanIntf = "%s.%s" % ( newIntf, vlan )
3870 commands += [
3871 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
3872 host + " ip link set up %s" % vlanIntf,
3873 "px hintf.name = '" + vlanIntf + "'",
3874 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
3875 ]
3876 newIntf = vlanIntf
3877 commands += [
3878 # Set mac address of the host-newSw interface
3879 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
3880 # Set IP address of the host-newSw interface
3881 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
3882 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
3883 ]
3884 if ipv6:
3885 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
3886 commands += [
3887 "net",
3888 host + " ifconfig"
3889 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003890 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003891 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003892 self.handle.sendline( cmd )
3893 self.handle.expect( "mininet>" )
3894 main.log.info( "====> %s ", self.handle.before )
3895 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003896 except pexpect.TIMEOUT:
3897 main.log.error( self.name + ": TIMEOUT exception found" )
3898 main.log.error( self.name + ": " + self.handle.before )
3899 main.cleanAndExit()
3900 except pexpect.EOF:
3901 main.log.error( self.name + ": EOF exception found" )
3902 main.log.error( self.name + ": " + self.handle.before )
3903 return main.FALSE
3904 except Exception:
3905 main.log.exception( self.name + ": Uncaught exception!" )
3906 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07003907
You Wang6e5b48e2018-07-23 16:17:38 -07003908 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
3909 macAddr=None, prefixLen=None, ipv6=False,
3910 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07003911 """
You Wang6e5b48e2018-07-23 16:17:38 -07003912 Moves a dual-homed host from one switch-pair to another pair on the fly
3913 Optional:
3914 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3915 prefixLen: length of the host IP prefix
3916 ipv6: move an IPv6 host if True
3917 intfSuffix1: suffix of the first new interface
3918 intfSuffix2: suffix of the second new interface
3919 bondSuffix: suffix of the new bond interface
3920 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07003921 """
You Wang7ea90582018-07-19 15:27:58 -07003922 if self.handle:
3923 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003924 bondIntf = "%s-%s" % ( host, bondSuffix )
3925 newIntf = "%s-%s" % ( host, intfSuffix1 )
3926 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07003927 commands = [
3928 # Bring link between oldSw-host down
3929 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3930 # Bring link between oldPairSw-host down
3931 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
3932 # Determine hostintf and Oldswitchintf
3933 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07003934 ]
3935 # Determine ip address of the host-oldSw interface
3936 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3937 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3938 commands += [
3939 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07003940 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3941 # Detach interface between oldSw-host
3942 "px " + oldSw + ".detach( sintf )",
3943 # Determine hostintf and Oldpairswitchintf
3944 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
3945 # Detach interface between oldPairSw-host
3946 "px " + oldPairSw + ".detach( sintfpair )",
3947 # Add link between host-newSw
3948 "py net.addLink(" + host + "," + newSw + ", 2)",
3949 # Add link between host-newPairSw
3950 "py net.addLink(" + host + "," + newPairSw + ")",
3951 # Determine hostintf and Newswitchintf
3952 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3953 # Determine hostintf and NewPairswitchintf
3954 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
3955 # Attach interface between newSw-host
3956 "px " + newSw + ".attach( sintf )",
3957 # Attach interface between newPairSw-host
3958 "px " + newPairSw + ".attach( sintfpair )",
3959 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07003960 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07003961 host + ' ip link set %s down' % newIntf,
3962 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07003963 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
3964 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07003965 host + ' ip addr flush dev %s' % newIntf,
3966 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07003967 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07003968 "px lowestIntf = min( [ hintf, hintfpair ] )",
3969 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07003970 "px lowestIntf.name = '" + bondIntf + "'",
3971 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07003972 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
3973 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07003974 ]
3975 if vlan:
3976 vlanIntf = "%s.%s" % ( bondIntf, vlan )
3977 commands += [
3978 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
3979 host + " ip link set up %s" % vlanIntf,
3980 "px lowestIntf.name = '" + vlanIntf + "'",
3981 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
3982 ]
3983 bondIntf = vlanIntf
3984 commands += [
3985 # Set macaddress of the host-newSw interface
3986 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07003987 # Set ipaddress of the host-newSw interface
3988 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
3989 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07003990 ]
You Wang6e5b48e2018-07-23 16:17:38 -07003991 if ipv6:
3992 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
3993 commands += [
3994 "net",
3995 host + " ifconfig"
3996 ]
You Wang7ea90582018-07-19 15:27:58 -07003997 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07003998 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07003999 self.handle.sendline( cmd )
4000 self.handle.expect( "mininet>" )
4001 main.log.info( "====> %s ", self.handle.before )
4002 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07004003 except pexpect.TIMEOUT:
4004 main.log.error( self.name + ": TIMEOUT exception found" )
4005 main.log.error( self.name + ": " + self.handle.before )
4006 main.cleanAndExit()
4007 except pexpect.EOF:
4008 main.log.error( self.name + ": EOF exception found" )
4009 main.log.error( self.name + ": " + self.handle.before )
4010 return main.FALSE
4011 except Exception:
4012 main.log.exception( self.name + ": Uncaught exception!" )
4013 return main.FALSE
4014
adminbae64d82013-08-01 10:50:15 -07004015if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004016 sys.modules[ __name__ ] = MininetCliDriver()