blob: ddd72b31e338f3ea04602539910dfab3d8128746 [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 Wang48381752018-05-07 13:50:57 -0700577 def discoverHosts( self, hostList=[], wait=1, dstIp="6.6.6.6", dstIp6="1020::3fe" ):
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700578 '''
You Wang48381752018-05-07 13:50:57 -0700579 Hosts in hostList will do a single ping to a non-existent address for ONOS to
580 discover them. A host will use ping/ping6 to send echo requests depending on if
581 it has IPv4/IPv6 addresses configured.
582 Optional:
583 hostList: a list of names of the hosts that need to be discovered. If not
584 specified mininet will send ping from all the hosts
585 wait: timeout for IPv4/IPv6 echo requests
586 dstIp: destination address used by IPv4 hosts
587 dstIp6: destination address used by IPv6 hosts
588 Returns:
589 main.TRUE if all ping packets were successfully sent. Otherwise main.FALSE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700590 '''
591 try:
You Wang48381752018-05-07 13:50:57 -0700592 if not hostList:
593 hosts = self.getHosts( getInterfaces=False )
594 hostList = hosts.keys()
595 discoveryResult = main.TRUE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700596 for host in hostList:
You 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 Wang48381752018-05-07 13:50:57 -0700601 cmd = "{} ping -c 1 -i 1 -W {} {}".format( host, wait, dstIp )
602 main.log.debug( "Sending IPv4 probe ping from host {}".format( host ) )
603 elif self.getIPAddress( host, proto='IPV6' ):
You Wang0b82aa52018-06-06 14:33:58 -0700604 flushCmd = "{} ip -6 neigh flush all".format( host )
You Wang48381752018-05-07 13:50:57 -0700605 cmd = "{} ping6 -c 1 -i 1 -W {} {}".format( host, wait, dstIp6 )
606 main.log.debug( "Sending IPv6 probe ping from host {}".format( host ) )
607 else:
608 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
609 discoveryResult = main.FALSE
610 if cmd:
You Wang0b82aa52018-06-06 14:33:58 -0700611 self.handle.sendline( flushCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700612 self.handle.expect( "mininet>" )
You Wang48381752018-05-07 13:50:57 -0700613 self.handle.sendline( cmd )
Jon Halla604fd42018-05-04 14:27:27 -0700614 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700615 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700616 except pexpect.TIMEOUT:
617 main.log.exception( self.name + ": TIMEOUT exception" )
618 response = self.handle.before
619 # NOTE: Send ctrl-c to make sure command is stopped
620 self.handle.send( "\x03" )
621 self.handle.expect( "Interrupt" )
622 response += self.handle.before + self.handle.after
623 self.handle.expect( "mininet>" )
624 response += self.handle.before + self.handle.after
625 main.log.debug( response )
626 return main.FALSE
627 except pexpect.EOF:
628 main.log.error( self.name + ": EOF exception found" )
629 main.log.error( self.name + ": " + self.handle.before )
630 main.cleanAndExit()
631 except Exception:
632 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800633 main.cleanAndExit()
634
635 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
636 """
637 Verify ping from each host in srcList to each host in dstList
638
639 acceptableFailed: max number of acceptable failed pings
640
641 Returns main.TRUE if all src hosts can reach all dst hosts
642 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
643 """
644 try:
645 main.log.info( "Verifying ping from each src host to each dst host" )
646 isReachable = main.TRUE
647 wait = int( wait )
648 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
649 pingResponse = "Ping output:\n"
650 failedPingsTotal = 0
651 for host in srcList:
652 pingResponse += str( str( host ) + " -> " )
653 for temp in dstList:
654 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700655 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
656 assert dstIP, "Not able to get IP address of host {}".format( temp )
657 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800658 while failedPings <= acceptableFailed:
659 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
660 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700661 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800662 response = self.handle.before
663 if re.search( ',\s0\%\spacket\sloss', response ):
664 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800665 break
666 else:
667 failedPings += 1
668 time.sleep(1)
669 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700670 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800671 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700672 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800673 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700674 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800675 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700676 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700677 except AssertionError:
678 main.log.exception( "" )
679 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700680 except pexpect.TIMEOUT:
681 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800682 response = self.handle.before
683 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700684 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800685 self.handle.expect( "Interrupt" )
686 response += self.handle.before + self.handle.after
687 self.handle.expect( "mininet>" )
688 response += self.handle.before + self.handle.after
689 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700690 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700691 except pexpect.EOF:
692 main.log.error( self.name + ": EOF exception found" )
693 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700694 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700695 except Exception:
696 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700697 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700698
Jon Hall7eb38402015-01-08 17:19:54 -0800699 def pingHost( self, **pingParams ):
700 """
Jon Hall3b489db2015-10-05 14:38:37 -0700701 Ping from one mininet host to another
702 Currently the only supported Params: SRC, TARGET, and WAIT
703 """
704 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700705 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700706 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800707 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700708 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700709 try:
Jon Hall61282e32015-03-19 11:34:11 -0700710 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800711 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700712 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700713 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700714 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800715 main.log.error(
716 self.name +
717 ": timeout when waiting for response from mininet" )
718 main.log.error( "response: " + str( self.handle.before ) )
719 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700720 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800721 main.log.error(
722 self.name +
723 ": timeout when waiting for response from mininet" )
724 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700725 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700726 if re.search( ',\s0\%\spacket\sloss', response ):
727 main.log.info( self.name + ": no packets lost, host is reachable" )
728 return main.TRUE
729 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800730 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700731 self.name +
732 ": PACKET LOST, HOST IS NOT REACHABLE" )
733 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800734 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800735 main.log.error( self.name + ": EOF exception found" )
736 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700737 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700738 except Exception:
739 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700740 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700741
742 def ping6pair( self, **pingParams ):
743 """
GlennRC2cf7d952015-09-11 16:32:13 -0700744 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700745 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000746 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700747 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
748 """
Jon Hall3b489db2015-10-05 14:38:37 -0700749 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700750 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700751 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530752 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700753 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700754 try:
755 main.log.info( "Sending: " + command )
756 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700757 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700758 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700759 if i == 1:
760 main.log.error(
761 self.name +
762 ": timeout when waiting for response from mininet" )
763 main.log.error( "response: " + str( self.handle.before ) )
764 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
765 if i == 1:
766 main.log.error(
767 self.name +
768 ": timeout when waiting for response from mininet" )
769 main.log.error( "response: " + str( self.handle.before ) )
770 response = self.handle.before
771 main.log.info( self.name + ": Ping Response: " + response )
772 if re.search( ',\s0\%\spacket\sloss', response ):
773 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700774 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700775 else:
alisone4121a92016-11-22 16:31:36 -0800776 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700777 self.name +
778 ": PACKET LOST, HOST IS NOT REACHABLE" )
779 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700780 except pexpect.EOF:
781 main.log.error( self.name + ": EOF exception found" )
782 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700783 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700784 except Exception:
785 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700786 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800787
You Wangdb927a52016-02-26 11:03:28 -0800788 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
789 """
790 Description:
791 Ping a set of destination host from host CLI.
792 Logging into a Mininet host CLI is required before calling this funtion.
793 Params:
794 dstIPList is a list of destination ip addresses
795 Returns:
796 main.TRUE if the destination host is reachable
797 main.FALSE otherwise
798 """
799 isReachable = main.TRUE
800 wait = int( wait )
801 cmd = "ping"
802 if IPv6:
803 cmd = cmd + "6"
804 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
805 try:
806 for dstIP in dstIPList:
807 pingCmd = cmd + " " + dstIP
808 self.handle.sendline( pingCmd )
809 i = self.handle.expect( [ self.hostPrompt,
810 '\*\*\* Unknown command: ' + pingCmd,
811 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700812 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700813 # For some reason we need to send something
814 # Otherwise ping results won't be read by handle
815 self.handle.sendline( "" )
816 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800817 if i == 0:
818 response = self.handle.before
819 if not re.search( ',\s0\%\spacket\sloss', response ):
820 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
821 isReachable = main.FALSE
822 elif i == 1:
823 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700824 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800825 elif i == 2:
826 main.log.error( self.name + ": timeout when waiting for response" )
827 isReachable = main.FALSE
828 else:
829 main.log.error( self.name + ": unknown response: " + self.handle.before )
830 isReachable = main.FALSE
831 except pexpect.TIMEOUT:
832 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800833 response = self.handle.before
834 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700835 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800836 self.handle.expect( "Interrupt" )
837 response += self.handle.before + self.handle.after
838 self.handle.expect( "mininet>" )
839 response += self.handle.before + self.handle.after
840 main.log.debug( response )
You Wangdb927a52016-02-26 11:03:28 -0800841 isReachable = main.FALSE
842 except pexpect.EOF:
843 main.log.error( self.name + ": EOF exception found" )
844 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700845 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800846 except Exception:
847 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700848 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800849 return isReachable
850
Jon Hall7eb38402015-01-08 17:19:54 -0800851 def checkIP( self, host ):
852 """
853 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700854 try:
855 if self.handle:
856 try:
857 response = self.execute(
858 cmd=host +
859 " ifconfig",
860 prompt="mininet>",
861 timeout=10 )
862 except pexpect.EOF:
863 main.log.error( self.name + ": EOF exception found" )
864 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700865 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700866
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700867 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
868 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
869 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
870 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
871 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
872 "[0-9]|25[0-5]|[0-9]{1,2})"
873 # pattern = "inet addr:10.0.0.6"
874 if re.search( pattern, response ):
875 main.log.info( self.name + ": Host Ip configured properly" )
876 return main.TRUE
877 else:
878 main.log.error( self.name + ": Host IP not found" )
879 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700880 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700881 main.log.error( self.name + ": Connection failed to the host" )
882 except Exception:
883 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700884 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800885
Jon Hall7eb38402015-01-08 17:19:54 -0800886 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800887 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700888 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800889 response = self.execute(
890 cmd="h1 /usr/sbin/sshd -D&",
891 prompt="mininet>",
892 timeout=10 )
893 response = self.execute(
894 cmd="h4 /usr/sbin/sshd -D&",
895 prompt="mininet>",
896 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700897 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800898 vars( self )[ key ] = connectargs[ key ]
899 response = self.execute(
900 cmd="xterm h1 h4 ",
901 prompt="mininet>",
902 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800903 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800904 main.log.error( self.name + ": EOF exception found" )
905 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700906 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700907 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800908 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700909 if self.flag == 0:
910 self.flag = 1
911 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800912 else:
adminbae64d82013-08-01 10:50:15 -0700913 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800914
You Wang6260ed52018-07-18 17:54:25 -0700915 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=24 ):
Jon Hall53c5e662016-04-13 16:06:56 -0700916 """
917 Moves a host from one switch to another on the fly
Jonghwan Hyun785471d2018-05-14 14:48:19 -0700918 If macAddr is specified, change MAC address of the host interface
919 to specified MAC address.
Jon Hall53c5e662016-04-13 16:06:56 -0700920 Note: The intf between host and oldSw when detached
921 using detach(), will still show up in the 'net'
922 cmd, because switch.detach() doesn't affect switch.intfs[]
923 ( which is correct behavior since the interfaces
924 haven't moved ).
925 """
926 if self.handle:
927 try:
928 # Bring link between oldSw-host down
929 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
930 "'," + "'down')"
931 print "cmd1= ", cmd
932 response = self.execute( cmd=cmd,
933 prompt="mininet>",
934 timeout=10 )
935
936 # Determine hostintf and Oldswitchintf
937 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
938 ")[0]"
939 print "cmd2= ", cmd
940 self.handle.sendline( cmd )
941 self.handle.expect( "mininet>" )
942
943 # Determine ip and mac address of the host-oldSw interface
944 cmd = "px ipaddr = hintf.IP()"
945 print "cmd3= ", cmd
946 self.handle.sendline( cmd )
947 self.handle.expect( "mininet>" )
948
Jonghwan Hyun785471d2018-05-14 14:48:19 -0700949 if macAddr is None:
950 cmd = "px macaddr = hintf.MAC()"
951 else:
952 cmd = 'px macaddr = "%s"' % macAddr
Jon Hall53c5e662016-04-13 16:06:56 -0700953 print "cmd3= ", cmd
954 self.handle.sendline( cmd )
955 self.handle.expect( "mininet>" )
956
957 # Detach interface between oldSw-host
958 cmd = "px " + oldSw + ".detach( sintf )"
959 print "cmd4= ", cmd
960 self.handle.sendline( cmd )
961 self.handle.expect( "mininet>" )
962
963 # Add link between host-newSw
964 cmd = "py net.addLink(" + host + "," + newSw + ")"
965 print "cmd5= ", cmd
966 self.handle.sendline( cmd )
967 self.handle.expect( "mininet>" )
968
969 # Determine hostintf and Newswitchintf
970 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jonghwan Hyun785471d2018-05-14 14:48:19 -0700971 ")[-1]"
Jon Hall53c5e662016-04-13 16:06:56 -0700972 print "cmd6= ", cmd
973 self.handle.sendline( cmd )
974 self.handle.expect( "mininet>" )
975
976 # Attach interface between newSw-host
977 cmd = "px " + newSw + ".attach( sintf )"
978 print "cmd3= ", cmd
979 self.handle.sendline( cmd )
980 self.handle.expect( "mininet>" )
981
982 # Set ipaddress of the host-newSw interface
Jonghwan Hyun785471d2018-05-14 14:48:19 -0700983 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf, " \
984 "prefixLen = %s )" % str( prefixLen )
Jon Hall53c5e662016-04-13 16:06:56 -0700985 print "cmd7 = ", cmd
986 self.handle.sendline( cmd )
987 self.handle.expect( "mininet>" )
988
989 # Set macaddress of the host-newSw interface
990 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
991 print "cmd8 = ", cmd
992 self.handle.sendline( cmd )
993 self.handle.expect( "mininet>" )
994
995 cmd = "net"
996 print "cmd9 = ", cmd
997 self.handle.sendline( cmd )
998 self.handle.expect( "mininet>" )
999 print "output = ", self.handle.before
1000
1001 # Determine ipaddress of the host-newSw interface
1002 cmd = host + " ifconfig"
1003 print "cmd10= ", cmd
1004 self.handle.sendline( cmd )
1005 self.handle.expect( "mininet>" )
1006 print "ifconfig o/p = ", self.handle.before
1007
1008 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001009
1010 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001011 main.log.error( self.name + ": TIMEOUT exception found" )
1012 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001013 main.cleanAndExit()
Jon Hall53c5e662016-04-13 16:06:56 -07001014 except pexpect.EOF:
1015 main.log.error( self.name + ": EOF exception found" )
1016 main.log.error( self.name + ": " + self.handle.before )
1017 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001018 except Exception:
1019 main.log.exception( self.name + ": Uncaught exception!" )
1020 return main.FALSE
Jon Hall53c5e662016-04-13 16:06:56 -07001021
You Wang6260ed52018-07-18 17:54:25 -07001022 def moveHostv6( self, host, oldSw, newSw, macAddr=None, prefixLen=64 ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001023 """
1024 Moves a host from one switch to another on the fly
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001025 If macAddr is specified, change MAC address of the host interface
1026 to specified MAC address.
kelvin-onlaba1484582015-02-02 15:46:20 -08001027 Note: The intf between host and oldSw when detached
1028 using detach(), will still show up in the 'net'
1029 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -07001030 ( which is correct behavior since the interfaces
1031 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -08001032 """
1033 if self.handle:
1034 try:
You Wang6260ed52018-07-18 17:54:25 -07001035 IP = str( self.getIPAddress( host, proto='IPV6' ) ) + "/" + str( prefixLen )
kelvin-onlaba1484582015-02-02 15:46:20 -08001036 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -07001037 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -08001038 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -08001039 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -08001040 response = self.execute( cmd=cmd,
1041 prompt="mininet>",
1042 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -07001043
kelvin-onlaba1484582015-02-02 15:46:20 -08001044 # Determine hostintf and Oldswitchintf
1045 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -08001046 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -08001047 print "cmd2= ", cmd
1048 self.handle.sendline( cmd )
1049 self.handle.expect( "mininet>" )
1050
shahshreya73537862015-02-11 15:15:24 -08001051 # Determine ip and mac address of the host-oldSw interface
You Wang6260ed52018-07-18 17:54:25 -07001052 cmd = 'px ipaddr = "{}"'.format( IP )
kelvin-onlaba1484582015-02-02 15:46:20 -08001053 print "cmd3= ", cmd
1054 self.handle.sendline( cmd )
1055 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -08001056
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001057 if macAddr is None:
1058 cmd = "px macaddr = hintf.MAC()"
1059 else:
1060 cmd = 'px macaddr = "%s"' % macAddr
shahshreya73537862015-02-11 15:15:24 -08001061 print "cmd3= ", cmd
1062 self.handle.sendline( cmd )
1063 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001064
kelvin-onlaba1484582015-02-02 15:46:20 -08001065 # Detach interface between oldSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001066 cmd = "px " + oldSw + ".detach(sintf)"
kelvin-onlaba1484582015-02-02 15:46:20 -08001067 print "cmd4= ", cmd
1068 self.handle.sendline( cmd )
1069 self.handle.expect( "mininet>" )
1070
1071 # Add link between host-newSw
1072 cmd = "py net.addLink(" + host + "," + newSw + ")"
1073 print "cmd5= ", cmd
1074 self.handle.sendline( cmd )
1075 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001076
kelvin-onlaba1484582015-02-02 15:46:20 -08001077 # Determine hostintf and Newswitchintf
1078 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001079 ")[-1]"
kelvin-onlaba1484582015-02-02 15:46:20 -08001080 print "cmd6= ", cmd
1081 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -07001082 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001083
1084 # Attach interface between newSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001085 cmd = "px " + newSw + ".attach(sintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001086 print "cmd6= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001087 self.handle.sendline( cmd )
1088 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -08001089
1090 # Set macaddress of the host-newSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001091 cmd = "px " + host + ".setMAC(mac = macaddr, intf = hintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001092 print "cmd7 = ", cmd
1093 self.handle.sendline( cmd )
1094 self.handle.expect( "mininet>" )
1095
1096 # Set ipaddress of the host-newSw interface
You Wang6260ed52018-07-18 17:54:25 -07001097 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf, " \
1098 "prefixLen = %s )" % str( prefixLen )
shahshreya73537862015-02-11 15:15:24 -08001099 print "cmd8 = ", cmd
1100 self.handle.sendline( cmd )
1101 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001102
Jon Hall439c8912016-04-15 02:22:03 -07001103 cmd = host + " ifconfig"
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001104 print "cmd9 =", cmd
1105 response = self.execute( cmd = cmd, prompt="mininet>", timeout=10 )
Jon Hall439c8912016-04-15 02:22:03 -07001106 print response
You Wang6260ed52018-07-18 17:54:25 -07001107 pattern = "-eth([\w])"
Jeremyd9e4eb12016-04-13 12:09:06 -07001108 ipAddressSearch = re.search( pattern, response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001109 print ipAddressSearch.group( 1 )
1110 intf = host + "-eth" + str( ipAddressSearch.group( 1 ) )
Jon Hall439c8912016-04-15 02:22:03 -07001111 cmd = host + " ip -6 addr add %s dev %s" % ( IP, intf )
1112 print "cmd10 = ", cmd
1113 self.handle.sendline( cmd )
1114 self.handle.expect( "mininet>" )
1115
kelvin-onlaba1484582015-02-02 15:46:20 -08001116 cmd = "net"
Jon Hall439c8912016-04-15 02:22:03 -07001117 print "cmd11 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001118 self.handle.sendline( cmd )
1119 self.handle.expect( "mininet>" )
1120 print "output = ", self.handle.before
1121
1122 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -08001123 cmd = host + " ifconfig"
Jon Hall439c8912016-04-15 02:22:03 -07001124 print "cmd12= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001125 self.handle.sendline( cmd )
1126 self.handle.expect( "mininet>" )
1127 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -07001128
kelvin-onlaba1484582015-02-02 15:46:20 -08001129 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001130 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001131 main.log.error( self.name + ": TIMEOUT exception found" )
1132 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001133 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08001134 except pexpect.EOF:
1135 main.log.error( self.name + ": EOF exception found" )
1136 main.log.error( self.name + ": " + self.handle.before )
1137 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001138 except Exception:
1139 main.log.exception( self.name + ": Uncaught exception!" )
1140 return main.FALSE
kelvin-onlaba1484582015-02-02 15:46:20 -08001141
Jon Hall7eb38402015-01-08 17:19:54 -08001142 def changeIP( self, host, intf, newIP, newNetmask ):
1143 """
1144 Changes the ip address of a host on the fly
1145 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001146 if self.handle:
1147 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001148 cmd = host + " ifconfig " + intf + " " + \
1149 newIP + " " + 'netmask' + " " + newNetmask
1150 self.handle.sendline( cmd )
1151 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001152 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001153 main.log.info( "response = " + response )
1154 main.log.info(
1155 "Ip of host " +
1156 host +
1157 " changed to new IP " +
1158 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -08001159 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001160 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001161 main.log.error( self.name + ": TIMEOUT exception found" )
1162 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001163 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001164 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001165 main.log.error( self.name + ": EOF exception found" )
1166 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001167 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001168 except Exception:
1169 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001170 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001171
Jon Hall7eb38402015-01-08 17:19:54 -08001172 def changeDefaultGateway( self, host, newGW ):
1173 """
1174 Changes the default gateway of a host
1175 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001176 if self.handle:
1177 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001178 cmd = host + " route add default gw " + newGW
1179 self.handle.sendline( cmd )
1180 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001181 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001182 main.log.info( "response = " + response )
1183 main.log.info(
1184 "Default gateway of host " +
1185 host +
1186 " changed to " +
1187 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -08001188 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001189 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001190 main.log.error( self.name + ": TIMEOUT exception found" )
1191 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001192 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001193 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001194 main.log.error( self.name + ": EOF exception found" )
1195 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001196 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001197 except Exception:
1198 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001199 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001200
You Wange24d6272018-03-27 21:18:50 -07001201 def addRoute( self, host, dstIP, interface, ipv6=False ):
1202 """
1203 Add a route to host
1204 Ex: h1 route add -host 224.2.0.1 h1-eth0
1205 """
1206 if self.handle:
1207 try:
1208 cmd = str( host )
1209 if ipv6:
1210 cmd += " route -A inet6 add "
1211 else:
1212 cmd += " route add -host "
1213 cmd += str( dstIP ) + " " + str( interface )
1214 self.handle.sendline( cmd )
1215 self.handle.expect( "mininet>" )
1216 response = self.handle.before
1217 main.log.debug( "response = " + response )
1218 return main.TRUE
1219 except pexpect.TIMEOUT:
1220 main.log.error( self.name + ": TIMEOUT exception found" )
1221 main.log.error( self.name + ": " + self.handle.before )
1222 main.cleanAndExit()
1223 except pexpect.EOF:
1224 main.log.error( self.name + ": EOF exception found" )
1225 main.log.error( self.name + ": " + self.handle.before )
1226 return main.FALSE
1227 except Exception:
1228 main.log.exception( self.name + ": Uncaught exception!" )
1229 main.cleanAndExit()
1230
Jon Hall7eb38402015-01-08 17:19:54 -08001231 def addStaticMACAddress( self, host, GW, macaddr ):
1232 """
Jon Hallefbd9792015-03-05 16:11:36 -08001233 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001234 if self.handle:
1235 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001236 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1237 cmd = host + " arp -s " + GW + " " + macaddr
1238 self.handle.sendline( cmd )
1239 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001240 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001241 main.log.info( "response = " + response )
1242 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001243 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001244 GW +
1245 " changed to " +
1246 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001247 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001248 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001249 main.log.error( self.name + ": TIMEOUT exception found" )
1250 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001251 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001252 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001253 main.log.error( self.name + ": EOF exception found" )
1254 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001255 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001256 except Exception:
1257 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001258 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001259
Jon Hall7eb38402015-01-08 17:19:54 -08001260 def verifyStaticGWandMAC( self, host ):
1261 """
1262 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001263 if self.handle:
1264 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001265 # h1 arp -an
1266 cmd = host + " arp -an "
1267 self.handle.sendline( cmd )
1268 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001269 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001270 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001271 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001272 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001273 main.log.error( self.name + ": TIMEOUT exception found" )
1274 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001275 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001276 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001277 main.log.error( self.name + ": EOF exception found" )
1278 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001279 return main.FALSE
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()
shahshreyad0c80432014-12-04 16:56:05 -08001283
Jon Hall7eb38402015-01-08 17:19:54 -08001284 def getMacAddress( self, host ):
1285 """
1286 Verifies the host's ip configured or not."""
1287 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001288 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001289 response = self.execute(
1290 cmd=host +
1291 " ifconfig",
1292 prompt="mininet>",
1293 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001294 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001295 main.log.error( self.name + ": EOF exception found" )
1296 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001297 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001298 except Exception:
1299 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001300 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001301
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001302 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001303 macAddressSearch = re.search( pattern, response, re.I )
1304 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001305 main.log.info(
1306 self.name +
1307 ": Mac-Address of Host " +
1308 host +
1309 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001310 macAddress )
1311 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001312 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001313 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001314
Jon Hall7eb38402015-01-08 17:19:54 -08001315 def getInterfaceMACAddress( self, host, interface ):
1316 """
1317 Return the IP address of the interface on the given host"""
1318 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001319 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001320 response = self.execute( cmd=host + " ifconfig " + interface,
1321 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001322 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001323 main.log.error( self.name + ": EOF exception found" )
1324 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001325 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001326 except Exception:
1327 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001328 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001329
1330 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001331 macAddressSearch = re.search( pattern, response, re.I )
1332 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001333 main.log.info( "No mac address found in %s" % response )
1334 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001335 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001336 main.log.info(
1337 "Mac-Address of " +
1338 host +
1339 ":" +
1340 interface +
1341 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001342 macAddress )
1343 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001344 else:
1345 main.log.error( "Connection failed to the host" )
1346
You Wang5da39c82018-04-26 22:55:08 -07001347 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001348 """
1349 Verifies the host's ip configured or not."""
1350 if self.handle:
1351 try:
1352 response = self.execute(
1353 cmd=host +
1354 " ifconfig",
1355 prompt="mininet>",
1356 timeout=10 )
1357 except pexpect.EOF:
1358 main.log.error( self.name + ": EOF exception found" )
1359 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001360 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001361 except Exception:
1362 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001363 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001364
sathishmad953462015-12-03 17:42:07 +05301365 pattern = ''
1366 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001367 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301368 else:
Jon Hall439c8912016-04-15 02:22:03 -07001369 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001370 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001371 if not ipAddressSearch:
1372 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001373 main.log.info(
1374 self.name +
1375 ": IP-Address of Host " +
1376 host +
1377 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001378 ipAddressSearch.group( 1 ) )
1379 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001380 else:
1381 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001382
Jon Hall7eb38402015-01-08 17:19:54 -08001383 def getSwitchDPID( self, switch ):
1384 """
1385 return the datapath ID of the switch"""
1386 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001387 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001388 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001389 response = self.execute(
1390 cmd=cmd,
1391 prompt="mininet>",
1392 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001393 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001394 main.log.error( self.name + ": EOF exception found" )
1395 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001396 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001397 except Exception:
1398 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001399 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001400 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001401 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001402 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001403 main.log.info(
1404 "Couldn't find DPID for switch %s, found: %s" %
1405 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001406 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001407 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001408 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001409 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001410
Jon Hall7eb38402015-01-08 17:19:54 -08001411 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001412 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001413 self.handle.sendline( "" )
1414 self.expect( "mininet>" )
1415 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001416 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001417 response = self.execute(
1418 cmd=cmd,
1419 prompt="mininet>",
1420 timeout=10 )
1421 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001422 response = self.handle.before
1423 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001424 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001425 main.log.error( self.name + ": TIMEOUT exception found" )
1426 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001427 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001428 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001429 main.log.error( self.name + ": EOF exception found" )
1430 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001431 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001432 except Exception:
1433 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001434 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001435
Jon Hall7eb38402015-01-08 17:19:54 -08001436 def getInterfaces( self, node ):
1437 """
1438 return information dict about interfaces connected to the node"""
1439 if self.handle:
1440 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001441 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001442 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001443 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001444 response = self.execute(
1445 cmd=cmd,
1446 prompt="mininet>",
1447 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001448 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001449 main.log.error( self.name + ": EOF exception found" )
1450 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001451 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001452 except Exception:
1453 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001454 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001455 return response
1456 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001457 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001458
Jon Hall7eb38402015-01-08 17:19:54 -08001459 def dump( self ):
1460 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001461 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001462 response = self.execute(
1463 cmd='dump',
1464 prompt='mininet>',
1465 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001466 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001467 main.log.error( self.name + ": EOF exception found" )
1468 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001469 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001470 except Exception:
1471 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001472 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001473 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001474
Jon Hall7eb38402015-01-08 17:19:54 -08001475 def intfs( self ):
1476 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001477 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001478 response = self.execute(
1479 cmd='intfs',
1480 prompt='mininet>',
1481 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001482 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001483 main.log.error( self.name + ": EOF exception found" )
1484 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001485 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001486 except Exception:
1487 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001488 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001489 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001490
Jon Hall7eb38402015-01-08 17:19:54 -08001491 def net( self ):
1492 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001493 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001494 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001495 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001496 main.log.error( self.name + ": EOF exception found" )
1497 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001498 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001499 except Exception:
1500 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001501 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001502 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001503
Devin Lima7cfdbd2017-09-29 15:02:22 -07001504 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001505 main.log.info( self.name + ": List network links" )
1506 try:
1507 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001508 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001509 except pexpect.EOF:
1510 main.log.error( self.name + ": EOF exception found" )
1511 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001512 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001513 except Exception:
1514 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001515 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001516 return response
1517
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001518 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001519 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001520 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001521
kelvin-onlab7cce9382015-07-17 10:21:03 -07001522 @parm:
1523 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1524 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001525 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001526 try:
1527 for host1 in hosts:
1528 for host2 in hosts:
1529 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001530 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1531 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001532 except Exception:
1533 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001534 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001535
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001536 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001537 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001538 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1539 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001540
kelvin-onlab7cce9382015-07-17 10:21:03 -07001541 @parm:
1542 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1543 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001544 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001545 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1546 try:
1547 # Setup the mininet command
1548 cmd1 = 'iperf ' + host1 + " " + host2
1549 self.handle.sendline( cmd1 )
1550 outcome = self.handle.expect( "mininet>", timeout )
1551 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001552
kelvin-onlab7cce9382015-07-17 10:21:03 -07001553 # checks if there are results in the mininet response
1554 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001555 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001556 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001557 response = response.split( "\r\n" )
1558 response = response[ len( response )-2 ]
1559 response = response.split( ": " )
1560 response = response[ len( response )-1 ]
1561 response = response.replace( "[", "" )
1562 response = response.replace( "]", "" )
1563 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001564
kelvin-onlab7cce9382015-07-17 10:21:03 -07001565 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001566 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001567
kelvin-onlab7cce9382015-07-17 10:21:03 -07001568 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001569 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001570 if len( bandwidth ) == 2:
1571 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001572 return main.TRUE
1573 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001574 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001575 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001576 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001577 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001578 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001579 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001580 main.log.error( self.name + ": TIMEOUT exception found" )
1581 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001582 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001583 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001584 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001585 self.handle.expect( "Interrupt" )
1586 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001587 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001588 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001589 main.log.error( self.name + ": EOF exception found" )
1590 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001591 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001592 except Exception:
1593 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001594 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001595
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001596 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001597 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1598 try:
1599 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001600 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001601 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001602 outcome1 = self.handle.expect( "mininet>" )
1603 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001604 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001605 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001606 response1 = self.handle.before
1607 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001608 print response1, response2
1609 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001610 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001611 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001612 return main.TRUE
1613 else:
1614 main.log.error( self.name + ": iperf test failed" )
1615 return main.FALSE
1616 except pexpect.TIMEOUT:
1617 main.log.error( self.name + ": TIMEOUT exception found" )
1618 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001619 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001620 self.handle.expect( "Interrupt" )
1621 self.handle.expect( "mininet>" )
1622 return main.FALSE
1623 except pexpect.EOF:
1624 main.log.error( self.name + ": EOF exception found" )
1625 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001626 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001627 except Exception:
1628 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001629 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001630
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001631 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001632 '''
GlennRC61321f22015-07-16 13:36:54 -07001633 Runs the iperfudp function with a given set of hosts and specified
1634 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001635
GlennRC61321f22015-07-16 13:36:54 -07001636 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001637 bandwidth: the targeted bandwidth, in megabits ('M')
1638 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001639 try:
1640 for host1 in hosts:
1641 for host2 in hosts:
1642 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001643 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1644 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001645 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001646 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001647 return main.FALSE
1648 except Exception:
1649 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001650 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001651
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001652 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001653 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001654 Creates an iperf UDP test with a specific bandwidth.
1655 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001656
kelvin-onlab7cce9382015-07-17 10:21:03 -07001657 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001658 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1659 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001660 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001661 try:
1662 # setup the mininet command
1663 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001664 self.handle.sendline( cmd )
1665 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001666 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001667
kelvin-onlab7cce9382015-07-17 10:21:03 -07001668 # check if there are in results in the mininet response
1669 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001670 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001671 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001672 response = response.split( "\r\n" )
1673 response = response[ len( response )-2 ]
1674 response = response.split( ": " )
1675 response = response[ len( response )-1 ]
1676 response = response.replace( "[", "" )
1677 response = response.replace( "]", "" )
1678 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001679
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001680 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001681
kelvin-onlab7cce9382015-07-17 10:21:03 -07001682 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001683 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001684 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001685 # if one entry is blank then something is wrong
1686 for item in mnBandwidth:
1687 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001688 main.log.error( self.name + ": Could not parse iperf output" )
1689 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001690 return main.FALSE
1691 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001692 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001693 return main.TRUE
1694 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001695 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001696 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001697
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001698 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001699 main.log.error( self.name + ": TIMEOUT exception found" )
1700 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001701 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001702 except pexpect.EOF:
1703 main.log.error( self.name + ": EOF exception found" )
1704 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001705 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001706 except Exception:
1707 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001708 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001709
Jon Hall7eb38402015-01-08 17:19:54 -08001710 def nodes( self ):
1711 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001712 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001713 response = self.execute(
1714 cmd='nodes',
1715 prompt='mininet>',
1716 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001717 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001718 main.log.error( self.name + ": EOF exception found" )
1719 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001720 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001721 except Exception:
1722 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001723 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001724 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001725
Jon Hall7eb38402015-01-08 17:19:54 -08001726 def pingpair( self ):
1727 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001728 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001729 response = self.execute(
1730 cmd='pingpair',
1731 prompt='mininet>',
1732 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001733 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001734 main.log.error( self.name + ": EOF exception found" )
1735 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001736 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001737 except Exception:
1738 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001739 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001740
Jon Hall7eb38402015-01-08 17:19:54 -08001741 if re.search( ',\s0\%\spacket\sloss', response ):
1742 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001743 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001744 else:
alisone4121a92016-11-22 16:31:36 -08001745 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001746 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001747
Jon Hall7eb38402015-01-08 17:19:54 -08001748 def link( self, **linkargs ):
1749 """
GlennRCed771242016-01-13 17:02:47 -08001750 Bring link( s ) between two nodes up or down
1751 """
Jon Hall6094a362014-04-11 14:46:56 -07001752 try:
GlennRCed771242016-01-13 17:02:47 -08001753 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1754 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1755 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1756 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1757
1758 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1759 cmd = "link {} {} {}".format( end1, end2, option )
1760 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001761 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001762 response = self.handle.before
1763 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001764 if "not in network" in response:
1765 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1766 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001767 return main.TRUE
1768 except pexpect.TIMEOUT:
1769 main.log.exception( self.name + ": Command timed out" )
1770 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001771 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001772 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001773 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001774 except Exception:
1775 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001776 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001777
pingping-lin8244a3b2015-09-16 13:36:56 -07001778 def switch( self, **switchargs ):
1779 """
1780 start/stop a switch
1781 """
1782 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1783 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1784 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1785 command = "switch " + str( sw ) + " " + str( option )
1786 main.log.info( command )
1787 try:
1788 self.handle.sendline( command )
1789 self.handle.expect( "mininet>" )
1790 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001791 main.log.error( self.name + ": TIMEOUT exception found" )
1792 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001793 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001794 except pexpect.EOF:
1795 main.log.error( self.name + ": EOF exception found" )
1796 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001797 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001798 return main.TRUE
1799
pingping-lin5bb663b2015-09-24 11:47:50 -07001800 def node( self, nodeName, commandStr ):
1801 """
1802 Carry out a command line on a given node
1803 @parm:
1804 nodeName: the node name in Mininet testbed
1805 commandStr: the command line will be carried out on the node
1806 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1807 """
1808 command = str( nodeName ) + " " + str( commandStr )
1809 main.log.info( command )
1810
1811 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001812 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001813 if re.search( "Unknown command", response ):
1814 main.log.warn( response )
1815 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001816 if re.search( "Permission denied", response ):
1817 main.log.warn( response )
1818 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001819 except pexpect.EOF:
1820 main.log.error( self.name + ": EOF exception found" )
1821 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001822 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001823 main.log.info( " response is :" )
1824 main.log.info( response )
1825 return response
1826
Jon Hall7eb38402015-01-08 17:19:54 -08001827 def yank( self, **yankargs ):
1828 """
1829 yank a mininet switch interface to a host"""
1830 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001831 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001832 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1833 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001834 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001835 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001836 response = self.execute(
1837 cmd=command,
1838 prompt="mininet>",
1839 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001840 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001841 main.log.error( self.name + ": EOF exception found" )
1842 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001843 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001844 except Exception:
1845 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001846 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001847 return main.TRUE
1848
Jon Hall7eb38402015-01-08 17:19:54 -08001849 def plug( self, **plugargs ):
1850 """
1851 plug the yanked mininet switch interface to a switch"""
1852 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001853 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001854 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1855 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001856 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001857 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001858 response = self.execute(
1859 cmd=command,
1860 prompt="mininet>",
1861 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001862 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001863 main.log.error( self.name + ": EOF exception found" )
1864 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001865 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001866 except Exception:
1867 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001868 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001869 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001870
Jon Hall7eb38402015-01-08 17:19:54 -08001871 def dpctl( self, **dpctlargs ):
1872 """
1873 Run dpctl command on all switches."""
1874 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001875 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001876 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1877 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1878 command = "dpctl " + cmd + " " + str( cmdargs )
1879 try:
1880 response = self.execute(
1881 cmd=command,
1882 prompt="mininet>",
1883 timeout=10 )
1884 except pexpect.EOF:
1885 main.log.error( self.name + ": EOF exception found" )
1886 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001887 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001888 except Exception:
1889 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001890 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001891 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001892
kelvin-onlabd3b64892015-01-20 13:26:24 -08001893 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001894 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001895 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001896 try:
1897 fileInput = path + '/lib/Mininet/INSTALL'
1898 version = super( Mininet, self ).getVersion()
1899 pattern = 'Mininet\s\w\.\w\.\w\w*'
1900 for line in open( fileInput, 'r' ).readlines():
1901 result = re.match( pattern, line )
1902 if result:
1903 version = result.group( 0 )
1904 return version
1905 except Exception:
1906 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001907 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001908
kelvin-onlabd3b64892015-01-20 13:26:24 -08001909 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001910 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001911 Parameters:
1912 sw: The name of an OVS switch. Example "s1"
1913 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001914 The output of the command from the mininet cli
1915 or main.FALSE on timeout"""
1916 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001917 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001918 response = self.execute(
1919 cmd=command,
1920 prompt="mininet>",
1921 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001922 if response:
Jon Hallab611372018-02-21 15:26:05 -08001923 if "no bridge named" in response:
1924 main.log.error( self.name + ": Error in getSwController: " +
1925 self.handle.before )
1926 return main.FALSE
1927 else:
1928 return response
admin2a9548d2014-06-17 14:08:07 -07001929 else:
1930 return main.FALSE
1931 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001932 main.log.error( self.name + ": EOF exception found" )
1933 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001934 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001935 except Exception:
1936 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001937 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001938
Charles Chan029be652015-08-24 01:46:10 +08001939 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001940 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001941 Description:
1942 Assign switches to the controllers ( for ovs use only )
1943 Required:
1944 sw - Name of the switch. This can be a list or a string.
1945 ip - Ip addresses of controllers. This can be a list or a string.
1946 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001947 port - ONOS use port 6653, if no list of ports is passed, then
1948 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001949 ptcp - ptcp number, This can be a string or a list that has
1950 the same length as switch. This is optional and not required
1951 when using ovs switches.
1952 NOTE: If switches and ptcp are given in a list type they should have the
1953 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1954 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001955
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001956 Return:
1957 Returns main.TRUE if mininet correctly assigned switches to
1958 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001959 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001960 """
1961 assignResult = main.TRUE
1962 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001963 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001964 command = "sh ovs-vsctl set-controller "
1965 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001966 try:
1967 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001968 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001969 if isinstance( port, types.StringType ) or \
1970 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001971 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001972 elif isinstance( port, types.ListType ):
1973 main.log.error( self.name + ": Only one controller " +
1974 "assigned and a list of ports has" +
1975 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001976 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001977 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001978 main.log.error( self.name + ": Invalid controller port " +
1979 "number. Please specify correct " +
1980 "controller port" )
1981 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001982
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001983 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001984 if isinstance( port, types.StringType ) or \
1985 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001986 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001987 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1988 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001989 elif isinstance( port, types.ListType ):
1990 if ( len( ip ) != len( port ) ):
1991 main.log.error( self.name + ": Port list = " +
1992 str( len( port ) ) +
1993 "should be the same as controller" +
1994 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001995 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001996 else:
1997 onosIp = ""
1998 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001999 onosIp += "tcp:" + str( ipAddress ) + ":" + \
2000 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002001 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002002 main.log.error( self.name + ": Invalid controller port " +
2003 "number. Please specify correct " +
2004 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002005 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07002006 else:
2007 main.log.error( self.name + ": Invalid ip address" )
2008 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002009
2010 if isinstance( sw, types.StringType ):
2011 command += sw + " "
2012 if ptcp:
2013 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07002014 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002015 elif isinstance( ptcp, types.ListType ):
2016 main.log.error( self.name + ": Only one switch is " +
2017 "being set and multiple PTCP is " +
2018 "being passed " )
2019 else:
2020 main.log.error( self.name + ": Invalid PTCP" )
2021 ptcp = ""
2022 command += onosIp
2023 commandList.append( command )
2024
2025 elif isinstance( sw, types.ListType ):
2026 if ptcp:
2027 if isinstance( ptcp, types.ListType ):
2028 if len( ptcp ) != len( sw ):
2029 main.log.error( self.name + ": PTCP length = " +
2030 str( len( ptcp ) ) +
2031 " is not the same as switch" +
2032 " length = " +
2033 str( len( sw ) ) )
2034 return main.FALSE
2035 else:
2036 for switch, ptcpNum in zip( sw, ptcp ):
2037 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07002038 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07002039 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002040 tempCmd += onosIp
2041 commandList.append( tempCmd )
2042 else:
2043 main.log.error( self.name + ": Invalid PTCP" )
2044 return main.FALSE
2045 else:
2046 for switch in sw:
2047 tempCmd = "sh ovs-vsctl set-controller "
2048 tempCmd += switch + " " + onosIp
2049 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002050 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002051 main.log.error( self.name + ": Invalid switch type " )
2052 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002053
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002054 for cmd in commandList:
2055 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002056 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08002057 if "no bridge named" in self.handle.before:
2058 main.log.error( self.name + ": Error in assignSwController: " +
2059 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002060 except pexpect.TIMEOUT:
2061 main.log.error( self.name + ": pexpect.TIMEOUT found" )
2062 return main.FALSE
2063 except pexpect.EOF:
2064 main.log.error( self.name + ": EOF exception found" )
2065 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002066 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002067 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002068 except pexpect.EOF:
2069 main.log.error( self.name + ": EOF exception found" )
2070 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002071 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002072 except Exception:
2073 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002074 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07002075
kelvin-onlabd3b64892015-01-20 13:26:24 -08002076 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08002077 """
2078 Removes the controller target from sw"""
2079 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07002080 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002081 response = self.execute(
2082 cmd=command,
2083 prompt="mininet>",
2084 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08002085 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002086 main.log.error( self.name + ": EOF exception found" )
2087 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002088 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002089 except Exception:
2090 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002091 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002092 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002093 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07002094
kelvin-onlabd3b64892015-01-20 13:26:24 -08002095 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002096 """
Jon Hallb1290e82014-11-18 16:17:48 -05002097 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002098 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002099 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002100 NOTE: cannot currently specify what type of switch
2101 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08002102 sw = name of the new switch as a string
2103 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05002104 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08002105 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002106 """
2107 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002108 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05002109 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002110 response = self.execute(
2111 cmd=command,
2112 prompt="mininet>",
2113 timeout=10 )
2114 if re.search( "already exists!", response ):
2115 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002116 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002117 elif re.search( "Error", response ):
2118 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002119 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002120 elif re.search( "usage:", response ):
2121 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002122 return main.FALSE
2123 else:
2124 return main.TRUE
2125 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002126 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07002127 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002128 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002129 except Exception:
2130 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002131 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002132
kelvin-onlabd3b64892015-01-20 13:26:24 -08002133 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08002134 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08002135 delete a switch from the mininet topology
2136 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002137 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08002138 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08002139 sw = name of the switch as a string
2140 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002141 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05002142 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002143 response = self.execute(
2144 cmd=command,
2145 prompt="mininet>",
2146 timeout=10 )
2147 if re.search( "no switch named", response ):
2148 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002149 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002150 elif re.search( "Error", response ):
2151 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002152 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002153 elif re.search( "usage:", response ):
2154 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002155 return main.FALSE
2156 else:
2157 return main.TRUE
2158 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002159 main.log.error( self.name + ": EOF exception found" )
2160 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002161 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002162 except Exception:
2163 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002164 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002165
You Wangdb8cd0a2016-05-26 15:19:45 -07002166 def getSwitchRandom( self, timeout=60, nonCut=True ):
2167 """
2168 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002169 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002170 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002171 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002172 it just randomly returns one switch from all current switches in
2173 Mininet.
2174 Returns the name of the chosen switch.
2175 """
2176 import random
2177 candidateSwitches = []
2178 try:
2179 if not nonCut:
2180 switches = self.getSwitches( timeout=timeout )
2181 assert len( switches ) != 0
2182 for switchName in switches.keys():
2183 candidateSwitches.append( switchName )
2184 else:
2185 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002186 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002187 return None
2188 self.graph.update( graphDict )
2189 candidateSwitches = self.graph.getNonCutVertices()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002190 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002191 return None
2192 elif len( candidateSwitches ) == 0:
2193 main.log.info( self.name + ": No candidate switch for deletion" )
2194 return None
2195 else:
2196 switch = random.sample( candidateSwitches, 1 )
2197 return switch[ 0 ]
2198 except KeyError:
2199 main.log.exception( self.name + ": KeyError exception found" )
2200 return None
2201 except AssertionError:
2202 main.log.exception( self.name + ": AssertionError exception found" )
2203 return None
2204 except Exception:
2205 main.log.exception( self.name + ": Uncaught exception" )
2206 return None
2207
2208 def delSwitchRandom( self, timeout=60, nonCut=True ):
2209 """
2210 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002211 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002212 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002213 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002214 otherwise it just randomly delete one switch from all current
2215 switches in Mininet.
2216 Returns the name of the deleted switch
2217 """
2218 try:
2219 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002220 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002221 return None
2222 else:
2223 deletionResult = self.delSwitch( switch )
2224 if deletionResult:
2225 return switch
2226 else:
2227 return None
2228 except Exception:
2229 main.log.exception( self.name + ": Uncaught exception" )
2230 return None
2231
kelvin-onlabd3b64892015-01-20 13:26:24 -08002232 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002233 """
2234 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002235 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002236 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002237 NOTE: cannot currently specify what type of link
2238 required params:
2239 node1 = the string node name of the first endpoint of the link
2240 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002241 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002242 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002243 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002244 response = self.execute(
2245 cmd=command,
2246 prompt="mininet>",
2247 timeout=10 )
2248 if re.search( "doesnt exist!", response ):
2249 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002250 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002251 elif re.search( "Error", response ):
2252 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002253 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002254 elif re.search( "usage:", response ):
2255 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002256 return main.FALSE
2257 else:
2258 return main.TRUE
2259 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002260 main.log.error( self.name + ": EOF exception found" )
2261 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002262 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002263 except Exception:
2264 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002265 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002266
kelvin-onlabd3b64892015-01-20 13:26:24 -08002267 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002268 """
2269 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002270 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002271 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002272 required params:
2273 node1 = the string node name of the first endpoint of the link
2274 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002275 returns: main.FALSE on an error, else main.TRUE
2276 """
Jon Hallffb386d2014-11-21 13:43:38 -08002277 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002278 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002279 response = self.execute(
2280 cmd=command,
2281 prompt="mininet>",
2282 timeout=10 )
2283 if re.search( "no node named", response ):
2284 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002285 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002286 elif re.search( "Error", response ):
2287 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002288 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002289 elif re.search( "usage:", response ):
2290 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002291 return main.FALSE
2292 else:
2293 return main.TRUE
2294 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002295 main.log.error( self.name + ": EOF exception found" )
2296 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002297 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002298 except Exception:
2299 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002300 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002301
You Wangdb8cd0a2016-05-26 15:19:45 -07002302 def getLinkRandom( self, timeout=60, nonCut=True ):
2303 """
2304 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002305 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002306 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002307 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002308 it just randomly returns one link from all current links in
2309 Mininet.
2310 Returns the link as a list, e.g. [ 's1', 's2' ]
2311 """
2312 import random
2313 candidateLinks = []
2314 try:
2315 if not nonCut:
2316 links = self.getLinks( timeout=timeout )
2317 assert len( links ) != 0
2318 for link in links:
2319 # Exclude host-switch link
2320 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2321 continue
2322 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2323 else:
2324 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002325 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002326 return None
2327 self.graph.update( graphDict )
2328 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002329 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002330 return None
2331 elif len( candidateLinks ) == 0:
2332 main.log.info( self.name + ": No candidate link for deletion" )
2333 return None
2334 else:
2335 link = random.sample( candidateLinks, 1 )
2336 return link[ 0 ]
2337 except KeyError:
2338 main.log.exception( self.name + ": KeyError exception found" )
2339 return None
2340 except AssertionError:
2341 main.log.exception( self.name + ": AssertionError exception found" )
2342 return None
2343 except Exception:
2344 main.log.exception( self.name + ": Uncaught exception" )
2345 return None
2346
2347 def delLinkRandom( self, timeout=60, nonCut=True ):
2348 """
2349 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002350 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002351 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002352 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002353 otherwise it just randomly delete one link from all current links
2354 in Mininet.
2355 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2356 """
2357 try:
2358 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002359 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002360 return None
2361 else:
2362 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2363 if deletionResult:
2364 return link
2365 else:
2366 return None
2367 except Exception:
2368 main.log.exception( self.name + ": Uncaught exception" )
2369 return None
2370
kelvin-onlabd3b64892015-01-20 13:26:24 -08002371 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002372 """
Jon Hallb1290e82014-11-18 16:17:48 -05002373 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002374 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002375 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002376 NOTE: cannot currently specify what type of host
2377 required params:
2378 hostname = the string hostname
2379 optional key-value params
2380 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002381 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002382 """
2383 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002384 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002385 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002386 response = self.execute(
2387 cmd=command,
2388 prompt="mininet>",
2389 timeout=10 )
2390 if re.search( "already exists!", response ):
2391 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002392 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002393 elif re.search( "doesnt exists!", response ):
2394 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002395 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002396 elif re.search( "Error", response ):
2397 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002398 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002399 elif re.search( "usage:", response ):
2400 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002401 return main.FALSE
2402 else:
2403 return main.TRUE
2404 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002405 main.log.error( self.name + ": EOF exception found" )
2406 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002407 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002408 except Exception:
2409 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002410 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002411
kelvin-onlabd3b64892015-01-20 13:26:24 -08002412 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002413 """
2414 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002415 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002416 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002417 NOTE: this uses a custom mn function
2418 required params:
2419 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002420 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002421 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002422 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002423 response = self.execute(
2424 cmd=command,
2425 prompt="mininet>",
2426 timeout=10 )
2427 if re.search( "no host named", response ):
2428 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002429 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002430 elif re.search( "Error", response ):
2431 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002432 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002433 elif re.search( "usage:", response ):
2434 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002435 return main.FALSE
2436 else:
2437 return main.TRUE
2438 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002439 main.log.error( self.name + ": EOF exception found" )
2440 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002441 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002442 except Exception:
2443 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002444 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002445
Jon Hall7eb38402015-01-08 17:19:54 -08002446 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002447 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002448 Called at the end of the test to stop the mininet and
2449 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002450 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002451 try:
2452 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002453 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002454 timeout=2 )
2455 response = main.TRUE
2456 if i == 0:
2457 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002458 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002459 return main.TRUE
2460 # print "Disconnecting Mininet"
2461 if self.handle:
2462 self.handle.sendline( "exit" )
2463 self.handle.expect( "exit" )
2464 self.handle.expect( "(.*)" )
2465 else:
2466 main.log.error( "Connection failed to the host" )
2467 return response
2468 except pexpect.EOF:
2469 main.log.error( self.name + ": EOF exception found" )
2470 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002471 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002472 except Exception:
2473 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002474 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002475
Devin Lima7cfdbd2017-09-29 15:02:22 -07002476 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002477 """
Jon Hall21270ac2015-02-16 17:59:55 -08002478 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002479 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002480 main.FALSE if the pexpect handle does not exist.
2481
Jon Halld61331b2015-02-17 16:35:47 -08002482 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002483 """
Jon Halld61331b2015-02-17 16:35:47 -08002484 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002485 response = ''
2486 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002487 try:
Jon Halld80cc142015-07-06 13:36:05 -07002488 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002489 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002490 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002491 pexpect.EOF,
2492 pexpect.TIMEOUT ],
2493 timeout )
2494 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002495 main.log.info( "Exiting mininet.." )
2496 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002497 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002498 prompt=self.prompt,
2499 timeout=exitTimeout )
2500 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002501 self.handle.sendline( "sudo mn -c" )
2502 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002503
Jeremyd9e4eb12016-04-13 12:09:06 -07002504 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002505 main.log.info( " Mininet trying to exit while not " +
2506 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002507 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002508 elif i == 2:
2509 main.log.error( "Something went wrong exiting mininet" )
2510 elif i == 3: # timeout
2511 main.log.error( "Something went wrong exiting mininet " +
2512 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002513
You Wang18db8592018-04-02 13:52:03 -07002514 self.handle.sendline( "" )
2515 self.handle.expect( self.prompt )
2516 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2517
Hari Krishnab35c6d02015-03-18 11:13:51 -07002518 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002519 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002520 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002521 self.handle.sendline(
2522 "sudo kill -9 \`ps -ef | grep \"" +
2523 fileName +
2524 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002525 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002526 main.log.error( self.name + ": TIMEOUT exception found" )
2527 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002528 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002529 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002530 main.log.error( self.name + ": EOF exception found" )
2531 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002532 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002533 except Exception:
2534 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002535 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002536 else:
2537 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002538 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002539 return response
2540
YPZhang26a139e2016-04-25 14:01:55 -07002541 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002542 """
2543 Description:
2544 Sends arp message from mininet host for hosts discovery
2545 Required:
2546 host - hosts name
2547 Optional:
2548 ip - ip address that does not exist in the network so there would
2549 be no reply.
2550 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002551 if ethDevice:
2552 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002553 cmd = srcHost + " arping -c1 "
2554 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002555 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 -07002556 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002557 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002558 if output:
2559 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002560 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002561 i = self.handle.expect( [ "mininet>", "arping: " ] )
2562 if i == 0:
2563 return main.TRUE
2564 elif i == 1:
2565 response = self.handle.before + self.handle.after
2566 self.handle.expect( "mininet>" )
2567 response += self.handle.before + self.handle.after
2568 main.log.warn( "Error sending arping, output was: " +
2569 response )
2570 return main.FALSE
2571 except pexpect.TIMEOUT:
2572 main.log.error( self.name + ": TIMEOUT exception found" )
2573 main.log.warn( self.handle.before )
2574 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002575 except pexpect.EOF:
2576 main.log.error( self.name + ": EOF exception found" )
2577 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002578 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002579 except Exception:
2580 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002581 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002582
Jon Hall7eb38402015-01-08 17:19:54 -08002583 def decToHex( self, num ):
2584 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002585
Jon Hall7eb38402015-01-08 17:19:54 -08002586 def getSwitchFlowCount( self, switch ):
2587 """
2588 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002589 if self.handle:
2590 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2591 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002592 response = self.execute(
2593 cmd=cmd,
2594 prompt="mininet>",
2595 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002596 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002597 main.log.error( self.name + ": EOF exception found" )
2598 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002599 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002600 except Exception:
2601 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002602 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002603 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002604 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002605 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002606 main.log.info(
2607 "Couldn't find flows on switch %s, found: %s" %
2608 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002609 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002610 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002611 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002612 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002613
Jon Hall9ed8f372016-02-24 17:34:07 -08002614 def checkFlows( self, sw, dumpFormat=None ):
2615 if dumpFormat:
2616 command = "sh ovs-ofctl -F " + \
2617 dumpFormat + " dump-flows " + str( sw )
2618 else:
2619 command = "sh ovs-ofctl dump-flows " + str( sw )
2620 try:
2621 response = self.execute(
2622 cmd=command,
2623 prompt="mininet>",
2624 timeout=10 )
2625 return response
2626 except pexpect.EOF:
2627 main.log.error( self.name + ": EOF exception found" )
2628 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002629 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002630 except Exception:
2631 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002632 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002633
GlennRC68467eb2015-11-16 18:01:01 -08002634 def flowTableComp( self, flowTable1, flowTable2 ):
2635 # This function compares the selctors and treatments of each flow
2636 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002637 assert flowTable1, "flowTable1 is empty or None"
2638 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002639 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002640 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002641 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002642 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002643 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2644 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002645 for field in dFields:
2646 try:
2647 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002648 except KeyError:
2649 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002650 try:
2651 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002652 except KeyError:
2653 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002654 for i in range( len( flowTable1 ) ):
2655 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002656 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002657 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002658 returnValue = main.FALSE
2659 break
2660 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002661 except AssertionError:
2662 main.log.exception( "Nothing to compare" )
2663 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002664 except Exception:
2665 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002666 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002667
GlennRC528ad292015-11-12 10:38:18 -08002668 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002669 '''
GlennRC956ea742015-11-05 16:14:15 -08002670 Discription: Parses flows into json format.
2671 NOTE: this can parse any string thats separated with commas
2672 Arguments:
2673 Required:
2674 flows: a list of strings that represnt flows
2675 Optional:
2676 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2677 debug: prints out the final result
2678 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002679 '''
GlennRC528ad292015-11-12 10:38:18 -08002680 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002681 try:
2682 for flow in flowTable:
2683 jsonFlow = {}
2684 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002685 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002686 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002687 for i in range( len( parsedFlow ) ):
2688 item = parsedFlow[ i ]
2689 if item[ 0 ] == " ":
2690 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002691 # grab the selector and treatment from the parsed flow
2692 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002693 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002694 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002695 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002696 index = 0
2697 # parse the flags
2698 # NOTE: This only parses one flag
2699 flag = {}
2700 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002701 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002702 index += 1
2703 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002704 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002705 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002706 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002707 # the priority is stuck in the selecter so put it back
2708 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002709 if 'priority' in sel[0]:
2710 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002711 # parse selector
2712 criteria = []
2713 for item in sel:
2714 # this is the type of the packet e.g. "arp"
2715 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002716 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002717 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002718 field = item.split( "=" )
2719 criteria.append( { field[ 0 ]: field[ 1 ] } )
2720 selector = { "selector": { "criteria": sorted( criteria ) } }
2721 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002722 # get rid of the action part e.g. "action=output:2"
2723 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002724 treat = treat.split( "=" )
2725 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002726 # parse treatment
2727 action = []
2728 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002729 if ":" in item:
2730 field = item.split( ":" )
2731 action.append( { field[ 0 ]: field[ 1 ] } )
2732 else:
2733 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2734 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002735 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002736 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002737 # parse the rest of the flow
2738 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002739 field = item.split( "=" )
2740 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002741 # add the treatment and the selector to the json flow
2742 jsonFlow.update( selector )
2743 jsonFlow.update( treatment )
2744 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002745
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002746 if debug:
2747 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002748
You Wang91c37cf2016-05-23 09:39:42 -07002749 # add the json flow to the json flow table
2750 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002751
You Wang91c37cf2016-05-23 09:39:42 -07002752 return jsonFlowTable
2753
2754 except IndexError:
2755 main.log.exception( self.name + ": IndexError found" )
2756 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002757 except pexpect.EOF:
2758 main.log.error( self.name + ": EOF exception found" )
2759 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002760 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002761 except Exception:
2762 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002763 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002764
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002765 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002766 '''
2767 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002768 Each element is a flow.
2769 Arguments:
2770 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002771 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002772 a list of switches.
2773 Optional:
2774 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2775 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002776 '''
GlennRC956ea742015-11-05 16:14:15 -08002777 try:
2778 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002779 if isinstance( sw, list ):
2780 switches.extend( sw )
2781 else:
2782 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002783
2784 flows = []
2785 for s in switches:
2786 cmd = "sh ovs-ofctl dump-flows " + s
2787
GlennRC528ad292015-11-12 10:38:18 -08002788 if "1.0" == version:
2789 cmd += " -F OpenFlow10-table_id"
2790 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002791 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002792
2793 main.log.info( "Sending: " + cmd )
2794 self.handle.sendline( cmd )
2795 self.handle.expect( "mininet>" )
2796 response = self.handle.before
2797 response = response.split( "\r\n" )
2798 # dump the first two elements and the last
2799 # the first element is the command that was sent
2800 # the second is the table header
2801 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002802 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002803 flows.extend( response )
2804
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002805 if debug:
2806 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002807
GlennRC528ad292015-11-12 10:38:18 -08002808 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002809
GlennRC956ea742015-11-05 16:14:15 -08002810 except pexpect.EOF:
2811 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002812 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002813 except Exception:
2814 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002815 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002816
2817 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002818 '''
GlennRC956ea742015-11-05 16:14:15 -08002819 Discription: Checks whether the ID provided matches a flow ID in Mininet
2820 Arguments:
2821 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002822 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002823 a list of switches.
2824 flowId: the flow ID in hex format. Can also be a list of IDs
2825 Optional:
2826 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2827 debug: prints out the final result
2828 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2829 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002830 '''
GlennRC956ea742015-11-05 16:14:15 -08002831 try:
2832 main.log.info( "Getting flows from Mininet" )
2833 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002834 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002835 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002836
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002837 if debug:
2838 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002839
2840 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002841 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002842 result = False
2843 for f in flows:
2844 if flowId in f.get( 'cookie' ):
2845 result = True
2846 break
2847 # flowId is a list
2848 else:
2849 result = True
2850 # Get flow IDs from Mininet
2851 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2852 # Save the IDs that are not in Mininet
2853 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2854
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002855 if debug:
2856 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002857
2858 # Print out the IDs that are not in Mininet
2859 if absentIds:
2860 main.log.warn( "Absent ids: {}".format( absentIds ) )
2861 result = False
2862
2863 return main.TRUE if result else main.FALSE
2864
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002865 except pexpect.EOF:
2866 main.log.error( self.name + ": EOF exception found" )
2867 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002868 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002869 except Exception:
2870 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002871 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002872
Charles Chan029be652015-08-24 01:46:10 +08002873 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002874 """
Jon Hallefbd9792015-03-05 16:11:36 -08002875 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002876 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002877 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002878 self.handle.sendline( "" )
2879 self.handle.expect( "mininet>" )
2880 self.handle.sendline(
2881 "sh sudo tcpdump -n -i " +
2882 intf +
2883 " " +
2884 port +
2885 " -w " +
2886 filename.strip() +
2887 " &" )
2888 self.handle.sendline( "" )
2889 i = self.handle.expect( [ 'No\ssuch\device',
2890 'listening\son',
2891 pexpect.TIMEOUT,
2892 "mininet>" ],
2893 timeout=10 )
2894 main.log.warn( self.handle.before + self.handle.after )
2895 self.handle.sendline( "" )
2896 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002897 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002898 main.log.error(
2899 self.name +
2900 ": tcpdump - No such device exists. " +
2901 "tcpdump attempted on: " +
2902 intf )
admin2a9548d2014-06-17 14:08:07 -07002903 return main.FALSE
2904 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002905 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002906 return main.TRUE
2907 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002908 main.log.error(
2909 self.name +
2910 ": tcpdump command timed out! Check interface name," +
2911 " given interface was: " +
2912 intf )
admin2a9548d2014-06-17 14:08:07 -07002913 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002914 elif i == 3:
2915 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002916 return main.TRUE
2917 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002918 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002919 return main.FALSE
2920 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002921 main.log.error( self.name + ": EOF exception found" )
2922 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002923 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002924 except Exception:
2925 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002926 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002927
kelvin-onlabd3b64892015-01-20 13:26:24 -08002928 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002929 """
2930 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002931 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002932 self.handle.sendline( "sh sudo pkill tcpdump" )
2933 self.handle.expect( "mininet>" )
2934 self.handle.sendline( "" )
2935 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002936 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002937 main.log.error( self.name + ": TIMEOUT exception found" )
2938 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002939 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002940 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002941 main.log.error( self.name + ": EOF exception found" )
2942 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002943 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002944 except Exception:
2945 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002946 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002947
Jon Halld80cc142015-07-06 13:36:05 -07002948 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002949 """
2950 Read ports from a Mininet switch.
2951
2952 Returns a json structure containing information about the
2953 ports of the given switch.
2954 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002955 try:
2956 response = self.getInterfaces( nodeName )
2957 # TODO: Sanity check on response. log if no such switch exists
2958 ports = []
2959 for line in response.split( "\n" ):
2960 if not line.startswith( "name=" ):
2961 continue
2962 portVars = {}
2963 for var in line.split( "," ):
2964 key, value = var.split( "=" )
2965 portVars[ key ] = value
2966 isUp = portVars.pop( 'enabled', "True" )
2967 isUp = "True" in isUp
2968 if verbose:
2969 main.log.info( "Reading switch port %s(%s)" %
2970 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2971 mac = portVars[ 'mac' ]
2972 if mac == 'None':
2973 mac = None
2974 ips = []
2975 ip = portVars[ 'ip' ]
2976 if ip == 'None':
2977 ip = None
2978 ips.append( ip )
2979 name = portVars[ 'name' ]
2980 if name == 'None':
2981 name = None
2982 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2983 if name == 'lo':
2984 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2985 else:
2986 portNo = re.search( portRe, name ).group( 'port' )
2987 ports.append( { 'of_port': portNo,
2988 'mac': str( mac ).replace( '\'', '' ),
2989 'name': name,
2990 'ips': ips,
2991 'enabled': isUp } )
2992 return ports
2993 except pexpect.EOF:
2994 main.log.error( self.name + ": EOF exception found" )
2995 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002996 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002997 except Exception:
2998 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002999 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003000
You Wangdb8cd0a2016-05-26 15:19:45 -07003001 def getOVSPorts( self, nodeName ):
3002 """
3003 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
3004
3005 Returns a list of dictionaries containing information about each
3006 port of the given switch.
3007 """
3008 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
3009 try:
3010 response = self.execute(
3011 cmd=command,
3012 prompt="mininet>",
3013 timeout=10 )
3014 ports = []
3015 if response:
3016 for line in response.split( "\n" ):
3017 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
3018 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003019 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07003020 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
3021 result = re.search( pattern, line )
3022 if result:
3023 index = result.group( 'index' )
3024 name = result.group( 'name' )
3025 # This port number is extracted from port name
3026 port = result.group( 'port' )
3027 mac = result.group( 'mac' )
3028 ports.append( { 'index': index,
3029 'name': name,
3030 'port': port,
3031 'mac': mac } )
3032 return ports
3033 except pexpect.EOF:
3034 main.log.error( self.name + ": EOF exception found" )
3035 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003036 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003037 except Exception:
3038 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003039 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003040
Devin Lima7cfdbd2017-09-29 15:02:22 -07003041 def getSwitches( self, verbose=False, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07003042 """
3043 Read switches from Mininet.
3044
3045 Returns a dictionary whose keys are the switch names and the value is
3046 a dictionary containing information about the switch.
3047 """
Jon Halla22481b2015-07-28 17:46:01 -07003048 # NOTE: To support new Mininet switch classes, just append the new
3049 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07003050
Jon Halla22481b2015-07-28 17:46:01 -07003051 # Regex patterns to parse 'dump' output
3052 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07003053 # <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 -07003054 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07003055 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
3056 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
3057 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003058 try:
3059 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
3060 swRE = r"<(?P<class>" + switchClasses + r")" +\
3061 r"(?P<options>\{.*\})?\s" +\
3062 r"(?P<name>[^:]+)\:\s" +\
3063 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
3064 r"\spid=(?P<pid>(\d)+)"
3065 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07003066 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003067 output = {}
3068 dump = self.dump().split( "\n" )
3069 for line in dump:
3070 result = re.search( swRE, line, re.I )
3071 if result:
3072 name = result.group( 'name' )
3073 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
3074 pid = result.group( 'pid' )
3075 swClass = result.group( 'class' )
3076 options = result.group( 'options' )
3077 if verbose:
3078 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
3079 ports = self.getPorts( name )
3080 output[ name ] = { "dpid": dpid,
3081 "ports": ports,
3082 "swClass": swClass,
3083 "pid": pid,
3084 "options": options }
3085 return output
3086 except pexpect.EOF:
3087 main.log.error( self.name + ": EOF exception found" )
3088 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003089 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003090 except Exception:
3091 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003092 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003093
You Wangd66de192018-04-30 17:30:12 -07003094 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08003095 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
3096 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07003097 """
3098 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08003099 Optional:
3100 hostClass: it is used to match the class of the mininet host. It
3101 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07003102 Returns a dictionary whose keys are the host names and the value is
3103 a dictionary containing information about the host.
3104 """
3105 # Regex patterns to parse dump output
3106 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07003107 # <Host h1: pid=12725>
3108 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
3109 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
3110 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07003111 # NOTE: Does not correctly match hosts with multi-links
3112 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
3113 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003114 try:
You Wang53dba1e2018-02-02 17:45:44 -08003115 if not isinstance( hostClass, types.ListType ):
3116 hostClass = [ str( hostClass ) ]
3117 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08003118 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
3119 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
3120 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07003121 if update:
3122 # update mn port info
3123 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003124 # Get mininet dump
3125 dump = self.dump().split( "\n" )
3126 hosts = {}
3127 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08003128 result = re.search( hostRE, line )
3129 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003130 name = result.group( 'name' )
3131 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07003132 if getInterfaces:
3133 response = self.getInterfaces( name )
3134 # Populate interface info
3135 for line in response.split( "\n" ):
3136 if line.startswith( "name=" ):
3137 portVars = {}
3138 for var in line.split( "," ):
3139 key, value = var.split( "=" )
3140 portVars[ key ] = value
3141 isUp = portVars.pop( 'enabled', "True" )
3142 isUp = "True" in isUp
3143 if verbose:
3144 main.log.info( "Reading host port %s(%s)" %
3145 ( portVars[ 'name' ],
3146 portVars[ 'mac' ] ) )
3147 mac = portVars[ 'mac' ]
3148 if mac == 'None':
3149 mac = None
3150 ips = []
3151 ip = portVars[ 'ip' ]
3152 if ip == 'None':
3153 ip = None
3154 ips.append( ip )
3155 intfName = portVars[ 'name' ]
3156 if name == 'None':
3157 name = None
3158 interfaces.append( {
3159 "name": intfName,
3160 "ips": ips,
3161 "mac": str( mac ),
3162 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003163 hosts[ name ] = { "interfaces": interfaces }
3164 return hosts
3165 except pexpect.EOF:
3166 main.log.error( self.name + ": EOF exception found" )
3167 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003168 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003169 except Exception:
3170 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003171 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003172
Devin Lima7cfdbd2017-09-29 15:02:22 -07003173 def getLinks( self, timeout=20, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07003174 """
3175 Gathers information about current Mininet links. These links may not
3176 be up if one of the ports is down.
3177
3178 Returns a list of dictionaries with link endpoints.
3179
3180 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07003181 { 'node1': str( node1 name )
3182 'node2': str( node2 name )
3183 'port1': str( port1 of_port )
3184 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07003185 Note: The port number returned is the eth#, not necessarily the of_port
3186 number. In Mininet, for OVS switch, these should be the same. For
3187 hosts, this is just the eth#.
3188 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003189 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003190 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003191 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07003192
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003193 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003194 # s1-eth3<->s2-eth1 (OK OK)
3195 # s13-eth3<->h27-eth0 (OK OK)
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003196 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
3197 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
3198 links = []
3199 for line in response:
3200 match = re.search( linkRE, line )
3201 if match:
3202 node1 = match.group( 'node1' )
3203 node2 = match.group( 'node2' )
3204 port1 = match.group( 'port1' )
3205 port2 = match.group( 'port2' )
3206 links.append( { 'node1': node1,
3207 'node2': node2,
3208 'port1': port1,
3209 'port2': port2 } )
3210 return links
3211
3212 except pexpect.EOF:
3213 main.log.error( self.name + ": EOF exception found" )
3214 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003215 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003216 except Exception:
3217 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003218 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003219
3220 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003221 """
3222 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003223 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003224
Jon Hallafa8a472015-06-12 14:02:42 -07003225 Dependencies:
3226 1. numpy - "sudo pip install numpy"
3227 """
3228 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003229 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003230 try:
3231 mnDPIDs = []
3232 for swName, switch in switches.iteritems():
3233 mnDPIDs.append( switch[ 'dpid' ].lower() )
3234 mnDPIDs.sort()
3235 if switchesJson == "": # if rest call fails
3236 main.log.error(
3237 self.name +
3238 ".compareSwitches(): Empty JSON object given from ONOS" )
3239 return main.FALSE
3240 onos = switchesJson
3241 onosDPIDs = []
3242 for switch in onos:
3243 if switch[ 'available' ]:
3244 onosDPIDs.append(
3245 switch[ 'id' ].replace(
3246 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003247 '' ).replace(
3248 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003249 '' ).lower() )
3250 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003251
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003252 if mnDPIDs != onosDPIDs:
3253 switchResults = main.FALSE
3254 main.log.error( "Switches in MN but not in ONOS:" )
3255 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3256 main.log.error( str( list1 ) )
3257 main.log.error( "Switches in ONOS but not in MN:" )
3258 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3259 main.log.error( str( list2 ) )
3260 else: # list of dpid's match in onos and mn
3261 switchResults = main.TRUE
3262 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003263
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003264 # FIXME: this does not look for extra ports in ONOS, only checks that
3265 # ONOS has what is in MN
3266 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003267
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003268 # PORTS
3269 for name, mnSwitch in switches.iteritems():
3270 mnPorts = []
3271 onosPorts = []
3272 switchResult = main.TRUE
3273 for port in mnSwitch[ 'ports' ]:
3274 if port[ 'enabled' ]:
3275 mnPorts.append( int( port[ 'of_port' ] ) )
3276 for onosSwitch in portsJson:
3277 if onosSwitch[ 'device' ][ 'available' ]:
3278 if onosSwitch[ 'device' ][ 'id' ].replace(
3279 ':',
3280 '' ).replace(
3281 "of",
3282 '' ) == mnSwitch[ 'dpid' ]:
3283 for port in onosSwitch[ 'ports' ]:
3284 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003285 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003286 # onosPorts.append( 'local' )
3287 onosPorts.append( long( uint64( -2 ) ) )
3288 else:
3289 onosPorts.append( int( port[ 'port' ] ) )
3290 break
3291 mnPorts.sort( key=float )
3292 onosPorts.sort( key=float )
3293
3294 mnPortsLog = mnPorts
3295 onosPortsLog = onosPorts
3296 mnPorts = [ x for x in mnPorts ]
3297 onosPorts = [ x for x in onosPorts ]
3298
3299 # TODO: handle other reserved port numbers besides LOCAL
3300 # NOTE: Reserved ports
3301 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3302 # long( uint64( -2 ) )
3303 for mnPort in mnPortsLog:
3304 if mnPort in onosPorts:
3305 # don't set results to true here as this is just one of
3306 # many checks and it might override a failure
3307 mnPorts.remove( mnPort )
3308 onosPorts.remove( mnPort )
3309
3310 # NOTE: OVS reports this as down since there is no link
3311 # So ignoring these for now
3312 # TODO: Come up with a better way of handling these
3313 if 65534 in mnPorts:
3314 mnPorts.remove( 65534 )
3315 if long( uint64( -2 ) ) in onosPorts:
3316 onosPorts.remove( long( uint64( -2 ) ) )
3317 if len( mnPorts ): # the ports of this switch don't match
3318 switchResult = main.FALSE
3319 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3320 if len( onosPorts ): # the ports of this switch don't match
3321 switchResult = main.FALSE
3322 main.log.warn(
3323 "Ports in ONOS but not MN: " +
3324 str( onosPorts ) )
3325 if switchResult == main.FALSE:
3326 main.log.error(
3327 "The list of ports for switch %s(%s) does not match:" %
3328 ( name, mnSwitch[ 'dpid' ] ) )
3329 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3330 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3331 portsResults = portsResults and switchResult
3332 finalResults = finalResults and portsResults
3333 return finalResults
3334 except pexpect.EOF:
3335 main.log.error( self.name + ": EOF exception found" )
3336 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003337 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003338 except Exception:
3339 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003340 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003341
Jon Hallafa8a472015-06-12 14:02:42 -07003342 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003343 """
3344 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003345 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003346
Jon Hallafa8a472015-06-12 14:02:42 -07003347 """
Jon Hall7eb38402015-01-08 17:19:54 -08003348 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003349 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003350 try:
3351 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003352
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003353 mnLinks = []
3354 for l in links:
3355 try:
3356 node1 = switches[ l[ 'node1' ] ]
3357 node2 = switches[ l[ 'node2' ] ]
3358 enabled = True
3359 for port in node1[ 'ports' ]:
3360 if port[ 'of_port' ] == l[ 'port1' ]:
3361 enabled = enabled and port[ 'enabled' ]
3362 for port in node2[ 'ports' ]:
3363 if port[ 'of_port' ] == l[ 'port2' ]:
3364 enabled = enabled and port[ 'enabled' ]
3365 if enabled:
3366 mnLinks.append( l )
3367 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003368 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003369 if 2 * len( mnLinks ) == len( onos ):
3370 linkResults = main.TRUE
3371 else:
3372 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003373 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003374 "Mininet has " + str( len( mnLinks ) ) +
3375 " bidirectional links and ONOS has " +
3376 str( len( onos ) ) + " unidirectional links" )
3377
3378 # iterate through MN links and check if an ONOS link exists in
3379 # both directions
3380 for link in mnLinks:
3381 # TODO: Find a more efficient search method
3382 node1 = None
3383 port1 = None
3384 node2 = None
3385 port2 = None
3386 firstDir = main.FALSE
3387 secondDir = main.FALSE
3388 for swName, switch in switches.iteritems():
3389 if swName == link[ 'node1' ]:
3390 node1 = switch[ 'dpid' ]
3391 for port in switch[ 'ports' ]:
3392 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3393 port1 = port[ 'of_port' ]
3394 if node1 is not None and node2 is not None:
3395 break
3396 if swName == link[ 'node2' ]:
3397 node2 = switch[ 'dpid' ]
3398 for port in switch[ 'ports' ]:
3399 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3400 port2 = port[ 'of_port' ]
3401 if node1 is not None and node2 is not None:
3402 break
3403
3404 for onosLink in onos:
3405 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3406 ":", '' ).replace( "of", '' )
3407 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3408 ":", '' ).replace( "of", '' )
3409 onosPort1 = onosLink[ 'src' ][ 'port' ]
3410 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3411
3412 # check onos link from node1 to node2
3413 if str( onosNode1 ) == str( node1 ) and str(
3414 onosNode2 ) == str( node2 ):
3415 if int( onosPort1 ) == int( port1 ) and int(
3416 onosPort2 ) == int( port2 ):
3417 firstDir = main.TRUE
3418 else:
Jon Hallab611372018-02-21 15:26:05 -08003419 # The right switches, but wrong ports, could be
3420 # another link between these devices, or onos
3421 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003422 main.log.warn(
3423 'The port numbers do not match for ' +
3424 str( link ) +
3425 ' between ONOS and MN. When checking ONOS for ' +
3426 'link %s/%s -> %s/%s' %
3427 ( node1, port1, node2, port2 ) +
3428 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003429 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3430 '. This could be another link between these devices' +
3431 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003432
3433 # check onos link from node2 to node1
3434 elif ( str( onosNode1 ) == str( node2 ) and
3435 str( onosNode2 ) == str( node1 ) ):
3436 if ( int( onosPort1 ) == int( port2 )
3437 and int( onosPort2 ) == int( port1 ) ):
3438 secondDir = main.TRUE
3439 else:
Jon Hallab611372018-02-21 15:26:05 -08003440 # The right switches, but wrong ports, could be
3441 # another link between these devices, or onos
3442 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003443 main.log.warn(
3444 'The port numbers do not match for ' +
3445 str( link ) +
3446 ' between ONOS and MN. When checking ONOS for ' +
3447 'link %s/%s -> %s/%s' %
3448 ( node1, port1, node2, port2 ) +
3449 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003450 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3451 '. This could be another link between these devices' +
3452 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003453 else: # this is not the link you're looking for
3454 pass
3455 if not firstDir:
3456 main.log.error(
3457 'ONOS does not have the link %s/%s -> %s/%s' %
3458 ( node1, port1, node2, port2 ) )
3459 if not secondDir:
3460 main.log.error(
3461 'ONOS does not have the link %s/%s -> %s/%s' %
3462 ( node2, port2, node1, port1 ) )
3463 linkResults = linkResults and firstDir and secondDir
3464 return linkResults
3465 except pexpect.EOF:
3466 main.log.error( self.name + ": EOF exception found" )
3467 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003468 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003469 except Exception:
3470 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003471 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003472
Jon Hallafa8a472015-06-12 14:02:42 -07003473 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003474 """
Jon Hallafa8a472015-06-12 14:02:42 -07003475 Compare mn and onos Hosts.
3476 Since Mininet hosts are quiet, ONOS will only know of them when they
3477 speak. For this reason, we will only check that the hosts in ONOS
3478 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003479
Jon Hallafa8a472015-06-12 14:02:42 -07003480 Arguments:
3481 hostsJson: parsed json object from the onos hosts api
3482 Returns:
3483 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003484 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003485 try:
3486 hostResults = main.TRUE
3487 for onosHost in hostsJson:
3488 onosMAC = onosHost[ 'mac' ].lower()
3489 match = False
3490 for mnHost, info in hosts.iteritems():
3491 for mnIntf in info[ 'interfaces' ]:
3492 if onosMAC == mnIntf[ 'mac' ].lower():
3493 match = True
3494 for ip in mnIntf[ 'ips' ]:
3495 if ip in onosHost[ 'ipAddresses' ]:
3496 pass # all is well
3497 else:
3498 # misssing ip
3499 main.log.error( "ONOS host " +
3500 onosHost[ 'id' ] +
3501 " has a different IP(" +
3502 str( onosHost[ 'ipAddresses' ] ) +
3503 ") than the Mininet host(" +
3504 str( ip ) +
3505 ")." )
3506 output = json.dumps(
3507 onosHost,
3508 sort_keys=True,
3509 indent=4,
3510 separators=( ',', ': ' ) )
3511 main.log.info( output )
3512 hostResults = main.FALSE
3513 if not match:
3514 hostResults = main.FALSE
3515 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3516 "corresponding Mininet host." )
3517 output = json.dumps( onosHost,
3518 sort_keys=True,
3519 indent=4,
3520 separators=( ',', ': ' ) )
3521 main.log.info( output )
3522 return hostResults
3523 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003524 main.log.error( self.name + ": EOF exception found" )
3525 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003526 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003527 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003528 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003529 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003530
You Wangd66de192018-04-30 17:30:12 -07003531 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003532 """
3533 Description:
3534 Verify that all hosts have IP address assigned to them
3535 Optional:
3536 hostList: If specified, verifications only happen to the hosts
3537 in hostList
3538 prefix: at least one of the ip address assigned to the host
3539 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003540 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003541 Returns:
3542 main.TRUE if all hosts have specific IP address assigned;
3543 main.FALSE otherwise
3544 """
3545 try:
You Wangd66de192018-04-30 17:30:12 -07003546 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003547 if not hostList:
3548 hostList = hosts.keys()
3549 for hostName in hosts.keys():
3550 if hostName not in hostList:
3551 continue
3552 ipList = []
3553 self.handle.sendline( str( hostName ) + " ip a" )
3554 self.handle.expect( "mininet>" )
3555 ipa = self.handle.before
3556 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3557 ipList += re.findall( ipv4Pattern, ipa )
3558 # It's tricky to make regex for IPv6 addresses and this one is simplified
3559 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})/'
3560 ipList += re.findall( ipv6Pattern, ipa )
3561 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3562 if not ipList:
3563 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3564 else:
3565 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3566 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3567 else:
3568 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3569 hostList.remove( hostName )
3570 return main.FALSE if hostList else main.TRUE
3571 except KeyError:
3572 main.log.exception( self.name + ": host data not as expected: " + hosts )
3573 return None
3574 except pexpect.EOF:
3575 main.log.error( self.name + ": EOF exception found" )
3576 main.log.error( self.name + ": " + self.handle.before )
3577 main.cleanAndExit()
3578 except Exception:
3579 main.log.exception( self.name + ": Uncaught exception" )
3580 return None
3581
Jon Hallafa8a472015-06-12 14:02:42 -07003582 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003583 """
3584 Returns a list of all hosts
3585 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003586 try:
3587 self.handle.sendline( "" )
3588 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003589
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003590 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3591 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003592
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003593 handlePy = self.handle.before
3594 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3595 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003596
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003597 self.handle.sendline( "" )
3598 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003599
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003600 hostStr = handlePy.replace( "]", "" )
3601 hostStr = hostStr.replace( "'", "" )
3602 hostStr = hostStr.replace( "[", "" )
3603 hostStr = hostStr.replace( " ", "" )
3604 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003605
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003606 return hostList
3607 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003608 main.log.error( self.name + ": TIMEOUT exception found" )
3609 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003610 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003611 except pexpect.EOF:
3612 main.log.error( self.name + ": EOF exception found" )
3613 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003614 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003615 except Exception:
3616 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003617 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003618
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003619 def getSwitch( self ):
3620 """
3621 Returns a list of all switches
3622 Again, don't ask question just use it...
3623 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003624 try:
3625 # get host list...
3626 hostList = self.getHosts()
3627 # Make host set
3628 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003629
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003630 # Getting all the nodes in mininet
3631 self.handle.sendline( "" )
3632 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003633
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003634 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3635 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003636
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003637 handlePy = self.handle.before
3638 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3639 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003640
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003641 self.handle.sendline( "" )
3642 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003643
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003644 nodesStr = handlePy.replace( "]", "" )
3645 nodesStr = nodesStr.replace( "'", "" )
3646 nodesStr = nodesStr.replace( "[", "" )
3647 nodesStr = nodesStr.replace( " ", "" )
3648 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003649
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003650 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003651 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003652 nodesSet.discard( 'c0' )
3653 nodesSet.discard( 'c1' )
3654 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003655
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003656 switchSet = nodesSet - hostSet
3657 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003658
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003659 return switchList
3660 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003661 main.log.error( self.name + ": TIMEOUT exception found" )
3662 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003663 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003664 except pexpect.EOF:
3665 main.log.error( self.name + ": EOF exception found" )
3666 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003667 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003668 except Exception:
3669 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003670 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003671
You Wangdb8cd0a2016-05-26 15:19:45 -07003672 def getGraphDict( self, timeout=60, useId=True, includeHost=False ):
3673 """
3674 Return a dictionary which describes the latest Mininet topology data as a
3675 graph.
3676 An example of the dictionary:
3677 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3678 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3679 Each vertex should at least have an 'edges' attribute which describes the
3680 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003681 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003682 list of attributes.
3683 An example of the edges dictionary:
3684 'edges': { vertex2: { 'port': ..., 'weight': ... },
3685 vertex3: { 'port': ..., 'weight': ... } }
3686 If useId == True, dpid/mac will be used instead of names to identify
3687 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3688 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003689 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003690 in topology data.
3691 Note that link or switch that are brought down by 'link x x down' or 'switch
3692 x down' commands still show in the output of Mininet CLI commands such as
3693 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3694 recommended to use delLink() or delSwitch functions to simulate link/switch
3695 down, and addLink() or addSwitch to add them back.
3696 """
3697 graphDict = {}
3698 try:
3699 links = self.getLinks( timeout=timeout )
3700 portDict = {}
3701 if useId:
3702 switches = self.getSwitches()
3703 if includeHost:
3704 hosts = self.getHosts()
3705 for link in links:
3706 # FIXME: support 'includeHost' argument
3707 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3708 continue
3709 nodeName1 = link[ 'node1' ]
3710 nodeName2 = link[ 'node2' ]
3711 port1 = link[ 'port1' ]
3712 port2 = link[ 'port2' ]
3713 # Loop for two nodes
3714 for i in range( 2 ):
3715 # Get port index from OVS
3716 # The index extracted from port name may be inconsistent with ONOS
3717 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003718 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003719 portList = self.getOVSPorts( nodeName1 )
3720 if len( portList ) == 0:
3721 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3722 return None
3723 portDict[ nodeName1 ] = portList
3724 for port in portDict[ nodeName1 ]:
3725 if port[ 'port' ] == port1:
3726 portIndex = port[ 'index' ]
3727 break
3728 if portIndex == -1:
3729 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3730 return None
3731 if useId:
3732 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3733 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3734 else:
3735 node1 = nodeName1
3736 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003737 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003738 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003739 graphDict[ node1 ] = { 'edges': {},
3740 'dpid': switches[ nodeName1 ][ 'dpid' ],
3741 'name': nodeName1,
3742 'ports': switches[ nodeName1 ][ 'ports' ],
3743 'swClass': switches[ nodeName1 ][ 'swClass' ],
3744 'pid': switches[ nodeName1 ][ 'pid' ],
3745 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003746 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003747 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003748 else:
3749 # Assert node2 is not connected to any current links of node1
3750 assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003751 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
You Wangdb8cd0a2016-05-26 15:19:45 -07003752 # Swap two nodes/ports
3753 nodeName1, nodeName2 = nodeName2, nodeName1
3754 port1, port2 = port2, port1
3755 return graphDict
3756 except KeyError:
3757 main.log.exception( self.name + ": KeyError exception found" )
3758 return None
3759 except AssertionError:
3760 main.log.exception( self.name + ": AssertionError exception found" )
3761 return None
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()
You Wangdb8cd0a2016-05-26 15:19:45 -07003766 except Exception:
3767 main.log.exception( self.name + ": Uncaught exception" )
3768 return None
3769
Devin Lima7cfdbd2017-09-29 15:02:22 -07003770 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003771 """
3772 updates the port address and status information for
3773 each port in mn"""
3774 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003775 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003776 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003777 self.handle.sendline( "" )
3778 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003779
Jon Hall7eb38402015-01-08 17:19:54 -08003780 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003781 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003782
Jon Hall7eb38402015-01-08 17:19:54 -08003783 self.handle.sendline( "" )
3784 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003785
Jon Hallb1290e82014-11-18 16:17:48 -05003786 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003787 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003788 main.log.error( self.name + ": TIMEOUT exception found" )
3789 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003790 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003791 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003792 main.log.error( self.name + ": EOF exception found" )
3793 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003794 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003795 except Exception:
3796 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003797 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003798
Jon Halld80cc142015-07-06 13:36:05 -07003799 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003800 """
3801 Add vlan tag to a host.
3802 Dependencies:
3803 This class depends on the "vlan" package
3804 $ sudo apt-get install vlan
3805 Configuration:
3806 Load the 8021q module into the kernel
3807 $sudo modprobe 8021q
3808
3809 To make this setup permanent:
3810 $ sudo su -c 'echo "8021q" >> /etc/modules'
3811 """
3812 if self.handle:
3813 try:
Jon Halld80cc142015-07-06 13:36:05 -07003814 # get the ip address of the host
3815 main.log.info( "Get the ip address of the host" )
3816 ipaddr = self.getIPAddress( host )
3817 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003818
Jon Halld80cc142015-07-06 13:36:05 -07003819 # remove IP from interface intf
3820 # Ex: h1 ifconfig h1-eth0 inet 0
3821 main.log.info( "Remove IP from interface " )
3822 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3823 self.handle.sendline( cmd2 )
3824 self.handle.expect( "mininet>" )
3825 response = self.handle.before
3826 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003827
Jon Halld80cc142015-07-06 13:36:05 -07003828 # create VLAN interface
3829 # Ex: h1 vconfig add h1-eth0 100
3830 main.log.info( "Create Vlan" )
3831 cmd3 = host + " vconfig add " + intf + " " + vlan
3832 self.handle.sendline( cmd3 )
3833 self.handle.expect( "mininet>" )
3834 response = self.handle.before
3835 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003836
Jon Halld80cc142015-07-06 13:36:05 -07003837 # assign the host's IP to the VLAN interface
3838 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3839 main.log.info( "Assign the host IP to the vlan interface" )
3840 vintf = intf + "." + vlan
3841 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3842 self.handle.sendline( cmd4 )
3843 self.handle.expect( "mininet>" )
3844 response = self.handle.before
3845 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003846
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003847 # update Mininet node variables
3848 main.log.info( "Update Mininet node variables" )
3849 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3850 self.handle.sendline( cmd5 )
3851 self.handle.expect( "mininet>" )
3852 response = self.handle.before
3853 main.log.info( "====> %s ", response )
3854
3855 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3856 self.handle.sendline( cmd6 )
3857 self.handle.expect( "mininet>" )
3858 response = self.handle.before
3859 main.log.info( "====> %s ", response )
3860
3861 return main.TRUE
3862 except pexpect.TIMEOUT:
3863 main.log.error( self.name + ": TIMEOUT exception found" )
3864 main.log.error( self.name + ": " + self.handle.before )
3865 main.cleanAndExit()
3866 except pexpect.EOF:
3867 main.log.error( self.name + ": EOF exception found" )
3868 main.log.error( self.name + ": " + self.handle.before )
3869 return main.FALSE
3870 except Exception:
3871 main.log.exception( self.name + ": Uncaught exception!" )
3872 return main.FALSE
3873
3874 def removeVLAN( self, host, intf ):
3875 """
3876 Remove vlan tag from a host.
3877 Dependencies:
3878 This class depends on the "vlan" package
3879 $ sudo apt-get install vlan
3880 Configuration:
3881 Load the 8021q module into the kernel
3882 $sudo modprobe 8021q
3883
3884 To make this setup permanent:
3885 $ sudo su -c 'echo "8021q" >> /etc/modules'
3886 """
3887 if self.handle:
3888 try:
3889 # get the ip address of the host
3890 main.log.info( "Get the ip address of the host" )
3891 ipaddr = self.getIPAddress( host )
3892
3893 # remove VLAN interface
3894 # Ex: h1 vconfig rem h1-eth0.100
3895 main.log.info( "Remove Vlan interface" )
3896 cmd2 = host + " vconfig rem " + intf
3897 self.handle.sendline( cmd2 )
3898 self.handle.expect( "mininet>" )
3899 response = self.handle.before
3900 main.log.info( "====> %s ", response )
3901
3902 # assign the host's IP to the original interface
3903 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3904 main.log.info( "Assign the host IP to the original interface" )
3905 original_intf = intf.split(".")[0]
3906 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3907 self.handle.sendline( cmd3 )
3908 self.handle.expect( "mininet>" )
3909 response = self.handle.before
3910 main.log.info( "====> %s ", response )
3911
3912 # update Mininet node variables
3913 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3914 self.handle.sendline( cmd4 )
3915 self.handle.expect( "mininet>" )
3916 response = self.handle.before
3917 main.log.info( "====> %s ", response )
3918
3919 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3920 self.handle.sendline( cmd5 )
3921 self.handle.expect( "mininet>" )
3922 response = self.handle.before
3923 main.log.info( "====> %s ", response )
3924
kaouthera3f13ca22015-05-05 15:01:41 -07003925 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003926 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003927 main.log.error( self.name + ": TIMEOUT exception found" )
3928 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003929 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003930 except pexpect.EOF:
3931 main.log.error( self.name + ": EOF exception found" )
3932 main.log.error( self.name + ": " + self.handle.before )
3933 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003934 except Exception:
3935 main.log.exception( self.name + ": Uncaught exception!" )
3936 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003937
Jon Hall892818c2015-10-20 17:58:34 -07003938 def createHostComponent( self, name ):
3939 """
3940 Creates a new mininet cli component with the same parameters as self.
3941 This new component is intended to be used to login to the hosts created
3942 by mininet.
3943
3944 Arguments:
3945 name - The string of the name of this component. The new component
3946 will be assigned to main.<name> .
3947 In addition, main.<name>.name = str( name )
3948 """
3949 try:
3950 # look to see if this component already exists
3951 getattr( main, name )
3952 except AttributeError:
3953 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003954 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3955 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003956 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003957 except pexpect.EOF:
3958 main.log.error( self.name + ": EOF exception found" )
3959 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003960 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003961 except Exception:
3962 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003963 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003964 else:
3965 # namespace is not clear!
3966 main.log.error( name + " component already exists!" )
3967 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003968 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003969
3970 def removeHostComponent( self, name ):
3971 """
3972 Remove host component
3973 Arguments:
3974 name - The string of the name of the component to delete.
3975 """
3976 try:
3977 # Get host component
3978 component = getattr( main, name )
3979 except AttributeError:
3980 main.log.error( "Component " + name + " does not exist." )
3981 return
3982 try:
3983 # Disconnect from component
3984 component.disconnect()
3985 # Delete component
3986 delattr( main, name )
3987 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003988 del( main.componentDictionary[ name ] )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003989 except pexpect.EOF:
3990 main.log.error( self.name + ": EOF exception found" )
3991 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003992 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003993 except Exception:
3994 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003995 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003996
3997 def startHostCli( self, host=None ):
3998 """
3999 Use the mininet m utility to connect to the host's cli
4000 """
4001 # These are fields that can be used by scapy packets. Initialized to None
4002 self.hostIp = None
4003 self.hostMac = None
4004 try:
4005 if not host:
4006 host = self.name
4007 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07004008 self.handle.sendline( "cd" )
4009 self.handle.expect( self.hostPrompt )
4010 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07004011 self.handle.expect( self.hostPrompt )
4012 return main.TRUE
4013 except pexpect.TIMEOUT:
4014 main.log.exception( self.name + ": Command timed out" )
4015 return main.FALSE
4016 except pexpect.EOF:
4017 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07004018 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07004019 except Exception:
4020 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004021 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07004022
YPZhang801d46d2016-08-08 13:26:28 -07004023 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004024 '''
4025
YPZhang801d46d2016-08-08 13:26:28 -07004026 Args:
4027 devicename: switch name
4028 intf: port name on switch
4029 status: up or down
4030
4031 Returns: boolean to show success change status
4032
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004033 '''
YPZhang801d46d2016-08-08 13:26:28 -07004034 if status == "down" or status == "up":
4035 try:
4036 cmd = devicename + " ifconfig " + intf + " " + status
4037 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004038 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07004039 return main.TRUE
4040 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004041 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07004042 return main.FALSE
4043 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004044 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07004045 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07004046 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004047 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07004048 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07004049 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004050 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004051 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07004052 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004053 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07004054 return main.FALSE
4055
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004056 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
4057 macAddr=None, prefixLen=None, bondedName='bond1' ):
4058 """
4059 Moves a dual-homed host from one switch-pair to another pair on the fly
4060 If macAddr is specified, change MAC address of the bonded host interface
4061 to specified MAC address.
4062 Assumes that the host has two interfaces (eth0 and eth1) originally.
4063 """
4064
4065 bond1 = "%s-%s" % ( host, bondedName )
4066 newIntf = host + '-eth2'
4067 newIntfPair = host + '-eth3'
4068 commands = [
4069 # Bring link between oldSw-host down
4070 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
4071 # Bring link between oldPairSw-host down
4072 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
4073 # Determine hostintf and Oldswitchintf
4074 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
4075 # Determine ip and mac address of the host-oldSw interface
4076 "px ipaddr = hintf.IP()",
4077 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
4078 # Detach interface between oldSw-host
4079 "px " + oldSw + ".detach( sintf )",
4080 # Determine hostintf and Oldpairswitchintf
4081 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
4082 # Detach interface between oldPairSw-host
4083 "px " + oldPairSw + ".detach( sintfpair )",
4084 # Add link between host-newSw
4085 "py net.addLink(" + host + "," + newSw + ", 2)",
4086 # Add link between host-newPairSw
4087 "py net.addLink(" + host + "," + newPairSw + ")",
4088 # Determine hostintf and Newswitchintf
4089 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
4090 # Determine hostintf and NewPairswitchintf
4091 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
4092 # Attach interface between newSw-host
4093 "px " + newSw + ".attach( sintf )",
4094 # Attach interface between newPairSw-host
4095 "px " + newPairSw + ".attach( sintfpair )",
4096 # Bond two interfaces
4097 host + ' ip link add %s type bond' % bond1,
4098 host + ' ip link set %s down' % newIntf,
4099 host + ' ip link set %s down' % newIntfPair,
4100 host + ' ip link set %s master %s' % ( newIntf, bond1 ),
4101 host + ' ip link set %s master %s' % ( newIntfPair, bond1 ),
4102 host + ' ip addr flush dev %s' % newIntf,
4103 host + ' ip addr flush dev %s' % newIntfPair,
4104 host + ' ip link set %s up' % bond1,
4105 "px lowestIntf = min( [ hintf, hintfpair ] )",
4106 "px highestIntf = max( [ hintf, hintfpair ] )",
4107 "px lowestIntf.name = '" + bond1 + "'",
4108 "px " + host + ".nameToIntf['" + bond1 + "'] = lowestIntf",
4109 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
4110 "px del " + host + ".ports[ highestIntf ]",
4111 # Set ipaddress of the host-newSw interface
4112 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
4113 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
4114 # Set macaddress of the host-newSw interface
4115 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
4116 "net",
4117 # Determine ipaddress of the bonded host interface
4118 host + " ifconfig",
4119 ]
4120
4121 if self.handle:
4122 try:
4123 for cmd in commands:
4124 print "cmd= ", cmd
4125 self.handle.sendline( cmd )
4126 self.handle.expect( "mininet>" )
4127 main.log.info( "====> %s ", self.handle.before )
4128 return main.TRUE
4129
4130 except pexpect.TIMEOUT:
4131 main.log.error( self.name + ": TIMEOUT exception found" )
4132 main.log.error( self.name + ": " + self.handle.before )
4133 main.cleanAndExit()
4134 except pexpect.EOF:
4135 main.log.error( self.name + ": EOF exception found" )
4136 main.log.error( self.name + ": " + self.handle.before )
4137 return main.FALSE
4138 except Exception:
4139 main.log.exception( self.name + ": Uncaught exception!" )
4140 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07004141
adminbae64d82013-08-01 10:50:15 -07004142if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004143 sys.modules[ __name__ ] = MininetCliDriver()