blob: 9c2f2e8bc36a078ba2fb02cc2851c62487cebb82 [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 Wang48381752018-05-07 13:50:57 -0700597 cmd = ""
598 if self.getIPAddress( host ):
599 cmd = "{} ping -c 1 -i 1 -W {} {}".format( host, wait, dstIp )
600 main.log.debug( "Sending IPv4 probe ping from host {}".format( host ) )
601 elif self.getIPAddress( host, proto='IPV6' ):
602 cmd = "{} ping6 -c 1 -i 1 -W {} {}".format( host, wait, dstIp6 )
603 main.log.debug( "Sending IPv6 probe ping from host {}".format( host ) )
604 else:
605 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
606 discoveryResult = main.FALSE
607 if cmd:
You Wang547893e2018-05-08 13:34:59 -0700608 self.handle.sendline( "{} ip neigh flush all".format( host ) )
Jon Halla604fd42018-05-04 14:27:27 -0700609 self.handle.expect( "mininet>" )
You Wang48381752018-05-07 13:50:57 -0700610 self.handle.sendline( cmd )
Jon Halla604fd42018-05-04 14:27:27 -0700611 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700612 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700613 except pexpect.TIMEOUT:
614 main.log.exception( self.name + ": TIMEOUT exception" )
615 response = self.handle.before
616 # NOTE: Send ctrl-c to make sure command is stopped
617 self.handle.send( "\x03" )
618 self.handle.expect( "Interrupt" )
619 response += self.handle.before + self.handle.after
620 self.handle.expect( "mininet>" )
621 response += self.handle.before + self.handle.after
622 main.log.debug( response )
623 return main.FALSE
624 except pexpect.EOF:
625 main.log.error( self.name + ": EOF exception found" )
626 main.log.error( self.name + ": " + self.handle.before )
627 main.cleanAndExit()
628 except Exception:
629 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800630 main.cleanAndExit()
631
632 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
633 """
634 Verify ping from each host in srcList to each host in dstList
635
636 acceptableFailed: max number of acceptable failed pings
637
638 Returns main.TRUE if all src hosts can reach all dst hosts
639 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
640 """
641 try:
642 main.log.info( "Verifying ping from each src host to each dst host" )
643 isReachable = main.TRUE
644 wait = int( wait )
645 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
646 pingResponse = "Ping output:\n"
647 failedPingsTotal = 0
648 for host in srcList:
649 pingResponse += str( str( host ) + " -> " )
650 for temp in dstList:
651 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700652 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
653 assert dstIP, "Not able to get IP address of host {}".format( temp )
654 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800655 while failedPings <= acceptableFailed:
656 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
657 self.handle.sendline( pingCmd )
Jon Halla604fd42018-05-04 14:27:27 -0700658 self.handle.expect( "mininet>", timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800659 response = self.handle.before
660 if re.search( ',\s0\%\spacket\sloss', response ):
661 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800662 break
663 else:
664 failedPings += 1
665 time.sleep(1)
666 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700667 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800668 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700669 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800670 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700671 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800672 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700673 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700674 except AssertionError:
675 main.log.exception( "" )
676 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700677 except pexpect.TIMEOUT:
678 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800679 response = self.handle.before
680 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700681 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800682 self.handle.expect( "Interrupt" )
683 response += self.handle.before + self.handle.after
684 self.handle.expect( "mininet>" )
685 response += self.handle.before + self.handle.after
686 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700687 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700688 except pexpect.EOF:
689 main.log.error( self.name + ": EOF exception found" )
690 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700691 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700692 except Exception:
693 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700694 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700695
Jon Hall7eb38402015-01-08 17:19:54 -0800696 def pingHost( self, **pingParams ):
697 """
Jon Hall3b489db2015-10-05 14:38:37 -0700698 Ping from one mininet host to another
699 Currently the only supported Params: SRC, TARGET, and WAIT
700 """
701 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700702 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700703 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800704 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700705 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700706 try:
Jon Hall61282e32015-03-19 11:34:11 -0700707 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800708 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700709 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700710 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700711 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800712 main.log.error(
713 self.name +
714 ": timeout when waiting for response from mininet" )
715 main.log.error( "response: " + str( self.handle.before ) )
716 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700717 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800718 main.log.error(
719 self.name +
720 ": timeout when waiting for response from mininet" )
721 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700722 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700723 if re.search( ',\s0\%\spacket\sloss', response ):
724 main.log.info( self.name + ": no packets lost, host is reachable" )
725 return main.TRUE
726 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800727 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700728 self.name +
729 ": PACKET LOST, HOST IS NOT REACHABLE" )
730 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800731 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800732 main.log.error( self.name + ": EOF exception found" )
733 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700734 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700735 except Exception:
736 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700737 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700738
739 def ping6pair( self, **pingParams ):
740 """
GlennRC2cf7d952015-09-11 16:32:13 -0700741 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700742 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000743 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700744 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
745 """
Jon Hall3b489db2015-10-05 14:38:37 -0700746 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700747 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700748 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530749 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700750 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700751 try:
752 main.log.info( "Sending: " + command )
753 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700754 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700755 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700756 if i == 1:
757 main.log.error(
758 self.name +
759 ": timeout when waiting for response from mininet" )
760 main.log.error( "response: " + str( self.handle.before ) )
761 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
762 if i == 1:
763 main.log.error(
764 self.name +
765 ": timeout when waiting for response from mininet" )
766 main.log.error( "response: " + str( self.handle.before ) )
767 response = self.handle.before
768 main.log.info( self.name + ": Ping Response: " + response )
769 if re.search( ',\s0\%\spacket\sloss', response ):
770 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700771 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700772 else:
alisone4121a92016-11-22 16:31:36 -0800773 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700774 self.name +
775 ": PACKET LOST, HOST IS NOT REACHABLE" )
776 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700777 except pexpect.EOF:
778 main.log.error( self.name + ": EOF exception found" )
779 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700780 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700781 except Exception:
782 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700783 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800784
You Wangdb927a52016-02-26 11:03:28 -0800785 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
786 """
787 Description:
788 Ping a set of destination host from host CLI.
789 Logging into a Mininet host CLI is required before calling this funtion.
790 Params:
791 dstIPList is a list of destination ip addresses
792 Returns:
793 main.TRUE if the destination host is reachable
794 main.FALSE otherwise
795 """
796 isReachable = main.TRUE
797 wait = int( wait )
798 cmd = "ping"
799 if IPv6:
800 cmd = cmd + "6"
801 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
802 try:
803 for dstIP in dstIPList:
804 pingCmd = cmd + " " + dstIP
805 self.handle.sendline( pingCmd )
806 i = self.handle.expect( [ self.hostPrompt,
807 '\*\*\* Unknown command: ' + pingCmd,
808 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700809 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700810 # For some reason we need to send something
811 # Otherwise ping results won't be read by handle
812 self.handle.sendline( "" )
813 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800814 if i == 0:
815 response = self.handle.before
816 if not re.search( ',\s0\%\spacket\sloss', response ):
817 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
818 isReachable = main.FALSE
819 elif i == 1:
820 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700821 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800822 elif i == 2:
823 main.log.error( self.name + ": timeout when waiting for response" )
824 isReachable = main.FALSE
825 else:
826 main.log.error( self.name + ": unknown response: " + self.handle.before )
827 isReachable = main.FALSE
828 except pexpect.TIMEOUT:
829 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800830 response = self.handle.before
831 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700832 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800833 self.handle.expect( "Interrupt" )
834 response += self.handle.before + self.handle.after
835 self.handle.expect( "mininet>" )
836 response += self.handle.before + self.handle.after
837 main.log.debug( response )
You Wangdb927a52016-02-26 11:03:28 -0800838 isReachable = main.FALSE
839 except pexpect.EOF:
840 main.log.error( self.name + ": EOF exception found" )
841 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700842 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800843 except Exception:
844 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700845 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800846 return isReachable
847
Jon Hall7eb38402015-01-08 17:19:54 -0800848 def checkIP( self, host ):
849 """
850 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700851 try:
852 if self.handle:
853 try:
854 response = self.execute(
855 cmd=host +
856 " ifconfig",
857 prompt="mininet>",
858 timeout=10 )
859 except pexpect.EOF:
860 main.log.error( self.name + ": EOF exception found" )
861 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700862 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700863
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700864 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
865 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
866 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
867 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
868 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
869 "[0-9]|25[0-5]|[0-9]{1,2})"
870 # pattern = "inet addr:10.0.0.6"
871 if re.search( pattern, response ):
872 main.log.info( self.name + ": Host Ip configured properly" )
873 return main.TRUE
874 else:
875 main.log.error( self.name + ": Host IP not found" )
876 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700877 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700878 main.log.error( self.name + ": Connection failed to the host" )
879 except Exception:
880 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700881 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800882
Jon Hall7eb38402015-01-08 17:19:54 -0800883 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800884 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700885 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800886 response = self.execute(
887 cmd="h1 /usr/sbin/sshd -D&",
888 prompt="mininet>",
889 timeout=10 )
890 response = self.execute(
891 cmd="h4 /usr/sbin/sshd -D&",
892 prompt="mininet>",
893 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700894 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800895 vars( self )[ key ] = connectargs[ key ]
896 response = self.execute(
897 cmd="xterm h1 h4 ",
898 prompt="mininet>",
899 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800900 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800901 main.log.error( self.name + ": EOF exception found" )
902 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700903 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700904 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800905 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700906 if self.flag == 0:
907 self.flag = 1
908 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800909 else:
adminbae64d82013-08-01 10:50:15 -0700910 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800911
Jonghwan Hyun785471d2018-05-14 14:48:19 -0700912 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=None ):
Jon Hall53c5e662016-04-13 16:06:56 -0700913 """
914 Moves a host from one switch to another on the fly
Jonghwan Hyun785471d2018-05-14 14:48:19 -0700915 If macAddr is specified, change MAC address of the host interface
916 to specified MAC address.
Jon Hall53c5e662016-04-13 16:06:56 -0700917 Note: The intf between host and oldSw when detached
918 using detach(), will still show up in the 'net'
919 cmd, because switch.detach() doesn't affect switch.intfs[]
920 ( which is correct behavior since the interfaces
921 haven't moved ).
922 """
923 if self.handle:
924 try:
925 # Bring link between oldSw-host down
926 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
927 "'," + "'down')"
928 print "cmd1= ", cmd
929 response = self.execute( cmd=cmd,
930 prompt="mininet>",
931 timeout=10 )
932
933 # Determine hostintf and Oldswitchintf
934 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
935 ")[0]"
936 print "cmd2= ", cmd
937 self.handle.sendline( cmd )
938 self.handle.expect( "mininet>" )
939
940 # Determine ip and mac address of the host-oldSw interface
941 cmd = "px ipaddr = hintf.IP()"
942 print "cmd3= ", cmd
943 self.handle.sendline( cmd )
944 self.handle.expect( "mininet>" )
945
Jonghwan Hyun785471d2018-05-14 14:48:19 -0700946 if macAddr is None:
947 cmd = "px macaddr = hintf.MAC()"
948 else:
949 cmd = 'px macaddr = "%s"' % macAddr
Jon Hall53c5e662016-04-13 16:06:56 -0700950 print "cmd3= ", cmd
951 self.handle.sendline( cmd )
952 self.handle.expect( "mininet>" )
953
954 # Detach interface between oldSw-host
955 cmd = "px " + oldSw + ".detach( sintf )"
956 print "cmd4= ", cmd
957 self.handle.sendline( cmd )
958 self.handle.expect( "mininet>" )
959
960 # Add link between host-newSw
961 cmd = "py net.addLink(" + host + "," + newSw + ")"
962 print "cmd5= ", cmd
963 self.handle.sendline( cmd )
964 self.handle.expect( "mininet>" )
965
966 # Determine hostintf and Newswitchintf
967 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jonghwan Hyun785471d2018-05-14 14:48:19 -0700968 ")[-1]"
Jon Hall53c5e662016-04-13 16:06:56 -0700969 print "cmd6= ", cmd
970 self.handle.sendline( cmd )
971 self.handle.expect( "mininet>" )
972
973 # Attach interface between newSw-host
974 cmd = "px " + newSw + ".attach( sintf )"
975 print "cmd3= ", cmd
976 self.handle.sendline( cmd )
977 self.handle.expect( "mininet>" )
978
979 # Set ipaddress of the host-newSw interface
Jonghwan Hyun785471d2018-05-14 14:48:19 -0700980 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf, " \
981 "prefixLen = %s )" % str( prefixLen )
Jon Hall53c5e662016-04-13 16:06:56 -0700982 print "cmd7 = ", cmd
983 self.handle.sendline( cmd )
984 self.handle.expect( "mininet>" )
985
986 # Set macaddress of the host-newSw interface
987 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
988 print "cmd8 = ", cmd
989 self.handle.sendline( cmd )
990 self.handle.expect( "mininet>" )
991
992 cmd = "net"
993 print "cmd9 = ", cmd
994 self.handle.sendline( cmd )
995 self.handle.expect( "mininet>" )
996 print "output = ", self.handle.before
997
998 # Determine ipaddress of the host-newSw interface
999 cmd = host + " ifconfig"
1000 print "cmd10= ", cmd
1001 self.handle.sendline( cmd )
1002 self.handle.expect( "mininet>" )
1003 print "ifconfig o/p = ", self.handle.before
1004
1005 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001006
1007 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001008 main.log.error( self.name + ": TIMEOUT exception found" )
1009 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001010 main.cleanAndExit()
Jon Hall53c5e662016-04-13 16:06:56 -07001011 except pexpect.EOF:
1012 main.log.error( self.name + ": EOF exception found" )
1013 main.log.error( self.name + ": " + self.handle.before )
1014 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001015 except Exception:
1016 main.log.exception( self.name + ": Uncaught exception!" )
1017 return main.FALSE
Jon Hall53c5e662016-04-13 16:06:56 -07001018
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001019 def moveHostv6( self, host, oldSw, newSw, macAddr=None ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001020 """
1021 Moves a host from one switch to another on the fly
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001022 If macAddr is specified, change MAC address of the host interface
1023 to specified MAC address.
kelvin-onlaba1484582015-02-02 15:46:20 -08001024 Note: The intf between host and oldSw when detached
1025 using detach(), will still show up in the 'net'
1026 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -07001027 ( which is correct behavior since the interfaces
1028 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -08001029 """
1030 if self.handle:
1031 try:
Jon Hall439c8912016-04-15 02:22:03 -07001032 IP = str( self.getIPAddress( host, proto='IPV6' ) ) + "/64"
kelvin-onlaba1484582015-02-02 15:46:20 -08001033 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -07001034 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -08001035 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -08001036 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -08001037 response = self.execute( cmd=cmd,
1038 prompt="mininet>",
1039 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -07001040
kelvin-onlaba1484582015-02-02 15:46:20 -08001041 # Determine hostintf and Oldswitchintf
1042 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -08001043 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -08001044 print "cmd2= ", cmd
1045 self.handle.sendline( cmd )
1046 self.handle.expect( "mininet>" )
1047
shahshreya73537862015-02-11 15:15:24 -08001048 # Determine ip and mac address of the host-oldSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001049 cmd = "px ipaddr = " + str( IP )
kelvin-onlaba1484582015-02-02 15:46:20 -08001050 print "cmd3= ", cmd
1051 self.handle.sendline( cmd )
1052 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -08001053
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001054 if macAddr is None:
1055 cmd = "px macaddr = hintf.MAC()"
1056 else:
1057 cmd = 'px macaddr = "%s"' % macAddr
shahshreya73537862015-02-11 15:15:24 -08001058 print "cmd3= ", cmd
1059 self.handle.sendline( cmd )
1060 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001061
kelvin-onlaba1484582015-02-02 15:46:20 -08001062 # Detach interface between oldSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001063 cmd = "px " + oldSw + ".detach(sintf)"
kelvin-onlaba1484582015-02-02 15:46:20 -08001064 print "cmd4= ", cmd
1065 self.handle.sendline( cmd )
1066 self.handle.expect( "mininet>" )
1067
1068 # Add link between host-newSw
1069 cmd = "py net.addLink(" + host + "," + newSw + ")"
1070 print "cmd5= ", cmd
1071 self.handle.sendline( cmd )
1072 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001073
kelvin-onlaba1484582015-02-02 15:46:20 -08001074 # Determine hostintf and Newswitchintf
1075 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001076 ")[-1]"
kelvin-onlaba1484582015-02-02 15:46:20 -08001077 print "cmd6= ", cmd
1078 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -07001079 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001080
1081 # Attach interface between newSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001082 cmd = "px " + newSw + ".attach(sintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001083 print "cmd6= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001084 self.handle.sendline( cmd )
1085 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -08001086
1087 # Set macaddress of the host-newSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001088 cmd = "px " + host + ".setMAC(mac = macaddr, intf = hintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001089 print "cmd7 = ", cmd
1090 self.handle.sendline( cmd )
1091 self.handle.expect( "mininet>" )
1092
1093 # Set ipaddress of the host-newSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001094 cmd = "px " + host + ".setIP(ip = ipaddr, intf = hintf)"
shahshreya73537862015-02-11 15:15:24 -08001095 print "cmd8 = ", cmd
1096 self.handle.sendline( cmd )
1097 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001098
Jon Hall439c8912016-04-15 02:22:03 -07001099 cmd = host + " ifconfig"
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001100 print "cmd9 =", cmd
1101 response = self.execute( cmd = cmd, prompt="mininet>", timeout=10 )
Jon Hall439c8912016-04-15 02:22:03 -07001102 print response
1103 pattern = "h\d-eth([\w])"
Jeremyd9e4eb12016-04-13 12:09:06 -07001104 ipAddressSearch = re.search( pattern, response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001105 print ipAddressSearch.group( 1 )
1106 intf = host + "-eth" + str( ipAddressSearch.group( 1 ) )
Jon Hall439c8912016-04-15 02:22:03 -07001107 cmd = host + " ip -6 addr add %s dev %s" % ( IP, intf )
1108 print "cmd10 = ", cmd
1109 self.handle.sendline( cmd )
1110 self.handle.expect( "mininet>" )
1111
kelvin-onlaba1484582015-02-02 15:46:20 -08001112 cmd = "net"
Jon Hall439c8912016-04-15 02:22:03 -07001113 print "cmd11 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001114 self.handle.sendline( cmd )
1115 self.handle.expect( "mininet>" )
1116 print "output = ", self.handle.before
1117
1118 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -08001119 cmd = host + " ifconfig"
Jon Hall439c8912016-04-15 02:22:03 -07001120 print "cmd12= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001121 self.handle.sendline( cmd )
1122 self.handle.expect( "mininet>" )
1123 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -07001124
kelvin-onlaba1484582015-02-02 15:46:20 -08001125 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001126 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001127 main.log.error( self.name + ": TIMEOUT exception found" )
1128 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001129 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08001130 except pexpect.EOF:
1131 main.log.error( self.name + ": EOF exception found" )
1132 main.log.error( self.name + ": " + self.handle.before )
1133 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001134 except Exception:
1135 main.log.exception( self.name + ": Uncaught exception!" )
1136 return main.FALSE
kelvin-onlaba1484582015-02-02 15:46:20 -08001137
Jon Hall7eb38402015-01-08 17:19:54 -08001138 def changeIP( self, host, intf, newIP, newNetmask ):
1139 """
1140 Changes the ip address of a host on the fly
1141 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001142 if self.handle:
1143 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001144 cmd = host + " ifconfig " + intf + " " + \
1145 newIP + " " + 'netmask' + " " + newNetmask
1146 self.handle.sendline( cmd )
1147 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001148 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001149 main.log.info( "response = " + response )
1150 main.log.info(
1151 "Ip of host " +
1152 host +
1153 " changed to new IP " +
1154 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -08001155 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001156 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001157 main.log.error( self.name + ": TIMEOUT exception found" )
1158 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001159 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001160 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001161 main.log.error( self.name + ": EOF exception found" )
1162 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001163 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001164 except Exception:
1165 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001166 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001167
Jon Hall7eb38402015-01-08 17:19:54 -08001168 def changeDefaultGateway( self, host, newGW ):
1169 """
1170 Changes the default gateway of a host
1171 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001172 if self.handle:
1173 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001174 cmd = host + " route add default gw " + newGW
1175 self.handle.sendline( cmd )
1176 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001177 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001178 main.log.info( "response = " + response )
1179 main.log.info(
1180 "Default gateway of host " +
1181 host +
1182 " changed to " +
1183 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -08001184 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001185 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001186 main.log.error( self.name + ": TIMEOUT exception found" )
1187 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001188 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001189 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001190 main.log.error( self.name + ": EOF exception found" )
1191 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001192 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001193 except Exception:
1194 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001195 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001196
You Wange24d6272018-03-27 21:18:50 -07001197 def addRoute( self, host, dstIP, interface, ipv6=False ):
1198 """
1199 Add a route to host
1200 Ex: h1 route add -host 224.2.0.1 h1-eth0
1201 """
1202 if self.handle:
1203 try:
1204 cmd = str( host )
1205 if ipv6:
1206 cmd += " route -A inet6 add "
1207 else:
1208 cmd += " route add -host "
1209 cmd += str( dstIP ) + " " + str( interface )
1210 self.handle.sendline( cmd )
1211 self.handle.expect( "mininet>" )
1212 response = self.handle.before
1213 main.log.debug( "response = " + response )
1214 return main.TRUE
1215 except pexpect.TIMEOUT:
1216 main.log.error( self.name + ": TIMEOUT exception found" )
1217 main.log.error( self.name + ": " + self.handle.before )
1218 main.cleanAndExit()
1219 except pexpect.EOF:
1220 main.log.error( self.name + ": EOF exception found" )
1221 main.log.error( self.name + ": " + self.handle.before )
1222 return main.FALSE
1223 except Exception:
1224 main.log.exception( self.name + ": Uncaught exception!" )
1225 main.cleanAndExit()
1226
Jon Hall7eb38402015-01-08 17:19:54 -08001227 def addStaticMACAddress( self, host, GW, macaddr ):
1228 """
Jon Hallefbd9792015-03-05 16:11:36 -08001229 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001230 if self.handle:
1231 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001232 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1233 cmd = host + " arp -s " + GW + " " + macaddr
1234 self.handle.sendline( cmd )
1235 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001236 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001237 main.log.info( "response = " + response )
1238 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001239 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001240 GW +
1241 " changed to " +
1242 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001243 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001244 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001245 main.log.error( self.name + ": TIMEOUT exception found" )
1246 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001247 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001248 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001249 main.log.error( self.name + ": EOF exception found" )
1250 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001251 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001252 except Exception:
1253 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001254 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001255
Jon Hall7eb38402015-01-08 17:19:54 -08001256 def verifyStaticGWandMAC( self, host ):
1257 """
1258 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001259 if self.handle:
1260 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001261 # h1 arp -an
1262 cmd = host + " arp -an "
1263 self.handle.sendline( cmd )
1264 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001265 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001266 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001267 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001268 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001269 main.log.error( self.name + ": TIMEOUT exception found" )
1270 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001271 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001272 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001273 main.log.error( self.name + ": EOF exception found" )
1274 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001275 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001276 except Exception:
1277 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001278 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001279
Jon Hall7eb38402015-01-08 17:19:54 -08001280 def getMacAddress( self, host ):
1281 """
1282 Verifies the host's ip configured or not."""
1283 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001284 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001285 response = self.execute(
1286 cmd=host +
1287 " ifconfig",
1288 prompt="mininet>",
1289 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001290 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001291 main.log.error( self.name + ": EOF exception found" )
1292 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001293 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001294 except Exception:
1295 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001296 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001297
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001298 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001299 macAddressSearch = re.search( pattern, response, re.I )
1300 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001301 main.log.info(
1302 self.name +
1303 ": Mac-Address of Host " +
1304 host +
1305 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001306 macAddress )
1307 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001308 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001309 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001310
Jon Hall7eb38402015-01-08 17:19:54 -08001311 def getInterfaceMACAddress( self, host, interface ):
1312 """
1313 Return the IP address of the interface on the given host"""
1314 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001315 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001316 response = self.execute( cmd=host + " ifconfig " + interface,
1317 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001318 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001319 main.log.error( self.name + ": EOF exception found" )
1320 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001321 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001322 except Exception:
1323 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001324 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001325
1326 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001327 macAddressSearch = re.search( pattern, response, re.I )
1328 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001329 main.log.info( "No mac address found in %s" % response )
1330 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001331 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001332 main.log.info(
1333 "Mac-Address of " +
1334 host +
1335 ":" +
1336 interface +
1337 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001338 macAddress )
1339 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001340 else:
1341 main.log.error( "Connection failed to the host" )
1342
You Wang5da39c82018-04-26 22:55:08 -07001343 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001344 """
1345 Verifies the host's ip configured or not."""
1346 if self.handle:
1347 try:
1348 response = self.execute(
1349 cmd=host +
1350 " ifconfig",
1351 prompt="mininet>",
1352 timeout=10 )
1353 except pexpect.EOF:
1354 main.log.error( self.name + ": EOF exception found" )
1355 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001356 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001357 except Exception:
1358 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001359 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001360
sathishmad953462015-12-03 17:42:07 +05301361 pattern = ''
1362 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001363 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301364 else:
Jon Hall439c8912016-04-15 02:22:03 -07001365 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001366 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001367 if not ipAddressSearch:
1368 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001369 main.log.info(
1370 self.name +
1371 ": IP-Address of Host " +
1372 host +
1373 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001374 ipAddressSearch.group( 1 ) )
1375 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001376 else:
1377 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001378
Jon Hall7eb38402015-01-08 17:19:54 -08001379 def getSwitchDPID( self, switch ):
1380 """
1381 return the datapath ID of the switch"""
1382 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001383 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001384 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001385 response = self.execute(
1386 cmd=cmd,
1387 prompt="mininet>",
1388 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001389 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001390 main.log.error( self.name + ": EOF exception found" )
1391 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001392 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001393 except Exception:
1394 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001395 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001396 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001397 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001398 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001399 main.log.info(
1400 "Couldn't find DPID for switch %s, found: %s" %
1401 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001402 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001403 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001404 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001405 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001406
Jon Hall7eb38402015-01-08 17:19:54 -08001407 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001408 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001409 self.handle.sendline( "" )
1410 self.expect( "mininet>" )
1411 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001412 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001413 response = self.execute(
1414 cmd=cmd,
1415 prompt="mininet>",
1416 timeout=10 )
1417 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001418 response = self.handle.before
1419 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001420 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001421 main.log.error( self.name + ": TIMEOUT exception found" )
1422 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001423 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001424 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001425 main.log.error( self.name + ": EOF exception found" )
1426 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001427 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001428 except Exception:
1429 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001430 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001431
Jon Hall7eb38402015-01-08 17:19:54 -08001432 def getInterfaces( self, node ):
1433 """
1434 return information dict about interfaces connected to the node"""
1435 if self.handle:
1436 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001437 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001438 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001439 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001440 response = self.execute(
1441 cmd=cmd,
1442 prompt="mininet>",
1443 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001444 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001445 main.log.error( self.name + ": EOF exception found" )
1446 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001447 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001448 except Exception:
1449 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001450 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001451 return response
1452 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001453 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001454
Jon Hall7eb38402015-01-08 17:19:54 -08001455 def dump( self ):
1456 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001457 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001458 response = self.execute(
1459 cmd='dump',
1460 prompt='mininet>',
1461 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001462 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001463 main.log.error( self.name + ": EOF exception found" )
1464 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001465 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001466 except Exception:
1467 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001468 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001469 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001470
Jon Hall7eb38402015-01-08 17:19:54 -08001471 def intfs( self ):
1472 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001473 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001474 response = self.execute(
1475 cmd='intfs',
1476 prompt='mininet>',
1477 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001478 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001479 main.log.error( self.name + ": EOF exception found" )
1480 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001481 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001482 except Exception:
1483 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001484 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001485 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001486
Jon Hall7eb38402015-01-08 17:19:54 -08001487 def net( self ):
1488 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001489 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001490 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001491 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001492 main.log.error( self.name + ": EOF exception found" )
1493 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001494 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001495 except Exception:
1496 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001497 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001498 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001499
Devin Lima7cfdbd2017-09-29 15:02:22 -07001500 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001501 main.log.info( self.name + ": List network links" )
1502 try:
1503 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001504 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001505 except pexpect.EOF:
1506 main.log.error( self.name + ": EOF exception found" )
1507 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001508 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001509 except Exception:
1510 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001511 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001512 return response
1513
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001514 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001515 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001516 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001517
kelvin-onlab7cce9382015-07-17 10:21:03 -07001518 @parm:
1519 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1520 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001521 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001522 try:
1523 for host1 in hosts:
1524 for host2 in hosts:
1525 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001526 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1527 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001528 except Exception:
1529 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001530 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001531
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001532 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001533 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001534 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1535 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001536
kelvin-onlab7cce9382015-07-17 10:21:03 -07001537 @parm:
1538 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1539 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001540 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001541 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1542 try:
1543 # Setup the mininet command
1544 cmd1 = 'iperf ' + host1 + " " + host2
1545 self.handle.sendline( cmd1 )
1546 outcome = self.handle.expect( "mininet>", timeout )
1547 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001548
kelvin-onlab7cce9382015-07-17 10:21:03 -07001549 # checks if there are results in the mininet response
1550 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001551 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001552 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001553 response = response.split( "\r\n" )
1554 response = response[ len( response )-2 ]
1555 response = response.split( ": " )
1556 response = response[ len( response )-1 ]
1557 response = response.replace( "[", "" )
1558 response = response.replace( "]", "" )
1559 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001560
kelvin-onlab7cce9382015-07-17 10:21:03 -07001561 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001562 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001563
kelvin-onlab7cce9382015-07-17 10:21:03 -07001564 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001565 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001566 if len( bandwidth ) == 2:
1567 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001568 return main.TRUE
1569 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001570 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001571 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001572 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001573 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001574 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001575 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001576 main.log.error( self.name + ": TIMEOUT exception found" )
1577 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001578 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001579 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001580 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001581 self.handle.expect( "Interrupt" )
1582 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001583 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001584 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001585 main.log.error( self.name + ": EOF exception found" )
1586 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001587 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001588 except Exception:
1589 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001590 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001591
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001592 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001593 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1594 try:
1595 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001596 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001597 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001598 outcome1 = self.handle.expect( "mininet>" )
1599 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001600 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001601 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001602 response1 = self.handle.before
1603 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001604 print response1, response2
1605 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001606 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001607 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001608 return main.TRUE
1609 else:
1610 main.log.error( self.name + ": iperf test failed" )
1611 return main.FALSE
1612 except pexpect.TIMEOUT:
1613 main.log.error( self.name + ": TIMEOUT exception found" )
1614 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001615 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001616 self.handle.expect( "Interrupt" )
1617 self.handle.expect( "mininet>" )
1618 return main.FALSE
1619 except pexpect.EOF:
1620 main.log.error( self.name + ": EOF exception found" )
1621 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001622 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001623 except Exception:
1624 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001625 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001626
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001627 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001628 '''
GlennRC61321f22015-07-16 13:36:54 -07001629 Runs the iperfudp function with a given set of hosts and specified
1630 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001631
GlennRC61321f22015-07-16 13:36:54 -07001632 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001633 bandwidth: the targeted bandwidth, in megabits ('M')
1634 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001635 try:
1636 for host1 in hosts:
1637 for host2 in hosts:
1638 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001639 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1640 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001641 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001642 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001643 return main.FALSE
1644 except Exception:
1645 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001646 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001647
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001648 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001649 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001650 Creates an iperf UDP test with a specific bandwidth.
1651 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001652
kelvin-onlab7cce9382015-07-17 10:21:03 -07001653 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001654 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1655 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001656 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001657 try:
1658 # setup the mininet command
1659 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001660 self.handle.sendline( cmd )
1661 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001662 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001663
kelvin-onlab7cce9382015-07-17 10:21:03 -07001664 # check if there are in results in the mininet response
1665 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001666 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001667 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001668 response = response.split( "\r\n" )
1669 response = response[ len( response )-2 ]
1670 response = response.split( ": " )
1671 response = response[ len( response )-1 ]
1672 response = response.replace( "[", "" )
1673 response = response.replace( "]", "" )
1674 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001675
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001676 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001677
kelvin-onlab7cce9382015-07-17 10:21:03 -07001678 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001679 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001680 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001681 # if one entry is blank then something is wrong
1682 for item in mnBandwidth:
1683 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001684 main.log.error( self.name + ": Could not parse iperf output" )
1685 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001686 return main.FALSE
1687 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001688 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001689 return main.TRUE
1690 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001691 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001692 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001693
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001694 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001695 main.log.error( self.name + ": TIMEOUT exception found" )
1696 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001697 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001698 except pexpect.EOF:
1699 main.log.error( self.name + ": EOF exception found" )
1700 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001701 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001702 except Exception:
1703 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001704 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001705
Jon Hall7eb38402015-01-08 17:19:54 -08001706 def nodes( self ):
1707 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001708 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001709 response = self.execute(
1710 cmd='nodes',
1711 prompt='mininet>',
1712 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001713 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001714 main.log.error( self.name + ": EOF exception found" )
1715 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001716 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001717 except Exception:
1718 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001719 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001720 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001721
Jon Hall7eb38402015-01-08 17:19:54 -08001722 def pingpair( self ):
1723 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001724 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001725 response = self.execute(
1726 cmd='pingpair',
1727 prompt='mininet>',
1728 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001729 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001730 main.log.error( self.name + ": EOF exception found" )
1731 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001732 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001733 except Exception:
1734 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001735 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001736
Jon Hall7eb38402015-01-08 17:19:54 -08001737 if re.search( ',\s0\%\spacket\sloss', response ):
1738 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001739 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001740 else:
alisone4121a92016-11-22 16:31:36 -08001741 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001742 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001743
Jon Hall7eb38402015-01-08 17:19:54 -08001744 def link( self, **linkargs ):
1745 """
GlennRCed771242016-01-13 17:02:47 -08001746 Bring link( s ) between two nodes up or down
1747 """
Jon Hall6094a362014-04-11 14:46:56 -07001748 try:
GlennRCed771242016-01-13 17:02:47 -08001749 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1750 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1751 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1752 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1753
1754 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1755 cmd = "link {} {} {}".format( end1, end2, option )
1756 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001757 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001758 response = self.handle.before
1759 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001760 if "not in network" in response:
1761 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1762 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001763 return main.TRUE
1764 except pexpect.TIMEOUT:
1765 main.log.exception( self.name + ": Command timed out" )
1766 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001767 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001768 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001769 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001770 except Exception:
1771 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001772 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001773
pingping-lin8244a3b2015-09-16 13:36:56 -07001774 def switch( self, **switchargs ):
1775 """
1776 start/stop a switch
1777 """
1778 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1779 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1780 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1781 command = "switch " + str( sw ) + " " + str( option )
1782 main.log.info( command )
1783 try:
1784 self.handle.sendline( command )
1785 self.handle.expect( "mininet>" )
1786 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001787 main.log.error( self.name + ": TIMEOUT exception found" )
1788 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001789 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001790 except pexpect.EOF:
1791 main.log.error( self.name + ": EOF 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 return main.TRUE
1795
pingping-lin5bb663b2015-09-24 11:47:50 -07001796 def node( self, nodeName, commandStr ):
1797 """
1798 Carry out a command line on a given node
1799 @parm:
1800 nodeName: the node name in Mininet testbed
1801 commandStr: the command line will be carried out on the node
1802 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1803 """
1804 command = str( nodeName ) + " " + str( commandStr )
1805 main.log.info( command )
1806
1807 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001808 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001809 if re.search( "Unknown command", response ):
1810 main.log.warn( response )
1811 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001812 if re.search( "Permission denied", response ):
1813 main.log.warn( response )
1814 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001815 except pexpect.EOF:
1816 main.log.error( self.name + ": EOF exception found" )
1817 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001818 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001819 main.log.info( " response is :" )
1820 main.log.info( response )
1821 return response
1822
Jon Hall7eb38402015-01-08 17:19:54 -08001823 def yank( self, **yankargs ):
1824 """
1825 yank a mininet switch interface to a host"""
1826 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001827 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001828 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1829 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001830 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001831 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001832 response = self.execute(
1833 cmd=command,
1834 prompt="mininet>",
1835 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001836 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001837 main.log.error( self.name + ": EOF exception found" )
1838 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001839 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001840 except Exception:
1841 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001842 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001843 return main.TRUE
1844
Jon Hall7eb38402015-01-08 17:19:54 -08001845 def plug( self, **plugargs ):
1846 """
1847 plug the yanked mininet switch interface to a switch"""
1848 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001849 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001850 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1851 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001852 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001853 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001854 response = self.execute(
1855 cmd=command,
1856 prompt="mininet>",
1857 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001858 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001859 main.log.error( self.name + ": EOF exception found" )
1860 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001861 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001862 except Exception:
1863 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001864 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001865 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001866
Jon Hall7eb38402015-01-08 17:19:54 -08001867 def dpctl( self, **dpctlargs ):
1868 """
1869 Run dpctl command on all switches."""
1870 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001871 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001872 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1873 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1874 command = "dpctl " + cmd + " " + str( cmdargs )
1875 try:
1876 response = self.execute(
1877 cmd=command,
1878 prompt="mininet>",
1879 timeout=10 )
1880 except pexpect.EOF:
1881 main.log.error( self.name + ": EOF exception found" )
1882 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001883 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001884 except Exception:
1885 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001886 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001887 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001888
kelvin-onlabd3b64892015-01-20 13:26:24 -08001889 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001890 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001891 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001892 try:
1893 fileInput = path + '/lib/Mininet/INSTALL'
1894 version = super( Mininet, self ).getVersion()
1895 pattern = 'Mininet\s\w\.\w\.\w\w*'
1896 for line in open( fileInput, 'r' ).readlines():
1897 result = re.match( pattern, line )
1898 if result:
1899 version = result.group( 0 )
1900 return version
1901 except Exception:
1902 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001903 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001904
kelvin-onlabd3b64892015-01-20 13:26:24 -08001905 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001906 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001907 Parameters:
1908 sw: The name of an OVS switch. Example "s1"
1909 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001910 The output of the command from the mininet cli
1911 or main.FALSE on timeout"""
1912 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001913 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001914 response = self.execute(
1915 cmd=command,
1916 prompt="mininet>",
1917 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001918 if response:
Jon Hallab611372018-02-21 15:26:05 -08001919 if "no bridge named" in response:
1920 main.log.error( self.name + ": Error in getSwController: " +
1921 self.handle.before )
1922 return main.FALSE
1923 else:
1924 return response
admin2a9548d2014-06-17 14:08:07 -07001925 else:
1926 return main.FALSE
1927 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001928 main.log.error( self.name + ": EOF exception found" )
1929 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001930 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001931 except Exception:
1932 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001933 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001934
Charles Chan029be652015-08-24 01:46:10 +08001935 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001936 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001937 Description:
1938 Assign switches to the controllers ( for ovs use only )
1939 Required:
1940 sw - Name of the switch. This can be a list or a string.
1941 ip - Ip addresses of controllers. This can be a list or a string.
1942 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001943 port - ONOS use port 6653, if no list of ports is passed, then
1944 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001945 ptcp - ptcp number, This can be a string or a list that has
1946 the same length as switch. This is optional and not required
1947 when using ovs switches.
1948 NOTE: If switches and ptcp are given in a list type they should have the
1949 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1950 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001951
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001952 Return:
1953 Returns main.TRUE if mininet correctly assigned switches to
1954 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001955 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001956 """
1957 assignResult = main.TRUE
1958 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001959 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001960 command = "sh ovs-vsctl set-controller "
1961 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001962 try:
1963 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001964 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001965 if isinstance( port, types.StringType ) or \
1966 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001967 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001968 elif isinstance( port, types.ListType ):
1969 main.log.error( self.name + ": Only one controller " +
1970 "assigned and a list of ports has" +
1971 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001972 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001973 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001974 main.log.error( self.name + ": Invalid controller port " +
1975 "number. Please specify correct " +
1976 "controller port" )
1977 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001978
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001979 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001980 if isinstance( port, types.StringType ) or \
1981 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001982 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001983 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1984 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001985 elif isinstance( port, types.ListType ):
1986 if ( len( ip ) != len( port ) ):
1987 main.log.error( self.name + ": Port list = " +
1988 str( len( port ) ) +
1989 "should be the same as controller" +
1990 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001991 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001992 else:
1993 onosIp = ""
1994 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001995 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1996 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001997 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001998 main.log.error( self.name + ": Invalid controller port " +
1999 "number. Please specify correct " +
2000 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002001 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07002002 else:
2003 main.log.error( self.name + ": Invalid ip address" )
2004 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002005
2006 if isinstance( sw, types.StringType ):
2007 command += sw + " "
2008 if ptcp:
2009 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07002010 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002011 elif isinstance( ptcp, types.ListType ):
2012 main.log.error( self.name + ": Only one switch is " +
2013 "being set and multiple PTCP is " +
2014 "being passed " )
2015 else:
2016 main.log.error( self.name + ": Invalid PTCP" )
2017 ptcp = ""
2018 command += onosIp
2019 commandList.append( command )
2020
2021 elif isinstance( sw, types.ListType ):
2022 if ptcp:
2023 if isinstance( ptcp, types.ListType ):
2024 if len( ptcp ) != len( sw ):
2025 main.log.error( self.name + ": PTCP length = " +
2026 str( len( ptcp ) ) +
2027 " is not the same as switch" +
2028 " length = " +
2029 str( len( sw ) ) )
2030 return main.FALSE
2031 else:
2032 for switch, ptcpNum in zip( sw, ptcp ):
2033 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07002034 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07002035 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002036 tempCmd += onosIp
2037 commandList.append( tempCmd )
2038 else:
2039 main.log.error( self.name + ": Invalid PTCP" )
2040 return main.FALSE
2041 else:
2042 for switch in sw:
2043 tempCmd = "sh ovs-vsctl set-controller "
2044 tempCmd += switch + " " + onosIp
2045 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002046 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002047 main.log.error( self.name + ": Invalid switch type " )
2048 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002049
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002050 for cmd in commandList:
2051 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002052 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08002053 if "no bridge named" in self.handle.before:
2054 main.log.error( self.name + ": Error in assignSwController: " +
2055 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002056 except pexpect.TIMEOUT:
2057 main.log.error( self.name + ": pexpect.TIMEOUT found" )
2058 return main.FALSE
2059 except pexpect.EOF:
2060 main.log.error( self.name + ": EOF exception found" )
2061 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002062 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002063 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002064 except pexpect.EOF:
2065 main.log.error( self.name + ": EOF exception found" )
2066 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002067 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002068 except Exception:
2069 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002070 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07002071
kelvin-onlabd3b64892015-01-20 13:26:24 -08002072 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08002073 """
2074 Removes the controller target from sw"""
2075 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07002076 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002077 response = self.execute(
2078 cmd=command,
2079 prompt="mininet>",
2080 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08002081 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002082 main.log.error( self.name + ": EOF exception found" )
2083 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002084 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002085 except Exception:
2086 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002087 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002088 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002089 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07002090
kelvin-onlabd3b64892015-01-20 13:26:24 -08002091 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002092 """
Jon Hallb1290e82014-11-18 16:17:48 -05002093 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002094 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002095 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002096 NOTE: cannot currently specify what type of switch
2097 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08002098 sw = name of the new switch as a string
2099 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05002100 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08002101 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002102 """
2103 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002104 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05002105 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002106 response = self.execute(
2107 cmd=command,
2108 prompt="mininet>",
2109 timeout=10 )
2110 if re.search( "already exists!", response ):
2111 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002112 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002113 elif re.search( "Error", response ):
2114 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002115 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002116 elif re.search( "usage:", response ):
2117 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002118 return main.FALSE
2119 else:
2120 return main.TRUE
2121 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002122 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07002123 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002124 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002125 except Exception:
2126 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002127 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002128
kelvin-onlabd3b64892015-01-20 13:26:24 -08002129 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08002130 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08002131 delete a switch from the mininet topology
2132 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002133 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08002134 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08002135 sw = name of the switch as a string
2136 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002137 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05002138 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002139 response = self.execute(
2140 cmd=command,
2141 prompt="mininet>",
2142 timeout=10 )
2143 if re.search( "no switch named", response ):
2144 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002145 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002146 elif re.search( "Error", response ):
2147 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002148 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002149 elif re.search( "usage:", response ):
2150 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002151 return main.FALSE
2152 else:
2153 return main.TRUE
2154 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002155 main.log.error( self.name + ": EOF exception found" )
2156 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002157 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002158 except Exception:
2159 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002160 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002161
You Wangdb8cd0a2016-05-26 15:19:45 -07002162 def getSwitchRandom( self, timeout=60, nonCut=True ):
2163 """
2164 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002165 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002166 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002167 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002168 it just randomly returns one switch from all current switches in
2169 Mininet.
2170 Returns the name of the chosen switch.
2171 """
2172 import random
2173 candidateSwitches = []
2174 try:
2175 if not nonCut:
2176 switches = self.getSwitches( timeout=timeout )
2177 assert len( switches ) != 0
2178 for switchName in switches.keys():
2179 candidateSwitches.append( switchName )
2180 else:
2181 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002182 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002183 return None
2184 self.graph.update( graphDict )
2185 candidateSwitches = self.graph.getNonCutVertices()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002186 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002187 return None
2188 elif len( candidateSwitches ) == 0:
2189 main.log.info( self.name + ": No candidate switch for deletion" )
2190 return None
2191 else:
2192 switch = random.sample( candidateSwitches, 1 )
2193 return switch[ 0 ]
2194 except KeyError:
2195 main.log.exception( self.name + ": KeyError exception found" )
2196 return None
2197 except AssertionError:
2198 main.log.exception( self.name + ": AssertionError exception found" )
2199 return None
2200 except Exception:
2201 main.log.exception( self.name + ": Uncaught exception" )
2202 return None
2203
2204 def delSwitchRandom( self, timeout=60, nonCut=True ):
2205 """
2206 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002207 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002208 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002209 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002210 otherwise it just randomly delete one switch from all current
2211 switches in Mininet.
2212 Returns the name of the deleted switch
2213 """
2214 try:
2215 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002216 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002217 return None
2218 else:
2219 deletionResult = self.delSwitch( switch )
2220 if deletionResult:
2221 return switch
2222 else:
2223 return None
2224 except Exception:
2225 main.log.exception( self.name + ": Uncaught exception" )
2226 return None
2227
kelvin-onlabd3b64892015-01-20 13:26:24 -08002228 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002229 """
2230 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002231 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002232 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002233 NOTE: cannot currently specify what type of link
2234 required params:
2235 node1 = the string node name of the first endpoint of the link
2236 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002237 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002238 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002239 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002240 response = self.execute(
2241 cmd=command,
2242 prompt="mininet>",
2243 timeout=10 )
2244 if re.search( "doesnt exist!", response ):
2245 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002246 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002247 elif re.search( "Error", response ):
2248 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002249 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002250 elif re.search( "usage:", response ):
2251 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002252 return main.FALSE
2253 else:
2254 return main.TRUE
2255 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002256 main.log.error( self.name + ": EOF exception found" )
2257 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002258 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002259 except Exception:
2260 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002261 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002262
kelvin-onlabd3b64892015-01-20 13:26:24 -08002263 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002264 """
2265 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002266 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002267 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002268 required params:
2269 node1 = the string node name of the first endpoint of the link
2270 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002271 returns: main.FALSE on an error, else main.TRUE
2272 """
Jon Hallffb386d2014-11-21 13:43:38 -08002273 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002274 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002275 response = self.execute(
2276 cmd=command,
2277 prompt="mininet>",
2278 timeout=10 )
2279 if re.search( "no node named", response ):
2280 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002281 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002282 elif re.search( "Error", response ):
2283 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002284 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002285 elif re.search( "usage:", response ):
2286 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002287 return main.FALSE
2288 else:
2289 return main.TRUE
2290 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002291 main.log.error( self.name + ": EOF exception found" )
2292 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002293 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002294 except Exception:
2295 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002296 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002297
You Wangdb8cd0a2016-05-26 15:19:45 -07002298 def getLinkRandom( self, timeout=60, nonCut=True ):
2299 """
2300 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002301 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002302 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002303 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002304 it just randomly returns one link from all current links in
2305 Mininet.
2306 Returns the link as a list, e.g. [ 's1', 's2' ]
2307 """
2308 import random
2309 candidateLinks = []
2310 try:
2311 if not nonCut:
2312 links = self.getLinks( timeout=timeout )
2313 assert len( links ) != 0
2314 for link in links:
2315 # Exclude host-switch link
2316 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2317 continue
2318 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2319 else:
2320 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002321 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002322 return None
2323 self.graph.update( graphDict )
2324 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002325 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002326 return None
2327 elif len( candidateLinks ) == 0:
2328 main.log.info( self.name + ": No candidate link for deletion" )
2329 return None
2330 else:
2331 link = random.sample( candidateLinks, 1 )
2332 return link[ 0 ]
2333 except KeyError:
2334 main.log.exception( self.name + ": KeyError exception found" )
2335 return None
2336 except AssertionError:
2337 main.log.exception( self.name + ": AssertionError exception found" )
2338 return None
2339 except Exception:
2340 main.log.exception( self.name + ": Uncaught exception" )
2341 return None
2342
2343 def delLinkRandom( self, timeout=60, nonCut=True ):
2344 """
2345 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002346 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002347 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002348 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002349 otherwise it just randomly delete one link from all current links
2350 in Mininet.
2351 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2352 """
2353 try:
2354 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002355 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002356 return None
2357 else:
2358 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2359 if deletionResult:
2360 return link
2361 else:
2362 return None
2363 except Exception:
2364 main.log.exception( self.name + ": Uncaught exception" )
2365 return None
2366
kelvin-onlabd3b64892015-01-20 13:26:24 -08002367 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002368 """
Jon Hallb1290e82014-11-18 16:17:48 -05002369 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002370 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002371 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002372 NOTE: cannot currently specify what type of host
2373 required params:
2374 hostname = the string hostname
2375 optional key-value params
2376 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002377 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002378 """
2379 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002380 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002381 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002382 response = self.execute(
2383 cmd=command,
2384 prompt="mininet>",
2385 timeout=10 )
2386 if re.search( "already exists!", response ):
2387 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002388 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002389 elif re.search( "doesnt exists!", response ):
2390 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002391 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002392 elif re.search( "Error", response ):
2393 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002394 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002395 elif re.search( "usage:", response ):
2396 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002397 return main.FALSE
2398 else:
2399 return main.TRUE
2400 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002401 main.log.error( self.name + ": EOF exception found" )
2402 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002403 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002404 except Exception:
2405 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002406 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002407
kelvin-onlabd3b64892015-01-20 13:26:24 -08002408 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002409 """
2410 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002411 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002412 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002413 NOTE: this uses a custom mn function
2414 required params:
2415 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002416 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002417 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002418 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002419 response = self.execute(
2420 cmd=command,
2421 prompt="mininet>",
2422 timeout=10 )
2423 if re.search( "no host named", response ):
2424 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002425 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002426 elif re.search( "Error", response ):
2427 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002428 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002429 elif re.search( "usage:", response ):
2430 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002431 return main.FALSE
2432 else:
2433 return main.TRUE
2434 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002435 main.log.error( self.name + ": EOF exception found" )
2436 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002437 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002438 except Exception:
2439 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002440 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002441
Jon Hall7eb38402015-01-08 17:19:54 -08002442 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002443 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002444 Called at the end of the test to stop the mininet and
2445 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002446 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002447 try:
2448 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002449 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002450 timeout=2 )
2451 response = main.TRUE
2452 if i == 0:
2453 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002454 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002455 return main.TRUE
2456 # print "Disconnecting Mininet"
2457 if self.handle:
2458 self.handle.sendline( "exit" )
2459 self.handle.expect( "exit" )
2460 self.handle.expect( "(.*)" )
2461 else:
2462 main.log.error( "Connection failed to the host" )
2463 return response
2464 except pexpect.EOF:
2465 main.log.error( self.name + ": EOF exception found" )
2466 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002467 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002468 except Exception:
2469 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002470 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002471
Devin Lima7cfdbd2017-09-29 15:02:22 -07002472 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002473 """
Jon Hall21270ac2015-02-16 17:59:55 -08002474 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002475 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002476 main.FALSE if the pexpect handle does not exist.
2477
Jon Halld61331b2015-02-17 16:35:47 -08002478 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002479 """
Jon Halld61331b2015-02-17 16:35:47 -08002480 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002481 response = ''
2482 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002483 try:
Jon Halld80cc142015-07-06 13:36:05 -07002484 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002485 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002486 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002487 pexpect.EOF,
2488 pexpect.TIMEOUT ],
2489 timeout )
2490 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002491 main.log.info( "Exiting mininet.." )
2492 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002493 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002494 prompt=self.prompt,
2495 timeout=exitTimeout )
2496 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002497 self.handle.sendline( "sudo mn -c" )
2498 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002499
Jeremyd9e4eb12016-04-13 12:09:06 -07002500 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002501 main.log.info( " Mininet trying to exit while not " +
2502 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002503 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002504 elif i == 2:
2505 main.log.error( "Something went wrong exiting mininet" )
2506 elif i == 3: # timeout
2507 main.log.error( "Something went wrong exiting mininet " +
2508 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002509
You Wang18db8592018-04-02 13:52:03 -07002510 self.handle.sendline( "" )
2511 self.handle.expect( self.prompt )
2512 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2513
Hari Krishnab35c6d02015-03-18 11:13:51 -07002514 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002515 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002516 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002517 self.handle.sendline(
2518 "sudo kill -9 \`ps -ef | grep \"" +
2519 fileName +
2520 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002521 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002522 main.log.error( self.name + ": TIMEOUT exception found" )
2523 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002524 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002525 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002526 main.log.error( self.name + ": EOF exception found" )
2527 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002528 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002529 except Exception:
2530 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002531 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002532 else:
2533 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002534 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002535 return response
2536
YPZhang26a139e2016-04-25 14:01:55 -07002537 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002538 """
2539 Description:
2540 Sends arp message from mininet host for hosts discovery
2541 Required:
2542 host - hosts name
2543 Optional:
2544 ip - ip address that does not exist in the network so there would
2545 be no reply.
2546 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002547 if ethDevice:
2548 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002549 cmd = srcHost + " arping -c1 "
2550 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002551 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 -07002552 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002553 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002554 if output:
2555 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002556 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002557 i = self.handle.expect( [ "mininet>", "arping: " ] )
2558 if i == 0:
2559 return main.TRUE
2560 elif i == 1:
2561 response = self.handle.before + self.handle.after
2562 self.handle.expect( "mininet>" )
2563 response += self.handle.before + self.handle.after
2564 main.log.warn( "Error sending arping, output was: " +
2565 response )
2566 return main.FALSE
2567 except pexpect.TIMEOUT:
2568 main.log.error( self.name + ": TIMEOUT exception found" )
2569 main.log.warn( self.handle.before )
2570 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002571 except pexpect.EOF:
2572 main.log.error( self.name + ": EOF exception found" )
2573 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002574 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002575 except Exception:
2576 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002577 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002578
Jon Hall7eb38402015-01-08 17:19:54 -08002579 def decToHex( self, num ):
2580 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002581
Jon Hall7eb38402015-01-08 17:19:54 -08002582 def getSwitchFlowCount( self, switch ):
2583 """
2584 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002585 if self.handle:
2586 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2587 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002588 response = self.execute(
2589 cmd=cmd,
2590 prompt="mininet>",
2591 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002592 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002593 main.log.error( self.name + ": EOF exception found" )
2594 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002595 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002596 except Exception:
2597 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002598 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002599 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002600 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002601 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002602 main.log.info(
2603 "Couldn't find flows on switch %s, found: %s" %
2604 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002605 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002606 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002607 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002608 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002609
Jon Hall9ed8f372016-02-24 17:34:07 -08002610 def checkFlows( self, sw, dumpFormat=None ):
2611 if dumpFormat:
2612 command = "sh ovs-ofctl -F " + \
2613 dumpFormat + " dump-flows " + str( sw )
2614 else:
2615 command = "sh ovs-ofctl dump-flows " + str( sw )
2616 try:
2617 response = self.execute(
2618 cmd=command,
2619 prompt="mininet>",
2620 timeout=10 )
2621 return response
2622 except pexpect.EOF:
2623 main.log.error( self.name + ": EOF exception found" )
2624 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002625 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002626 except Exception:
2627 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002628 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002629
GlennRC68467eb2015-11-16 18:01:01 -08002630 def flowTableComp( self, flowTable1, flowTable2 ):
2631 # This function compares the selctors and treatments of each flow
2632 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002633 assert flowTable1, "flowTable1 is empty or None"
2634 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002635 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002636 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002637 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002638 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002639 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2640 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002641 for field in dFields:
2642 try:
2643 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002644 except KeyError:
2645 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002646 try:
2647 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002648 except KeyError:
2649 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002650 for i in range( len( flowTable1 ) ):
2651 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002652 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002653 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002654 returnValue = main.FALSE
2655 break
2656 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002657 except AssertionError:
2658 main.log.exception( "Nothing to compare" )
2659 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002660 except Exception:
2661 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002662 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002663
GlennRC528ad292015-11-12 10:38:18 -08002664 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002665 '''
GlennRC956ea742015-11-05 16:14:15 -08002666 Discription: Parses flows into json format.
2667 NOTE: this can parse any string thats separated with commas
2668 Arguments:
2669 Required:
2670 flows: a list of strings that represnt flows
2671 Optional:
2672 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2673 debug: prints out the final result
2674 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002675 '''
GlennRC528ad292015-11-12 10:38:18 -08002676 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002677 try:
2678 for flow in flowTable:
2679 jsonFlow = {}
2680 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002681 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002682 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002683 for i in range( len( parsedFlow ) ):
2684 item = parsedFlow[ i ]
2685 if item[ 0 ] == " ":
2686 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002687 # grab the selector and treatment from the parsed flow
2688 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002689 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002690 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002691 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002692 index = 0
2693 # parse the flags
2694 # NOTE: This only parses one flag
2695 flag = {}
2696 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002697 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002698 index += 1
2699 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002700 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002701 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002702 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002703 # the priority is stuck in the selecter so put it back
2704 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002705 if 'priority' in sel[0]:
2706 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002707 # parse selector
2708 criteria = []
2709 for item in sel:
2710 # this is the type of the packet e.g. "arp"
2711 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002712 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002713 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002714 field = item.split( "=" )
2715 criteria.append( { field[ 0 ]: field[ 1 ] } )
2716 selector = { "selector": { "criteria": sorted( criteria ) } }
2717 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002718 # get rid of the action part e.g. "action=output:2"
2719 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002720 treat = treat.split( "=" )
2721 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002722 # parse treatment
2723 action = []
2724 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002725 if ":" in item:
2726 field = item.split( ":" )
2727 action.append( { field[ 0 ]: field[ 1 ] } )
2728 else:
2729 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2730 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002731 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002732 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002733 # parse the rest of the flow
2734 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002735 field = item.split( "=" )
2736 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002737 # add the treatment and the selector to the json flow
2738 jsonFlow.update( selector )
2739 jsonFlow.update( treatment )
2740 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002741
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002742 if debug:
2743 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002744
You Wang91c37cf2016-05-23 09:39:42 -07002745 # add the json flow to the json flow table
2746 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002747
You Wang91c37cf2016-05-23 09:39:42 -07002748 return jsonFlowTable
2749
2750 except IndexError:
2751 main.log.exception( self.name + ": IndexError found" )
2752 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002753 except pexpect.EOF:
2754 main.log.error( self.name + ": EOF exception found" )
2755 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002756 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002757 except Exception:
2758 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002759 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002760
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002761 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002762 '''
2763 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002764 Each element is a flow.
2765 Arguments:
2766 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002767 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002768 a list of switches.
2769 Optional:
2770 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2771 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002772 '''
GlennRC956ea742015-11-05 16:14:15 -08002773 try:
2774 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002775 if isinstance( sw, list ):
2776 switches.extend( sw )
2777 else:
2778 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002779
2780 flows = []
2781 for s in switches:
2782 cmd = "sh ovs-ofctl dump-flows " + s
2783
GlennRC528ad292015-11-12 10:38:18 -08002784 if "1.0" == version:
2785 cmd += " -F OpenFlow10-table_id"
2786 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002787 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002788
2789 main.log.info( "Sending: " + cmd )
2790 self.handle.sendline( cmd )
2791 self.handle.expect( "mininet>" )
2792 response = self.handle.before
2793 response = response.split( "\r\n" )
2794 # dump the first two elements and the last
2795 # the first element is the command that was sent
2796 # the second is the table header
2797 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002798 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002799 flows.extend( response )
2800
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002801 if debug:
2802 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002803
GlennRC528ad292015-11-12 10:38:18 -08002804 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002805
GlennRC956ea742015-11-05 16:14:15 -08002806 except pexpect.EOF:
2807 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002808 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002809 except Exception:
2810 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002811 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002812
2813 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002814 '''
GlennRC956ea742015-11-05 16:14:15 -08002815 Discription: Checks whether the ID provided matches a flow ID in Mininet
2816 Arguments:
2817 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002818 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002819 a list of switches.
2820 flowId: the flow ID in hex format. Can also be a list of IDs
2821 Optional:
2822 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2823 debug: prints out the final result
2824 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2825 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002826 '''
GlennRC956ea742015-11-05 16:14:15 -08002827 try:
2828 main.log.info( "Getting flows from Mininet" )
2829 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002830 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002831 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002832
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002833 if debug:
2834 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002835
2836 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002837 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002838 result = False
2839 for f in flows:
2840 if flowId in f.get( 'cookie' ):
2841 result = True
2842 break
2843 # flowId is a list
2844 else:
2845 result = True
2846 # Get flow IDs from Mininet
2847 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2848 # Save the IDs that are not in Mininet
2849 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2850
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002851 if debug:
2852 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002853
2854 # Print out the IDs that are not in Mininet
2855 if absentIds:
2856 main.log.warn( "Absent ids: {}".format( absentIds ) )
2857 result = False
2858
2859 return main.TRUE if result else main.FALSE
2860
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002861 except pexpect.EOF:
2862 main.log.error( self.name + ": EOF exception found" )
2863 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002864 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002865 except Exception:
2866 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002867 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002868
Charles Chan029be652015-08-24 01:46:10 +08002869 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002870 """
Jon Hallefbd9792015-03-05 16:11:36 -08002871 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002872 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002873 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002874 self.handle.sendline( "" )
2875 self.handle.expect( "mininet>" )
2876 self.handle.sendline(
2877 "sh sudo tcpdump -n -i " +
2878 intf +
2879 " " +
2880 port +
2881 " -w " +
2882 filename.strip() +
2883 " &" )
2884 self.handle.sendline( "" )
2885 i = self.handle.expect( [ 'No\ssuch\device',
2886 'listening\son',
2887 pexpect.TIMEOUT,
2888 "mininet>" ],
2889 timeout=10 )
2890 main.log.warn( self.handle.before + self.handle.after )
2891 self.handle.sendline( "" )
2892 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002893 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002894 main.log.error(
2895 self.name +
2896 ": tcpdump - No such device exists. " +
2897 "tcpdump attempted on: " +
2898 intf )
admin2a9548d2014-06-17 14:08:07 -07002899 return main.FALSE
2900 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002901 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002902 return main.TRUE
2903 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002904 main.log.error(
2905 self.name +
2906 ": tcpdump command timed out! Check interface name," +
2907 " given interface was: " +
2908 intf )
admin2a9548d2014-06-17 14:08:07 -07002909 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002910 elif i == 3:
2911 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002912 return main.TRUE
2913 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002914 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002915 return main.FALSE
2916 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002917 main.log.error( self.name + ": EOF exception found" )
2918 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002919 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002920 except Exception:
2921 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002922 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002923
kelvin-onlabd3b64892015-01-20 13:26:24 -08002924 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002925 """
2926 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002927 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002928 self.handle.sendline( "sh sudo pkill tcpdump" )
2929 self.handle.expect( "mininet>" )
2930 self.handle.sendline( "" )
2931 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002932 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002933 main.log.error( self.name + ": TIMEOUT exception found" )
2934 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002935 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002936 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002937 main.log.error( self.name + ": EOF exception found" )
2938 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002939 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002940 except Exception:
2941 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002942 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002943
Jon Halld80cc142015-07-06 13:36:05 -07002944 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002945 """
2946 Read ports from a Mininet switch.
2947
2948 Returns a json structure containing information about the
2949 ports of the given switch.
2950 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002951 try:
2952 response = self.getInterfaces( nodeName )
2953 # TODO: Sanity check on response. log if no such switch exists
2954 ports = []
2955 for line in response.split( "\n" ):
2956 if not line.startswith( "name=" ):
2957 continue
2958 portVars = {}
2959 for var in line.split( "," ):
2960 key, value = var.split( "=" )
2961 portVars[ key ] = value
2962 isUp = portVars.pop( 'enabled', "True" )
2963 isUp = "True" in isUp
2964 if verbose:
2965 main.log.info( "Reading switch port %s(%s)" %
2966 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2967 mac = portVars[ 'mac' ]
2968 if mac == 'None':
2969 mac = None
2970 ips = []
2971 ip = portVars[ 'ip' ]
2972 if ip == 'None':
2973 ip = None
2974 ips.append( ip )
2975 name = portVars[ 'name' ]
2976 if name == 'None':
2977 name = None
2978 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2979 if name == 'lo':
2980 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2981 else:
2982 portNo = re.search( portRe, name ).group( 'port' )
2983 ports.append( { 'of_port': portNo,
2984 'mac': str( mac ).replace( '\'', '' ),
2985 'name': name,
2986 'ips': ips,
2987 'enabled': isUp } )
2988 return ports
2989 except pexpect.EOF:
2990 main.log.error( self.name + ": EOF exception found" )
2991 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002992 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002993 except Exception:
2994 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002995 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002996
You Wangdb8cd0a2016-05-26 15:19:45 -07002997 def getOVSPorts( self, nodeName ):
2998 """
2999 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
3000
3001 Returns a list of dictionaries containing information about each
3002 port of the given switch.
3003 """
3004 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
3005 try:
3006 response = self.execute(
3007 cmd=command,
3008 prompt="mininet>",
3009 timeout=10 )
3010 ports = []
3011 if response:
3012 for line in response.split( "\n" ):
3013 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
3014 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003015 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07003016 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
3017 result = re.search( pattern, line )
3018 if result:
3019 index = result.group( 'index' )
3020 name = result.group( 'name' )
3021 # This port number is extracted from port name
3022 port = result.group( 'port' )
3023 mac = result.group( 'mac' )
3024 ports.append( { 'index': index,
3025 'name': name,
3026 'port': port,
3027 'mac': mac } )
3028 return ports
3029 except pexpect.EOF:
3030 main.log.error( self.name + ": EOF exception found" )
3031 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003032 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003033 except Exception:
3034 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003035 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003036
Devin Lima7cfdbd2017-09-29 15:02:22 -07003037 def getSwitches( self, verbose=False, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07003038 """
3039 Read switches from Mininet.
3040
3041 Returns a dictionary whose keys are the switch names and the value is
3042 a dictionary containing information about the switch.
3043 """
Jon Halla22481b2015-07-28 17:46:01 -07003044 # NOTE: To support new Mininet switch classes, just append the new
3045 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07003046
Jon Halla22481b2015-07-28 17:46:01 -07003047 # Regex patterns to parse 'dump' output
3048 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07003049 # <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 -07003050 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07003051 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
3052 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
3053 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003054 try:
3055 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
3056 swRE = r"<(?P<class>" + switchClasses + r")" +\
3057 r"(?P<options>\{.*\})?\s" +\
3058 r"(?P<name>[^:]+)\:\s" +\
3059 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
3060 r"\spid=(?P<pid>(\d)+)"
3061 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07003062 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003063 output = {}
3064 dump = self.dump().split( "\n" )
3065 for line in dump:
3066 result = re.search( swRE, line, re.I )
3067 if result:
3068 name = result.group( 'name' )
3069 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
3070 pid = result.group( 'pid' )
3071 swClass = result.group( 'class' )
3072 options = result.group( 'options' )
3073 if verbose:
3074 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
3075 ports = self.getPorts( name )
3076 output[ name ] = { "dpid": dpid,
3077 "ports": ports,
3078 "swClass": swClass,
3079 "pid": pid,
3080 "options": options }
3081 return output
3082 except pexpect.EOF:
3083 main.log.error( self.name + ": EOF exception found" )
3084 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003085 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003086 except Exception:
3087 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003088 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003089
You Wangd66de192018-04-30 17:30:12 -07003090 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08003091 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
3092 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07003093 """
3094 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08003095 Optional:
3096 hostClass: it is used to match the class of the mininet host. It
3097 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07003098 Returns a dictionary whose keys are the host names and the value is
3099 a dictionary containing information about the host.
3100 """
3101 # Regex patterns to parse dump output
3102 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07003103 # <Host h1: pid=12725>
3104 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
3105 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
3106 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07003107 # NOTE: Does not correctly match hosts with multi-links
3108 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
3109 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003110 try:
You Wang53dba1e2018-02-02 17:45:44 -08003111 if not isinstance( hostClass, types.ListType ):
3112 hostClass = [ str( hostClass ) ]
3113 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08003114 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
3115 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
3116 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07003117 if update:
3118 # update mn port info
3119 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003120 # Get mininet dump
3121 dump = self.dump().split( "\n" )
3122 hosts = {}
3123 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08003124 result = re.search( hostRE, line )
3125 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003126 name = result.group( 'name' )
3127 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07003128 if getInterfaces:
3129 response = self.getInterfaces( name )
3130 # Populate interface info
3131 for line in response.split( "\n" ):
3132 if line.startswith( "name=" ):
3133 portVars = {}
3134 for var in line.split( "," ):
3135 key, value = var.split( "=" )
3136 portVars[ key ] = value
3137 isUp = portVars.pop( 'enabled', "True" )
3138 isUp = "True" in isUp
3139 if verbose:
3140 main.log.info( "Reading host port %s(%s)" %
3141 ( portVars[ 'name' ],
3142 portVars[ 'mac' ] ) )
3143 mac = portVars[ 'mac' ]
3144 if mac == 'None':
3145 mac = None
3146 ips = []
3147 ip = portVars[ 'ip' ]
3148 if ip == 'None':
3149 ip = None
3150 ips.append( ip )
3151 intfName = portVars[ 'name' ]
3152 if name == 'None':
3153 name = None
3154 interfaces.append( {
3155 "name": intfName,
3156 "ips": ips,
3157 "mac": str( mac ),
3158 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003159 hosts[ name ] = { "interfaces": interfaces }
3160 return hosts
3161 except pexpect.EOF:
3162 main.log.error( self.name + ": EOF exception found" )
3163 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003164 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003165 except Exception:
3166 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003167 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003168
Devin Lima7cfdbd2017-09-29 15:02:22 -07003169 def getLinks( self, timeout=20, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07003170 """
3171 Gathers information about current Mininet links. These links may not
3172 be up if one of the ports is down.
3173
3174 Returns a list of dictionaries with link endpoints.
3175
3176 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07003177 { 'node1': str( node1 name )
3178 'node2': str( node2 name )
3179 'port1': str( port1 of_port )
3180 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07003181 Note: The port number returned is the eth#, not necessarily the of_port
3182 number. In Mininet, for OVS switch, these should be the same. For
3183 hosts, this is just the eth#.
3184 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003185 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003186 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003187 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07003188
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003189 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003190 # s1-eth3<->s2-eth1 (OK OK)
3191 # s13-eth3<->h27-eth0 (OK OK)
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003192 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
3193 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
3194 links = []
3195 for line in response:
3196 match = re.search( linkRE, line )
3197 if match:
3198 node1 = match.group( 'node1' )
3199 node2 = match.group( 'node2' )
3200 port1 = match.group( 'port1' )
3201 port2 = match.group( 'port2' )
3202 links.append( { 'node1': node1,
3203 'node2': node2,
3204 'port1': port1,
3205 'port2': port2 } )
3206 return links
3207
3208 except pexpect.EOF:
3209 main.log.error( self.name + ": EOF exception found" )
3210 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003211 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003212 except Exception:
3213 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003214 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003215
3216 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003217 """
3218 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003219 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003220
Jon Hallafa8a472015-06-12 14:02:42 -07003221 Dependencies:
3222 1. numpy - "sudo pip install numpy"
3223 """
3224 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003225 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003226 try:
3227 mnDPIDs = []
3228 for swName, switch in switches.iteritems():
3229 mnDPIDs.append( switch[ 'dpid' ].lower() )
3230 mnDPIDs.sort()
3231 if switchesJson == "": # if rest call fails
3232 main.log.error(
3233 self.name +
3234 ".compareSwitches(): Empty JSON object given from ONOS" )
3235 return main.FALSE
3236 onos = switchesJson
3237 onosDPIDs = []
3238 for switch in onos:
3239 if switch[ 'available' ]:
3240 onosDPIDs.append(
3241 switch[ 'id' ].replace(
3242 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003243 '' ).replace(
3244 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003245 '' ).lower() )
3246 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003247
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003248 if mnDPIDs != onosDPIDs:
3249 switchResults = main.FALSE
3250 main.log.error( "Switches in MN but not in ONOS:" )
3251 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3252 main.log.error( str( list1 ) )
3253 main.log.error( "Switches in ONOS but not in MN:" )
3254 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3255 main.log.error( str( list2 ) )
3256 else: # list of dpid's match in onos and mn
3257 switchResults = main.TRUE
3258 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003259
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003260 # FIXME: this does not look for extra ports in ONOS, only checks that
3261 # ONOS has what is in MN
3262 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003263
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003264 # PORTS
3265 for name, mnSwitch in switches.iteritems():
3266 mnPorts = []
3267 onosPorts = []
3268 switchResult = main.TRUE
3269 for port in mnSwitch[ 'ports' ]:
3270 if port[ 'enabled' ]:
3271 mnPorts.append( int( port[ 'of_port' ] ) )
3272 for onosSwitch in portsJson:
3273 if onosSwitch[ 'device' ][ 'available' ]:
3274 if onosSwitch[ 'device' ][ 'id' ].replace(
3275 ':',
3276 '' ).replace(
3277 "of",
3278 '' ) == mnSwitch[ 'dpid' ]:
3279 for port in onosSwitch[ 'ports' ]:
3280 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003281 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003282 # onosPorts.append( 'local' )
3283 onosPorts.append( long( uint64( -2 ) ) )
3284 else:
3285 onosPorts.append( int( port[ 'port' ] ) )
3286 break
3287 mnPorts.sort( key=float )
3288 onosPorts.sort( key=float )
3289
3290 mnPortsLog = mnPorts
3291 onosPortsLog = onosPorts
3292 mnPorts = [ x for x in mnPorts ]
3293 onosPorts = [ x for x in onosPorts ]
3294
3295 # TODO: handle other reserved port numbers besides LOCAL
3296 # NOTE: Reserved ports
3297 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3298 # long( uint64( -2 ) )
3299 for mnPort in mnPortsLog:
3300 if mnPort in onosPorts:
3301 # don't set results to true here as this is just one of
3302 # many checks and it might override a failure
3303 mnPorts.remove( mnPort )
3304 onosPorts.remove( mnPort )
3305
3306 # NOTE: OVS reports this as down since there is no link
3307 # So ignoring these for now
3308 # TODO: Come up with a better way of handling these
3309 if 65534 in mnPorts:
3310 mnPorts.remove( 65534 )
3311 if long( uint64( -2 ) ) in onosPorts:
3312 onosPorts.remove( long( uint64( -2 ) ) )
3313 if len( mnPorts ): # the ports of this switch don't match
3314 switchResult = main.FALSE
3315 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3316 if len( onosPorts ): # the ports of this switch don't match
3317 switchResult = main.FALSE
3318 main.log.warn(
3319 "Ports in ONOS but not MN: " +
3320 str( onosPorts ) )
3321 if switchResult == main.FALSE:
3322 main.log.error(
3323 "The list of ports for switch %s(%s) does not match:" %
3324 ( name, mnSwitch[ 'dpid' ] ) )
3325 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3326 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3327 portsResults = portsResults and switchResult
3328 finalResults = finalResults and portsResults
3329 return finalResults
3330 except pexpect.EOF:
3331 main.log.error( self.name + ": EOF exception found" )
3332 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003333 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003334 except Exception:
3335 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003336 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003337
Jon Hallafa8a472015-06-12 14:02:42 -07003338 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003339 """
3340 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003341 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003342
Jon Hallafa8a472015-06-12 14:02:42 -07003343 """
Jon Hall7eb38402015-01-08 17:19:54 -08003344 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003345 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003346 try:
3347 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003348
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003349 mnLinks = []
3350 for l in links:
3351 try:
3352 node1 = switches[ l[ 'node1' ] ]
3353 node2 = switches[ l[ 'node2' ] ]
3354 enabled = True
3355 for port in node1[ 'ports' ]:
3356 if port[ 'of_port' ] == l[ 'port1' ]:
3357 enabled = enabled and port[ 'enabled' ]
3358 for port in node2[ 'ports' ]:
3359 if port[ 'of_port' ] == l[ 'port2' ]:
3360 enabled = enabled and port[ 'enabled' ]
3361 if enabled:
3362 mnLinks.append( l )
3363 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003364 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003365 if 2 * len( mnLinks ) == len( onos ):
3366 linkResults = main.TRUE
3367 else:
3368 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003369 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003370 "Mininet has " + str( len( mnLinks ) ) +
3371 " bidirectional links and ONOS has " +
3372 str( len( onos ) ) + " unidirectional links" )
3373
3374 # iterate through MN links and check if an ONOS link exists in
3375 # both directions
3376 for link in mnLinks:
3377 # TODO: Find a more efficient search method
3378 node1 = None
3379 port1 = None
3380 node2 = None
3381 port2 = None
3382 firstDir = main.FALSE
3383 secondDir = main.FALSE
3384 for swName, switch in switches.iteritems():
3385 if swName == link[ 'node1' ]:
3386 node1 = switch[ 'dpid' ]
3387 for port in switch[ 'ports' ]:
3388 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3389 port1 = port[ 'of_port' ]
3390 if node1 is not None and node2 is not None:
3391 break
3392 if swName == link[ 'node2' ]:
3393 node2 = switch[ 'dpid' ]
3394 for port in switch[ 'ports' ]:
3395 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3396 port2 = port[ 'of_port' ]
3397 if node1 is not None and node2 is not None:
3398 break
3399
3400 for onosLink in onos:
3401 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3402 ":", '' ).replace( "of", '' )
3403 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3404 ":", '' ).replace( "of", '' )
3405 onosPort1 = onosLink[ 'src' ][ 'port' ]
3406 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3407
3408 # check onos link from node1 to node2
3409 if str( onosNode1 ) == str( node1 ) and str(
3410 onosNode2 ) == str( node2 ):
3411 if int( onosPort1 ) == int( port1 ) and int(
3412 onosPort2 ) == int( port2 ):
3413 firstDir = main.TRUE
3414 else:
Jon Hallab611372018-02-21 15:26:05 -08003415 # The right switches, but wrong ports, could be
3416 # another link between these devices, or onos
3417 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003418 main.log.warn(
3419 'The port numbers do not match for ' +
3420 str( link ) +
3421 ' between ONOS and MN. When checking ONOS for ' +
3422 'link %s/%s -> %s/%s' %
3423 ( node1, port1, node2, port2 ) +
3424 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003425 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3426 '. This could be another link between these devices' +
3427 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003428
3429 # check onos link from node2 to node1
3430 elif ( str( onosNode1 ) == str( node2 ) and
3431 str( onosNode2 ) == str( node1 ) ):
3432 if ( int( onosPort1 ) == int( port2 )
3433 and int( onosPort2 ) == int( port1 ) ):
3434 secondDir = main.TRUE
3435 else:
Jon Hallab611372018-02-21 15:26:05 -08003436 # The right switches, but wrong ports, could be
3437 # another link between these devices, or onos
3438 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003439 main.log.warn(
3440 'The port numbers do not match for ' +
3441 str( link ) +
3442 ' between ONOS and MN. When checking ONOS for ' +
3443 'link %s/%s -> %s/%s' %
3444 ( node1, port1, node2, port2 ) +
3445 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003446 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3447 '. This could be another link between these devices' +
3448 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003449 else: # this is not the link you're looking for
3450 pass
3451 if not firstDir:
3452 main.log.error(
3453 'ONOS does not have the link %s/%s -> %s/%s' %
3454 ( node1, port1, node2, port2 ) )
3455 if not secondDir:
3456 main.log.error(
3457 'ONOS does not have the link %s/%s -> %s/%s' %
3458 ( node2, port2, node1, port1 ) )
3459 linkResults = linkResults and firstDir and secondDir
3460 return linkResults
3461 except pexpect.EOF:
3462 main.log.error( self.name + ": EOF exception found" )
3463 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003464 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003465 except Exception:
3466 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003467 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003468
Jon Hallafa8a472015-06-12 14:02:42 -07003469 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003470 """
Jon Hallafa8a472015-06-12 14:02:42 -07003471 Compare mn and onos Hosts.
3472 Since Mininet hosts are quiet, ONOS will only know of them when they
3473 speak. For this reason, we will only check that the hosts in ONOS
3474 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003475
Jon Hallafa8a472015-06-12 14:02:42 -07003476 Arguments:
3477 hostsJson: parsed json object from the onos hosts api
3478 Returns:
3479 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003480 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003481 try:
3482 hostResults = main.TRUE
3483 for onosHost in hostsJson:
3484 onosMAC = onosHost[ 'mac' ].lower()
3485 match = False
3486 for mnHost, info in hosts.iteritems():
3487 for mnIntf in info[ 'interfaces' ]:
3488 if onosMAC == mnIntf[ 'mac' ].lower():
3489 match = True
3490 for ip in mnIntf[ 'ips' ]:
3491 if ip in onosHost[ 'ipAddresses' ]:
3492 pass # all is well
3493 else:
3494 # misssing ip
3495 main.log.error( "ONOS host " +
3496 onosHost[ 'id' ] +
3497 " has a different IP(" +
3498 str( onosHost[ 'ipAddresses' ] ) +
3499 ") than the Mininet host(" +
3500 str( ip ) +
3501 ")." )
3502 output = json.dumps(
3503 onosHost,
3504 sort_keys=True,
3505 indent=4,
3506 separators=( ',', ': ' ) )
3507 main.log.info( output )
3508 hostResults = main.FALSE
3509 if not match:
3510 hostResults = main.FALSE
3511 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3512 "corresponding Mininet host." )
3513 output = json.dumps( onosHost,
3514 sort_keys=True,
3515 indent=4,
3516 separators=( ',', ': ' ) )
3517 main.log.info( output )
3518 return hostResults
3519 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003520 main.log.error( self.name + ": EOF exception found" )
3521 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003522 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003523 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003524 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003525 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003526
You Wangd66de192018-04-30 17:30:12 -07003527 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003528 """
3529 Description:
3530 Verify that all hosts have IP address assigned to them
3531 Optional:
3532 hostList: If specified, verifications only happen to the hosts
3533 in hostList
3534 prefix: at least one of the ip address assigned to the host
3535 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003536 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003537 Returns:
3538 main.TRUE if all hosts have specific IP address assigned;
3539 main.FALSE otherwise
3540 """
3541 try:
You Wangd66de192018-04-30 17:30:12 -07003542 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003543 if not hostList:
3544 hostList = hosts.keys()
3545 for hostName in hosts.keys():
3546 if hostName not in hostList:
3547 continue
3548 ipList = []
3549 self.handle.sendline( str( hostName ) + " ip a" )
3550 self.handle.expect( "mininet>" )
3551 ipa = self.handle.before
3552 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3553 ipList += re.findall( ipv4Pattern, ipa )
3554 # It's tricky to make regex for IPv6 addresses and this one is simplified
3555 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})/'
3556 ipList += re.findall( ipv6Pattern, ipa )
3557 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3558 if not ipList:
3559 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3560 else:
3561 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3562 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3563 else:
3564 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3565 hostList.remove( hostName )
3566 return main.FALSE if hostList else main.TRUE
3567 except KeyError:
3568 main.log.exception( self.name + ": host data not as expected: " + hosts )
3569 return None
3570 except pexpect.EOF:
3571 main.log.error( self.name + ": EOF exception found" )
3572 main.log.error( self.name + ": " + self.handle.before )
3573 main.cleanAndExit()
3574 except Exception:
3575 main.log.exception( self.name + ": Uncaught exception" )
3576 return None
3577
Jon Hallafa8a472015-06-12 14:02:42 -07003578 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003579 """
3580 Returns a list of all hosts
3581 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003582 try:
3583 self.handle.sendline( "" )
3584 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003585
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003586 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3587 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003588
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003589 handlePy = self.handle.before
3590 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3591 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003592
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003593 self.handle.sendline( "" )
3594 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003595
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003596 hostStr = handlePy.replace( "]", "" )
3597 hostStr = hostStr.replace( "'", "" )
3598 hostStr = hostStr.replace( "[", "" )
3599 hostStr = hostStr.replace( " ", "" )
3600 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003601
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003602 return hostList
3603 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003604 main.log.error( self.name + ": TIMEOUT exception found" )
3605 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003606 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003607 except pexpect.EOF:
3608 main.log.error( self.name + ": EOF 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 Exception:
3612 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003613 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003614
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003615 def getSwitch( self ):
3616 """
3617 Returns a list of all switches
3618 Again, don't ask question just use it...
3619 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003620 try:
3621 # get host list...
3622 hostList = self.getHosts()
3623 # Make host set
3624 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003625
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003626 # Getting all the nodes in mininet
3627 self.handle.sendline( "" )
3628 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003629
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003630 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3631 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003632
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003633 handlePy = self.handle.before
3634 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3635 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003636
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003637 self.handle.sendline( "" )
3638 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003639
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003640 nodesStr = handlePy.replace( "]", "" )
3641 nodesStr = nodesStr.replace( "'", "" )
3642 nodesStr = nodesStr.replace( "[", "" )
3643 nodesStr = nodesStr.replace( " ", "" )
3644 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003645
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003646 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003647 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003648 nodesSet.discard( 'c0' )
3649 nodesSet.discard( 'c1' )
3650 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003651
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003652 switchSet = nodesSet - hostSet
3653 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003654
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003655 return switchList
3656 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003657 main.log.error( self.name + ": TIMEOUT exception found" )
3658 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003659 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003660 except pexpect.EOF:
3661 main.log.error( self.name + ": EOF 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 Exception:
3665 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003666 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003667
You Wangdb8cd0a2016-05-26 15:19:45 -07003668 def getGraphDict( self, timeout=60, useId=True, includeHost=False ):
3669 """
3670 Return a dictionary which describes the latest Mininet topology data as a
3671 graph.
3672 An example of the dictionary:
3673 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3674 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3675 Each vertex should at least have an 'edges' attribute which describes the
3676 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003677 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003678 list of attributes.
3679 An example of the edges dictionary:
3680 'edges': { vertex2: { 'port': ..., 'weight': ... },
3681 vertex3: { 'port': ..., 'weight': ... } }
3682 If useId == True, dpid/mac will be used instead of names to identify
3683 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3684 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003685 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003686 in topology data.
3687 Note that link or switch that are brought down by 'link x x down' or 'switch
3688 x down' commands still show in the output of Mininet CLI commands such as
3689 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3690 recommended to use delLink() or delSwitch functions to simulate link/switch
3691 down, and addLink() or addSwitch to add them back.
3692 """
3693 graphDict = {}
3694 try:
3695 links = self.getLinks( timeout=timeout )
3696 portDict = {}
3697 if useId:
3698 switches = self.getSwitches()
3699 if includeHost:
3700 hosts = self.getHosts()
3701 for link in links:
3702 # FIXME: support 'includeHost' argument
3703 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3704 continue
3705 nodeName1 = link[ 'node1' ]
3706 nodeName2 = link[ 'node2' ]
3707 port1 = link[ 'port1' ]
3708 port2 = link[ 'port2' ]
3709 # Loop for two nodes
3710 for i in range( 2 ):
3711 # Get port index from OVS
3712 # The index extracted from port name may be inconsistent with ONOS
3713 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003714 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003715 portList = self.getOVSPorts( nodeName1 )
3716 if len( portList ) == 0:
3717 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3718 return None
3719 portDict[ nodeName1 ] = portList
3720 for port in portDict[ nodeName1 ]:
3721 if port[ 'port' ] == port1:
3722 portIndex = port[ 'index' ]
3723 break
3724 if portIndex == -1:
3725 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3726 return None
3727 if useId:
3728 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3729 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3730 else:
3731 node1 = nodeName1
3732 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003733 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003734 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003735 graphDict[ node1 ] = { 'edges': {},
3736 'dpid': switches[ nodeName1 ][ 'dpid' ],
3737 'name': nodeName1,
3738 'ports': switches[ nodeName1 ][ 'ports' ],
3739 'swClass': switches[ nodeName1 ][ 'swClass' ],
3740 'pid': switches[ nodeName1 ][ 'pid' ],
3741 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003742 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003743 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003744 else:
3745 # Assert node2 is not connected to any current links of node1
3746 assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003747 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
You Wangdb8cd0a2016-05-26 15:19:45 -07003748 # Swap two nodes/ports
3749 nodeName1, nodeName2 = nodeName2, nodeName1
3750 port1, port2 = port2, port1
3751 return graphDict
3752 except KeyError:
3753 main.log.exception( self.name + ": KeyError exception found" )
3754 return None
3755 except AssertionError:
3756 main.log.exception( self.name + ": AssertionError exception found" )
3757 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003758 except pexpect.EOF:
3759 main.log.error( self.name + ": EOF exception found" )
3760 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003761 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003762 except Exception:
3763 main.log.exception( self.name + ": Uncaught exception" )
3764 return None
3765
Devin Lima7cfdbd2017-09-29 15:02:22 -07003766 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003767 """
3768 updates the port address and status information for
3769 each port in mn"""
3770 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003771 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003772 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003773 self.handle.sendline( "" )
3774 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003775
Jon Hall7eb38402015-01-08 17:19:54 -08003776 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003777 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003778
Jon Hall7eb38402015-01-08 17:19:54 -08003779 self.handle.sendline( "" )
3780 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003781
Jon Hallb1290e82014-11-18 16:17:48 -05003782 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003783 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003784 main.log.error( self.name + ": TIMEOUT exception found" )
3785 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003786 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003787 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003788 main.log.error( self.name + ": EOF exception found" )
3789 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003790 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003791 except Exception:
3792 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003793 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003794
Jon Halld80cc142015-07-06 13:36:05 -07003795 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003796 """
3797 Add vlan tag to a host.
3798 Dependencies:
3799 This class depends on the "vlan" package
3800 $ sudo apt-get install vlan
3801 Configuration:
3802 Load the 8021q module into the kernel
3803 $sudo modprobe 8021q
3804
3805 To make this setup permanent:
3806 $ sudo su -c 'echo "8021q" >> /etc/modules'
3807 """
3808 if self.handle:
3809 try:
Jon Halld80cc142015-07-06 13:36:05 -07003810 # get the ip address of the host
3811 main.log.info( "Get the ip address of the host" )
3812 ipaddr = self.getIPAddress( host )
3813 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003814
Jon Halld80cc142015-07-06 13:36:05 -07003815 # remove IP from interface intf
3816 # Ex: h1 ifconfig h1-eth0 inet 0
3817 main.log.info( "Remove IP from interface " )
3818 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3819 self.handle.sendline( cmd2 )
3820 self.handle.expect( "mininet>" )
3821 response = self.handle.before
3822 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003823
Jon Halld80cc142015-07-06 13:36:05 -07003824 # create VLAN interface
3825 # Ex: h1 vconfig add h1-eth0 100
3826 main.log.info( "Create Vlan" )
3827 cmd3 = host + " vconfig add " + intf + " " + vlan
3828 self.handle.sendline( cmd3 )
3829 self.handle.expect( "mininet>" )
3830 response = self.handle.before
3831 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003832
Jon Halld80cc142015-07-06 13:36:05 -07003833 # assign the host's IP to the VLAN interface
3834 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3835 main.log.info( "Assign the host IP to the vlan interface" )
3836 vintf = intf + "." + vlan
3837 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3838 self.handle.sendline( cmd4 )
3839 self.handle.expect( "mininet>" )
3840 response = self.handle.before
3841 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003842
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003843 # update Mininet node variables
3844 main.log.info( "Update Mininet node variables" )
3845 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3846 self.handle.sendline( cmd5 )
3847 self.handle.expect( "mininet>" )
3848 response = self.handle.before
3849 main.log.info( "====> %s ", response )
3850
3851 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3852 self.handle.sendline( cmd6 )
3853 self.handle.expect( "mininet>" )
3854 response = self.handle.before
3855 main.log.info( "====> %s ", response )
3856
3857 return main.TRUE
3858 except pexpect.TIMEOUT:
3859 main.log.error( self.name + ": TIMEOUT exception found" )
3860 main.log.error( self.name + ": " + self.handle.before )
3861 main.cleanAndExit()
3862 except pexpect.EOF:
3863 main.log.error( self.name + ": EOF exception found" )
3864 main.log.error( self.name + ": " + self.handle.before )
3865 return main.FALSE
3866 except Exception:
3867 main.log.exception( self.name + ": Uncaught exception!" )
3868 return main.FALSE
3869
3870 def removeVLAN( self, host, intf ):
3871 """
3872 Remove vlan tag from a host.
3873 Dependencies:
3874 This class depends on the "vlan" package
3875 $ sudo apt-get install vlan
3876 Configuration:
3877 Load the 8021q module into the kernel
3878 $sudo modprobe 8021q
3879
3880 To make this setup permanent:
3881 $ sudo su -c 'echo "8021q" >> /etc/modules'
3882 """
3883 if self.handle:
3884 try:
3885 # get the ip address of the host
3886 main.log.info( "Get the ip address of the host" )
3887 ipaddr = self.getIPAddress( host )
3888
3889 # remove VLAN interface
3890 # Ex: h1 vconfig rem h1-eth0.100
3891 main.log.info( "Remove Vlan interface" )
3892 cmd2 = host + " vconfig rem " + intf
3893 self.handle.sendline( cmd2 )
3894 self.handle.expect( "mininet>" )
3895 response = self.handle.before
3896 main.log.info( "====> %s ", response )
3897
3898 # assign the host's IP to the original interface
3899 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3900 main.log.info( "Assign the host IP to the original interface" )
3901 original_intf = intf.split(".")[0]
3902 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3903 self.handle.sendline( cmd3 )
3904 self.handle.expect( "mininet>" )
3905 response = self.handle.before
3906 main.log.info( "====> %s ", response )
3907
3908 # update Mininet node variables
3909 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3910 self.handle.sendline( cmd4 )
3911 self.handle.expect( "mininet>" )
3912 response = self.handle.before
3913 main.log.info( "====> %s ", response )
3914
3915 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3916 self.handle.sendline( cmd5 )
3917 self.handle.expect( "mininet>" )
3918 response = self.handle.before
3919 main.log.info( "====> %s ", response )
3920
kaouthera3f13ca22015-05-05 15:01:41 -07003921 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003922 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003923 main.log.error( self.name + ": TIMEOUT exception found" )
3924 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003925 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003926 except pexpect.EOF:
3927 main.log.error( self.name + ": EOF exception found" )
3928 main.log.error( self.name + ": " + self.handle.before )
3929 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003930 except Exception:
3931 main.log.exception( self.name + ": Uncaught exception!" )
3932 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003933
Jon Hall892818c2015-10-20 17:58:34 -07003934 def createHostComponent( self, name ):
3935 """
3936 Creates a new mininet cli component with the same parameters as self.
3937 This new component is intended to be used to login to the hosts created
3938 by mininet.
3939
3940 Arguments:
3941 name - The string of the name of this component. The new component
3942 will be assigned to main.<name> .
3943 In addition, main.<name>.name = str( name )
3944 """
3945 try:
3946 # look to see if this component already exists
3947 getattr( main, name )
3948 except AttributeError:
3949 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003950 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3951 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003952 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003953 except pexpect.EOF:
3954 main.log.error( self.name + ": EOF exception found" )
3955 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003956 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003957 except Exception:
3958 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003959 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003960 else:
3961 # namespace is not clear!
3962 main.log.error( name + " component already exists!" )
3963 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003964 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003965
3966 def removeHostComponent( self, name ):
3967 """
3968 Remove host component
3969 Arguments:
3970 name - The string of the name of the component to delete.
3971 """
3972 try:
3973 # Get host component
3974 component = getattr( main, name )
3975 except AttributeError:
3976 main.log.error( "Component " + name + " does not exist." )
3977 return
3978 try:
3979 # Disconnect from component
3980 component.disconnect()
3981 # Delete component
3982 delattr( main, name )
3983 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003984 del( main.componentDictionary[ name ] )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003985 except pexpect.EOF:
3986 main.log.error( self.name + ": EOF exception found" )
3987 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003988 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003989 except Exception:
3990 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003991 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003992
3993 def startHostCli( self, host=None ):
3994 """
3995 Use the mininet m utility to connect to the host's cli
3996 """
3997 # These are fields that can be used by scapy packets. Initialized to None
3998 self.hostIp = None
3999 self.hostMac = None
4000 try:
4001 if not host:
4002 host = self.name
4003 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07004004 self.handle.sendline( "cd" )
4005 self.handle.expect( self.hostPrompt )
4006 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07004007 self.handle.expect( self.hostPrompt )
4008 return main.TRUE
4009 except pexpect.TIMEOUT:
4010 main.log.exception( self.name + ": Command timed out" )
4011 return main.FALSE
4012 except pexpect.EOF:
4013 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07004014 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07004015 except Exception:
4016 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004017 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07004018
YPZhang801d46d2016-08-08 13:26:28 -07004019 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004020 '''
4021
YPZhang801d46d2016-08-08 13:26:28 -07004022 Args:
4023 devicename: switch name
4024 intf: port name on switch
4025 status: up or down
4026
4027 Returns: boolean to show success change status
4028
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004029 '''
YPZhang801d46d2016-08-08 13:26:28 -07004030 if status == "down" or status == "up":
4031 try:
4032 cmd = devicename + " ifconfig " + intf + " " + status
4033 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004034 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07004035 return main.TRUE
4036 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004037 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07004038 return main.FALSE
4039 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004040 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07004041 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07004042 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004043 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07004044 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07004045 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004046 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004047 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07004048 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004049 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07004050 return main.FALSE
4051
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004052 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
4053 macAddr=None, prefixLen=None, bondedName='bond1' ):
4054 """
4055 Moves a dual-homed host from one switch-pair to another pair on the fly
4056 If macAddr is specified, change MAC address of the bonded host interface
4057 to specified MAC address.
4058 Assumes that the host has two interfaces (eth0 and eth1) originally.
4059 """
4060
4061 bond1 = "%s-%s" % ( host, bondedName )
4062 newIntf = host + '-eth2'
4063 newIntfPair = host + '-eth3'
4064 commands = [
4065 # Bring link between oldSw-host down
4066 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
4067 # Bring link between oldPairSw-host down
4068 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
4069 # Determine hostintf and Oldswitchintf
4070 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
4071 # Determine ip and mac address of the host-oldSw interface
4072 "px ipaddr = hintf.IP()",
4073 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
4074 # Detach interface between oldSw-host
4075 "px " + oldSw + ".detach( sintf )",
4076 # Determine hostintf and Oldpairswitchintf
4077 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
4078 # Detach interface between oldPairSw-host
4079 "px " + oldPairSw + ".detach( sintfpair )",
4080 # Add link between host-newSw
4081 "py net.addLink(" + host + "," + newSw + ", 2)",
4082 # Add link between host-newPairSw
4083 "py net.addLink(" + host + "," + newPairSw + ")",
4084 # Determine hostintf and Newswitchintf
4085 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
4086 # Determine hostintf and NewPairswitchintf
4087 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
4088 # Attach interface between newSw-host
4089 "px " + newSw + ".attach( sintf )",
4090 # Attach interface between newPairSw-host
4091 "px " + newPairSw + ".attach( sintfpair )",
4092 # Bond two interfaces
4093 host + ' ip link add %s type bond' % bond1,
4094 host + ' ip link set %s down' % newIntf,
4095 host + ' ip link set %s down' % newIntfPair,
4096 host + ' ip link set %s master %s' % ( newIntf, bond1 ),
4097 host + ' ip link set %s master %s' % ( newIntfPair, bond1 ),
4098 host + ' ip addr flush dev %s' % newIntf,
4099 host + ' ip addr flush dev %s' % newIntfPair,
4100 host + ' ip link set %s up' % bond1,
4101 "px lowestIntf = min( [ hintf, hintfpair ] )",
4102 "px highestIntf = max( [ hintf, hintfpair ] )",
4103 "px lowestIntf.name = '" + bond1 + "'",
4104 "px " + host + ".nameToIntf['" + bond1 + "'] = lowestIntf",
4105 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
4106 "px del " + host + ".ports[ highestIntf ]",
4107 # Set ipaddress of the host-newSw interface
4108 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
4109 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
4110 # Set macaddress of the host-newSw interface
4111 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
4112 "net",
4113 # Determine ipaddress of the bonded host interface
4114 host + " ifconfig",
4115 ]
4116
4117 if self.handle:
4118 try:
4119 for cmd in commands:
4120 print "cmd= ", cmd
4121 self.handle.sendline( cmd )
4122 self.handle.expect( "mininet>" )
4123 main.log.info( "====> %s ", self.handle.before )
4124 return main.TRUE
4125
4126 except pexpect.TIMEOUT:
4127 main.log.error( self.name + ": TIMEOUT exception found" )
4128 main.log.error( self.name + ": " + self.handle.before )
4129 main.cleanAndExit()
4130 except pexpect.EOF:
4131 main.log.error( self.name + ": EOF exception found" )
4132 main.log.error( self.name + ": " + self.handle.before )
4133 return main.FALSE
4134 except Exception:
4135 main.log.exception( self.name + ": Uncaught exception!" )
4136 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07004137
adminbae64d82013-08-01 10:50:15 -07004138if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004139 sys.modules[ __name__ ] = MininetCliDriver()