blob: 54d9747d9244085f8da1592ec7c0a14a116b33f8 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
Jon Hall7eb38402015-01-08 17:19:54 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004Copyright 2012 Open Networking Foundation (ONF)
adminbae64d82013-08-01 10:50:15 -07005
Jeremy Songsterae01bba2016-07-11 15:39:17 -07006Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
7the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
8or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
adminbae64d82013-08-01 10:50:15 -07009
Jon Hall7eb38402015-01-08 17:19:54 -080010TestON is free software: you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation, either version 2 of the License, or
13( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070014
Jon Hall7eb38402015-01-08 17:19:54 -080015TestON is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070019
Jon Hall7eb38402015-01-08 17:19:54 -080020You should have received a copy of the GNU General Public License
21along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070022
Jon Hallbe6dfc42015-01-12 17:37:25 -080023MininetCliDriver is the basic driver which will handle the Mininet functions
24
25Some functions rely on a modified version of Mininet. These functions
26should all be noted in the comments. To get this MN version run these commands
27from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080028 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080029 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080030 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080031 git pull
32
Jon Hall272a4db2015-01-12 17:43:48 -080033
34 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080035changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070036import pexpect
adminbae64d82013-08-01 10:50:15 -070037import re
38import sys
kelvin-onlabfa6ada82015-06-11 13:06:24 -070039import types
kelvin-onlaba4074292015-07-09 15:19:49 -070040import os
Devin Lima7cfdbd2017-09-29 15:02:22 -070041import time
Jon Hall1ccf82c2014-10-15 14:55:16 -040042from math import pow
adminbae64d82013-08-01 10:50:15 -070043from drivers.common.cli.emulatordriver import Emulator
You Wangdb8cd0a2016-05-26 15:19:45 -070044from core.graph import Graph
adminbae64d82013-08-01 10:50:15 -070045
Jon Hall7eb38402015-01-08 17:19:54 -080046
kelvin-onlab50907142015-04-01 13:37:45 -070047class MininetCliDriver( Emulator ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -070048
Jon Hall7eb38402015-01-08 17:19:54 -080049 """
50 MininetCliDriver is the basic driver which will handle
51 the Mininet functions"""
52 def __init__( self ):
Devin Limdc78e202017-06-09 18:30:07 -070053 super( MininetCliDriver, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070054 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080055 self.name = None
kelvin-onlabd9e23de2015-08-06 10:34:44 -070056 self.home = None
Jon Hall7eb38402015-01-08 17:19:54 -080057 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070058 self.flag = 0
Jon Hall892818c2015-10-20 17:58:34 -070059 # TODO: Refactor driver to use these everywhere
60 self.mnPrompt = "mininet>"
61 self.hostPrompt = "~#"
62 self.bashPrompt = "\$"
63 self.scapyPrompt = ">>>"
You Wangdb8cd0a2016-05-26 15:19:45 -070064 self.graph = Graph()
adminbae64d82013-08-01 10:50:15 -070065
Jon Hall7eb38402015-01-08 17:19:54 -080066 def connect( self, **connectargs ):
67 """
68 Here the main is the TestON instance after creating
69 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080070 try:
71 for key in connectargs:
72 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070073 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080074 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070075 for key in self.options:
76 if key == "home":
77 self.home = self.options[ 'home' ]
78 break
79 if self.home is None or self.home == "":
80 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070081
82 try:
Jon Hall892818c2015-10-20 17:58:34 -070083 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070084 self.ip_address = os.getenv( str( self.ip_address ) )
85 else:
86 main.log.info( self.name +
87 ": Trying to connect to " +
88 self.ip_address )
89
90 except KeyError:
91 main.log.info( "Invalid host name," +
92 " connecting to local host instead" )
93 self.ip_address = 'localhost'
94 except Exception as inst:
95 main.log.error( "Uncaught exception: " + str( inst ) )
96
kelvin-onlaba1484582015-02-02 15:46:20 -080097 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070098 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080099 self ).connect(
100 user_name=self.user_name,
101 ip_address=self.ip_address,
102 port=None,
103 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -0800104
kelvin-onlaba1484582015-02-02 15:46:20 -0800105 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -0800106 main.log.info( "Connection successful to the host " +
107 self.user_name +
108 "@" +
109 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800110 return main.TRUE
111 else:
112 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800113 self.user_name +
114 "@" +
115 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800116 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800117 return main.FALSE
118 except pexpect.EOF:
119 main.log.error( self.name + ": EOF exception found" )
120 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700121 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800122 except Exception:
123 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700124 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -0800125
kelvin-onlab10e8d392015-06-03 13:53:45 -0700126 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800127 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700128 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000129 Starts Mininet accepts a topology(.py) file and/or an optional
kelvin-onlabf512e942015-06-08 19:42:59 -0700130 argument, to start the mininet, as a parameter.
131 Can also send regular mininet command to load up desired topology.
alison12f34c32016-06-10 14:39:21 -0700132 Eg. Pass in a string 'mn --topo=tree,3,3' to mnCmd
kelvin-onlabf512e942015-06-08 19:42:59 -0700133 Options:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000134 topoFile = file path for topology file (.py)
kelvin-onlabf512e942015-06-08 19:42:59 -0700135 args = extra option added when starting the topology from the file
136 mnCmd = Mininet command use to start topology
137 Returns:
138 main.TRUE if the mininet starts successfully, main.FALSE
139 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800140 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700141 try:
142 if self.handle:
143 # make sure old networks are cleaned up
144 main.log.info( self.name +
145 ": Clearing any residual state or processes" )
146 self.handle.sendline( "sudo mn -c" )
147 i = self.handle.expect( [ 'password\sfor\s',
148 'Cleanup\scomplete',
Jon Hallefbd9792015-03-05 16:11:36 -0800149 pexpect.EOF,
150 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700151 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800152 if i == 0:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700153 # Sudo asking for password
154 main.log.info( self.name + ": Sending sudo password" )
155 self.handle.sendline( self.pwd )
Jon Hall173f2a02018-01-11 13:56:37 -0800156 i = self.handle.expect( [ '%s:' % self.user_name,
Devin Limdc78e202017-06-09 18:30:07 -0700157 self.prompt,
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700158 pexpect.EOF,
159 pexpect.TIMEOUT ],
160 timeout )
161 if i == 1:
162 main.log.info( self.name + ": Clean" )
Jon Hall689d8e42015-04-03 13:59:24 -0700163 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700164 main.log.error( self.name + ": Connection terminated" )
165 elif i == 3: # timeout
166 main.log.error( self.name + ": Something while cleaning " +
167 "Mininet took too long... " )
168 # Craft the string to start mininet
169 cmdString = "sudo "
170 if not mnCmd:
171 if topoFile is None or topoFile == '': # If no file is given
172 main.log.info( self.name + ": building fresh Mininet" )
173 cmdString += "mn "
174 if args is None or args == '':
175 # If no args given, use args from .topo file
176 args = self.options[ 'arg1' ] +\
177 " " + self.options[ 'arg2' ] +\
178 " --mac --controller " +\
179 self.options[ 'controller' ] + " " +\
180 self.options[ 'arg3' ]
181 else: # else only use given args
182 pass
183 # TODO: allow use of topo args and method args?
184 else: # Use given topology file
185 main.log.info(
186 "Starting Mininet from topo file " +
187 topoFile )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700188 cmdString += "-E python " + topoFile + " "
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700189 if args is None:
190 args = ''
191 # TODO: allow use of args from .topo file?
192 cmdString += args
193 else:
194 main.log.info( "Starting Mininet topology using '" + mnCmd +
195 "' command" )
196 cmdString += mnCmd
197 # Send the command and check if network started
198 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -0700199 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700200 main.log.info( "Sending '" + cmdString + "' to " + self.name )
201 self.handle.sendline( cmdString )
Devin Lima7cfdbd2017-09-29 15:02:22 -0700202 startTime = time.time()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700203 while True:
204 i = self.handle.expect( [ 'mininet>',
Jon Hallbc743112018-04-18 11:09:01 -0700205 'Exception|Error',
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700206 '\*\*\*',
207 pexpect.EOF,
Jon Hallab611372018-02-21 15:26:05 -0800208 pexpect.TIMEOUT,
209 "No such file or directory"],
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700210 timeout )
211 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -0700212 main.log.info( self.name + ": Mininet built\nTime Took : " + str( time.time() - startTime ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700213 return main.TRUE
214 elif i == 1:
215 response = str( self.handle.before +
216 self.handle.after )
Devin Limdc78e202017-06-09 18:30:07 -0700217 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700218 response += str( self.handle.before +
219 self.handle.after )
220 main.log.error(
221 self.name +
222 ": Launching Mininet failed: " + response )
223 return main.FALSE
224 elif i == 2:
225 self.handle.expect( [ "\n",
226 pexpect.EOF,
227 pexpect.TIMEOUT ],
228 timeout )
229 main.log.info( self.handle.before )
230 elif i == 3:
231 main.log.error( self.name + ": Connection timeout" )
232 return main.FALSE
233 elif i == 4: # timeout
234 main.log.error(
235 self.name +
236 ": Something took too long... " )
Jon Hallbc743112018-04-18 11:09:01 -0700237 main.log.debug( self.handle.before + self.handle.after )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700238 return main.FALSE
Jon Hallab611372018-02-21 15:26:05 -0800239 elif i == 5:
240 main.log.error( self.name + ": " + self.handle.before + self.handle.after )
241 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700242 # Why did we hit this part?
243 main.log.error( "startNet did not return correctly" )
244 return main.FASLE
245 else: # if no handle
246 main.log.error( self.name + ": Connection failed to the host " +
247 self.user_name + "@" + self.ip_address )
248 main.log.error( self.name + ": Failed to connect to the Mininet" )
249 return main.FALSE
250 except pexpect.TIMEOUT:
251 main.log.exception( self.name + ": TIMEOUT exception found while starting Mininet" )
252 main.log.error( self.name + ": " + self.handle.before )
adminbae64d82013-08-01 10:50:15 -0700253 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700254 except pexpect.EOF:
255 main.log.error( self.name + ": EOF exception found" )
256 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700257 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700258 except Exception:
259 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700260 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800261
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800262 def numSwitchesNlinks( self, topoType, depth, fanout ):
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700263 try:
264 if topoType == 'tree':
265 # In tree topology, if fanout arg is not given, by default it is 2
266 if fanout is None:
267 fanout = 2
268 k = 0
269 count = 0
270 while( k <= depth - 1 ):
271 count = count + pow( fanout, k )
272 k = k + 1
273 numSwitches = count
274 while( k <= depth - 2 ):
275 # depth-2 gives you only core links and not considering
276 # edge links as seen by ONOS. If all the links including
277 # edge links are required, do depth-1
278 count = count + pow( fanout, k )
279 k = k + 1
280 numLinks = count * fanout
281 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
282 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800283
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700284 elif topoType == 'linear':
285 # In linear topology, if fanout or numHostsPerSw is not given,
286 # by default it is 1
287 if fanout is None:
288 fanout = 1
289 numSwitches = depth
290 numHostsPerSw = fanout
291 totalNumHosts = numSwitches * numHostsPerSw
292 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hallab611372018-02-21 15:26:05 -0800293 main.log.debug( "num_switches for %s(%d,%d) = %d and links=%d" %
294 ( topoType, depth, fanout, numSwitches, numLinks ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700295 topoDict = { "num_switches": int( numSwitches ),
296 "num_corelinks": int( numLinks ) }
297 return topoDict
298 except Exception:
299 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700300 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400301
kelvin-onlabd3b64892015-01-20 13:26:24 -0800302 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700303 """
304 Calculate the number of switches and links in a topo."""
305 # TODO: combine this function and numSwitchesNlinks
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700306 try:
307 argList = self.options[ 'arg1' ].split( "," )
308 topoArgList = argList[ 0 ].split( " " )
309 argList = map( int, argList[ 1: ] )
310 topoArgList = topoArgList[ 1: ] + argList
Jon Hall689d8e42015-04-03 13:59:24 -0700311
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700312 topoDict = self.numSwitchesNlinks( *topoArgList )
313 return topoDict
314 except Exception:
315 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700316 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400317
GlennRCf07c44a2015-09-18 13:33:46 -0700318 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800319 """
320 Verifies the reachability of the hosts using pingall command.
321 Optional parameter timeout allows you to specify how long to
322 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700323 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700324 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700325 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700326 ping
327 acceptableFailed - Set the number of acceptable failed pings for the
328 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800329 Returns:
330 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700331 otherwise main.FALSE
332 """
333 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700334 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700335 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700336 if self.handle:
337 main.log.info(
338 self.name +
339 ": Checking reachabilty to the hosts using pingall" )
340 response = ""
341 failedPings = 0
342 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700343 cmd = "pingall"
344 if protocol == "IPv6":
345 cmd = "py net.pingAll6()"
346 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700347 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700348 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700349 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700350 pexpect.EOF,
351 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700352 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700353 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700354 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700355 response += self.handle.before
356 break
357 elif i == 1:
358 response += self.handle.before + self.handle.after
359 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700360 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700361 returnValue = main.FALSE
362 if shortCircuit:
363 main.log.error( self.name +
364 ": Aborting pingall - "
365 + str( failedPings ) +
366 " pings failed" )
367 break
Jon Hall390696c2015-05-05 17:13:41 -0700368 if ( time.time() - startTime ) > timeout:
369 returnValue = main.FALSE
370 main.log.error( self.name +
371 ": Aborting pingall - " +
372 "Function took too long " )
373 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700374 elif i == 2:
375 main.log.error( self.name +
376 ": EOF exception found" )
377 main.log.error( self.name + ": " +
378 self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700379 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700380 elif i == 3:
381 response += self.handle.before
382 main.log.error( self.name +
383 ": TIMEOUT exception found" )
384 main.log.error( self.name +
385 ": " +
386 str( response ) )
387 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800388 self.handle.send( "\x03" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700389 self.handle.expect( "Interrupt" )
390 self.handle.expect( "mininet>" )
391 break
392 pattern = "Results\:"
393 main.log.info( "Pingall output: " + str( response ) )
394 if re.search( pattern, response ):
395 main.log.info( self.name + ": Pingall finished with "
396 + str( failedPings ) + " failed pings" )
397 return returnValue
398 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700399 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800400 self.handle.send( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700401 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700402 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700403 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700404 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700405 main.log.error( self.name + ": Connection failed to the host" )
Devin Lim44075962017-08-11 10:56:37 -0700406 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700407 except pexpect.TIMEOUT:
408 if response:
409 main.log.info( "Pingall output: " + str( response ) )
410 main.log.error( self.name + ": pexpect.TIMEOUT found" )
411 return main.FALSE
412 except pexpect.EOF:
413 main.log.error( self.name + ": EOF exception found" )
414 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700415 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -0700416
Jon Hall7eb38402015-01-08 17:19:54 -0800417 def fpingHost( self, **pingParams ):
418 """
419 Uses the fping package for faster pinging...
420 *requires fping to be installed on machine running mininet"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700421 try:
422 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
423 command = args[ "SRC" ] + \
424 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
425 self.handle.sendline( command )
426 self.handle.expect(
427 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
428 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
429 response = self.handle.before
430 if re.search( ":\s-", response ):
431 main.log.info( self.name + ": Ping fail" )
432 return main.FALSE
433 elif re.search( ":\s\d{1,2}\.\d\d", response ):
434 main.log.info( self.name + ": Ping good!" )
435 return main.TRUE
436 main.log.info( self.name + ": Install fping on mininet machine... " )
437 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700438 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700439 except Exception:
440 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700441 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700442
Jon Hall3b489db2015-10-05 14:38:37 -0700443 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400444 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700445 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700446
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400447 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700448 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700449
450 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400451 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700452
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400453 Returns main.FALSE if one or more of hosts specified
454 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700455 wait = int( wait )
456 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400457
458 try:
459 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700460
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400461 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700462 pingResponse = "IPv4 ping across specified hosts\n"
463 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400464 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700465 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400466 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700467 pingList = hostList[ :listIndex ] + \
468 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700469
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700470 pingResponse += str( str( host ) + " -> " )
GlennRCd10d3cc2015-09-24 12:47:16 -0700471
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400472 for temp in pingList:
473 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700474 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700475 self.handle.sendline( pingCmd )
476 self.handle.expect( "mininet>", timeout=wait + 1 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400477 response = self.handle.before
478 if re.search( ',\s0\%\spacket\sloss', response ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700479 pingResponse += str( " h" + str( temp[ 1: ] ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400480 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700481 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400482 # One of the host to host pair is unreachable
483 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700484 failedPings += 1
You Wang11f9ead2018-03-21 14:34:59 -0700485 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
GlennRCd10d3cc2015-09-24 12:47:16 -0700486 pingResponse += "\n"
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700487 main.log.info( pingResponse + "Failed pings: " + str( failedPings ) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700488 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700489 except pexpect.TIMEOUT:
490 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800491 response = self.handle.before
492 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700493 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800494 self.handle.expect( "Interrupt" )
495 response += self.handle.before + self.handle.after
496 self.handle.expect( "mininet>" )
497 response += self.handle.before + self.handle.after
498 main.log.debug( response )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700499 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400500 except pexpect.EOF:
501 main.log.error( self.name + ": EOF exception found" )
502 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700503 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700504 except Exception:
505 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700506 main.cleanAndExit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400507
You Wangf19d9f42018-02-23 16:34:19 -0800508 def pingIpv6Hosts( self, hostList, wait=1, acceptableFailed=0 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700509 """
You Wangf19d9f42018-02-23 16:34:19 -0800510 IPv6 ping all hosts in hostList.
511
512 acceptableFailed: max number of acceptable failed pings
Hari Krishna9592fc82015-07-31 15:11:15 -0700513
Jon Hall3b489db2015-10-05 14:38:37 -0700514 Returns main.TRUE if all hosts specified can reach each other
Jon Hall3b489db2015-10-05 14:38:37 -0700515 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700516 """
517 try:
518 main.log.info( "Testing reachability between specified IPv6 hosts" )
519 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700520 wait = int( wait )
521 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700522 pingResponse = "IPv6 Pingall output:\n"
You Wangf19d9f42018-02-23 16:34:19 -0800523 failedPingsTotal = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700524 for host in hostList:
525 listIndex = hostList.index( host )
526 # List of hosts to ping other than itself
527 pingList = hostList[ :listIndex ] + \
528 hostList[ ( listIndex + 1 ): ]
529
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700530 pingResponse += str( str( host ) + " -> " )
GlennRC2cf7d952015-09-11 16:32:13 -0700531
Hari Krishna9592fc82015-07-31 15:11:15 -0700532 for temp in pingList:
533 # Current host pings all other hosts specified
You Wangf19d9f42018-02-23 16:34:19 -0800534 failedPings = 0
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700535 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
You Wangf19d9f42018-02-23 16:34:19 -0800536 while failedPings <= acceptableFailed:
537 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
538 self.handle.sendline( pingCmd )
539 self.handle.expect( "mininet>", timeout=wait + 1 )
540 response = self.handle.before
541 if re.search( ',\s0\%\spacket\sloss', response ):
You Wangba231e72018-03-01 13:18:21 -0800542 pingResponse += " " + str( temp )
543 break
544 else:
545 failedPings += 1
546 time.sleep(1)
547 if failedPings > acceptableFailed:
548 # One of the host to host pair is unreachable
549 pingResponse += " X"
550 isReachable = main.FALSE
551 failedPingsTotal += 1
You Wang11f9ead2018-03-21 14:34:59 -0700552 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
You Wangba231e72018-03-01 13:18:21 -0800553 pingResponse += "\n"
554 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
555 return isReachable
556
557 except pexpect.TIMEOUT:
558 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800559 response = self.handle.before
560 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700561 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800562 self.handle.expect( "Interrupt" )
563 response += self.handle.before + self.handle.after
564 self.handle.expect( "mininet>" )
565 response += self.handle.before + self.handle.after
566 main.log.debug( response )
You Wangba231e72018-03-01 13:18:21 -0800567 return main.FALSE
568 except pexpect.EOF:
569 main.log.error( self.name + ": EOF exception found" )
570 main.log.error( self.name + ": " + self.handle.before )
571 main.cleanAndExit()
572 except Exception:
573 main.log.exception( self.name + ": Uncaught exception!" )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700574
575 main.cleanAndExit()
576
You Wangac363b92018-05-05 00:01:07 +0000577 def discoverIpv4Hosts( self, hostList, wait=1 , dstIp="6.6.6.6"):
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700578 '''
579 Can only be used if hosts already have ipv4 addresses.
580
581 Hosts in hostList will do a single ping to a non-existent (dstIp) address for ONOS
582 to discover them again.
583 '''
584 try:
585 main.log.info( "Issuing dumb pings for ipv6 hosts to be discovered" )
586 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
587 for host in hostList:
588 pingCmd = str( host ) + cmd + dstIp
589 self.handle.sendline( pingCmd )
590 self.handle.expect( "mininet>", timeout=wait + 1 )
591
592 except pexpect.TIMEOUT:
593 main.log.exception( self.name + ": TIMEOUT exception" )
594 response = self.handle.before
595 # NOTE: Send ctrl-c to make sure command is stopped
596 self.handle.send( "\x03" )
597 self.handle.expect( "Interrupt" )
598 response += self.handle.before + self.handle.after
599 self.handle.expect( "mininet>" )
600 response += self.handle.before + self.handle.after
601 main.log.debug( response )
602 return main.FALSE
603 except pexpect.EOF:
604 main.log.error( self.name + ": EOF exception found" )
605 main.log.error( self.name + ": " + self.handle.before )
606 main.cleanAndExit()
607 except Exception:
608 main.log.exception( self.name + ": Uncaught exception!" )
609 main.cleanAndExit()
610
611 def discoverIpv6Hosts( self, hostList, wait=1, dstIp="1020::3fe" ):
612 '''
613 Can only be used if hosts already have ipv6 addresses.
614
615 Hosts in hostList will do a single ping to a non-existent address (dstIp) for ONOS
616 to discover them again.
617 '''
618 try:
619 main.log.info( "Issuing dump pings for ipv6 hosts to be discovered" )
620 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
621 for host in hostList:
622 pingCmd = str( host ) + cmd + dstIp
623 self.handle.sendline( pingCmd )
624 self.handle.expect( "mininet>", timeout=wait + 1 )
625
626 except pexpect.TIMEOUT:
627 main.log.exception( self.name + ": TIMEOUT exception" )
628 response = self.handle.before
629 # NOTE: Send ctrl-c to make sure command is stopped
630 self.handle.send( "\x03" )
631 self.handle.expect( "Interrupt" )
632 response += self.handle.before + self.handle.after
633 self.handle.expect( "mininet>" )
634 response += self.handle.before + self.handle.after
635 main.log.debug( response )
636 return main.FALSE
637 except pexpect.EOF:
638 main.log.error( self.name + ": EOF exception found" )
639 main.log.error( self.name + ": " + self.handle.before )
640 main.cleanAndExit()
641 except Exception:
642 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800643 main.cleanAndExit()
644
645 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
646 """
647 Verify ping from each host in srcList to each host in dstList
648
649 acceptableFailed: max number of acceptable failed pings
650
651 Returns main.TRUE if all src hosts can reach all dst hosts
652 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
653 """
654 try:
655 main.log.info( "Verifying ping from each src host to each dst host" )
656 isReachable = main.TRUE
657 wait = int( wait )
658 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
659 pingResponse = "Ping output:\n"
660 failedPingsTotal = 0
661 for host in srcList:
662 pingResponse += str( str( host ) + " -> " )
663 for temp in dstList:
664 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700665 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
666 assert dstIP, "Not able to get IP address of host {}".format( temp )
667 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800668 while failedPings <= acceptableFailed:
669 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
670 self.handle.sendline( pingCmd )
671 self.handle.expect( "mininet>", timeout=wait + 1 )
672 response = self.handle.before
673 if re.search( ',\s0\%\spacket\sloss', response ):
674 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800675 break
676 else:
677 failedPings += 1
678 time.sleep(1)
679 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700680 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800681 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700682 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800683 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700684 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800685 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700686 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700687 except AssertionError:
688 main.log.exception( "" )
689 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700690 except pexpect.TIMEOUT:
691 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800692 response = self.handle.before
693 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700694 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800695 self.handle.expect( "Interrupt" )
696 response += self.handle.before + self.handle.after
697 self.handle.expect( "mininet>" )
698 response += self.handle.before + self.handle.after
699 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700700 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700701 except pexpect.EOF:
702 main.log.error( self.name + ": EOF exception found" )
703 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700704 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700705 except Exception:
706 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700707 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700708
Jon Hall7eb38402015-01-08 17:19:54 -0800709 def pingHost( self, **pingParams ):
710 """
Jon Hall3b489db2015-10-05 14:38:37 -0700711 Ping from one mininet host to another
712 Currently the only supported Params: SRC, TARGET, and WAIT
713 """
714 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700715 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700716 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800717 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700718 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700719 try:
Jon Hall61282e32015-03-19 11:34:11 -0700720 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800721 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700722 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
723 timeout=wait + 1 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700724 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800725 main.log.error(
726 self.name +
727 ": timeout when waiting for response from mininet" )
728 main.log.error( "response: " + str( self.handle.before ) )
729 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700730 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800731 main.log.error(
732 self.name +
733 ": timeout when waiting for response from mininet" )
734 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700735 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700736 if re.search( ',\s0\%\spacket\sloss', response ):
737 main.log.info( self.name + ": no packets lost, host is reachable" )
738 return main.TRUE
739 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800740 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700741 self.name +
742 ": PACKET LOST, HOST IS NOT REACHABLE" )
743 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800744 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800745 main.log.error( self.name + ": EOF exception found" )
746 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700747 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700748 except Exception:
749 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700750 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700751
752 def ping6pair( self, **pingParams ):
753 """
GlennRC2cf7d952015-09-11 16:32:13 -0700754 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700755 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000756 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700757 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
758 """
Jon Hall3b489db2015-10-05 14:38:37 -0700759 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700760 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700761 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530762 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700763 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700764 try:
765 main.log.info( "Sending: " + command )
766 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700767 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
768 timeout=wait + 1 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700769 if i == 1:
770 main.log.error(
771 self.name +
772 ": timeout when waiting for response from mininet" )
773 main.log.error( "response: " + str( self.handle.before ) )
774 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
775 if i == 1:
776 main.log.error(
777 self.name +
778 ": timeout when waiting for response from mininet" )
779 main.log.error( "response: " + str( self.handle.before ) )
780 response = self.handle.before
781 main.log.info( self.name + ": Ping Response: " + response )
782 if re.search( ',\s0\%\spacket\sloss', response ):
783 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700784 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700785 else:
alisone4121a92016-11-22 16:31:36 -0800786 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700787 self.name +
788 ": PACKET LOST, HOST IS NOT REACHABLE" )
789 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700790 except pexpect.EOF:
791 main.log.error( self.name + ": EOF exception found" )
792 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700793 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700794 except Exception:
795 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700796 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800797
You Wangdb927a52016-02-26 11:03:28 -0800798 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
799 """
800 Description:
801 Ping a set of destination host from host CLI.
802 Logging into a Mininet host CLI is required before calling this funtion.
803 Params:
804 dstIPList is a list of destination ip addresses
805 Returns:
806 main.TRUE if the destination host is reachable
807 main.FALSE otherwise
808 """
809 isReachable = main.TRUE
810 wait = int( wait )
811 cmd = "ping"
812 if IPv6:
813 cmd = cmd + "6"
814 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
815 try:
816 for dstIP in dstIPList:
817 pingCmd = cmd + " " + dstIP
818 self.handle.sendline( pingCmd )
819 i = self.handle.expect( [ self.hostPrompt,
820 '\*\*\* Unknown command: ' + pingCmd,
821 pexpect.TIMEOUT ],
822 timeout=wait + 1 )
You Wang5da39c82018-04-26 22:55:08 -0700823 # For some reason we need to send something
824 # Otherwise ping results won't be read by handle
825 self.handle.sendline( "" )
826 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800827 if i == 0:
828 response = self.handle.before
829 if not re.search( ',\s0\%\spacket\sloss', response ):
830 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
831 isReachable = main.FALSE
832 elif i == 1:
833 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700834 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800835 elif i == 2:
836 main.log.error( self.name + ": timeout when waiting for response" )
837 isReachable = main.FALSE
838 else:
839 main.log.error( self.name + ": unknown response: " + self.handle.before )
840 isReachable = main.FALSE
841 except pexpect.TIMEOUT:
842 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800843 response = self.handle.before
844 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hall2c5ac942018-03-23 11:26:54 -0700845 self.handle.send( "\x03" )
Jon Hall3c910162018-03-07 14:42:16 -0800846 self.handle.expect( "Interrupt" )
847 response += self.handle.before + self.handle.after
848 self.handle.expect( "mininet>" )
849 response += self.handle.before + self.handle.after
850 main.log.debug( response )
You Wangdb927a52016-02-26 11:03:28 -0800851 isReachable = main.FALSE
852 except pexpect.EOF:
853 main.log.error( self.name + ": EOF exception found" )
854 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700855 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800856 except Exception:
857 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700858 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800859 return isReachable
860
Jon Hall7eb38402015-01-08 17:19:54 -0800861 def checkIP( self, host ):
862 """
863 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700864 try:
865 if self.handle:
866 try:
867 response = self.execute(
868 cmd=host +
869 " ifconfig",
870 prompt="mininet>",
871 timeout=10 )
872 except pexpect.EOF:
873 main.log.error( self.name + ": EOF exception found" )
874 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700875 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700876
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700877 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
878 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
879 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
880 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
881 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
882 "[0-9]|25[0-5]|[0-9]{1,2})"
883 # pattern = "inet addr:10.0.0.6"
884 if re.search( pattern, response ):
885 main.log.info( self.name + ": Host Ip configured properly" )
886 return main.TRUE
887 else:
888 main.log.error( self.name + ": Host IP not found" )
889 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700890 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700891 main.log.error( self.name + ": Connection failed to the host" )
892 except Exception:
893 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700894 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800895
Jon Hall7eb38402015-01-08 17:19:54 -0800896 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800897 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700898 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800899 response = self.execute(
900 cmd="h1 /usr/sbin/sshd -D&",
901 prompt="mininet>",
902 timeout=10 )
903 response = self.execute(
904 cmd="h4 /usr/sbin/sshd -D&",
905 prompt="mininet>",
906 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700907 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800908 vars( self )[ key ] = connectargs[ key ]
909 response = self.execute(
910 cmd="xterm h1 h4 ",
911 prompt="mininet>",
912 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800913 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800914 main.log.error( self.name + ": EOF exception found" )
915 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700916 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700917 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800918 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700919 if self.flag == 0:
920 self.flag = 1
921 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800922 else:
adminbae64d82013-08-01 10:50:15 -0700923 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800924
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700925 def moveHost( self, host, oldSw, newSw ):
Jon Hall53c5e662016-04-13 16:06:56 -0700926 """
927 Moves a host from one switch to another on the fly
928 Note: The intf between host and oldSw when detached
929 using detach(), will still show up in the 'net'
930 cmd, because switch.detach() doesn't affect switch.intfs[]
931 ( which is correct behavior since the interfaces
932 haven't moved ).
933 """
934 if self.handle:
935 try:
936 # Bring link between oldSw-host down
937 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
938 "'," + "'down')"
939 print "cmd1= ", cmd
940 response = self.execute( cmd=cmd,
941 prompt="mininet>",
942 timeout=10 )
943
944 # Determine hostintf and Oldswitchintf
945 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
946 ")[0]"
947 print "cmd2= ", cmd
948 self.handle.sendline( cmd )
949 self.handle.expect( "mininet>" )
950
951 # Determine ip and mac address of the host-oldSw interface
952 cmd = "px ipaddr = hintf.IP()"
953 print "cmd3= ", cmd
954 self.handle.sendline( cmd )
955 self.handle.expect( "mininet>" )
956
957 cmd = "px macaddr = hintf.MAC()"
958 print "cmd3= ", cmd
959 self.handle.sendline( cmd )
960 self.handle.expect( "mininet>" )
961
962 # Detach interface between oldSw-host
963 cmd = "px " + oldSw + ".detach( sintf )"
964 print "cmd4= ", cmd
965 self.handle.sendline( cmd )
966 self.handle.expect( "mininet>" )
967
968 # Add link between host-newSw
969 cmd = "py net.addLink(" + host + "," + newSw + ")"
970 print "cmd5= ", cmd
971 self.handle.sendline( cmd )
972 self.handle.expect( "mininet>" )
973
974 # Determine hostintf and Newswitchintf
975 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
976 ")[0]"
977 print "cmd6= ", cmd
978 self.handle.sendline( cmd )
979 self.handle.expect( "mininet>" )
980
981 # Attach interface between newSw-host
982 cmd = "px " + newSw + ".attach( sintf )"
983 print "cmd3= ", cmd
984 self.handle.sendline( cmd )
985 self.handle.expect( "mininet>" )
986
987 # Set ipaddress of the host-newSw interface
988 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
989 print "cmd7 = ", cmd
990 self.handle.sendline( cmd )
991 self.handle.expect( "mininet>" )
992
993 # Set macaddress of the host-newSw interface
994 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
995 print "cmd8 = ", cmd
996 self.handle.sendline( cmd )
997 self.handle.expect( "mininet>" )
998
999 cmd = "net"
1000 print "cmd9 = ", cmd
1001 self.handle.sendline( cmd )
1002 self.handle.expect( "mininet>" )
1003 print "output = ", self.handle.before
1004
1005 # Determine ipaddress of the host-newSw interface
1006 cmd = host + " ifconfig"
1007 print "cmd10= ", cmd
1008 self.handle.sendline( cmd )
1009 self.handle.expect( "mininet>" )
1010 print "ifconfig o/p = ", self.handle.before
1011
1012 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001013
1014 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001015 main.log.error( self.name + ": TIMEOUT exception found" )
1016 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001017 main.cleanAndExit()
Jon Hall53c5e662016-04-13 16:06:56 -07001018 except pexpect.EOF:
1019 main.log.error( self.name + ": EOF exception found" )
1020 main.log.error( self.name + ": " + self.handle.before )
1021 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001022 except Exception:
1023 main.log.exception( self.name + ": Uncaught exception!" )
1024 return main.FALSE
Jon Hall53c5e662016-04-13 16:06:56 -07001025
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001026 def moveHostv6( self, host, oldSw, newSw ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001027 """
1028 Moves a host from one switch to another on the fly
1029 Note: The intf between host and oldSw when detached
1030 using detach(), will still show up in the 'net'
1031 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -07001032 ( which is correct behavior since the interfaces
1033 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -08001034 """
1035 if self.handle:
1036 try:
Jon Hall439c8912016-04-15 02:22:03 -07001037 IP = str( self.getIPAddress( host, proto='IPV6' ) ) + "/64"
kelvin-onlaba1484582015-02-02 15:46:20 -08001038 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -07001039 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -08001040 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -08001041 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -08001042 response = self.execute( cmd=cmd,
1043 prompt="mininet>",
1044 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -07001045
kelvin-onlaba1484582015-02-02 15:46:20 -08001046 # Determine hostintf and Oldswitchintf
1047 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -08001048 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -08001049 print "cmd2= ", cmd
1050 self.handle.sendline( cmd )
1051 self.handle.expect( "mininet>" )
1052
shahshreya73537862015-02-11 15:15:24 -08001053 # Determine ip and mac address of the host-oldSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001054 cmd = "px ipaddr = " + str( IP )
kelvin-onlaba1484582015-02-02 15:46:20 -08001055 print "cmd3= ", cmd
1056 self.handle.sendline( cmd )
1057 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -08001058
1059 cmd = "px macaddr = hintf.MAC()"
1060 print "cmd3= ", cmd
1061 self.handle.sendline( cmd )
1062 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001063
kelvin-onlaba1484582015-02-02 15:46:20 -08001064 # Detach interface between oldSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001065 cmd = "px " + oldSw + ".detach(sintf)"
kelvin-onlaba1484582015-02-02 15:46:20 -08001066 print "cmd4= ", cmd
1067 self.handle.sendline( cmd )
1068 self.handle.expect( "mininet>" )
1069
1070 # Add link between host-newSw
1071 cmd = "py net.addLink(" + host + "," + newSw + ")"
1072 print "cmd5= ", cmd
1073 self.handle.sendline( cmd )
1074 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001075
kelvin-onlaba1484582015-02-02 15:46:20 -08001076 # Determine hostintf and Newswitchintf
1077 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -08001078 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -08001079 print "cmd6= ", cmd
1080 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -07001081 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001082
1083 # Attach interface between newSw-host
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001084 cmd = "px " + newSw + ".attach(sintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001085 print "cmd6= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001086 self.handle.sendline( cmd )
1087 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -08001088
1089 # Set macaddress of the host-newSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001090 cmd = "px " + host + ".setMAC(mac = macaddr, intf = hintf)"
Jon Hall439c8912016-04-15 02:22:03 -07001091 print "cmd7 = ", cmd
1092 self.handle.sendline( cmd )
1093 self.handle.expect( "mininet>" )
1094
1095 # Set ipaddress of the host-newSw interface
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001096 cmd = "px " + host + ".setIP(ip = ipaddr, intf = hintf)"
shahshreya73537862015-02-11 15:15:24 -08001097 print "cmd8 = ", cmd
1098 self.handle.sendline( cmd )
1099 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -07001100
Jon Hall439c8912016-04-15 02:22:03 -07001101 cmd = host + " ifconfig"
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001102 print "cmd9 =", cmd
1103 response = self.execute( cmd = cmd, prompt="mininet>", timeout=10 )
Jon Hall439c8912016-04-15 02:22:03 -07001104 print response
1105 pattern = "h\d-eth([\w])"
Jeremyd9e4eb12016-04-13 12:09:06 -07001106 ipAddressSearch = re.search( pattern, response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001107 print ipAddressSearch.group( 1 )
1108 intf = host + "-eth" + str( ipAddressSearch.group( 1 ) )
Jon Hall439c8912016-04-15 02:22:03 -07001109 cmd = host + " ip -6 addr add %s dev %s" % ( IP, intf )
1110 print "cmd10 = ", cmd
1111 self.handle.sendline( cmd )
1112 self.handle.expect( "mininet>" )
1113
kelvin-onlaba1484582015-02-02 15:46:20 -08001114 cmd = "net"
Jon Hall439c8912016-04-15 02:22:03 -07001115 print "cmd11 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001116 self.handle.sendline( cmd )
1117 self.handle.expect( "mininet>" )
1118 print "output = ", self.handle.before
1119
1120 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -08001121 cmd = host + " ifconfig"
Jon Hall439c8912016-04-15 02:22:03 -07001122 print "cmd12= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -08001123 self.handle.sendline( cmd )
1124 self.handle.expect( "mininet>" )
1125 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -07001126
kelvin-onlaba1484582015-02-02 15:46:20 -08001127 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001128 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001129 main.log.error( self.name + ": TIMEOUT exception found" )
1130 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001131 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08001132 except pexpect.EOF:
1133 main.log.error( self.name + ": EOF exception found" )
1134 main.log.error( self.name + ": " + self.handle.before )
1135 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001136 except Exception:
1137 main.log.exception( self.name + ": Uncaught exception!" )
1138 return main.FALSE
kelvin-onlaba1484582015-02-02 15:46:20 -08001139
Jon Hall7eb38402015-01-08 17:19:54 -08001140 def changeIP( self, host, intf, newIP, newNetmask ):
1141 """
1142 Changes the ip address of a host on the fly
1143 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001144 if self.handle:
1145 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001146 cmd = host + " ifconfig " + intf + " " + \
1147 newIP + " " + 'netmask' + " " + newNetmask
1148 self.handle.sendline( cmd )
1149 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001150 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001151 main.log.info( "response = " + response )
1152 main.log.info(
1153 "Ip of host " +
1154 host +
1155 " changed to new IP " +
1156 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -08001157 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001158 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001159 main.log.error( self.name + ": TIMEOUT exception found" )
1160 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001161 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001162 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001163 main.log.error( self.name + ": EOF exception found" )
1164 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001165 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001166 except Exception:
1167 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001168 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001169
Jon Hall7eb38402015-01-08 17:19:54 -08001170 def changeDefaultGateway( self, host, newGW ):
1171 """
1172 Changes the default gateway of a host
1173 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -08001174 if self.handle:
1175 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001176 cmd = host + " route add default gw " + newGW
1177 self.handle.sendline( cmd )
1178 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -08001179 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001180 main.log.info( "response = " + response )
1181 main.log.info(
1182 "Default gateway of host " +
1183 host +
1184 " changed to " +
1185 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -08001186 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001187 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001188 main.log.error( self.name + ": TIMEOUT exception found" )
1189 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001190 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001191 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001192 main.log.error( self.name + ": EOF exception found" )
1193 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001194 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001195 except Exception:
1196 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001197 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001198
You Wange24d6272018-03-27 21:18:50 -07001199 def addRoute( self, host, dstIP, interface, ipv6=False ):
1200 """
1201 Add a route to host
1202 Ex: h1 route add -host 224.2.0.1 h1-eth0
1203 """
1204 if self.handle:
1205 try:
1206 cmd = str( host )
1207 if ipv6:
1208 cmd += " route -A inet6 add "
1209 else:
1210 cmd += " route add -host "
1211 cmd += str( dstIP ) + " " + str( interface )
1212 self.handle.sendline( cmd )
1213 self.handle.expect( "mininet>" )
1214 response = self.handle.before
1215 main.log.debug( "response = " + response )
1216 return main.TRUE
1217 except pexpect.TIMEOUT:
1218 main.log.error( self.name + ": TIMEOUT exception found" )
1219 main.log.error( self.name + ": " + self.handle.before )
1220 main.cleanAndExit()
1221 except pexpect.EOF:
1222 main.log.error( self.name + ": EOF exception found" )
1223 main.log.error( self.name + ": " + self.handle.before )
1224 return main.FALSE
1225 except Exception:
1226 main.log.exception( self.name + ": Uncaught exception!" )
1227 main.cleanAndExit()
1228
Jon Hall7eb38402015-01-08 17:19:54 -08001229 def addStaticMACAddress( self, host, GW, macaddr ):
1230 """
Jon Hallefbd9792015-03-05 16:11:36 -08001231 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001232 if self.handle:
1233 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001234 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1235 cmd = host + " arp -s " + GW + " " + macaddr
1236 self.handle.sendline( cmd )
1237 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001238 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001239 main.log.info( "response = " + response )
1240 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001241 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001242 GW +
1243 " changed to " +
1244 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001245 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001246 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001247 main.log.error( self.name + ": TIMEOUT exception found" )
1248 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001249 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001250 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001251 main.log.error( self.name + ": EOF exception found" )
1252 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001253 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001254 except Exception:
1255 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001256 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001257
Jon Hall7eb38402015-01-08 17:19:54 -08001258 def verifyStaticGWandMAC( self, host ):
1259 """
1260 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001261 if self.handle:
1262 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001263 # h1 arp -an
1264 cmd = host + " arp -an "
1265 self.handle.sendline( cmd )
1266 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001267 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001268 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001269 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001270 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001271 main.log.error( self.name + ": TIMEOUT exception found" )
1272 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001273 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001274 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001275 main.log.error( self.name + ": EOF exception found" )
1276 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001277 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001278 except Exception:
1279 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001280 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001281
Jon Hall7eb38402015-01-08 17:19:54 -08001282 def getMacAddress( self, host ):
1283 """
1284 Verifies the host's ip configured or not."""
1285 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001286 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001287 response = self.execute(
1288 cmd=host +
1289 " ifconfig",
1290 prompt="mininet>",
1291 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001292 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001293 main.log.error( self.name + ": EOF exception found" )
1294 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001295 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001296 except Exception:
1297 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001298 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001299
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001300 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001301 macAddressSearch = re.search( pattern, response, re.I )
1302 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001303 main.log.info(
1304 self.name +
1305 ": Mac-Address of Host " +
1306 host +
1307 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001308 macAddress )
1309 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001310 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001311 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001312
Jon Hall7eb38402015-01-08 17:19:54 -08001313 def getInterfaceMACAddress( self, host, interface ):
1314 """
1315 Return the IP address of the interface on the given host"""
1316 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001317 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001318 response = self.execute( cmd=host + " ifconfig " + interface,
1319 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001320 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001321 main.log.error( self.name + ": EOF exception found" )
1322 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001323 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001324 except Exception:
1325 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001326 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001327
1328 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001329 macAddressSearch = re.search( pattern, response, re.I )
1330 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001331 main.log.info( "No mac address found in %s" % response )
1332 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001333 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001334 main.log.info(
1335 "Mac-Address of " +
1336 host +
1337 ":" +
1338 interface +
1339 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001340 macAddress )
1341 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001342 else:
1343 main.log.error( "Connection failed to the host" )
1344
You Wang5da39c82018-04-26 22:55:08 -07001345 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001346 """
1347 Verifies the host's ip configured or not."""
1348 if self.handle:
1349 try:
1350 response = self.execute(
1351 cmd=host +
1352 " ifconfig",
1353 prompt="mininet>",
1354 timeout=10 )
1355 except pexpect.EOF:
1356 main.log.error( self.name + ": EOF exception found" )
1357 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001358 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001359 except Exception:
1360 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001361 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001362
sathishmad953462015-12-03 17:42:07 +05301363 pattern = ''
1364 if proto == 'IPV4':
You Wang5da39c82018-04-26 22:55:08 -07001365 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
sathishmad953462015-12-03 17:42:07 +05301366 else:
Jon Hall439c8912016-04-15 02:22:03 -07001367 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001368 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001369 if not ipAddressSearch:
1370 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001371 main.log.info(
1372 self.name +
1373 ": IP-Address of Host " +
1374 host +
1375 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001376 ipAddressSearch.group( 1 ) )
1377 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001378 else:
1379 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001380
Jon Hall7eb38402015-01-08 17:19:54 -08001381 def getSwitchDPID( self, switch ):
1382 """
1383 return the datapath ID of the switch"""
1384 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001385 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001386 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001387 response = self.execute(
1388 cmd=cmd,
1389 prompt="mininet>",
1390 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001391 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001392 main.log.error( self.name + ": EOF exception found" )
1393 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001394 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001395 except Exception:
1396 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001397 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001398 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001399 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001400 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001401 main.log.info(
1402 "Couldn't find DPID for switch %s, found: %s" %
1403 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001404 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001405 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001406 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001407 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001408
Jon Hall7eb38402015-01-08 17:19:54 -08001409 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001410 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001411 self.handle.sendline( "" )
1412 self.expect( "mininet>" )
1413 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001414 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001415 response = self.execute(
1416 cmd=cmd,
1417 prompt="mininet>",
1418 timeout=10 )
1419 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001420 response = self.handle.before
1421 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001422 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001423 main.log.error( self.name + ": TIMEOUT exception found" )
1424 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001425 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001426 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001427 main.log.error( self.name + ": EOF exception found" )
1428 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001429 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001430 except Exception:
1431 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001432 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001433
Jon Hall7eb38402015-01-08 17:19:54 -08001434 def getInterfaces( self, node ):
1435 """
1436 return information dict about interfaces connected to the node"""
1437 if self.handle:
1438 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001439 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001440 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001441 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001442 response = self.execute(
1443 cmd=cmd,
1444 prompt="mininet>",
1445 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001446 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001447 main.log.error( self.name + ": EOF exception found" )
1448 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001449 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001450 except Exception:
1451 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001452 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001453 return response
1454 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001455 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001456
Jon Hall7eb38402015-01-08 17:19:54 -08001457 def dump( self ):
1458 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001459 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001460 response = self.execute(
1461 cmd='dump',
1462 prompt='mininet>',
1463 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001464 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001465 main.log.error( self.name + ": EOF exception found" )
1466 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001467 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001468 except Exception:
1469 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001470 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001471 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001472
Jon Hall7eb38402015-01-08 17:19:54 -08001473 def intfs( self ):
1474 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001475 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001476 response = self.execute(
1477 cmd='intfs',
1478 prompt='mininet>',
1479 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001480 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001481 main.log.error( self.name + ": EOF exception found" )
1482 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001483 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001484 except Exception:
1485 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001486 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001487 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001488
Jon Hall7eb38402015-01-08 17:19:54 -08001489 def net( self ):
1490 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001491 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001492 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001493 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001494 main.log.error( self.name + ": EOF exception found" )
1495 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001496 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001497 except Exception:
1498 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001499 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001500 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001501
Devin Lima7cfdbd2017-09-29 15:02:22 -07001502 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001503 main.log.info( self.name + ": List network links" )
1504 try:
1505 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001506 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001507 except pexpect.EOF:
1508 main.log.error( self.name + ": EOF exception found" )
1509 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001510 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001511 except Exception:
1512 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001513 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001514 return response
1515
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001516 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001517 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001518 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001519
kelvin-onlab7cce9382015-07-17 10:21:03 -07001520 @parm:
1521 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1522 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001523 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001524 try:
1525 for host1 in hosts:
1526 for host2 in hosts:
1527 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001528 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1529 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001530 except Exception:
1531 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001532 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001533
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001534 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001535 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001536 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1537 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001538
kelvin-onlab7cce9382015-07-17 10:21:03 -07001539 @parm:
1540 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1541 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001542 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001543 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1544 try:
1545 # Setup the mininet command
1546 cmd1 = 'iperf ' + host1 + " " + host2
1547 self.handle.sendline( cmd1 )
1548 outcome = self.handle.expect( "mininet>", timeout )
1549 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001550
kelvin-onlab7cce9382015-07-17 10:21:03 -07001551 # checks if there are results in the mininet response
1552 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001553 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001554 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001555 response = response.split( "\r\n" )
1556 response = response[ len( response )-2 ]
1557 response = response.split( ": " )
1558 response = response[ len( response )-1 ]
1559 response = response.replace( "[", "" )
1560 response = response.replace( "]", "" )
1561 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001562
kelvin-onlab7cce9382015-07-17 10:21:03 -07001563 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001564 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001565
kelvin-onlab7cce9382015-07-17 10:21:03 -07001566 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001567 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001568 if len( bandwidth ) == 2:
1569 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001570 return main.TRUE
1571 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001572 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001573 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001574 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001575 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001576 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001577 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001578 main.log.error( self.name + ": TIMEOUT exception found" )
1579 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001580 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001581 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hall2c5ac942018-03-23 11:26:54 -07001582 self.handle.send( "\x03" )
Jon Hall3b489db2015-10-05 14:38:37 -07001583 self.handle.expect( "Interrupt" )
1584 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001585 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001586 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001587 main.log.error( self.name + ": EOF exception found" )
1588 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001589 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001590 except Exception:
1591 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001592 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001593
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001594 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001595 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1596 try:
1597 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001598 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001599 self.handle.sendline( cmd1 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001600 outcome1 = self.handle.expect( "mininet>" )
1601 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001602 self.handle.sendline( cmd2 )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001603 outcome2 = self.handle.expect( "mininet>" )
Jon Hall439c8912016-04-15 02:22:03 -07001604 response1 = self.handle.before
1605 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001606 print response1, response2
1607 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001608 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001609 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001610 return main.TRUE
1611 else:
1612 main.log.error( self.name + ": iperf test failed" )
1613 return main.FALSE
1614 except pexpect.TIMEOUT:
1615 main.log.error( self.name + ": TIMEOUT exception found" )
1616 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hall2c5ac942018-03-23 11:26:54 -07001617 self.handle.send( "\x03" )
Jon Hall439c8912016-04-15 02:22:03 -07001618 self.handle.expect( "Interrupt" )
1619 self.handle.expect( "mininet>" )
1620 return main.FALSE
1621 except pexpect.EOF:
1622 main.log.error( self.name + ": EOF exception found" )
1623 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001624 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001625 except Exception:
1626 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001627 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001628
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001629 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001630 '''
GlennRC61321f22015-07-16 13:36:54 -07001631 Runs the iperfudp function with a given set of hosts and specified
1632 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001633
GlennRC61321f22015-07-16 13:36:54 -07001634 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001635 bandwidth: the targeted bandwidth, in megabits ('M')
1636 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001637 try:
1638 for host1 in hosts:
1639 for host2 in hosts:
1640 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001641 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1642 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001643 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001644 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001645 return main.FALSE
1646 except Exception:
1647 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001648 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001649
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001650 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001651 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001652 Creates an iperf UDP test with a specific bandwidth.
1653 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001654
kelvin-onlab7cce9382015-07-17 10:21:03 -07001655 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001656 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1657 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001658 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001659 try:
1660 # setup the mininet command
1661 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001662 self.handle.sendline( cmd )
1663 self.handle.expect( "mininet>" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001664 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001665
kelvin-onlab7cce9382015-07-17 10:21:03 -07001666 # check if there are in results in the mininet response
1667 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001668 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001669 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001670 response = response.split( "\r\n" )
1671 response = response[ len( response )-2 ]
1672 response = response.split( ": " )
1673 response = response[ len( response )-1 ]
1674 response = response.replace( "[", "" )
1675 response = response.replace( "]", "" )
1676 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001677
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001678 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001679
kelvin-onlab7cce9382015-07-17 10:21:03 -07001680 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001681 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001682 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001683 # if one entry is blank then something is wrong
1684 for item in mnBandwidth:
1685 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001686 main.log.error( self.name + ": Could not parse iperf output" )
1687 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001688 return main.FALSE
1689 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001690 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001691 return main.TRUE
1692 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001693 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001694 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001695
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001696 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001697 main.log.error( self.name + ": TIMEOUT exception found" )
1698 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001699 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001700 except pexpect.EOF:
1701 main.log.error( self.name + ": EOF exception found" )
1702 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001703 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001704 except Exception:
1705 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001706 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001707
Jon Hall7eb38402015-01-08 17:19:54 -08001708 def nodes( self ):
1709 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001710 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001711 response = self.execute(
1712 cmd='nodes',
1713 prompt='mininet>',
1714 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001715 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001716 main.log.error( self.name + ": EOF exception found" )
1717 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001718 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001719 except Exception:
1720 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001721 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001722 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001723
Jon Hall7eb38402015-01-08 17:19:54 -08001724 def pingpair( self ):
1725 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001726 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001727 response = self.execute(
1728 cmd='pingpair',
1729 prompt='mininet>',
1730 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001731 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001732 main.log.error( self.name + ": EOF exception found" )
1733 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001734 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001735 except Exception:
1736 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001737 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001738
Jon Hall7eb38402015-01-08 17:19:54 -08001739 if re.search( ',\s0\%\spacket\sloss', response ):
1740 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001741 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001742 else:
alisone4121a92016-11-22 16:31:36 -08001743 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001744 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001745
Jon Hall7eb38402015-01-08 17:19:54 -08001746 def link( self, **linkargs ):
1747 """
GlennRCed771242016-01-13 17:02:47 -08001748 Bring link( s ) between two nodes up or down
1749 """
Jon Hall6094a362014-04-11 14:46:56 -07001750 try:
GlennRCed771242016-01-13 17:02:47 -08001751 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1752 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1753 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1754 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1755
1756 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1757 cmd = "link {} {} {}".format( end1, end2, option )
1758 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001759 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001760 response = self.handle.before
1761 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001762 if "not in network" in response:
1763 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1764 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001765 return main.TRUE
1766 except pexpect.TIMEOUT:
1767 main.log.exception( self.name + ": Command timed out" )
1768 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001769 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001770 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001771 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001772 except Exception:
1773 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001774 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001775
pingping-lin8244a3b2015-09-16 13:36:56 -07001776 def switch( self, **switchargs ):
1777 """
1778 start/stop a switch
1779 """
1780 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1781 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1782 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1783 command = "switch " + str( sw ) + " " + str( option )
1784 main.log.info( command )
1785 try:
1786 self.handle.sendline( command )
1787 self.handle.expect( "mininet>" )
1788 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001789 main.log.error( self.name + ": TIMEOUT exception found" )
1790 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001791 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001792 except pexpect.EOF:
1793 main.log.error( self.name + ": EOF exception found" )
1794 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001795 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001796 return main.TRUE
1797
pingping-lin5bb663b2015-09-24 11:47:50 -07001798 def node( self, nodeName, commandStr ):
1799 """
1800 Carry out a command line on a given node
1801 @parm:
1802 nodeName: the node name in Mininet testbed
1803 commandStr: the command line will be carried out on the node
1804 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1805 """
1806 command = str( nodeName ) + " " + str( commandStr )
1807 main.log.info( command )
1808
1809 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001810 response = self.execute( cmd = command, prompt = "mininet>" )
pingping-lin5bb663b2015-09-24 11:47:50 -07001811 if re.search( "Unknown command", response ):
1812 main.log.warn( response )
1813 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001814 if re.search( "Permission denied", response ):
1815 main.log.warn( response )
1816 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001817 except pexpect.EOF:
1818 main.log.error( self.name + ": EOF exception found" )
1819 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001820 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001821 main.log.info( " response is :" )
1822 main.log.info( response )
1823 return response
1824
Jon Hall7eb38402015-01-08 17:19:54 -08001825 def yank( self, **yankargs ):
1826 """
1827 yank a mininet switch interface to a host"""
1828 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001829 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001830 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1831 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001832 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001833 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001834 response = self.execute(
1835 cmd=command,
1836 prompt="mininet>",
1837 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001838 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001839 main.log.error( self.name + ": EOF exception found" )
1840 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001841 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001842 except Exception:
1843 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001844 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001845 return main.TRUE
1846
Jon Hall7eb38402015-01-08 17:19:54 -08001847 def plug( self, **plugargs ):
1848 """
1849 plug the yanked mininet switch interface to a switch"""
1850 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001851 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001852 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1853 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001854 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001855 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001856 response = self.execute(
1857 cmd=command,
1858 prompt="mininet>",
1859 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001860 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001861 main.log.error( self.name + ": EOF exception found" )
1862 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001863 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001864 except Exception:
1865 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001866 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001867 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001868
Jon Hall7eb38402015-01-08 17:19:54 -08001869 def dpctl( self, **dpctlargs ):
1870 """
1871 Run dpctl command on all switches."""
1872 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001873 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001874 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1875 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1876 command = "dpctl " + cmd + " " + str( cmdargs )
1877 try:
1878 response = self.execute(
1879 cmd=command,
1880 prompt="mininet>",
1881 timeout=10 )
1882 except pexpect.EOF:
1883 main.log.error( self.name + ": EOF exception found" )
1884 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001885 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001886 except Exception:
1887 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001888 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001889 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001890
kelvin-onlabd3b64892015-01-20 13:26:24 -08001891 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001892 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001893 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001894 try:
1895 fileInput = path + '/lib/Mininet/INSTALL'
1896 version = super( Mininet, self ).getVersion()
1897 pattern = 'Mininet\s\w\.\w\.\w\w*'
1898 for line in open( fileInput, 'r' ).readlines():
1899 result = re.match( pattern, line )
1900 if result:
1901 version = result.group( 0 )
1902 return version
1903 except Exception:
1904 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001905 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001906
kelvin-onlabd3b64892015-01-20 13:26:24 -08001907 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001908 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001909 Parameters:
1910 sw: The name of an OVS switch. Example "s1"
1911 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001912 The output of the command from the mininet cli
1913 or main.FALSE on timeout"""
1914 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001915 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001916 response = self.execute(
1917 cmd=command,
1918 prompt="mininet>",
1919 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001920 if response:
Jon Hallab611372018-02-21 15:26:05 -08001921 if "no bridge named" in response:
1922 main.log.error( self.name + ": Error in getSwController: " +
1923 self.handle.before )
1924 return main.FALSE
1925 else:
1926 return response
admin2a9548d2014-06-17 14:08:07 -07001927 else:
1928 return main.FALSE
1929 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001930 main.log.error( self.name + ": EOF exception found" )
1931 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001932 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001933 except Exception:
1934 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001935 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001936
Charles Chan029be652015-08-24 01:46:10 +08001937 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001938 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001939 Description:
1940 Assign switches to the controllers ( for ovs use only )
1941 Required:
1942 sw - Name of the switch. This can be a list or a string.
1943 ip - Ip addresses of controllers. This can be a list or a string.
1944 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001945 port - ONOS use port 6653, if no list of ports is passed, then
1946 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001947 ptcp - ptcp number, This can be a string or a list that has
1948 the same length as switch. This is optional and not required
1949 when using ovs switches.
1950 NOTE: If switches and ptcp are given in a list type they should have the
1951 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1952 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001953
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001954 Return:
1955 Returns main.TRUE if mininet correctly assigned switches to
1956 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001957 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001958 """
1959 assignResult = main.TRUE
1960 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001961 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001962 command = "sh ovs-vsctl set-controller "
1963 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001964 try:
1965 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001966 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001967 if isinstance( port, types.StringType ) or \
1968 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001969 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001970 elif isinstance( port, types.ListType ):
1971 main.log.error( self.name + ": Only one controller " +
1972 "assigned and a list of ports has" +
1973 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001974 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001975 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001976 main.log.error( self.name + ": Invalid controller port " +
1977 "number. Please specify correct " +
1978 "controller port" )
1979 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001980
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001981 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001982 if isinstance( port, types.StringType ) or \
1983 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001984 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001985 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1986 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001987 elif isinstance( port, types.ListType ):
1988 if ( len( ip ) != len( port ) ):
1989 main.log.error( self.name + ": Port list = " +
1990 str( len( port ) ) +
1991 "should be the same as controller" +
1992 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001993 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001994 else:
1995 onosIp = ""
1996 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001997 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1998 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001999 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002000 main.log.error( self.name + ": Invalid controller port " +
2001 "number. Please specify correct " +
2002 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002003 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07002004 else:
2005 main.log.error( self.name + ": Invalid ip address" )
2006 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002007
2008 if isinstance( sw, types.StringType ):
2009 command += sw + " "
2010 if ptcp:
2011 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07002012 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002013 elif isinstance( ptcp, types.ListType ):
2014 main.log.error( self.name + ": Only one switch is " +
2015 "being set and multiple PTCP is " +
2016 "being passed " )
2017 else:
2018 main.log.error( self.name + ": Invalid PTCP" )
2019 ptcp = ""
2020 command += onosIp
2021 commandList.append( command )
2022
2023 elif isinstance( sw, types.ListType ):
2024 if ptcp:
2025 if isinstance( ptcp, types.ListType ):
2026 if len( ptcp ) != len( sw ):
2027 main.log.error( self.name + ": PTCP length = " +
2028 str( len( ptcp ) ) +
2029 " is not the same as switch" +
2030 " length = " +
2031 str( len( sw ) ) )
2032 return main.FALSE
2033 else:
2034 for switch, ptcpNum in zip( sw, ptcp ):
2035 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07002036 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07002037 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002038 tempCmd += onosIp
2039 commandList.append( tempCmd )
2040 else:
2041 main.log.error( self.name + ": Invalid PTCP" )
2042 return main.FALSE
2043 else:
2044 for switch in sw:
2045 tempCmd = "sh ovs-vsctl set-controller "
2046 tempCmd += switch + " " + onosIp
2047 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002048 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002049 main.log.error( self.name + ": Invalid switch type " )
2050 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002051
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002052 for cmd in commandList:
2053 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002054 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08002055 if "no bridge named" in self.handle.before:
2056 main.log.error( self.name + ": Error in assignSwController: " +
2057 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002058 except pexpect.TIMEOUT:
2059 main.log.error( self.name + ": pexpect.TIMEOUT found" )
2060 return main.FALSE
2061 except pexpect.EOF:
2062 main.log.error( self.name + ": EOF exception found" )
2063 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002064 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002065 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002066 except pexpect.EOF:
2067 main.log.error( self.name + ": EOF exception found" )
2068 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002069 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07002070 except Exception:
2071 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002072 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07002073
kelvin-onlabd3b64892015-01-20 13:26:24 -08002074 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08002075 """
2076 Removes the controller target from sw"""
2077 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07002078 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002079 response = self.execute(
2080 cmd=command,
2081 prompt="mininet>",
2082 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08002083 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002084 main.log.error( self.name + ": EOF exception found" )
2085 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002086 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002087 except Exception:
2088 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002089 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002090 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002091 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07002092
kelvin-onlabd3b64892015-01-20 13:26:24 -08002093 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002094 """
Jon Hallb1290e82014-11-18 16:17:48 -05002095 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002096 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002097 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002098 NOTE: cannot currently specify what type of switch
2099 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08002100 sw = name of the new switch as a string
2101 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05002102 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08002103 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002104 """
2105 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002106 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05002107 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002108 response = self.execute(
2109 cmd=command,
2110 prompt="mininet>",
2111 timeout=10 )
2112 if re.search( "already exists!", response ):
2113 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002114 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002115 elif re.search( "Error", response ):
2116 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002117 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002118 elif re.search( "usage:", response ):
2119 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002120 return main.FALSE
2121 else:
2122 return main.TRUE
2123 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002124 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07002125 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002126 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002127 except Exception:
2128 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002129 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002130
kelvin-onlabd3b64892015-01-20 13:26:24 -08002131 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08002132 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08002133 delete a switch from the mininet topology
2134 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002135 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08002136 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08002137 sw = name of the switch as a string
2138 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002139 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05002140 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002141 response = self.execute(
2142 cmd=command,
2143 prompt="mininet>",
2144 timeout=10 )
2145 if re.search( "no switch named", response ):
2146 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002147 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002148 elif re.search( "Error", response ):
2149 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002150 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002151 elif re.search( "usage:", response ):
2152 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002153 return main.FALSE
2154 else:
2155 return main.TRUE
2156 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002157 main.log.error( self.name + ": EOF exception found" )
2158 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002159 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002160 except Exception:
2161 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002162 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002163
You Wangdb8cd0a2016-05-26 15:19:45 -07002164 def getSwitchRandom( self, timeout=60, nonCut=True ):
2165 """
2166 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002167 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002168 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002169 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002170 it just randomly returns one switch from all current switches in
2171 Mininet.
2172 Returns the name of the chosen switch.
2173 """
2174 import random
2175 candidateSwitches = []
2176 try:
2177 if not nonCut:
2178 switches = self.getSwitches( timeout=timeout )
2179 assert len( switches ) != 0
2180 for switchName in switches.keys():
2181 candidateSwitches.append( switchName )
2182 else:
2183 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002184 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002185 return None
2186 self.graph.update( graphDict )
2187 candidateSwitches = self.graph.getNonCutVertices()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002188 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002189 return None
2190 elif len( candidateSwitches ) == 0:
2191 main.log.info( self.name + ": No candidate switch for deletion" )
2192 return None
2193 else:
2194 switch = random.sample( candidateSwitches, 1 )
2195 return switch[ 0 ]
2196 except KeyError:
2197 main.log.exception( self.name + ": KeyError exception found" )
2198 return None
2199 except AssertionError:
2200 main.log.exception( self.name + ": AssertionError exception found" )
2201 return None
2202 except Exception:
2203 main.log.exception( self.name + ": Uncaught exception" )
2204 return None
2205
2206 def delSwitchRandom( self, timeout=60, nonCut=True ):
2207 """
2208 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002209 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002210 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002211 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002212 otherwise it just randomly delete one switch from all current
2213 switches in Mininet.
2214 Returns the name of the deleted switch
2215 """
2216 try:
2217 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002218 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002219 return None
2220 else:
2221 deletionResult = self.delSwitch( switch )
2222 if deletionResult:
2223 return switch
2224 else:
2225 return None
2226 except Exception:
2227 main.log.exception( self.name + ": Uncaught exception" )
2228 return None
2229
kelvin-onlabd3b64892015-01-20 13:26:24 -08002230 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002231 """
2232 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002233 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002234 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002235 NOTE: cannot currently specify what type of link
2236 required params:
2237 node1 = the string node name of the first endpoint of the link
2238 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002239 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002240 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002241 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002242 response = self.execute(
2243 cmd=command,
2244 prompt="mininet>",
2245 timeout=10 )
2246 if re.search( "doesnt exist!", response ):
2247 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002248 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002249 elif re.search( "Error", response ):
2250 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002251 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002252 elif re.search( "usage:", response ):
2253 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002254 return main.FALSE
2255 else:
2256 return main.TRUE
2257 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002258 main.log.error( self.name + ": EOF exception found" )
2259 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002260 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002261 except Exception:
2262 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002263 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002264
kelvin-onlabd3b64892015-01-20 13:26:24 -08002265 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002266 """
2267 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002268 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002269 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002270 required params:
2271 node1 = the string node name of the first endpoint of the link
2272 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002273 returns: main.FALSE on an error, else main.TRUE
2274 """
Jon Hallffb386d2014-11-21 13:43:38 -08002275 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002276 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002277 response = self.execute(
2278 cmd=command,
2279 prompt="mininet>",
2280 timeout=10 )
2281 if re.search( "no node named", response ):
2282 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002283 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002284 elif re.search( "Error", response ):
2285 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002286 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002287 elif re.search( "usage:", response ):
2288 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002289 return main.FALSE
2290 else:
2291 return main.TRUE
2292 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002293 main.log.error( self.name + ": EOF exception found" )
2294 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002295 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002296 except Exception:
2297 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002298 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002299
You Wangdb8cd0a2016-05-26 15:19:45 -07002300 def getLinkRandom( self, timeout=60, nonCut=True ):
2301 """
2302 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002303 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002304 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002305 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002306 it just randomly returns one link from all current links in
2307 Mininet.
2308 Returns the link as a list, e.g. [ 's1', 's2' ]
2309 """
2310 import random
2311 candidateLinks = []
2312 try:
2313 if not nonCut:
2314 links = self.getLinks( timeout=timeout )
2315 assert len( links ) != 0
2316 for link in links:
2317 # Exclude host-switch link
2318 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2319 continue
2320 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2321 else:
2322 graphDict = self.getGraphDict( timeout=timeout, useId=False )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002323 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002324 return None
2325 self.graph.update( graphDict )
2326 candidateLinks = self.graph.getNonCutEdges()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002327 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002328 return None
2329 elif len( candidateLinks ) == 0:
2330 main.log.info( self.name + ": No candidate link for deletion" )
2331 return None
2332 else:
2333 link = random.sample( candidateLinks, 1 )
2334 return link[ 0 ]
2335 except KeyError:
2336 main.log.exception( self.name + ": KeyError exception found" )
2337 return None
2338 except AssertionError:
2339 main.log.exception( self.name + ": AssertionError exception found" )
2340 return None
2341 except Exception:
2342 main.log.exception( self.name + ": Uncaught exception" )
2343 return None
2344
2345 def delLinkRandom( self, timeout=60, nonCut=True ):
2346 """
2347 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002348 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002349 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002350 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002351 otherwise it just randomly delete one link from all current links
2352 in Mininet.
2353 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2354 """
2355 try:
2356 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002357 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002358 return None
2359 else:
2360 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2361 if deletionResult:
2362 return link
2363 else:
2364 return None
2365 except Exception:
2366 main.log.exception( self.name + ": Uncaught exception" )
2367 return None
2368
kelvin-onlabd3b64892015-01-20 13:26:24 -08002369 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002370 """
Jon Hallb1290e82014-11-18 16:17:48 -05002371 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002372 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002373 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002374 NOTE: cannot currently specify what type of host
2375 required params:
2376 hostname = the string hostname
2377 optional key-value params
2378 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002379 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002380 """
2381 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002382 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002383 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002384 response = self.execute(
2385 cmd=command,
2386 prompt="mininet>",
2387 timeout=10 )
2388 if re.search( "already exists!", response ):
2389 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002390 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002391 elif re.search( "doesnt exists!", response ):
2392 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002393 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002394 elif re.search( "Error", response ):
2395 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002396 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002397 elif re.search( "usage:", response ):
2398 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002399 return main.FALSE
2400 else:
2401 return main.TRUE
2402 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002403 main.log.error( self.name + ": EOF exception found" )
2404 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002405 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002406 except Exception:
2407 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002408 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002409
kelvin-onlabd3b64892015-01-20 13:26:24 -08002410 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002411 """
2412 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002413 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002414 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002415 NOTE: this uses a custom mn function
2416 required params:
2417 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002418 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002419 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002420 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002421 response = self.execute(
2422 cmd=command,
2423 prompt="mininet>",
2424 timeout=10 )
2425 if re.search( "no host named", response ):
2426 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002427 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002428 elif re.search( "Error", response ):
2429 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002430 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002431 elif re.search( "usage:", response ):
2432 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002433 return main.FALSE
2434 else:
2435 return main.TRUE
2436 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002437 main.log.error( self.name + ": EOF exception found" )
2438 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002439 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002440 except Exception:
2441 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002442 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002443
Jon Hall7eb38402015-01-08 17:19:54 -08002444 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002445 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002446 Called at the end of the test to stop the mininet and
2447 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002448 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002449 try:
2450 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002451 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002452 timeout=2 )
2453 response = main.TRUE
2454 if i == 0:
2455 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002456 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002457 return main.TRUE
2458 # print "Disconnecting Mininet"
2459 if self.handle:
2460 self.handle.sendline( "exit" )
2461 self.handle.expect( "exit" )
2462 self.handle.expect( "(.*)" )
2463 else:
2464 main.log.error( "Connection failed to the host" )
2465 return response
2466 except pexpect.EOF:
2467 main.log.error( self.name + ": EOF exception found" )
2468 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002469 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002470 except Exception:
2471 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002472 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002473
Devin Lima7cfdbd2017-09-29 15:02:22 -07002474 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002475 """
Jon Hall21270ac2015-02-16 17:59:55 -08002476 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002477 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002478 main.FALSE if the pexpect handle does not exist.
2479
Jon Halld61331b2015-02-17 16:35:47 -08002480 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002481 """
Jon Halld61331b2015-02-17 16:35:47 -08002482 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002483 response = ''
2484 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002485 try:
Jon Halld80cc142015-07-06 13:36:05 -07002486 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002487 i = self.handle.expect( [ 'mininet>',
Devin Limdc78e202017-06-09 18:30:07 -07002488 self.prompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002489 pexpect.EOF,
2490 pexpect.TIMEOUT ],
2491 timeout )
2492 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002493 main.log.info( "Exiting mininet.." )
2494 startTime = time.time()
Jeremyd9e4eb12016-04-13 12:09:06 -07002495 response = self.execute( cmd="exit",
Devin Lima7cfdbd2017-09-29 15:02:22 -07002496 prompt=self.prompt,
2497 timeout=exitTimeout )
2498 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jeremyd9e4eb12016-04-13 12:09:06 -07002499 self.handle.sendline( "sudo mn -c" )
2500 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002501
Jeremyd9e4eb12016-04-13 12:09:06 -07002502 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002503 main.log.info( " Mininet trying to exit while not " +
2504 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002505 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002506 elif i == 2:
2507 main.log.error( "Something went wrong exiting mininet" )
2508 elif i == 3: # timeout
2509 main.log.error( "Something went wrong exiting mininet " +
2510 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002511
You Wang18db8592018-04-02 13:52:03 -07002512 self.handle.sendline( "" )
2513 self.handle.expect( self.prompt )
2514 self.handle.sendline( "sudo killall -9 dhclient dhcpd zebra bgpd" )
2515
Hari Krishnab35c6d02015-03-18 11:13:51 -07002516 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002517 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002518 self.handle.expect( self.prompt )
Jon Halld80cc142015-07-06 13:36:05 -07002519 self.handle.sendline(
2520 "sudo kill -9 \`ps -ef | grep \"" +
2521 fileName +
2522 "\" | grep -v grep | awk '{print $2}'\`" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002523 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002524 main.log.error( self.name + ": TIMEOUT exception found" )
2525 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002526 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002527 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002528 main.log.error( self.name + ": EOF exception found" )
2529 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002530 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002531 except Exception:
2532 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002533 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002534 else:
2535 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002536 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002537 return response
2538
YPZhang26a139e2016-04-25 14:01:55 -07002539 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002540 """
2541 Description:
2542 Sends arp message from mininet host for hosts discovery
2543 Required:
2544 host - hosts name
2545 Optional:
2546 ip - ip address that does not exist in the network so there would
2547 be no reply.
2548 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002549 if ethDevice:
2550 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002551 cmd = srcHost + " arping -c1 "
2552 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002553 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 -07002554 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002555 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002556 if output:
2557 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002558 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002559 i = self.handle.expect( [ "mininet>", "arping: " ] )
2560 if i == 0:
2561 return main.TRUE
2562 elif i == 1:
2563 response = self.handle.before + self.handle.after
2564 self.handle.expect( "mininet>" )
2565 response += self.handle.before + self.handle.after
2566 main.log.warn( "Error sending arping, output was: " +
2567 response )
2568 return main.FALSE
2569 except pexpect.TIMEOUT:
2570 main.log.error( self.name + ": TIMEOUT exception found" )
2571 main.log.warn( self.handle.before )
2572 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002573 except pexpect.EOF:
2574 main.log.error( self.name + ": EOF exception found" )
2575 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002576 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002577 except Exception:
2578 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002579 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002580
Jon Hall7eb38402015-01-08 17:19:54 -08002581 def decToHex( self, num ):
2582 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002583
Jon Hall7eb38402015-01-08 17:19:54 -08002584 def getSwitchFlowCount( self, switch ):
2585 """
2586 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002587 if self.handle:
2588 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2589 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002590 response = self.execute(
2591 cmd=cmd,
2592 prompt="mininet>",
2593 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002594 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002595 main.log.error( self.name + ": EOF exception found" )
2596 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002597 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002598 except Exception:
2599 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002600 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002601 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002602 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002603 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002604 main.log.info(
2605 "Couldn't find flows on switch %s, found: %s" %
2606 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002607 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002608 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002609 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002610 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002611
Jon Hall9ed8f372016-02-24 17:34:07 -08002612 def checkFlows( self, sw, dumpFormat=None ):
2613 if dumpFormat:
2614 command = "sh ovs-ofctl -F " + \
2615 dumpFormat + " dump-flows " + str( sw )
2616 else:
2617 command = "sh ovs-ofctl dump-flows " + str( sw )
2618 try:
2619 response = self.execute(
2620 cmd=command,
2621 prompt="mininet>",
2622 timeout=10 )
2623 return response
2624 except pexpect.EOF:
2625 main.log.error( self.name + ": EOF exception found" )
2626 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002627 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002628 except Exception:
2629 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002630 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002631
GlennRC68467eb2015-11-16 18:01:01 -08002632 def flowTableComp( self, flowTable1, flowTable2 ):
2633 # This function compares the selctors and treatments of each flow
2634 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002635 assert flowTable1, "flowTable1 is empty or None"
2636 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002637 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002638 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002639 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002640 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002641 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2642 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002643 for field in dFields:
2644 try:
2645 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002646 except KeyError:
2647 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002648 try:
2649 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002650 except KeyError:
2651 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002652 for i in range( len( flowTable1 ) ):
2653 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002654 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002655 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002656 returnValue = main.FALSE
2657 break
2658 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002659 except AssertionError:
2660 main.log.exception( "Nothing to compare" )
2661 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002662 except Exception:
2663 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002664 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002665
GlennRC528ad292015-11-12 10:38:18 -08002666 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002667 '''
GlennRC956ea742015-11-05 16:14:15 -08002668 Discription: Parses flows into json format.
2669 NOTE: this can parse any string thats separated with commas
2670 Arguments:
2671 Required:
2672 flows: a list of strings that represnt flows
2673 Optional:
2674 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2675 debug: prints out the final result
2676 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002677 '''
GlennRC528ad292015-11-12 10:38:18 -08002678 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002679 try:
2680 for flow in flowTable:
2681 jsonFlow = {}
2682 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002683 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002684 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002685 for i in range( len( parsedFlow ) ):
2686 item = parsedFlow[ i ]
2687 if item[ 0 ] == " ":
2688 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002689 # grab the selector and treatment from the parsed flow
2690 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002691 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002692 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002693 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002694 index = 0
2695 # parse the flags
2696 # NOTE: This only parses one flag
2697 flag = {}
2698 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002699 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002700 index += 1
2701 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002702 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002703 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002704 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002705 # the priority is stuck in the selecter so put it back
2706 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002707 if 'priority' in sel[0]:
2708 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002709 # parse selector
2710 criteria = []
2711 for item in sel:
2712 # this is the type of the packet e.g. "arp"
2713 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002714 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002715 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002716 field = item.split( "=" )
2717 criteria.append( { field[ 0 ]: field[ 1 ] } )
2718 selector = { "selector": { "criteria": sorted( criteria ) } }
2719 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002720 # get rid of the action part e.g. "action=output:2"
2721 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002722 treat = treat.split( "=" )
2723 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002724 # parse treatment
2725 action = []
2726 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002727 if ":" in item:
2728 field = item.split( ":" )
2729 action.append( { field[ 0 ]: field[ 1 ] } )
2730 else:
2731 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2732 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002733 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002734 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002735 # parse the rest of the flow
2736 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002737 field = item.split( "=" )
2738 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002739 # add the treatment and the selector to the json flow
2740 jsonFlow.update( selector )
2741 jsonFlow.update( treatment )
2742 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002743
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002744 if debug:
2745 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002746
You Wang91c37cf2016-05-23 09:39:42 -07002747 # add the json flow to the json flow table
2748 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002749
You Wang91c37cf2016-05-23 09:39:42 -07002750 return jsonFlowTable
2751
2752 except IndexError:
2753 main.log.exception( self.name + ": IndexError found" )
2754 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002755 except pexpect.EOF:
2756 main.log.error( self.name + ": EOF exception found" )
2757 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002758 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002759 except Exception:
2760 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002761 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002762
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002763 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002764 '''
2765 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002766 Each element is a flow.
2767 Arguments:
2768 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002769 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002770 a list of switches.
2771 Optional:
2772 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2773 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002774 '''
GlennRC956ea742015-11-05 16:14:15 -08002775 try:
2776 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002777 if isinstance( sw, list ):
2778 switches.extend( sw )
2779 else:
2780 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002781
2782 flows = []
2783 for s in switches:
2784 cmd = "sh ovs-ofctl dump-flows " + s
2785
GlennRC528ad292015-11-12 10:38:18 -08002786 if "1.0" == version:
2787 cmd += " -F OpenFlow10-table_id"
2788 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002789 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002790
2791 main.log.info( "Sending: " + cmd )
2792 self.handle.sendline( cmd )
2793 self.handle.expect( "mininet>" )
2794 response = self.handle.before
2795 response = response.split( "\r\n" )
2796 # dump the first two elements and the last
2797 # the first element is the command that was sent
2798 # the second is the table header
2799 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002800 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002801 flows.extend( response )
2802
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002803 if debug:
2804 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002805
GlennRC528ad292015-11-12 10:38:18 -08002806 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002807
GlennRC956ea742015-11-05 16:14:15 -08002808 except pexpect.EOF:
2809 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002810 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002811 except Exception:
2812 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002813 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002814
2815 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002816 '''
GlennRC956ea742015-11-05 16:14:15 -08002817 Discription: Checks whether the ID provided matches a flow ID in Mininet
2818 Arguments:
2819 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002820 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002821 a list of switches.
2822 flowId: the flow ID in hex format. Can also be a list of IDs
2823 Optional:
2824 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2825 debug: prints out the final result
2826 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2827 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002828 '''
GlennRC956ea742015-11-05 16:14:15 -08002829 try:
2830 main.log.info( "Getting flows from Mininet" )
2831 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002832 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002833 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002834
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002835 if debug:
2836 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002837
2838 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002839 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002840 result = False
2841 for f in flows:
2842 if flowId in f.get( 'cookie' ):
2843 result = True
2844 break
2845 # flowId is a list
2846 else:
2847 result = True
2848 # Get flow IDs from Mininet
2849 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2850 # Save the IDs that are not in Mininet
2851 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2852
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002853 if debug:
2854 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002855
2856 # Print out the IDs that are not in Mininet
2857 if absentIds:
2858 main.log.warn( "Absent ids: {}".format( absentIds ) )
2859 result = False
2860
2861 return main.TRUE if result else main.FALSE
2862
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002863 except pexpect.EOF:
2864 main.log.error( self.name + ": EOF exception found" )
2865 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002866 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002867 except Exception:
2868 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002869 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002870
Charles Chan029be652015-08-24 01:46:10 +08002871 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002872 """
Jon Hallefbd9792015-03-05 16:11:36 -08002873 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002874 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002875 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002876 self.handle.sendline( "" )
2877 self.handle.expect( "mininet>" )
2878 self.handle.sendline(
2879 "sh sudo tcpdump -n -i " +
2880 intf +
2881 " " +
2882 port +
2883 " -w " +
2884 filename.strip() +
2885 " &" )
2886 self.handle.sendline( "" )
2887 i = self.handle.expect( [ 'No\ssuch\device',
2888 'listening\son',
2889 pexpect.TIMEOUT,
2890 "mininet>" ],
2891 timeout=10 )
2892 main.log.warn( self.handle.before + self.handle.after )
2893 self.handle.sendline( "" )
2894 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002895 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002896 main.log.error(
2897 self.name +
2898 ": tcpdump - No such device exists. " +
2899 "tcpdump attempted on: " +
2900 intf )
admin2a9548d2014-06-17 14:08:07 -07002901 return main.FALSE
2902 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002903 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002904 return main.TRUE
2905 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002906 main.log.error(
2907 self.name +
2908 ": tcpdump command timed out! Check interface name," +
2909 " given interface was: " +
2910 intf )
admin2a9548d2014-06-17 14:08:07 -07002911 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002912 elif i == 3:
2913 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002914 return main.TRUE
2915 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002916 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002917 return main.FALSE
2918 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002919 main.log.error( self.name + ": EOF exception found" )
2920 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002921 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002922 except Exception:
2923 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002924 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002925
kelvin-onlabd3b64892015-01-20 13:26:24 -08002926 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002927 """
2928 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002929 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002930 self.handle.sendline( "sh sudo pkill tcpdump" )
2931 self.handle.expect( "mininet>" )
2932 self.handle.sendline( "" )
2933 self.handle.expect( "mininet>" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002934 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002935 main.log.error( self.name + ": TIMEOUT exception found" )
2936 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002937 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002938 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002939 main.log.error( self.name + ": EOF exception found" )
2940 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002941 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002942 except Exception:
2943 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002944 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002945
Jon Halld80cc142015-07-06 13:36:05 -07002946 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002947 """
2948 Read ports from a Mininet switch.
2949
2950 Returns a json structure containing information about the
2951 ports of the given switch.
2952 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002953 try:
2954 response = self.getInterfaces( nodeName )
2955 # TODO: Sanity check on response. log if no such switch exists
2956 ports = []
2957 for line in response.split( "\n" ):
2958 if not line.startswith( "name=" ):
2959 continue
2960 portVars = {}
2961 for var in line.split( "," ):
2962 key, value = var.split( "=" )
2963 portVars[ key ] = value
2964 isUp = portVars.pop( 'enabled', "True" )
2965 isUp = "True" in isUp
2966 if verbose:
2967 main.log.info( "Reading switch port %s(%s)" %
2968 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2969 mac = portVars[ 'mac' ]
2970 if mac == 'None':
2971 mac = None
2972 ips = []
2973 ip = portVars[ 'ip' ]
2974 if ip == 'None':
2975 ip = None
2976 ips.append( ip )
2977 name = portVars[ 'name' ]
2978 if name == 'None':
2979 name = None
2980 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2981 if name == 'lo':
2982 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2983 else:
2984 portNo = re.search( portRe, name ).group( 'port' )
2985 ports.append( { 'of_port': portNo,
2986 'mac': str( mac ).replace( '\'', '' ),
2987 'name': name,
2988 'ips': ips,
2989 'enabled': isUp } )
2990 return ports
2991 except pexpect.EOF:
2992 main.log.error( self.name + ": EOF exception found" )
2993 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002994 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002995 except Exception:
2996 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002997 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002998
You Wangdb8cd0a2016-05-26 15:19:45 -07002999 def getOVSPorts( self, nodeName ):
3000 """
3001 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
3002
3003 Returns a list of dictionaries containing information about each
3004 port of the given switch.
3005 """
3006 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
3007 try:
3008 response = self.execute(
3009 cmd=command,
3010 prompt="mininet>",
3011 timeout=10 )
3012 ports = []
3013 if response:
3014 for line in response.split( "\n" ):
3015 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
3016 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003017 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07003018 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
3019 result = re.search( pattern, line )
3020 if result:
3021 index = result.group( 'index' )
3022 name = result.group( 'name' )
3023 # This port number is extracted from port name
3024 port = result.group( 'port' )
3025 mac = result.group( 'mac' )
3026 ports.append( { 'index': index,
3027 'name': name,
3028 'port': port,
3029 'mac': mac } )
3030 return ports
3031 except pexpect.EOF:
3032 main.log.error( self.name + ": EOF exception found" )
3033 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003034 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003035 except Exception:
3036 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003037 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003038
Devin Lima7cfdbd2017-09-29 15:02:22 -07003039 def getSwitches( self, verbose=False, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07003040 """
3041 Read switches from Mininet.
3042
3043 Returns a dictionary whose keys are the switch names and the value is
3044 a dictionary containing information about the switch.
3045 """
Jon Halla22481b2015-07-28 17:46:01 -07003046 # NOTE: To support new Mininet switch classes, just append the new
3047 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07003048
Jon Halla22481b2015-07-28 17:46:01 -07003049 # Regex patterns to parse 'dump' output
3050 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07003051 # <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 -07003052 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07003053 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
3054 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
3055 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003056 try:
3057 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
3058 swRE = r"<(?P<class>" + switchClasses + r")" +\
3059 r"(?P<options>\{.*\})?\s" +\
3060 r"(?P<name>[^:]+)\:\s" +\
3061 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
3062 r"\spid=(?P<pid>(\d)+)"
3063 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07003064 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003065 output = {}
3066 dump = self.dump().split( "\n" )
3067 for line in dump:
3068 result = re.search( swRE, line, re.I )
3069 if result:
3070 name = result.group( 'name' )
3071 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
3072 pid = result.group( 'pid' )
3073 swClass = result.group( 'class' )
3074 options = result.group( 'options' )
3075 if verbose:
3076 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
3077 ports = self.getPorts( name )
3078 output[ name ] = { "dpid": dpid,
3079 "ports": ports,
3080 "swClass": swClass,
3081 "pid": pid,
3082 "options": options }
3083 return output
3084 except pexpect.EOF:
3085 main.log.error( self.name + ": EOF exception found" )
3086 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003087 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003088 except Exception:
3089 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003090 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003091
You Wangd66de192018-04-30 17:30:12 -07003092 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08003093 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
3094 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07003095 """
3096 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08003097 Optional:
3098 hostClass: it is used to match the class of the mininet host. It
3099 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07003100 Returns a dictionary whose keys are the host names and the value is
3101 a dictionary containing information about the host.
3102 """
3103 # Regex patterns to parse dump output
3104 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07003105 # <Host h1: pid=12725>
3106 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
3107 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
3108 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07003109 # NOTE: Does not correctly match hosts with multi-links
3110 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
3111 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003112 try:
You Wang53dba1e2018-02-02 17:45:44 -08003113 if not isinstance( hostClass, types.ListType ):
3114 hostClass = [ str( hostClass ) ]
3115 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08003116 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
3117 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
3118 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07003119 if update:
3120 # update mn port info
3121 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003122 # Get mininet dump
3123 dump = self.dump().split( "\n" )
3124 hosts = {}
3125 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08003126 result = re.search( hostRE, line )
3127 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003128 name = result.group( 'name' )
3129 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07003130 if getInterfaces:
3131 response = self.getInterfaces( name )
3132 # Populate interface info
3133 for line in response.split( "\n" ):
3134 if line.startswith( "name=" ):
3135 portVars = {}
3136 for var in line.split( "," ):
3137 key, value = var.split( "=" )
3138 portVars[ key ] = value
3139 isUp = portVars.pop( 'enabled', "True" )
3140 isUp = "True" in isUp
3141 if verbose:
3142 main.log.info( "Reading host port %s(%s)" %
3143 ( portVars[ 'name' ],
3144 portVars[ 'mac' ] ) )
3145 mac = portVars[ 'mac' ]
3146 if mac == 'None':
3147 mac = None
3148 ips = []
3149 ip = portVars[ 'ip' ]
3150 if ip == 'None':
3151 ip = None
3152 ips.append( ip )
3153 intfName = portVars[ 'name' ]
3154 if name == 'None':
3155 name = None
3156 interfaces.append( {
3157 "name": intfName,
3158 "ips": ips,
3159 "mac": str( mac ),
3160 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003161 hosts[ name ] = { "interfaces": interfaces }
3162 return hosts
3163 except pexpect.EOF:
3164 main.log.error( self.name + ": EOF exception found" )
3165 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003166 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003167 except Exception:
3168 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003169 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003170
Devin Lima7cfdbd2017-09-29 15:02:22 -07003171 def getLinks( self, timeout=20, updateTimeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07003172 """
3173 Gathers information about current Mininet links. These links may not
3174 be up if one of the ports is down.
3175
3176 Returns a list of dictionaries with link endpoints.
3177
3178 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07003179 { 'node1': str( node1 name )
3180 'node2': str( node2 name )
3181 'port1': str( port1 of_port )
3182 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07003183 Note: The port number returned is the eth#, not necessarily the of_port
3184 number. In Mininet, for OVS switch, these should be the same. For
3185 hosts, this is just the eth#.
3186 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003187 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003188 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003189 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07003190
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003191 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003192 # s1-eth3<->s2-eth1 (OK OK)
3193 # s13-eth3<->h27-eth0 (OK OK)
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003194 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
3195 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
3196 links = []
3197 for line in response:
3198 match = re.search( linkRE, line )
3199 if match:
3200 node1 = match.group( 'node1' )
3201 node2 = match.group( 'node2' )
3202 port1 = match.group( 'port1' )
3203 port2 = match.group( 'port2' )
3204 links.append( { 'node1': node1,
3205 'node2': node2,
3206 'port1': port1,
3207 'port2': port2 } )
3208 return links
3209
3210 except pexpect.EOF:
3211 main.log.error( self.name + ": EOF exception found" )
3212 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003213 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003214 except Exception:
3215 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003216 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003217
3218 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003219 """
3220 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003221 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003222
Jon Hallafa8a472015-06-12 14:02:42 -07003223 Dependencies:
3224 1. numpy - "sudo pip install numpy"
3225 """
3226 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003227 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003228 try:
3229 mnDPIDs = []
3230 for swName, switch in switches.iteritems():
3231 mnDPIDs.append( switch[ 'dpid' ].lower() )
3232 mnDPIDs.sort()
3233 if switchesJson == "": # if rest call fails
3234 main.log.error(
3235 self.name +
3236 ".compareSwitches(): Empty JSON object given from ONOS" )
3237 return main.FALSE
3238 onos = switchesJson
3239 onosDPIDs = []
3240 for switch in onos:
3241 if switch[ 'available' ]:
3242 onosDPIDs.append(
3243 switch[ 'id' ].replace(
3244 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003245 '' ).replace(
3246 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003247 '' ).lower() )
3248 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003249
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003250 if mnDPIDs != onosDPIDs:
3251 switchResults = main.FALSE
3252 main.log.error( "Switches in MN but not in ONOS:" )
3253 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3254 main.log.error( str( list1 ) )
3255 main.log.error( "Switches in ONOS but not in MN:" )
3256 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3257 main.log.error( str( list2 ) )
3258 else: # list of dpid's match in onos and mn
3259 switchResults = main.TRUE
3260 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003261
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003262 # FIXME: this does not look for extra ports in ONOS, only checks that
3263 # ONOS has what is in MN
3264 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003265
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003266 # PORTS
3267 for name, mnSwitch in switches.iteritems():
3268 mnPorts = []
3269 onosPorts = []
3270 switchResult = main.TRUE
3271 for port in mnSwitch[ 'ports' ]:
3272 if port[ 'enabled' ]:
3273 mnPorts.append( int( port[ 'of_port' ] ) )
3274 for onosSwitch in portsJson:
3275 if onosSwitch[ 'device' ][ 'available' ]:
3276 if onosSwitch[ 'device' ][ 'id' ].replace(
3277 ':',
3278 '' ).replace(
3279 "of",
3280 '' ) == mnSwitch[ 'dpid' ]:
3281 for port in onosSwitch[ 'ports' ]:
3282 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003283 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003284 # onosPorts.append( 'local' )
3285 onosPorts.append( long( uint64( -2 ) ) )
3286 else:
3287 onosPorts.append( int( port[ 'port' ] ) )
3288 break
3289 mnPorts.sort( key=float )
3290 onosPorts.sort( key=float )
3291
3292 mnPortsLog = mnPorts
3293 onosPortsLog = onosPorts
3294 mnPorts = [ x for x in mnPorts ]
3295 onosPorts = [ x for x in onosPorts ]
3296
3297 # TODO: handle other reserved port numbers besides LOCAL
3298 # NOTE: Reserved ports
3299 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3300 # long( uint64( -2 ) )
3301 for mnPort in mnPortsLog:
3302 if mnPort in onosPorts:
3303 # don't set results to true here as this is just one of
3304 # many checks and it might override a failure
3305 mnPorts.remove( mnPort )
3306 onosPorts.remove( mnPort )
3307
3308 # NOTE: OVS reports this as down since there is no link
3309 # So ignoring these for now
3310 # TODO: Come up with a better way of handling these
3311 if 65534 in mnPorts:
3312 mnPorts.remove( 65534 )
3313 if long( uint64( -2 ) ) in onosPorts:
3314 onosPorts.remove( long( uint64( -2 ) ) )
3315 if len( mnPorts ): # the ports of this switch don't match
3316 switchResult = main.FALSE
3317 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3318 if len( onosPorts ): # the ports of this switch don't match
3319 switchResult = main.FALSE
3320 main.log.warn(
3321 "Ports in ONOS but not MN: " +
3322 str( onosPorts ) )
3323 if switchResult == main.FALSE:
3324 main.log.error(
3325 "The list of ports for switch %s(%s) does not match:" %
3326 ( name, mnSwitch[ 'dpid' ] ) )
3327 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3328 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3329 portsResults = portsResults and switchResult
3330 finalResults = finalResults and portsResults
3331 return finalResults
3332 except pexpect.EOF:
3333 main.log.error( self.name + ": EOF exception found" )
3334 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003335 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003336 except Exception:
3337 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003338 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003339
Jon Hallafa8a472015-06-12 14:02:42 -07003340 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003341 """
3342 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003343 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003344
Jon Hallafa8a472015-06-12 14:02:42 -07003345 """
Jon Hall7eb38402015-01-08 17:19:54 -08003346 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003347 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003348 try:
3349 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003350
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003351 mnLinks = []
3352 for l in links:
3353 try:
3354 node1 = switches[ l[ 'node1' ] ]
3355 node2 = switches[ l[ 'node2' ] ]
3356 enabled = True
3357 for port in node1[ 'ports' ]:
3358 if port[ 'of_port' ] == l[ 'port1' ]:
3359 enabled = enabled and port[ 'enabled' ]
3360 for port in node2[ 'ports' ]:
3361 if port[ 'of_port' ] == l[ 'port2' ]:
3362 enabled = enabled and port[ 'enabled' ]
3363 if enabled:
3364 mnLinks.append( l )
3365 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003366 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003367 if 2 * len( mnLinks ) == len( onos ):
3368 linkResults = main.TRUE
3369 else:
3370 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003371 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003372 "Mininet has " + str( len( mnLinks ) ) +
3373 " bidirectional links and ONOS has " +
3374 str( len( onos ) ) + " unidirectional links" )
3375
3376 # iterate through MN links and check if an ONOS link exists in
3377 # both directions
3378 for link in mnLinks:
3379 # TODO: Find a more efficient search method
3380 node1 = None
3381 port1 = None
3382 node2 = None
3383 port2 = None
3384 firstDir = main.FALSE
3385 secondDir = main.FALSE
3386 for swName, switch in switches.iteritems():
3387 if swName == link[ 'node1' ]:
3388 node1 = switch[ 'dpid' ]
3389 for port in switch[ 'ports' ]:
3390 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3391 port1 = port[ 'of_port' ]
3392 if node1 is not None and node2 is not None:
3393 break
3394 if swName == link[ 'node2' ]:
3395 node2 = switch[ 'dpid' ]
3396 for port in switch[ 'ports' ]:
3397 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3398 port2 = port[ 'of_port' ]
3399 if node1 is not None and node2 is not None:
3400 break
3401
3402 for onosLink in onos:
3403 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3404 ":", '' ).replace( "of", '' )
3405 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3406 ":", '' ).replace( "of", '' )
3407 onosPort1 = onosLink[ 'src' ][ 'port' ]
3408 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3409
3410 # check onos link from node1 to node2
3411 if str( onosNode1 ) == str( node1 ) and str(
3412 onosNode2 ) == str( node2 ):
3413 if int( onosPort1 ) == int( port1 ) and int(
3414 onosPort2 ) == int( port2 ):
3415 firstDir = main.TRUE
3416 else:
Jon Hallab611372018-02-21 15:26:05 -08003417 # The right switches, but wrong ports, could be
3418 # another link between these devices, or onos
3419 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003420 main.log.warn(
3421 'The port numbers do not match for ' +
3422 str( link ) +
3423 ' between ONOS and MN. When checking ONOS for ' +
3424 'link %s/%s -> %s/%s' %
3425 ( node1, port1, node2, port2 ) +
3426 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003427 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3428 '. This could be another link between these devices' +
3429 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003430
3431 # check onos link from node2 to node1
3432 elif ( str( onosNode1 ) == str( node2 ) and
3433 str( onosNode2 ) == str( node1 ) ):
3434 if ( int( onosPort1 ) == int( port2 )
3435 and int( onosPort2 ) == int( port1 ) ):
3436 secondDir = main.TRUE
3437 else:
Jon Hallab611372018-02-21 15:26:05 -08003438 # The right switches, but wrong ports, could be
3439 # another link between these devices, or onos
3440 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003441 main.log.warn(
3442 'The port numbers do not match for ' +
3443 str( link ) +
3444 ' between ONOS and MN. When checking ONOS for ' +
3445 'link %s/%s -> %s/%s' %
3446 ( node1, port1, node2, port2 ) +
3447 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003448 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3449 '. This could be another link between these devices' +
3450 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003451 else: # this is not the link you're looking for
3452 pass
3453 if not firstDir:
3454 main.log.error(
3455 'ONOS does not have the link %s/%s -> %s/%s' %
3456 ( node1, port1, node2, port2 ) )
3457 if not secondDir:
3458 main.log.error(
3459 'ONOS does not have the link %s/%s -> %s/%s' %
3460 ( node2, port2, node1, port1 ) )
3461 linkResults = linkResults and firstDir and secondDir
3462 return linkResults
3463 except pexpect.EOF:
3464 main.log.error( self.name + ": EOF exception found" )
3465 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003466 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003467 except Exception:
3468 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003469 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003470
Jon Hallafa8a472015-06-12 14:02:42 -07003471 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003472 """
Jon Hallafa8a472015-06-12 14:02:42 -07003473 Compare mn and onos Hosts.
3474 Since Mininet hosts are quiet, ONOS will only know of them when they
3475 speak. For this reason, we will only check that the hosts in ONOS
3476 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003477
Jon Hallafa8a472015-06-12 14:02:42 -07003478 Arguments:
3479 hostsJson: parsed json object from the onos hosts api
3480 Returns:
3481 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003482 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003483 try:
3484 hostResults = main.TRUE
3485 for onosHost in hostsJson:
3486 onosMAC = onosHost[ 'mac' ].lower()
3487 match = False
3488 for mnHost, info in hosts.iteritems():
3489 for mnIntf in info[ 'interfaces' ]:
3490 if onosMAC == mnIntf[ 'mac' ].lower():
3491 match = True
3492 for ip in mnIntf[ 'ips' ]:
3493 if ip in onosHost[ 'ipAddresses' ]:
3494 pass # all is well
3495 else:
3496 # misssing ip
3497 main.log.error( "ONOS host " +
3498 onosHost[ 'id' ] +
3499 " has a different IP(" +
3500 str( onosHost[ 'ipAddresses' ] ) +
3501 ") than the Mininet host(" +
3502 str( ip ) +
3503 ")." )
3504 output = json.dumps(
3505 onosHost,
3506 sort_keys=True,
3507 indent=4,
3508 separators=( ',', ': ' ) )
3509 main.log.info( output )
3510 hostResults = main.FALSE
3511 if not match:
3512 hostResults = main.FALSE
3513 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3514 "corresponding Mininet host." )
3515 output = json.dumps( onosHost,
3516 sort_keys=True,
3517 indent=4,
3518 separators=( ',', ': ' ) )
3519 main.log.info( output )
3520 return hostResults
3521 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003522 main.log.error( self.name + ": EOF exception found" )
3523 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003524 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003525 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003526 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003527 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003528
You Wangd66de192018-04-30 17:30:12 -07003529 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003530 """
3531 Description:
3532 Verify that all hosts have IP address assigned to them
3533 Optional:
3534 hostList: If specified, verifications only happen to the hosts
3535 in hostList
3536 prefix: at least one of the ip address assigned to the host
3537 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003538 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003539 Returns:
3540 main.TRUE if all hosts have specific IP address assigned;
3541 main.FALSE otherwise
3542 """
3543 try:
You Wangd66de192018-04-30 17:30:12 -07003544 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003545 if not hostList:
3546 hostList = hosts.keys()
3547 for hostName in hosts.keys():
3548 if hostName not in hostList:
3549 continue
3550 ipList = []
3551 self.handle.sendline( str( hostName ) + " ip a" )
3552 self.handle.expect( "mininet>" )
3553 ipa = self.handle.before
3554 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3555 ipList += re.findall( ipv4Pattern, ipa )
3556 # It's tricky to make regex for IPv6 addresses and this one is simplified
3557 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})/'
3558 ipList += re.findall( ipv6Pattern, ipa )
3559 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3560 if not ipList:
3561 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3562 else:
3563 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3564 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3565 else:
3566 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3567 hostList.remove( hostName )
3568 return main.FALSE if hostList else main.TRUE
3569 except KeyError:
3570 main.log.exception( self.name + ": host data not as expected: " + hosts )
3571 return None
3572 except pexpect.EOF:
3573 main.log.error( self.name + ": EOF exception found" )
3574 main.log.error( self.name + ": " + self.handle.before )
3575 main.cleanAndExit()
3576 except Exception:
3577 main.log.exception( self.name + ": Uncaught exception" )
3578 return None
3579
Jon Hallafa8a472015-06-12 14:02:42 -07003580 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003581 """
3582 Returns a list of all hosts
3583 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003584 try:
3585 self.handle.sendline( "" )
3586 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003587
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003588 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
3589 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003590
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003591 handlePy = self.handle.before
3592 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3593 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003594
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003595 self.handle.sendline( "" )
3596 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07003597
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003598 hostStr = handlePy.replace( "]", "" )
3599 hostStr = hostStr.replace( "'", "" )
3600 hostStr = hostStr.replace( "[", "" )
3601 hostStr = hostStr.replace( " ", "" )
3602 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003603
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003604 return hostList
3605 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003606 main.log.error( self.name + ": TIMEOUT exception found" )
3607 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003608 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003609 except pexpect.EOF:
3610 main.log.error( self.name + ": EOF exception found" )
3611 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003612 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003613 except Exception:
3614 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003615 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003616
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003617 def getSwitch( self ):
3618 """
3619 Returns a list of all switches
3620 Again, don't ask question just use it...
3621 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003622 try:
3623 # get host list...
3624 hostList = self.getHosts()
3625 # Make host set
3626 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003627
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003628 # Getting all the nodes in mininet
3629 self.handle.sendline( "" )
3630 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003631
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003632 self.handle.sendline( "py [ node.name for node in net.values() ]" )
3633 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003634
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003635 handlePy = self.handle.before
3636 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3637 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003638
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003639 self.handle.sendline( "" )
3640 self.handle.expect( "mininet>" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003641
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003642 nodesStr = handlePy.replace( "]", "" )
3643 nodesStr = nodesStr.replace( "'", "" )
3644 nodesStr = nodesStr.replace( "[", "" )
3645 nodesStr = nodesStr.replace( " ", "" )
3646 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003647
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003648 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003649 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003650 nodesSet.discard( 'c0' )
3651 nodesSet.discard( 'c1' )
3652 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003653
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003654 switchSet = nodesSet - hostSet
3655 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003656
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003657 return switchList
3658 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003659 main.log.error( self.name + ": TIMEOUT exception found" )
3660 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003661 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003662 except pexpect.EOF:
3663 main.log.error( self.name + ": EOF exception found" )
3664 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003665 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003666 except Exception:
3667 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003668 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003669
You Wangdb8cd0a2016-05-26 15:19:45 -07003670 def getGraphDict( self, timeout=60, useId=True, includeHost=False ):
3671 """
3672 Return a dictionary which describes the latest Mininet topology data as a
3673 graph.
3674 An example of the dictionary:
3675 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3676 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3677 Each vertex should at least have an 'edges' attribute which describes the
3678 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003679 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003680 list of attributes.
3681 An example of the edges dictionary:
3682 'edges': { vertex2: { 'port': ..., 'weight': ... },
3683 vertex3: { 'port': ..., 'weight': ... } }
3684 If useId == True, dpid/mac will be used instead of names to identify
3685 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3686 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003687 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003688 in topology data.
3689 Note that link or switch that are brought down by 'link x x down' or 'switch
3690 x down' commands still show in the output of Mininet CLI commands such as
3691 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3692 recommended to use delLink() or delSwitch functions to simulate link/switch
3693 down, and addLink() or addSwitch to add them back.
3694 """
3695 graphDict = {}
3696 try:
3697 links = self.getLinks( timeout=timeout )
3698 portDict = {}
3699 if useId:
3700 switches = self.getSwitches()
3701 if includeHost:
3702 hosts = self.getHosts()
3703 for link in links:
3704 # FIXME: support 'includeHost' argument
3705 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3706 continue
3707 nodeName1 = link[ 'node1' ]
3708 nodeName2 = link[ 'node2' ]
3709 port1 = link[ 'port1' ]
3710 port2 = link[ 'port2' ]
3711 # Loop for two nodes
3712 for i in range( 2 ):
3713 # Get port index from OVS
3714 # The index extracted from port name may be inconsistent with ONOS
3715 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003716 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003717 portList = self.getOVSPorts( nodeName1 )
3718 if len( portList ) == 0:
3719 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3720 return None
3721 portDict[ nodeName1 ] = portList
3722 for port in portDict[ nodeName1 ]:
3723 if port[ 'port' ] == port1:
3724 portIndex = port[ 'index' ]
3725 break
3726 if portIndex == -1:
3727 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3728 return None
3729 if useId:
3730 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3731 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3732 else:
3733 node1 = nodeName1
3734 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003735 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003736 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003737 graphDict[ node1 ] = { 'edges': {},
3738 'dpid': switches[ nodeName1 ][ 'dpid' ],
3739 'name': nodeName1,
3740 'ports': switches[ nodeName1 ][ 'ports' ],
3741 'swClass': switches[ nodeName1 ][ 'swClass' ],
3742 'pid': switches[ nodeName1 ][ 'pid' ],
3743 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003744 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003745 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003746 else:
3747 # Assert node2 is not connected to any current links of node1
3748 assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003749 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
You Wangdb8cd0a2016-05-26 15:19:45 -07003750 # Swap two nodes/ports
3751 nodeName1, nodeName2 = nodeName2, nodeName1
3752 port1, port2 = port2, port1
3753 return graphDict
3754 except KeyError:
3755 main.log.exception( self.name + ": KeyError exception found" )
3756 return None
3757 except AssertionError:
3758 main.log.exception( self.name + ": AssertionError exception found" )
3759 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003760 except pexpect.EOF:
3761 main.log.error( self.name + ": EOF exception found" )
3762 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003763 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003764 except Exception:
3765 main.log.exception( self.name + ": Uncaught exception" )
3766 return None
3767
Devin Lima7cfdbd2017-09-29 15:02:22 -07003768 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003769 """
3770 updates the port address and status information for
3771 each port in mn"""
3772 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08003773 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003774 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003775 self.handle.sendline( "" )
3776 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003777
Jon Hall7eb38402015-01-08 17:19:54 -08003778 self.handle.sendline( "update" )
Devin Lima7cfdbd2017-09-29 15:02:22 -07003779 self.handle.expect( "mininet>", timeout )
Jon Hall38481722014-11-04 16:50:05 -05003780
Jon Hall7eb38402015-01-08 17:19:54 -08003781 self.handle.sendline( "" )
3782 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05003783
Jon Hallb1290e82014-11-18 16:17:48 -05003784 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003785 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003786 main.log.error( self.name + ": TIMEOUT exception found" )
3787 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003788 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003789 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003790 main.log.error( self.name + ": EOF exception found" )
3791 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003792 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003793 except Exception:
3794 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003795 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003796
Jon Halld80cc142015-07-06 13:36:05 -07003797 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003798 """
3799 Add vlan tag to a host.
3800 Dependencies:
3801 This class depends on the "vlan" package
3802 $ sudo apt-get install vlan
3803 Configuration:
3804 Load the 8021q module into the kernel
3805 $sudo modprobe 8021q
3806
3807 To make this setup permanent:
3808 $ sudo su -c 'echo "8021q" >> /etc/modules'
3809 """
3810 if self.handle:
3811 try:
Jon Halld80cc142015-07-06 13:36:05 -07003812 # get the ip address of the host
3813 main.log.info( "Get the ip address of the host" )
3814 ipaddr = self.getIPAddress( host )
3815 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003816
Jon Halld80cc142015-07-06 13:36:05 -07003817 # remove IP from interface intf
3818 # Ex: h1 ifconfig h1-eth0 inet 0
3819 main.log.info( "Remove IP from interface " )
3820 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3821 self.handle.sendline( cmd2 )
3822 self.handle.expect( "mininet>" )
3823 response = self.handle.before
3824 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003825
Jon Halld80cc142015-07-06 13:36:05 -07003826 # create VLAN interface
3827 # Ex: h1 vconfig add h1-eth0 100
3828 main.log.info( "Create Vlan" )
3829 cmd3 = host + " vconfig add " + intf + " " + vlan
3830 self.handle.sendline( cmd3 )
3831 self.handle.expect( "mininet>" )
3832 response = self.handle.before
3833 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003834
Jon Halld80cc142015-07-06 13:36:05 -07003835 # assign the host's IP to the VLAN interface
3836 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3837 main.log.info( "Assign the host IP to the vlan interface" )
3838 vintf = intf + "." + vlan
3839 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3840 self.handle.sendline( cmd4 )
3841 self.handle.expect( "mininet>" )
3842 response = self.handle.before
3843 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003844
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003845 # update Mininet node variables
3846 main.log.info( "Update Mininet node variables" )
3847 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3848 self.handle.sendline( cmd5 )
3849 self.handle.expect( "mininet>" )
3850 response = self.handle.before
3851 main.log.info( "====> %s ", response )
3852
3853 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3854 self.handle.sendline( cmd6 )
3855 self.handle.expect( "mininet>" )
3856 response = self.handle.before
3857 main.log.info( "====> %s ", response )
3858
3859 return main.TRUE
3860 except pexpect.TIMEOUT:
3861 main.log.error( self.name + ": TIMEOUT exception found" )
3862 main.log.error( self.name + ": " + self.handle.before )
3863 main.cleanAndExit()
3864 except pexpect.EOF:
3865 main.log.error( self.name + ": EOF exception found" )
3866 main.log.error( self.name + ": " + self.handle.before )
3867 return main.FALSE
3868 except Exception:
3869 main.log.exception( self.name + ": Uncaught exception!" )
3870 return main.FALSE
3871
3872 def removeVLAN( self, host, intf ):
3873 """
3874 Remove vlan tag from a host.
3875 Dependencies:
3876 This class depends on the "vlan" package
3877 $ sudo apt-get install vlan
3878 Configuration:
3879 Load the 8021q module into the kernel
3880 $sudo modprobe 8021q
3881
3882 To make this setup permanent:
3883 $ sudo su -c 'echo "8021q" >> /etc/modules'
3884 """
3885 if self.handle:
3886 try:
3887 # get the ip address of the host
3888 main.log.info( "Get the ip address of the host" )
3889 ipaddr = self.getIPAddress( host )
3890
3891 # remove VLAN interface
3892 # Ex: h1 vconfig rem h1-eth0.100
3893 main.log.info( "Remove Vlan interface" )
3894 cmd2 = host + " vconfig rem " + intf
3895 self.handle.sendline( cmd2 )
3896 self.handle.expect( "mininet>" )
3897 response = self.handle.before
3898 main.log.info( "====> %s ", response )
3899
3900 # assign the host's IP to the original interface
3901 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3902 main.log.info( "Assign the host IP to the original interface" )
3903 original_intf = intf.split(".")[0]
3904 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3905 self.handle.sendline( cmd3 )
3906 self.handle.expect( "mininet>" )
3907 response = self.handle.before
3908 main.log.info( "====> %s ", response )
3909
3910 # update Mininet node variables
3911 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3912 self.handle.sendline( cmd4 )
3913 self.handle.expect( "mininet>" )
3914 response = self.handle.before
3915 main.log.info( "====> %s ", response )
3916
3917 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3918 self.handle.sendline( cmd5 )
3919 self.handle.expect( "mininet>" )
3920 response = self.handle.before
3921 main.log.info( "====> %s ", response )
3922
kaouthera3f13ca22015-05-05 15:01:41 -07003923 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003924 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003925 main.log.error( self.name + ": TIMEOUT exception found" )
3926 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003927 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003928 except pexpect.EOF:
3929 main.log.error( self.name + ": EOF exception found" )
3930 main.log.error( self.name + ": " + self.handle.before )
3931 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003932 except Exception:
3933 main.log.exception( self.name + ": Uncaught exception!" )
3934 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003935
Jon Hall892818c2015-10-20 17:58:34 -07003936 def createHostComponent( self, name ):
3937 """
3938 Creates a new mininet cli component with the same parameters as self.
3939 This new component is intended to be used to login to the hosts created
3940 by mininet.
3941
3942 Arguments:
3943 name - The string of the name of this component. The new component
3944 will be assigned to main.<name> .
3945 In addition, main.<name>.name = str( name )
3946 """
3947 try:
3948 # look to see if this component already exists
3949 getattr( main, name )
3950 except AttributeError:
3951 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003952 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3953 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall892818c2015-10-20 17:58:34 -07003954 main.componentInit( name )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003955 except pexpect.EOF:
3956 main.log.error( self.name + ": EOF exception found" )
3957 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003958 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003959 except Exception:
3960 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003961 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003962 else:
3963 # namespace is not clear!
3964 main.log.error( name + " component already exists!" )
3965 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003966 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003967
3968 def removeHostComponent( self, name ):
3969 """
3970 Remove host component
3971 Arguments:
3972 name - The string of the name of the component to delete.
3973 """
3974 try:
3975 # Get host component
3976 component = getattr( main, name )
3977 except AttributeError:
3978 main.log.error( "Component " + name + " does not exist." )
3979 return
3980 try:
3981 # Disconnect from component
3982 component.disconnect()
3983 # Delete component
3984 delattr( main, name )
3985 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003986 del( main.componentDictionary[ name ] )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003987 except pexpect.EOF:
3988 main.log.error( self.name + ": EOF exception found" )
3989 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003990 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003991 except Exception:
3992 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003993 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003994
3995 def startHostCli( self, host=None ):
3996 """
3997 Use the mininet m utility to connect to the host's cli
3998 """
3999 # These are fields that can be used by scapy packets. Initialized to None
4000 self.hostIp = None
4001 self.hostMac = None
4002 try:
4003 if not host:
4004 host = self.name
4005 self.handle.sendline( self.home + "/util/m " + host )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07004006 self.handle.sendline( "cd" )
4007 self.handle.expect( self.hostPrompt )
4008 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07004009 self.handle.expect( self.hostPrompt )
4010 return main.TRUE
4011 except pexpect.TIMEOUT:
4012 main.log.exception( self.name + ": Command timed out" )
4013 return main.FALSE
4014 except pexpect.EOF:
4015 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07004016 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07004017 except Exception:
4018 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004019 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07004020
YPZhang801d46d2016-08-08 13:26:28 -07004021 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004022 '''
4023
YPZhang801d46d2016-08-08 13:26:28 -07004024 Args:
4025 devicename: switch name
4026 intf: port name on switch
4027 status: up or down
4028
4029 Returns: boolean to show success change status
4030
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004031 '''
YPZhang801d46d2016-08-08 13:26:28 -07004032 if status == "down" or status == "up":
4033 try:
4034 cmd = devicename + " ifconfig " + intf + " " + status
4035 self.handle.sendline( cmd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004036 self.handle.expect( "mininet>" )
YPZhang801d46d2016-08-08 13:26:28 -07004037 return main.TRUE
4038 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004039 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07004040 return main.FALSE
4041 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004042 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07004043 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07004044 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004045 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07004046 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07004047 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004048 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004049 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07004050 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004051 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07004052 return main.FALSE
4053
4054
adminbae64d82013-08-01 10:50:15 -07004055if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004056 sys.modules[ __name__ ] = MininetCliDriver()