blob: 47123a4040a024657974b578f6efa86c56ace031 [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()
Jon Halldac3eae2020-06-05 12:04:06 -070065 self.sudoRequired = True
Jon Hall43060f62020-06-23 13:13:33 -070066 self.mExecDir = None
67 self.hostHome = None
adminbae64d82013-08-01 10:50:15 -070068
Jon Hall7eb38402015-01-08 17:19:54 -080069 def connect( self, **connectargs ):
70 """
71 Here the main is the TestON instance after creating
72 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080073 try:
74 for key in connectargs:
75 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070076 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080077 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070078 for key in self.options:
79 if key == "home":
80 self.home = self.options[ 'home' ]
Jon Halldac3eae2020-06-05 12:04:06 -070081 elif key == "sudo_required":
82 self.sudoRequired = False if self.options[ key ] == "false" else True
kelvin-onlabd9e23de2015-08-06 10:34:44 -070083 if self.home is None or self.home == "":
84 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070085
86 try:
Jon Hall892818c2015-10-20 17:58:34 -070087 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070088 self.ip_address = os.getenv( str( self.ip_address ) )
89 else:
90 main.log.info( self.name +
91 ": Trying to connect to " +
92 self.ip_address )
93
94 except KeyError:
95 main.log.info( "Invalid host name," +
96 " connecting to local host instead" )
97 self.ip_address = 'localhost'
98 except Exception as inst:
99 main.log.error( "Uncaught exception: " + str( inst ) )
100
kelvin-onlaba1484582015-02-02 15:46:20 -0800101 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -0700102 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -0800103 self ).connect(
104 user_name=self.user_name,
105 ip_address=self.ip_address,
106 port=None,
107 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -0800108
kelvin-onlaba1484582015-02-02 15:46:20 -0800109 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -0800110 main.log.info( "Connection successful to the host " +
111 self.user_name +
112 "@" +
113 self.ip_address )
Jon Hall43060f62020-06-23 13:13:33 -0700114 self.handle.sendline( "bash -i" )
115 self.handle.expect( self.bashPrompt )
kelvin-onlaba1484582015-02-02 15:46:20 -0800116 return main.TRUE
117 else:
118 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800119 self.user_name +
120 "@" +
121 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800122 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800123 return main.FALSE
124 except pexpect.EOF:
125 main.log.error( self.name + ": EOF exception found" )
126 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700127 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800128 except Exception:
129 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700130 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -0800131
kelvin-onlab10e8d392015-06-03 13:53:45 -0700132 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800133 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700134 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000135 Starts Mininet accepts a topology(.py) file and/or an optional
kelvin-onlabf512e942015-06-08 19:42:59 -0700136 argument, to start the mininet, as a parameter.
137 Can also send regular mininet command to load up desired topology.
alison12f34c32016-06-10 14:39:21 -0700138 Eg. Pass in a string 'mn --topo=tree,3,3' to mnCmd
kelvin-onlabf512e942015-06-08 19:42:59 -0700139 Options:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000140 topoFile = file path for topology file (.py)
kelvin-onlabf512e942015-06-08 19:42:59 -0700141 args = extra option added when starting the topology from the file
142 mnCmd = Mininet command use to start topology
143 Returns:
144 main.TRUE if the mininet starts successfully, main.FALSE
145 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800146 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700147 try:
148 if self.handle:
149 # make sure old networks are cleaned up
150 main.log.info( self.name +
151 ": Clearing any residual state or processes" )
Jon Halldac3eae2020-06-05 12:04:06 -0700152 cmd = "mn -c"
153 if self.sudoRequired:
154 cmd = "sudo " + cmd
155 self.handle.sendline( cmd )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700156 i = self.handle.expect( [ 'password\sfor\s',
157 'Cleanup\scomplete',
Jon Hallefbd9792015-03-05 16:11:36 -0800158 pexpect.EOF,
159 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700160 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800161 if i == 0:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700162 # Sudo asking for password
163 main.log.info( self.name + ": Sending sudo password" )
164 self.handle.sendline( self.pwd )
Jon Hall173f2a02018-01-11 13:56:37 -0800165 i = self.handle.expect( [ '%s:' % self.user_name,
Jon Hall3c0114c2020-08-11 15:07:42 -0700166 self.Prompt(),
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700167 pexpect.EOF,
168 pexpect.TIMEOUT ],
169 timeout )
170 if i == 1:
171 main.log.info( self.name + ": Clean" )
Jon Hall689d8e42015-04-03 13:59:24 -0700172 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700173 main.log.error( self.name + ": Connection terminated" )
174 elif i == 3: # timeout
175 main.log.error( self.name + ": Something while cleaning " +
176 "Mininet took too long... " )
177 # Craft the string to start mininet
Jon Halldac3eae2020-06-05 12:04:06 -0700178 if self.sudoRequired:
179 cmdString = "sudo "
180 else:
181 cmdString = ""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700182 if not mnCmd:
183 if topoFile is None or topoFile == '': # If no file is given
184 main.log.info( self.name + ": building fresh Mininet" )
185 cmdString += "mn "
186 if args is None or args == '':
187 # If no args given, use args from .topo file
188 args = self.options[ 'arg1' ] +\
189 " " + self.options[ 'arg2' ] +\
190 " --mac --controller " +\
191 self.options[ 'controller' ] + " " +\
192 self.options[ 'arg3' ]
193 else: # else only use given args
194 pass
195 # TODO: allow use of topo args and method args?
196 else: # Use given topology file
197 main.log.info(
198 "Starting Mininet from topo file " +
199 topoFile )
Jon Halldac3eae2020-06-05 12:04:06 -0700200 if self.sudoRequired:
201 cmdString += "-E "
202 cmdString += "python " + topoFile + " "
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700203 if args is None:
204 args = ''
205 # TODO: allow use of args from .topo file?
206 cmdString += args
207 else:
208 main.log.info( "Starting Mininet topology using '" + mnCmd +
209 "' command" )
210 cmdString += mnCmd
211 # Send the command and check if network started
212 self.handle.sendline( "" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700213 self.handle.expect( self.Prompt() )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700214 main.log.info( "Sending '" + cmdString + "' to " + self.name )
215 self.handle.sendline( cmdString )
Devin Lima7cfdbd2017-09-29 15:02:22 -0700216 startTime = time.time()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700217 while True:
Jon Hall3c0114c2020-08-11 15:07:42 -0700218 i = self.handle.expect( [ self.mnPrompt,
Jon Hallbc743112018-04-18 11:09:01 -0700219 'Exception|Error',
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700220 '\*\*\*',
221 pexpect.EOF,
Jon Hallab611372018-02-21 15:26:05 -0800222 pexpect.TIMEOUT,
223 "No such file or directory"],
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700224 timeout )
225 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -0700226 main.log.info( self.name + ": Mininet built\nTime Took : " + str( time.time() - startTime ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700227 return main.TRUE
228 elif i == 1:
229 response = str( self.handle.before +
230 self.handle.after )
Jon Hall3c0114c2020-08-11 15:07:42 -0700231 self.handle.expect( self.Prompt() )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700232 response += str( self.handle.before +
233 self.handle.after )
234 main.log.error(
235 self.name +
236 ": Launching Mininet failed: " + response )
237 return main.FALSE
238 elif i == 2:
239 self.handle.expect( [ "\n",
240 pexpect.EOF,
241 pexpect.TIMEOUT ],
242 timeout )
243 main.log.info( self.handle.before )
244 elif i == 3:
245 main.log.error( self.name + ": Connection timeout" )
246 return main.FALSE
247 elif i == 4: # timeout
248 main.log.error(
249 self.name +
250 ": Something took too long... " )
Jon Hallbc743112018-04-18 11:09:01 -0700251 main.log.debug( self.handle.before + self.handle.after )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700252 return main.FALSE
Jon Hallab611372018-02-21 15:26:05 -0800253 elif i == 5:
254 main.log.error( self.name + ": " + self.handle.before + self.handle.after )
255 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700256 # Why did we hit this part?
257 main.log.error( "startNet did not return correctly" )
258 return main.FASLE
259 else: # if no handle
260 main.log.error( self.name + ": Connection failed to the host " +
261 self.user_name + "@" + self.ip_address )
262 main.log.error( self.name + ": Failed to connect to the Mininet" )
263 return main.FALSE
264 except pexpect.TIMEOUT:
265 main.log.exception( self.name + ": TIMEOUT exception found while starting Mininet" )
266 main.log.error( self.name + ": " + self.handle.before )
adminbae64d82013-08-01 10:50:15 -0700267 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700268 except pexpect.EOF:
269 main.log.error( self.name + ": EOF exception found" )
270 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700271 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700272 except Exception:
273 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700274 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800275
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800276 def numSwitchesNlinks( self, topoType, depth, fanout ):
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700277 try:
278 if topoType == 'tree':
279 # In tree topology, if fanout arg is not given, by default it is 2
280 if fanout is None:
281 fanout = 2
282 k = 0
283 count = 0
284 while( k <= depth - 1 ):
285 count = count + pow( fanout, k )
286 k = k + 1
287 numSwitches = count
288 while( k <= depth - 2 ):
289 # depth-2 gives you only core links and not considering
290 # edge links as seen by ONOS. If all the links including
291 # edge links are required, do depth-1
292 count = count + pow( fanout, k )
293 k = k + 1
294 numLinks = count * fanout
295 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
296 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800297
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700298 elif topoType == 'linear':
299 # In linear topology, if fanout or numHostsPerSw is not given,
300 # by default it is 1
301 if fanout is None:
302 fanout = 1
303 numSwitches = depth
304 numHostsPerSw = fanout
305 totalNumHosts = numSwitches * numHostsPerSw
306 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hallab611372018-02-21 15:26:05 -0800307 main.log.debug( "num_switches for %s(%d,%d) = %d and links=%d" %
308 ( topoType, depth, fanout, numSwitches, numLinks ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700309 topoDict = { "num_switches": int( numSwitches ),
310 "num_corelinks": int( numLinks ) }
311 return topoDict
312 except Exception:
313 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700314 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400315
kelvin-onlabd3b64892015-01-20 13:26:24 -0800316 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700317 """
318 Calculate the number of switches and links in a topo."""
319 # TODO: combine this function and numSwitchesNlinks
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700320 try:
321 argList = self.options[ 'arg1' ].split( "," )
322 topoArgList = argList[ 0 ].split( " " )
323 argList = map( int, argList[ 1: ] )
324 topoArgList = topoArgList[ 1: ] + argList
Jon Hall689d8e42015-04-03 13:59:24 -0700325
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700326 topoDict = self.numSwitchesNlinks( *topoArgList )
327 return topoDict
328 except Exception:
329 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700330 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400331
GlennRCf07c44a2015-09-18 13:33:46 -0700332 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800333 """
334 Verifies the reachability of the hosts using pingall command.
335 Optional parameter timeout allows you to specify how long to
336 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700337 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700338 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700339 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700340 ping
341 acceptableFailed - Set the number of acceptable failed pings for the
342 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800343 Returns:
344 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700345 otherwise main.FALSE
346 """
347 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700348 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700349 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700350 if self.handle:
351 main.log.info(
352 self.name +
353 ": Checking reachabilty to the hosts using pingall" )
354 response = ""
355 failedPings = 0
356 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700357 cmd = "pingall"
358 if protocol == "IPv6":
359 cmd = "py net.pingAll6()"
360 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700361 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700362 while True:
Jon Hallf6aeda22020-07-28 09:12:56 -0700363 i = self.handle.expect( [ self.mnPrompt, "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700364 pexpect.EOF,
365 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700366 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700367 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700368 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700369 response += self.handle.before
370 break
371 elif i == 1:
372 response += self.handle.before + self.handle.after
373 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700374 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700375 returnValue = main.FALSE
376 if shortCircuit:
377 main.log.error( self.name +
378 ": Aborting pingall - "
379 + str( failedPings ) +
380 " pings failed" )
381 break
Jon Hall390696c2015-05-05 17:13:41 -0700382 if ( time.time() - startTime ) > timeout:
383 returnValue = main.FALSE
384 main.log.error( self.name +
385 ": Aborting pingall - " +
386 "Function took too long " )
387 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700388 elif i == 2:
389 main.log.error( self.name +
390 ": EOF exception found" )
391 main.log.error( self.name + ": " +
392 self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700393 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700394 elif i == 3:
395 response += self.handle.before
396 main.log.error( self.name +
397 ": TIMEOUT exception found" )
398 main.log.error( self.name +
399 ": " +
400 str( response ) )
401 # NOTE: Send ctrl-c to make sure pingall is done
Jon Hallf6aeda22020-07-28 09:12:56 -0700402 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
You Wang7ce29462019-03-04 13:37:14 -0800403 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -0700404 self.handle.expect( self.mnPrompt )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700405 break
406 pattern = "Results\:"
407 main.log.info( "Pingall output: " + str( response ) )
408 if re.search( pattern, response ):
409 main.log.info( self.name + ": Pingall finished with "
410 + str( failedPings ) + " failed pings" )
411 return returnValue
412 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700413 # NOTE: Send ctrl-c to make sure pingall is done
Jon Hallf6aeda22020-07-28 09:12:56 -0700414 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
You Wang7ce29462019-03-04 13:37:14 -0800415 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -0700416 self.handle.expect( self.mnPrompt )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700417 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700418 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700419 main.log.error( self.name + ": Connection failed to the host" )
Devin Lim44075962017-08-11 10:56:37 -0700420 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700421 except pexpect.TIMEOUT:
422 if response:
423 main.log.info( "Pingall output: " + str( response ) )
424 main.log.error( self.name + ": pexpect.TIMEOUT found" )
425 return main.FALSE
426 except pexpect.EOF:
427 main.log.error( self.name + ": EOF exception found" )
428 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700429 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -0700430
Jon Hall7eb38402015-01-08 17:19:54 -0800431 def fpingHost( self, **pingParams ):
432 """
433 Uses the fping package for faster pinging...
434 *requires fping to be installed on machine running mininet"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700435 try:
436 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
437 command = args[ "SRC" ] + \
438 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
439 self.handle.sendline( command )
440 self.handle.expect(
441 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
442 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
443 response = self.handle.before
444 if re.search( ":\s-", response ):
445 main.log.info( self.name + ": Ping fail" )
446 return main.FALSE
447 elif re.search( ":\s\d{1,2}\.\d\d", response ):
448 main.log.info( self.name + ": Ping good!" )
449 return main.TRUE
450 main.log.info( self.name + ": Install fping on mininet machine... " )
451 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700452 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700453 except Exception:
454 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700455 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700456
Jon Hall3b489db2015-10-05 14:38:37 -0700457 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400458 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700459 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700460
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400461 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700462 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700463
464 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400465 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700466
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400467 Returns main.FALSE if one or more of hosts specified
468 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700469 wait = int( wait )
470 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400471
472 try:
473 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700474
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400475 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700476 pingResponse = "IPv4 ping across specified hosts\n"
477 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400478 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700479 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400480 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700481 pingList = hostList[ :listIndex ] + \
482 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700483
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700484 pingResponse += str( str( host ) + " -> " )
GlennRCd10d3cc2015-09-24 12:47:16 -0700485
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400486 for temp in pingList:
487 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700488 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700489 self.handle.sendline( pingCmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700490 self.handle.expect( self.mnPrompt, timeout=wait + 5 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400491 response = self.handle.before
492 if re.search( ',\s0\%\spacket\sloss', response ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700493 pingResponse += str( " h" + str( temp[ 1: ] ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400494 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700495 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400496 # One of the host to host pair is unreachable
497 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700498 failedPings += 1
You Wang11f9ead2018-03-21 14:34:59 -0700499 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
GlennRCd10d3cc2015-09-24 12:47:16 -0700500 pingResponse += "\n"
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700501 main.log.info( pingResponse + "Failed pings: " + str( failedPings ) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700502 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700503 except pexpect.TIMEOUT:
504 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800505 response = self.handle.before
506 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hallf6aeda22020-07-28 09:12:56 -0700507 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
Jon Hall3c910162018-03-07 14:42:16 -0800508 response += self.handle.before + self.handle.after
You Wang7ce29462019-03-04 13:37:14 -0800509 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -0700510 self.handle.expect( self.mnPrompt )
Jon Hall3c910162018-03-07 14:42:16 -0800511 response += self.handle.before + self.handle.after
512 main.log.debug( response )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700513 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400514 except pexpect.EOF:
515 main.log.error( self.name + ": EOF exception found" )
516 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700517 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700518 except Exception:
519 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700520 main.cleanAndExit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400521
You Wangf19d9f42018-02-23 16:34:19 -0800522 def pingIpv6Hosts( self, hostList, wait=1, acceptableFailed=0 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700523 """
You Wangf19d9f42018-02-23 16:34:19 -0800524 IPv6 ping all hosts in hostList.
525
526 acceptableFailed: max number of acceptable failed pings
Hari Krishna9592fc82015-07-31 15:11:15 -0700527
Jon Hall3b489db2015-10-05 14:38:37 -0700528 Returns main.TRUE if all hosts specified can reach each other
Jon Hall3b489db2015-10-05 14:38:37 -0700529 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700530 """
531 try:
532 main.log.info( "Testing reachability between specified IPv6 hosts" )
533 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700534 wait = int( wait )
535 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700536 pingResponse = "IPv6 Pingall output:\n"
You Wangf19d9f42018-02-23 16:34:19 -0800537 failedPingsTotal = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700538 for host in hostList:
539 listIndex = hostList.index( host )
540 # List of hosts to ping other than itself
541 pingList = hostList[ :listIndex ] + \
542 hostList[ ( listIndex + 1 ): ]
543
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700544 pingResponse += str( str( host ) + " -> " )
GlennRC2cf7d952015-09-11 16:32:13 -0700545
Hari Krishna9592fc82015-07-31 15:11:15 -0700546 for temp in pingList:
547 # Current host pings all other hosts specified
You Wangf19d9f42018-02-23 16:34:19 -0800548 failedPings = 0
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700549 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
You Wangf19d9f42018-02-23 16:34:19 -0800550 while failedPings <= acceptableFailed:
551 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
552 self.handle.sendline( pingCmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700553 self.handle.expect( self.mnPrompt, timeout=wait + 5 )
You Wangf19d9f42018-02-23 16:34:19 -0800554 response = self.handle.before
555 if re.search( ',\s0\%\spacket\sloss', response ):
You Wangba231e72018-03-01 13:18:21 -0800556 pingResponse += " " + str( temp )
557 break
558 else:
559 failedPings += 1
560 time.sleep(1)
561 if failedPings > acceptableFailed:
562 # One of the host to host pair is unreachable
563 pingResponse += " X"
564 isReachable = main.FALSE
565 failedPingsTotal += 1
You Wang11f9ead2018-03-21 14:34:59 -0700566 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
You Wangba231e72018-03-01 13:18:21 -0800567 pingResponse += "\n"
568 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
569 return isReachable
570
571 except pexpect.TIMEOUT:
572 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800573 response = self.handle.before
574 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hallf6aeda22020-07-28 09:12:56 -0700575 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
Jon Hall3c910162018-03-07 14:42:16 -0800576 response += self.handle.before + self.handle.after
You Wang7ce29462019-03-04 13:37:14 -0800577 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -0700578 self.handle.expect( self.mnPrompt )
Jon Hall3c910162018-03-07 14:42:16 -0800579 response += self.handle.before + self.handle.after
580 main.log.debug( response )
You Wangba231e72018-03-01 13:18:21 -0800581 return main.FALSE
582 except pexpect.EOF:
583 main.log.error( self.name + ": EOF exception found" )
584 main.log.error( self.name + ": " + self.handle.before )
585 main.cleanAndExit()
586 except Exception:
587 main.log.exception( self.name + ": Uncaught exception!" )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700588
589 main.cleanAndExit()
590
You Wang32833172018-10-23 15:19:31 -0700591 def discoverHosts( self, hostList=[], wait=1000, dstIp="6.6.6.6", dstIp6="1020::3fe" ):
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700592 '''
You Wang32833172018-10-23 15:19:31 -0700593 Hosts in hostList will do a single ARP/ND to a non-existent address for ONOS to
594 discover them. A host will use arping/ndisc6 to send ARP/ND depending on if it
595 has IPv4/IPv6 addresses configured.
You Wang48381752018-05-07 13:50:57 -0700596 Optional:
597 hostList: a list of names of the hosts that need to be discovered. If not
598 specified mininet will send ping from all the hosts
You Wang32833172018-10-23 15:19:31 -0700599 wait: timeout for ARP/ND in milliseconds
You Wang48381752018-05-07 13:50:57 -0700600 dstIp: destination address used by IPv4 hosts
601 dstIp6: destination address used by IPv6 hosts
602 Returns:
You Wang32833172018-10-23 15:19:31 -0700603 main.TRUE if all packets were successfully sent. Otherwise main.FALSE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700604 '''
605 try:
You Wang32833172018-10-23 15:19:31 -0700606 hosts = self.getHosts()
You Wang48381752018-05-07 13:50:57 -0700607 if not hostList:
You Wang48381752018-05-07 13:50:57 -0700608 hostList = hosts.keys()
609 discoveryResult = main.TRUE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700610 for host in hostList:
You Wang0b82aa52018-06-06 14:33:58 -0700611 flushCmd = ""
You Wang036ec2c2019-02-27 15:44:15 -0800612 cmds = []
You Wang48381752018-05-07 13:50:57 -0700613 if self.getIPAddress( host ):
You Wang0b82aa52018-06-06 14:33:58 -0700614 flushCmd = "{} ip neigh flush all".format( host )
Jon Hall43060f62020-06-23 13:13:33 -0700615 intf = hosts[ host ][ 'interfaces' ][ 0 ].get( 'name' )
616 intfStr = "-i {}".format( intf ) if intf else ""
617 cmds.append( "{} arping -c 1 -w {} {} {}".format(
618 host, wait, intfStr, dstIp ) )
You Wang32833172018-10-23 15:19:31 -0700619 main.log.debug( "Sending IPv4 arping from host {}".format( host ) )
You Wang48381752018-05-07 13:50:57 -0700620 elif self.getIPAddress( host, proto='IPV6' ):
You Wang0b82aa52018-06-06 14:33:58 -0700621 flushCmd = "{} ip -6 neigh flush all".format( host )
You Wang036ec2c2019-02-27 15:44:15 -0800622 # FIXME: we are using the same ipv6Addr for all interfaces
623 ipv6Addr = self.getIPAddress( host, proto='IPV6' )
You Wangad347c92019-02-20 16:13:47 -0800624 for intf in hosts[ host ][ 'interfaces' ]:
625 intfName = intf[ 'name' ]
You Wang036ec2c2019-02-27 15:44:15 -0800626 cmds.append( "{} ndsend {} {}".format( host, ipv6Addr, intfName ) )
You Wangad347c92019-02-20 16:13:47 -0800627 main.log.debug( "Sending IPv6 ND from interface {} on host {}".format( intfName, host ) )
You Wang48381752018-05-07 13:50:57 -0700628 else:
629 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
630 discoveryResult = main.FALSE
You Wang036ec2c2019-02-27 15:44:15 -0800631 if flushCmd:
You Wang0b82aa52018-06-06 14:33:58 -0700632 self.handle.sendline( flushCmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700633 self.handle.expect( self.mnPrompt )
You Wang036ec2c2019-02-27 15:44:15 -0800634 for cmd in cmds:
You Wang48381752018-05-07 13:50:57 -0700635 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700636 self.handle.expect( self.mnPrompt, timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700637 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700638 except pexpect.TIMEOUT:
639 main.log.exception( self.name + ": TIMEOUT exception" )
640 response = self.handle.before
641 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hallf6aeda22020-07-28 09:12:56 -0700642 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700643 response += self.handle.before + self.handle.after
You Wang7ce29462019-03-04 13:37:14 -0800644 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -0700645 self.handle.expect( self.mnPrompt )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700646 response += self.handle.before + self.handle.after
647 main.log.debug( response )
648 return main.FALSE
649 except pexpect.EOF:
650 main.log.error( self.name + ": EOF exception found" )
651 main.log.error( self.name + ": " + self.handle.before )
652 main.cleanAndExit()
653 except Exception:
654 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800655 main.cleanAndExit()
656
657 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
658 """
659 Verify ping from each host in srcList to each host in dstList
660
661 acceptableFailed: max number of acceptable failed pings
662
663 Returns main.TRUE if all src hosts can reach all dst hosts
664 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
665 """
666 try:
667 main.log.info( "Verifying ping from each src host to each dst host" )
668 isReachable = main.TRUE
669 wait = int( wait )
670 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
671 pingResponse = "Ping output:\n"
672 failedPingsTotal = 0
673 for host in srcList:
674 pingResponse += str( str( host ) + " -> " )
675 for temp in dstList:
676 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700677 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
678 assert dstIP, "Not able to get IP address of host {}".format( temp )
679 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800680 while failedPings <= acceptableFailed:
681 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
682 self.handle.sendline( pingCmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700683 self.handle.expect( self.mnPrompt, timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800684 response = self.handle.before
685 if re.search( ',\s0\%\spacket\sloss', response ):
686 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800687 break
688 else:
689 failedPings += 1
690 time.sleep(1)
691 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700692 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800693 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700694 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800695 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700696 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800697 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700698 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700699 except AssertionError:
700 main.log.exception( "" )
701 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700702 except pexpect.TIMEOUT:
703 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800704 response = self.handle.before
705 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hallf6aeda22020-07-28 09:12:56 -0700706 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
Jon Hall3c910162018-03-07 14:42:16 -0800707 response += self.handle.before + self.handle.after
You Wang7ce29462019-03-04 13:37:14 -0800708 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -0700709 self.handle.expect( self.mnPrompt )
Jon Hall3c910162018-03-07 14:42:16 -0800710 response += self.handle.before + self.handle.after
711 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700712 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700713 except pexpect.EOF:
714 main.log.error( self.name + ": EOF exception found" )
715 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700716 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700717 except Exception:
718 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700719 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700720
Jon Hall7eb38402015-01-08 17:19:54 -0800721 def pingHost( self, **pingParams ):
722 """
Jon Hall3b489db2015-10-05 14:38:37 -0700723 Ping from one mininet host to another
724 Currently the only supported Params: SRC, TARGET, and WAIT
725 """
726 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700727 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700728 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800729 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700730 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700731 try:
Jon Hall61282e32015-03-19 11:34:11 -0700732 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800733 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700734 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700735 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700736 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800737 main.log.error(
738 self.name +
739 ": timeout when waiting for response from mininet" )
740 main.log.error( "response: " + str( self.handle.before ) )
Jon Hallf6aeda22020-07-28 09:12:56 -0700741 i = self.handle.expect( [ self.mnPrompt, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700742 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800743 main.log.error(
744 self.name +
745 ": timeout when waiting for response from mininet" )
746 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700747 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700748 if re.search( ',\s0\%\spacket\sloss', response ):
749 main.log.info( self.name + ": no packets lost, host is reachable" )
750 return main.TRUE
751 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800752 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700753 self.name +
754 ": PACKET LOST, HOST IS NOT REACHABLE" )
755 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800756 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800757 main.log.error( self.name + ": EOF exception found" )
758 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700759 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700760 except Exception:
761 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700762 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700763
764 def ping6pair( self, **pingParams ):
765 """
GlennRC2cf7d952015-09-11 16:32:13 -0700766 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700767 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000768 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700769 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
770 """
Jon Hall3b489db2015-10-05 14:38:37 -0700771 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700772 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700773 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530774 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700775 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700776 try:
777 main.log.info( "Sending: " + command )
778 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700779 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700780 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700781 if i == 1:
782 main.log.error(
783 self.name +
784 ": timeout when waiting for response from mininet" )
785 main.log.error( "response: " + str( self.handle.before ) )
Jon Hallf6aeda22020-07-28 09:12:56 -0700786 i = self.handle.expect( [ self.mnPrompt, pexpect.TIMEOUT ] )
Hari Krishna012a1c12015-08-25 14:23:58 -0700787 if i == 1:
788 main.log.error(
789 self.name +
790 ": timeout when waiting for response from mininet" )
791 main.log.error( "response: " + str( self.handle.before ) )
792 response = self.handle.before
793 main.log.info( self.name + ": Ping Response: " + response )
794 if re.search( ',\s0\%\spacket\sloss', response ):
795 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700796 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700797 else:
alisone4121a92016-11-22 16:31:36 -0800798 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700799 self.name +
800 ": PACKET LOST, HOST IS NOT REACHABLE" )
801 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700802 except pexpect.EOF:
803 main.log.error( self.name + ": EOF exception found" )
804 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700805 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700806 except Exception:
807 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700808 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800809
You Wangdb927a52016-02-26 11:03:28 -0800810 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
811 """
812 Description:
813 Ping a set of destination host from host CLI.
814 Logging into a Mininet host CLI is required before calling this funtion.
815 Params:
816 dstIPList is a list of destination ip addresses
817 Returns:
818 main.TRUE if the destination host is reachable
819 main.FALSE otherwise
820 """
821 isReachable = main.TRUE
822 wait = int( wait )
823 cmd = "ping"
824 if IPv6:
825 cmd = cmd + "6"
826 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
827 try:
828 for dstIP in dstIPList:
829 pingCmd = cmd + " " + dstIP
830 self.handle.sendline( pingCmd )
831 i = self.handle.expect( [ self.hostPrompt,
832 '\*\*\* Unknown command: ' + pingCmd,
833 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700834 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700835 # For some reason we need to send something
836 # Otherwise ping results won't be read by handle
Jon Hall43060f62020-06-23 13:13:33 -0700837 response = self.handle.before
You Wang5da39c82018-04-26 22:55:08 -0700838 self.handle.sendline( "" )
839 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800840 if i == 0:
Jon Hall43060f62020-06-23 13:13:33 -0700841 response += self.handle.before
You Wangdb927a52016-02-26 11:03:28 -0800842 if not re.search( ',\s0\%\spacket\sloss', response ):
843 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
844 isReachable = main.FALSE
845 elif i == 1:
846 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700847 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800848 elif i == 2:
849 main.log.error( self.name + ": timeout when waiting for response" )
850 isReachable = main.FALSE
851 else:
852 main.log.error( self.name + ": unknown response: " + self.handle.before )
853 isReachable = main.FALSE
854 except pexpect.TIMEOUT:
855 main.log.exception( self.name + ": TIMEOUT exception" )
You Wangd4fae5c2018-08-22 13:56:49 -0700856 self.exitFromCmd( [ self.hostPrompt, self.bashPrompt ] )
You Wangdb927a52016-02-26 11:03:28 -0800857 isReachable = main.FALSE
858 except pexpect.EOF:
859 main.log.error( self.name + ": EOF exception found" )
860 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700861 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800862 except Exception:
863 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700864 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800865 return isReachable
866
Jon Hall7eb38402015-01-08 17:19:54 -0800867 def checkIP( self, host ):
868 """
869 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700870 try:
871 if self.handle:
872 try:
873 response = self.execute(
874 cmd=host +
875 " ifconfig",
Jon Hallf6aeda22020-07-28 09:12:56 -0700876 prompt=self.mnPrompt,
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700877 timeout=10 )
878 except pexpect.EOF:
879 main.log.error( self.name + ": EOF exception found" )
880 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700881 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700882
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700883 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
884 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
885 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
886 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
887 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
888 "[0-9]|25[0-5]|[0-9]{1,2})"
889 # pattern = "inet addr:10.0.0.6"
890 if re.search( pattern, response ):
891 main.log.info( self.name + ": Host Ip configured properly" )
892 return main.TRUE
893 else:
894 main.log.error( self.name + ": Host IP not found" )
895 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700896 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700897 main.log.error( self.name + ": Connection failed to the host" )
898 except Exception:
899 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700900 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800901
Jon Hall7eb38402015-01-08 17:19:54 -0800902 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800903 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700904 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800905 response = self.execute(
906 cmd="h1 /usr/sbin/sshd -D&",
Jon Hallf6aeda22020-07-28 09:12:56 -0700907 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -0800908 timeout=10 )
909 response = self.execute(
910 cmd="h4 /usr/sbin/sshd -D&",
Jon Hallf6aeda22020-07-28 09:12:56 -0700911 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -0800912 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700913 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800914 vars( self )[ key ] = connectargs[ key ]
915 response = self.execute(
916 cmd="xterm h1 h4 ",
Jon Hallf6aeda22020-07-28 09:12:56 -0700917 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -0800918 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800919 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800920 main.log.error( self.name + ": EOF exception found" )
921 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700922 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700923 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800924 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700925 if self.flag == 0:
926 self.flag = 1
927 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800928 else:
adminbae64d82013-08-01 10:50:15 -0700929 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800930
Jon Hall7eb38402015-01-08 17:19:54 -0800931 def changeIP( self, host, intf, newIP, newNetmask ):
932 """
933 Changes the ip address of a host on the fly
934 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800935 if self.handle:
936 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800937 cmd = host + " ifconfig " + intf + " " + \
938 newIP + " " + 'netmask' + " " + newNetmask
939 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700940 self.handle.expect( self.mnPrompt )
shahshreyae6c7cf42014-11-26 16:39:01 -0800941 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800942 main.log.info( "response = " + response )
943 main.log.info(
944 "Ip of host " +
945 host +
946 " changed to new IP " +
947 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800948 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700949 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700950 main.log.error( self.name + ": TIMEOUT exception found" )
951 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700952 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800953 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800954 main.log.error( self.name + ": EOF exception found" )
955 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800956 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700957 except Exception:
958 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700959 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800960
Jon Hall7eb38402015-01-08 17:19:54 -0800961 def changeDefaultGateway( self, host, newGW ):
962 """
963 Changes the default gateway of a host
964 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800965 if self.handle:
966 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800967 cmd = host + " route add default gw " + newGW
968 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700969 self.handle.expect( self.mnPrompt )
shahshreyae6c7cf42014-11-26 16:39:01 -0800970 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800971 main.log.info( "response = " + response )
972 main.log.info(
973 "Default gateway of host " +
974 host +
975 " changed to " +
976 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800977 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700978 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700979 main.log.error( self.name + ": TIMEOUT exception found" )
980 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700981 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800982 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800983 main.log.error( self.name + ": EOF exception found" )
984 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800985 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700986 except Exception:
987 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700988 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800989
You Wange24d6272018-03-27 21:18:50 -0700990 def addRoute( self, host, dstIP, interface, ipv6=False ):
991 """
992 Add a route to host
993 Ex: h1 route add -host 224.2.0.1 h1-eth0
994 """
995 if self.handle:
996 try:
997 cmd = str( host )
998 if ipv6:
999 cmd += " route -A inet6 add "
1000 else:
1001 cmd += " route add -host "
1002 cmd += str( dstIP ) + " " + str( interface )
1003 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07001004 self.handle.expect( self.mnPrompt )
You Wange24d6272018-03-27 21:18:50 -07001005 response = self.handle.before
1006 main.log.debug( "response = " + response )
1007 return main.TRUE
1008 except pexpect.TIMEOUT:
1009 main.log.error( self.name + ": TIMEOUT exception found" )
1010 main.log.error( self.name + ": " + self.handle.before )
1011 main.cleanAndExit()
1012 except pexpect.EOF:
1013 main.log.error( self.name + ": EOF exception found" )
1014 main.log.error( self.name + ": " + self.handle.before )
1015 return main.FALSE
1016 except Exception:
1017 main.log.exception( self.name + ": Uncaught exception!" )
1018 main.cleanAndExit()
1019
Jon Hall7eb38402015-01-08 17:19:54 -08001020 def addStaticMACAddress( self, host, GW, macaddr ):
1021 """
Jon Hallefbd9792015-03-05 16:11:36 -08001022 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001023 if self.handle:
1024 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001025 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1026 cmd = host + " arp -s " + GW + " " + macaddr
1027 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07001028 self.handle.expect( self.mnPrompt )
shahshreyad0c80432014-12-04 16:56:05 -08001029 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001030 main.log.info( "response = " + response )
1031 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001032 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001033 GW +
1034 " changed to " +
1035 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001036 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001037 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001038 main.log.error( self.name + ": TIMEOUT exception found" )
1039 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001040 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001041 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001042 main.log.error( self.name + ": EOF exception found" )
1043 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001044 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001045 except Exception:
1046 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001047 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001048
Jon Hall7eb38402015-01-08 17:19:54 -08001049 def verifyStaticGWandMAC( self, host ):
1050 """
1051 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001052 if self.handle:
1053 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001054 # h1 arp -an
1055 cmd = host + " arp -an "
1056 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07001057 self.handle.expect( self.mnPrompt )
shahshreyad0c80432014-12-04 16:56:05 -08001058 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001059 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001060 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001061 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001062 main.log.error( self.name + ": TIMEOUT exception found" )
1063 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001064 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001065 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001066 main.log.error( self.name + ": EOF exception found" )
1067 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001068 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001069 except Exception:
1070 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001071 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001072
Jon Hall7eb38402015-01-08 17:19:54 -08001073 def getMacAddress( self, host ):
1074 """
1075 Verifies the host's ip configured or not."""
1076 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001077 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001078 response = self.execute(
1079 cmd=host +
1080 " ifconfig",
Jon Hallf6aeda22020-07-28 09:12:56 -07001081 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001082 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001083 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001084 main.log.error( self.name + ": EOF exception found" )
1085 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001086 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001087 except Exception:
1088 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001089 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001090
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001091 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001092 macAddressSearch = re.search( pattern, response, re.I )
1093 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001094 main.log.info(
1095 self.name +
1096 ": Mac-Address of Host " +
1097 host +
1098 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001099 macAddress )
1100 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001101 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001102 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001103
Jon Hall7eb38402015-01-08 17:19:54 -08001104 def getInterfaceMACAddress( self, host, interface ):
1105 """
1106 Return the IP address of the interface on the given host"""
1107 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001108 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001109 response = self.execute( cmd=host + " ifconfig " + interface,
Jon Hallf6aeda22020-07-28 09:12:56 -07001110 prompt=self.mnPrompt, timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001111 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001112 main.log.error( self.name + ": EOF exception found" )
1113 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001114 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001115 except Exception:
1116 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001117 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001118
1119 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001120 macAddressSearch = re.search( pattern, response, re.I )
1121 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001122 main.log.info( "No mac address found in %s" % response )
1123 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001124 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001125 main.log.info(
1126 "Mac-Address of " +
1127 host +
1128 ":" +
1129 interface +
1130 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001131 macAddress )
1132 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001133 else:
1134 main.log.error( "Connection failed to the host" )
1135
You Wang5da39c82018-04-26 22:55:08 -07001136 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001137 """
1138 Verifies the host's ip configured or not."""
1139 if self.handle:
1140 try:
1141 response = self.execute(
1142 cmd=host +
1143 " ifconfig",
Jon Hallf6aeda22020-07-28 09:12:56 -07001144 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001145 timeout=10 )
1146 except pexpect.EOF:
1147 main.log.error( self.name + ": EOF exception found" )
1148 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001149 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001150 except Exception:
1151 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001152 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001153
sathishmad953462015-12-03 17:42:07 +05301154 pattern = ''
1155 if proto == 'IPV4':
Jon Hall43060f62020-06-23 13:13:33 -07001156 ip4Pat = r"(\d+\.\d+\.\d+\.\d+)"
1157 pattern = r"inet\s(addr:)?(?P<ip>" + ip4Pat + ")\s\s((Bcast:" + ip4Pat + "\s\s|netmask\s" + ip4Pat + "\s\sbroadcast\s" + ip4Pat + "))"
sathishmad953462015-12-03 17:42:07 +05301158 else:
Jon Hall43060f62020-06-23 13:13:33 -07001159 inet6Pat = r'(?P<ip>((?:[0-9a-fA-F]{1,4})?(?:[:0-9a-fA-F]{1,4}){1,7}(?:::)?(?:[:0-9a-fA-F]{1,4}){1,7}))'
1160 pattern = r"inet6\s(addr:\s)?" + inet6Pat + r"(/\d+)?\s(Scope:(Global|Link)|\sprefixlen\s(\d)+\s\sscopeid 0x(\d+)\<(link|global>))"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001161 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001162 if not ipAddressSearch:
Jon Hall43060f62020-06-23 13:13:33 -07001163 main.log.debug( response )
1164 main.log.warn( "Could not find %s address" % proto )
Jon Hall3c910162018-03-07 14:42:16 -08001165 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001166 main.log.info(
1167 self.name +
1168 ": IP-Address of Host " +
1169 host +
1170 " is " +
Jon Hall43060f62020-06-23 13:13:33 -07001171 ipAddressSearch.group( 'ip' ) )
1172 return ipAddressSearch.group( 'ip' )
Jon Hall7eb38402015-01-08 17:19:54 -08001173 else:
1174 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001175
Jon Hall7eb38402015-01-08 17:19:54 -08001176 def getSwitchDPID( self, switch ):
1177 """
1178 return the datapath ID of the switch"""
1179 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001180 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001181 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001182 response = self.execute(
1183 cmd=cmd,
Jon Hallf6aeda22020-07-28 09:12:56 -07001184 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001185 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001186 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001187 main.log.error( self.name + ": EOF exception found" )
1188 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001189 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001190 except Exception:
1191 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001192 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001193 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001194 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001195 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001196 main.log.info(
1197 "Couldn't find DPID for switch %s, found: %s" %
1198 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001199 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001200 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001201 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001202 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001203
Jon Hall7eb38402015-01-08 17:19:54 -08001204 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001205 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001206 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07001207 self.expect( self.mnPrompt )
Jon Hall7eb38402015-01-08 17:19:54 -08001208 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001209 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001210 response = self.execute(
1211 cmd=cmd,
Jon Hallf6aeda22020-07-28 09:12:56 -07001212 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001213 timeout=10 )
Jon Hallf6aeda22020-07-28 09:12:56 -07001214 self.handle.expect( self.mnPrompt )
admin2580a0e2014-07-29 11:24:34 -07001215 response = self.handle.before
1216 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001217 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001218 main.log.error( self.name + ": TIMEOUT exception found" )
1219 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001220 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001221 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001222 main.log.error( self.name + ": EOF exception found" )
1223 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001224 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001225 except Exception:
1226 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001227 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001228
Jon Hall7eb38402015-01-08 17:19:54 -08001229 def getInterfaces( self, node ):
1230 """
1231 return information dict about interfaces connected to the node"""
1232 if self.handle:
1233 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001234 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001235 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001236 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001237 response = self.execute(
1238 cmd=cmd,
Jon Hallf6aeda22020-07-28 09:12:56 -07001239 prompt=self.mnPrompt,
You Wang7d14d642019-01-23 15:10:08 -08001240 timeout=10,
1241 logCmd=False )
Jon Hallfbc828e2015-01-06 17:30:19 -08001242 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001243 main.log.error( self.name + ": EOF exception found" )
1244 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001245 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001246 except Exception:
1247 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001248 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001249 return response
1250 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001251 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001252
Jon Hall7eb38402015-01-08 17:19:54 -08001253 def dump( self ):
1254 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001255 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001256 response = self.execute(
1257 cmd='dump',
Jon Hall3c0114c2020-08-11 15:07:42 -07001258 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001259 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001260 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001261 main.log.error( self.name + ": EOF exception found" )
1262 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001263 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001264 except Exception:
1265 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001266 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001267 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001268
Jon Hall7eb38402015-01-08 17:19:54 -08001269 def intfs( self ):
1270 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001271 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001272 response = self.execute(
1273 cmd='intfs',
Jon Hall3c0114c2020-08-11 15:07:42 -07001274 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001275 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001276 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001277 main.log.error( self.name + ": EOF exception found" )
1278 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001279 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001280 except Exception:
1281 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001282 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001283 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001284
Jon Hall7eb38402015-01-08 17:19:54 -08001285 def net( self ):
1286 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001287 try:
Jon Hall3c0114c2020-08-11 15:07:42 -07001288 response = self.execute( cmd='net', prompt=self.mnPrompt, timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001289 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001290 main.log.error( self.name + ": EOF exception found" )
1291 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001292 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001293 except Exception:
1294 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001295 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001296 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001297
Devin Lima7cfdbd2017-09-29 15:02:22 -07001298 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001299 main.log.info( self.name + ": List network links" )
1300 try:
Jon Hall3c0114c2020-08-11 15:07:42 -07001301 response = self.execute( cmd='links', prompt=self.mnPrompt,
YPZhang81a7d4e2016-04-18 13:10:17 -07001302 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001303 except pexpect.EOF:
1304 main.log.error( self.name + ": EOF exception found" )
1305 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001306 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001307 except Exception:
1308 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001309 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001310 return response
1311
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001312 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001313 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001314 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001315
kelvin-onlab7cce9382015-07-17 10:21:03 -07001316 @parm:
1317 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1318 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001319 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001320 try:
1321 for host1 in hosts:
1322 for host2 in hosts:
1323 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001324 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1325 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001326 except Exception:
1327 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001328 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001329
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001330 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001331 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001332 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1333 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001334
kelvin-onlab7cce9382015-07-17 10:21:03 -07001335 @parm:
1336 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1337 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001338 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001339 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1340 try:
1341 # Setup the mininet command
1342 cmd1 = 'iperf ' + host1 + " " + host2
1343 self.handle.sendline( cmd1 )
Jon Hallf6aeda22020-07-28 09:12:56 -07001344 outcome = self.handle.expect( self.mnPrompt, timeout )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001345 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001346
kelvin-onlab7cce9382015-07-17 10:21:03 -07001347 # checks if there are results in the mininet response
1348 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001349 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001350 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001351 response = response.split( "\r\n" )
1352 response = response[ len( response )-2 ]
1353 response = response.split( ": " )
1354 response = response[ len( response )-1 ]
1355 response = response.replace( "[", "" )
1356 response = response.replace( "]", "" )
1357 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001358
kelvin-onlab7cce9382015-07-17 10:21:03 -07001359 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001360 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001361
kelvin-onlab7cce9382015-07-17 10:21:03 -07001362 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001363 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001364 if len( bandwidth ) == 2:
1365 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001366 return main.TRUE
1367 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001368 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001369 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001370 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001371 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001372 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001373 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001374 main.log.error( self.name + ": TIMEOUT exception found" )
1375 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001376 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001377 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hallf6aeda22020-07-28 09:12:56 -07001378 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
You Wang7ce29462019-03-04 13:37:14 -08001379 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07001380 self.handle.expect( self.mnPrompt )
GlennRC61321f22015-07-16 13:36:54 -07001381 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001382 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001383 main.log.error( self.name + ": EOF exception found" )
1384 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001385 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001386 except Exception:
1387 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001388 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001389
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001390 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001391 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1392 try:
1393 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001394 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001395 self.handle.sendline( cmd1 )
Jon Hallf6aeda22020-07-28 09:12:56 -07001396 outcome1 = self.handle.expect( self.mnPrompt )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001397 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001398 self.handle.sendline( cmd2 )
Jon Hallf6aeda22020-07-28 09:12:56 -07001399 outcome2 = self.handle.expect( self.mnPrompt )
Jon Hall439c8912016-04-15 02:22:03 -07001400 response1 = self.handle.before
1401 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001402 print response1, response2
1403 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001404 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001405 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001406 return main.TRUE
1407 else:
1408 main.log.error( self.name + ": iperf test failed" )
1409 return main.FALSE
1410 except pexpect.TIMEOUT:
1411 main.log.error( self.name + ": TIMEOUT exception found" )
1412 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hallf6aeda22020-07-28 09:12:56 -07001413 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
You Wang7ce29462019-03-04 13:37:14 -08001414 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07001415 self.handle.expect( self.mnPrompt )
Jon Hall439c8912016-04-15 02:22:03 -07001416 return main.FALSE
1417 except pexpect.EOF:
1418 main.log.error( self.name + ": EOF exception found" )
1419 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001420 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001421 except Exception:
1422 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001423 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001424
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001425 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001426 '''
GlennRC61321f22015-07-16 13:36:54 -07001427 Runs the iperfudp function with a given set of hosts and specified
1428 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001429
GlennRC61321f22015-07-16 13:36:54 -07001430 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001431 bandwidth: the targeted bandwidth, in megabits ('M')
1432 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001433 try:
1434 for host1 in hosts:
1435 for host2 in hosts:
1436 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001437 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1438 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001439 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001440 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001441 return main.FALSE
1442 except Exception:
1443 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001444 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001445
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001446 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001447 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001448 Creates an iperf UDP test with a specific bandwidth.
1449 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001450
kelvin-onlab7cce9382015-07-17 10:21:03 -07001451 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001452 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1453 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001454 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001455 try:
1456 # setup the mininet command
1457 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001458 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07001459 self.handle.expect( self.mnPrompt )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001460 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001461
kelvin-onlab7cce9382015-07-17 10:21:03 -07001462 # check if there are in results in the mininet response
1463 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001464 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001465 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001466 response = response.split( "\r\n" )
1467 response = response[ len( response )-2 ]
1468 response = response.split( ": " )
1469 response = response[ len( response )-1 ]
1470 response = response.replace( "[", "" )
1471 response = response.replace( "]", "" )
1472 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001473
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001474 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001475
kelvin-onlab7cce9382015-07-17 10:21:03 -07001476 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001477 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001478 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001479 # if one entry is blank then something is wrong
1480 for item in mnBandwidth:
1481 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001482 main.log.error( self.name + ": Could not parse iperf output" )
1483 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001484 return main.FALSE
1485 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001486 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001487 return main.TRUE
1488 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001489 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001490 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001491
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001492 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001493 main.log.error( self.name + ": TIMEOUT exception found" )
1494 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001495 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001496 except pexpect.EOF:
1497 main.log.error( self.name + ": EOF exception found" )
1498 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001499 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001500 except Exception:
1501 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001502 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001503
Jon Hall7eb38402015-01-08 17:19:54 -08001504 def nodes( self ):
1505 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001506 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001507 response = self.execute(
1508 cmd='nodes',
Jon Hall3c0114c2020-08-11 15:07:42 -07001509 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001510 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001511 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001512 main.log.error( self.name + ": EOF exception found" )
1513 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001514 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001515 except Exception:
1516 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001517 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001518 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001519
Jon Hall7eb38402015-01-08 17:19:54 -08001520 def pingpair( self ):
1521 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001522 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001523 response = self.execute(
1524 cmd='pingpair',
Jon Hall3c0114c2020-08-11 15:07:42 -07001525 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001526 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001527 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001528 main.log.error( self.name + ": EOF exception found" )
1529 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001530 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001531 except Exception:
1532 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001533 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001534
Jon Hall7eb38402015-01-08 17:19:54 -08001535 if re.search( ',\s0\%\spacket\sloss', response ):
1536 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001537 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001538 else:
alisone4121a92016-11-22 16:31:36 -08001539 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001540 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001541
Jon Hall7eb38402015-01-08 17:19:54 -08001542 def link( self, **linkargs ):
1543 """
GlennRCed771242016-01-13 17:02:47 -08001544 Bring link( s ) between two nodes up or down
1545 """
Jon Hall6094a362014-04-11 14:46:56 -07001546 try:
GlennRCed771242016-01-13 17:02:47 -08001547 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1548 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1549 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1550 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1551
1552 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1553 cmd = "link {} {} {}".format( end1, end2, option )
1554 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07001555 self.handle.expect( self.mnPrompt )
GlennRCed771242016-01-13 17:02:47 -08001556 response = self.handle.before
1557 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001558 if "not in network" in response:
1559 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1560 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001561 return main.TRUE
1562 except pexpect.TIMEOUT:
1563 main.log.exception( self.name + ": Command timed out" )
1564 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001565 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001566 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001567 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001568 except Exception:
1569 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001570 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001571
pingping-lin8244a3b2015-09-16 13:36:56 -07001572 def switch( self, **switchargs ):
1573 """
1574 start/stop a switch
1575 """
1576 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1577 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1578 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1579 command = "switch " + str( sw ) + " " + str( option )
1580 main.log.info( command )
1581 try:
1582 self.handle.sendline( command )
Jon Hallf6aeda22020-07-28 09:12:56 -07001583 self.handle.expect( self.mnPrompt )
pingping-lin8244a3b2015-09-16 13:36:56 -07001584 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001585 main.log.error( self.name + ": TIMEOUT exception found" )
1586 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001587 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001588 except pexpect.EOF:
1589 main.log.error( self.name + ": EOF exception found" )
1590 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001591 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001592 return main.TRUE
1593
pingping-lin5bb663b2015-09-24 11:47:50 -07001594 def node( self, nodeName, commandStr ):
1595 """
1596 Carry out a command line on a given node
1597 @parm:
1598 nodeName: the node name in Mininet testbed
1599 commandStr: the command line will be carried out on the node
1600 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1601 """
1602 command = str( nodeName ) + " " + str( commandStr )
1603 main.log.info( command )
1604
1605 try:
Jon Hallf6aeda22020-07-28 09:12:56 -07001606 response = self.execute( cmd = command, prompt = self.mnPrompt )
pingping-lin5bb663b2015-09-24 11:47:50 -07001607 if re.search( "Unknown command", response ):
1608 main.log.warn( response )
1609 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001610 if re.search( "Permission denied", response ):
1611 main.log.warn( response )
1612 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001613 except pexpect.EOF:
1614 main.log.error( self.name + ": EOF exception found" )
1615 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001616 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001617 main.log.info( " response is :" )
1618 main.log.info( response )
1619 return response
1620
Jon Hall7eb38402015-01-08 17:19:54 -08001621 def yank( self, **yankargs ):
1622 """
1623 yank a mininet switch interface to a host"""
1624 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001625 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001626 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1627 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001628 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001629 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001630 response = self.execute(
1631 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001632 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001633 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001634 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001635 main.log.error( self.name + ": EOF exception found" )
1636 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001637 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001638 except Exception:
1639 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001640 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001641 return main.TRUE
1642
Jon Hall7eb38402015-01-08 17:19:54 -08001643 def plug( self, **plugargs ):
1644 """
1645 plug the yanked mininet switch interface to a switch"""
1646 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001647 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001648 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1649 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001650 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001651 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001652 response = self.execute(
1653 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001654 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001655 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001656 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001657 main.log.error( self.name + ": EOF exception found" )
1658 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001659 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001660 except Exception:
1661 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001662 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001663 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001664
Jon Hall7eb38402015-01-08 17:19:54 -08001665 def dpctl( self, **dpctlargs ):
1666 """
1667 Run dpctl command on all switches."""
1668 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001669 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001670 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1671 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1672 command = "dpctl " + cmd + " " + str( cmdargs )
1673 try:
1674 response = self.execute(
1675 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001676 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001677 timeout=10 )
1678 except pexpect.EOF:
1679 main.log.error( self.name + ": EOF exception found" )
1680 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001681 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001682 except Exception:
1683 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001684 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001685 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001686
kelvin-onlabd3b64892015-01-20 13:26:24 -08001687 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001688 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001689 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001690 try:
1691 fileInput = path + '/lib/Mininet/INSTALL'
1692 version = super( Mininet, self ).getVersion()
1693 pattern = 'Mininet\s\w\.\w\.\w\w*'
1694 for line in open( fileInput, 'r' ).readlines():
1695 result = re.match( pattern, line )
1696 if result:
1697 version = result.group( 0 )
1698 return version
1699 except Exception:
1700 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001701 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001702
kelvin-onlabd3b64892015-01-20 13:26:24 -08001703 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001704 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001705 Parameters:
1706 sw: The name of an OVS switch. Example "s1"
1707 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001708 The output of the command from the mininet cli
1709 or main.FALSE on timeout"""
1710 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001711 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001712 response = self.execute(
1713 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001714 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001715 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001716 if response:
Jon Hallab611372018-02-21 15:26:05 -08001717 if "no bridge named" in response:
1718 main.log.error( self.name + ": Error in getSwController: " +
1719 self.handle.before )
1720 return main.FALSE
1721 else:
1722 return response
admin2a9548d2014-06-17 14:08:07 -07001723 else:
1724 return main.FALSE
1725 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001726 main.log.error( self.name + ": EOF exception found" )
1727 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001728 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001729 except Exception:
1730 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001731 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001732
Charles Chan029be652015-08-24 01:46:10 +08001733 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001734 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001735 Description:
1736 Assign switches to the controllers ( for ovs use only )
1737 Required:
1738 sw - Name of the switch. This can be a list or a string.
1739 ip - Ip addresses of controllers. This can be a list or a string.
1740 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001741 port - ONOS use port 6653, if no list of ports is passed, then
1742 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001743 ptcp - ptcp number, This can be a string or a list that has
1744 the same length as switch. This is optional and not required
1745 when using ovs switches.
1746 NOTE: If switches and ptcp are given in a list type they should have the
1747 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1748 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001749
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001750 Return:
1751 Returns main.TRUE if mininet correctly assigned switches to
1752 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001753 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001754 """
1755 assignResult = main.TRUE
1756 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001757 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001758 command = "sh ovs-vsctl set-controller "
1759 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001760 try:
1761 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001762 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001763 if isinstance( port, types.StringType ) or \
1764 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001765 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001766 elif isinstance( port, types.ListType ):
1767 main.log.error( self.name + ": Only one controller " +
1768 "assigned and a list of ports has" +
1769 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001770 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001771 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001772 main.log.error( self.name + ": Invalid controller port " +
1773 "number. Please specify correct " +
1774 "controller port" )
1775 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001776
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001777 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001778 if isinstance( port, types.StringType ) or \
1779 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001780 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001781 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1782 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001783 elif isinstance( port, types.ListType ):
1784 if ( len( ip ) != len( port ) ):
1785 main.log.error( self.name + ": Port list = " +
1786 str( len( port ) ) +
1787 "should be the same as controller" +
1788 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001789 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001790 else:
1791 onosIp = ""
1792 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001793 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1794 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001795 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001796 main.log.error( self.name + ": Invalid controller port " +
1797 "number. Please specify correct " +
1798 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001799 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001800 else:
1801 main.log.error( self.name + ": Invalid ip address" )
1802 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001803
1804 if isinstance( sw, types.StringType ):
1805 command += sw + " "
1806 if ptcp:
1807 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001808 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001809 elif isinstance( ptcp, types.ListType ):
1810 main.log.error( self.name + ": Only one switch is " +
1811 "being set and multiple PTCP is " +
1812 "being passed " )
1813 else:
1814 main.log.error( self.name + ": Invalid PTCP" )
1815 ptcp = ""
1816 command += onosIp
1817 commandList.append( command )
1818
1819 elif isinstance( sw, types.ListType ):
1820 if ptcp:
1821 if isinstance( ptcp, types.ListType ):
1822 if len( ptcp ) != len( sw ):
1823 main.log.error( self.name + ": PTCP length = " +
1824 str( len( ptcp ) ) +
1825 " is not the same as switch" +
1826 " length = " +
1827 str( len( sw ) ) )
1828 return main.FALSE
1829 else:
1830 for switch, ptcpNum in zip( sw, ptcp ):
1831 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001832 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001833 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001834 tempCmd += onosIp
1835 commandList.append( tempCmd )
1836 else:
1837 main.log.error( self.name + ": Invalid PTCP" )
1838 return main.FALSE
1839 else:
1840 for switch in sw:
1841 tempCmd = "sh ovs-vsctl set-controller "
1842 tempCmd += switch + " " + onosIp
1843 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001844 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001845 main.log.error( self.name + ": Invalid switch type " )
1846 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001847
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001848 for cmd in commandList:
1849 try:
Jon Hallf6aeda22020-07-28 09:12:56 -07001850 self.execute( cmd=cmd, prompt=self.mnPrompt, timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08001851 if "no bridge named" in self.handle.before:
1852 main.log.error( self.name + ": Error in assignSwController: " +
1853 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001854 except pexpect.TIMEOUT:
1855 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1856 return main.FALSE
1857 except pexpect.EOF:
1858 main.log.error( self.name + ": EOF exception found" )
1859 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001860 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001861 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001862 except pexpect.EOF:
1863 main.log.error( self.name + ": EOF exception found" )
1864 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001865 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001866 except Exception:
1867 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001868 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001869
kelvin-onlabd3b64892015-01-20 13:26:24 -08001870 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001871 """
1872 Removes the controller target from sw"""
1873 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001874 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001875 response = self.execute(
1876 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001877 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001878 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001879 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001880 main.log.error( self.name + ": EOF exception found" )
1881 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001882 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001883 except Exception:
1884 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001885 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001886 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001887 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001888
kelvin-onlabd3b64892015-01-20 13:26:24 -08001889 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001890 """
Jon Hallb1290e82014-11-18 16:17:48 -05001891 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001892 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001893 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001894 NOTE: cannot currently specify what type of switch
1895 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001896 sw = name of the new switch as a string
1897 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001898 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001899 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001900 """
1901 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001902 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001903 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001904 response = self.execute(
1905 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001906 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001907 timeout=10 )
1908 if re.search( "already exists!", response ):
1909 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001910 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001911 elif re.search( "Error", response ):
1912 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001913 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001914 elif re.search( "usage:", response ):
1915 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001916 return main.FALSE
1917 else:
1918 return main.TRUE
1919 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001920 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001921 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001922 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001923 except Exception:
1924 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001925 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001926
kelvin-onlabd3b64892015-01-20 13:26:24 -08001927 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001928 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001929 delete a switch from the mininet topology
1930 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001931 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001932 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001933 sw = name of the switch as a string
1934 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001935 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001936 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001937 response = self.execute(
1938 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001939 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001940 timeout=10 )
1941 if re.search( "no switch named", response ):
1942 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001943 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001944 elif re.search( "Error", response ):
1945 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001946 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001947 elif re.search( "usage:", response ):
1948 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001949 return main.FALSE
1950 else:
1951 return main.TRUE
1952 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001953 main.log.error( self.name + ": EOF exception found" )
1954 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001955 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001956 except Exception:
1957 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001958 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001959
You Wangb1665b52019-02-01 15:49:48 -08001960 def getSwitchRandom( self, timeout=60, nonCut=True, excludeNodes=[], skipSwitches=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07001961 """
1962 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001963 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001964 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001965 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07001966 it just randomly returns one switch from all current switches in
1967 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08001968 excludeNodes will be pased to getGraphDict method
You Wangb1665b52019-02-01 15:49:48 -08001969 Switches specified in skipSwitches will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07001970 Returns the name of the chosen switch.
1971 """
1972 import random
1973 candidateSwitches = []
1974 try:
1975 if not nonCut:
You Wangb1665b52019-02-01 15:49:48 -08001976 switches = self.getSwitches( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07001977 assert len( switches ) != 0
1978 for switchName in switches.keys():
1979 candidateSwitches.append( switchName )
1980 else:
You Wang7d14d642019-01-23 15:10:08 -08001981 graphDict = self.getGraphDict( timeout=timeout, useId=False,
You Wang7d14d642019-01-23 15:10:08 -08001982 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001983 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001984 return None
1985 self.graph.update( graphDict )
1986 candidateSwitches = self.graph.getNonCutVertices()
You Wangb1665b52019-02-01 15:49:48 -08001987 candidateSwitches = [ switch for switch in candidateSwitches if switch not in skipSwitches ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001988 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001989 return None
1990 elif len( candidateSwitches ) == 0:
1991 main.log.info( self.name + ": No candidate switch for deletion" )
1992 return None
1993 else:
1994 switch = random.sample( candidateSwitches, 1 )
1995 return switch[ 0 ]
1996 except KeyError:
1997 main.log.exception( self.name + ": KeyError exception found" )
1998 return None
1999 except AssertionError:
2000 main.log.exception( self.name + ": AssertionError exception found" )
2001 return None
2002 except Exception:
2003 main.log.exception( self.name + ": Uncaught exception" )
2004 return None
2005
2006 def delSwitchRandom( self, timeout=60, nonCut=True ):
2007 """
2008 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002009 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002010 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002011 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002012 otherwise it just randomly delete one switch from all current
2013 switches in Mininet.
2014 Returns the name of the deleted switch
2015 """
2016 try:
2017 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002018 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002019 return None
2020 else:
2021 deletionResult = self.delSwitch( switch )
2022 if deletionResult:
2023 return switch
2024 else:
2025 return None
2026 except Exception:
2027 main.log.exception( self.name + ": Uncaught exception" )
2028 return None
2029
kelvin-onlabd3b64892015-01-20 13:26:24 -08002030 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002031 """
2032 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002033 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002034 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002035 NOTE: cannot currently specify what type of link
2036 required params:
2037 node1 = the string node name of the first endpoint of the link
2038 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002039 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002040 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002041 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002042 response = self.execute(
2043 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002044 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08002045 timeout=10 )
2046 if re.search( "doesnt exist!", response ):
2047 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002048 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002049 elif re.search( "Error", response ):
2050 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002051 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002052 elif re.search( "usage:", response ):
2053 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002054 return main.FALSE
2055 else:
2056 return main.TRUE
2057 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002058 main.log.error( self.name + ": EOF exception found" )
2059 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002060 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002061 except Exception:
2062 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002063 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002064
kelvin-onlabd3b64892015-01-20 13:26:24 -08002065 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002066 """
2067 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002068 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002069 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002070 required params:
2071 node1 = the string node name of the first endpoint of the link
2072 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002073 returns: main.FALSE on an error, else main.TRUE
2074 """
Jon Hallffb386d2014-11-21 13:43:38 -08002075 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002076 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002077 response = self.execute(
2078 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002079 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08002080 timeout=10 )
2081 if re.search( "no node named", response ):
2082 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002083 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002084 elif re.search( "Error", response ):
2085 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002086 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002087 elif re.search( "usage:", response ):
2088 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002089 return main.FALSE
2090 else:
2091 return main.TRUE
2092 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002093 main.log.error( self.name + ": EOF exception found" )
2094 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002095 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002096 except Exception:
2097 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002098 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002099
You Wangb1665b52019-02-01 15:49:48 -08002100 def getLinkRandom( self, timeout=60, nonCut=True, excludeNodes=[], skipLinks=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07002101 """
2102 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002103 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002104 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002105 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002106 it just randomly returns one link from all current links in
2107 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08002108 excludeNodes will be passed to getLinks method to exclude unexpected links.
You Wangb1665b52019-02-01 15:49:48 -08002109 Any link that has either end included in skipLinks will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07002110 Returns the link as a list, e.g. [ 's1', 's2' ]
2111 """
2112 import random
2113 candidateLinks = []
2114 try:
2115 if not nonCut:
You Wang7d14d642019-01-23 15:10:08 -08002116 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07002117 assert len( links ) != 0
2118 for link in links:
2119 # Exclude host-switch link
2120 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2121 continue
2122 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2123 else:
You Wang7d14d642019-01-23 15:10:08 -08002124 graphDict = self.getGraphDict( timeout=timeout, useId=False,
You Wang7d14d642019-01-23 15:10:08 -08002125 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002126 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002127 return None
2128 self.graph.update( graphDict )
2129 candidateLinks = self.graph.getNonCutEdges()
You Wangb1665b52019-02-01 15:49:48 -08002130 candidateLinks = [ link for link in candidateLinks
2131 if link[0] not in skipLinks and link[1] not in skipLinks ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002132 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002133 return None
2134 elif len( candidateLinks ) == 0:
2135 main.log.info( self.name + ": No candidate link for deletion" )
2136 return None
2137 else:
2138 link = random.sample( candidateLinks, 1 )
2139 return link[ 0 ]
2140 except KeyError:
2141 main.log.exception( self.name + ": KeyError exception found" )
2142 return None
2143 except AssertionError:
2144 main.log.exception( self.name + ": AssertionError exception found" )
2145 return None
2146 except Exception:
2147 main.log.exception( self.name + ": Uncaught exception" )
2148 return None
2149
2150 def delLinkRandom( self, timeout=60, nonCut=True ):
2151 """
2152 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002153 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002154 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002155 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002156 otherwise it just randomly delete one link from all current links
2157 in Mininet.
2158 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2159 """
2160 try:
2161 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002162 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002163 return None
2164 else:
2165 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2166 if deletionResult:
2167 return link
2168 else:
2169 return None
2170 except Exception:
2171 main.log.exception( self.name + ": Uncaught exception" )
2172 return None
2173
kelvin-onlabd3b64892015-01-20 13:26:24 -08002174 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002175 """
Jon Hallb1290e82014-11-18 16:17:48 -05002176 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002177 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002178 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002179 NOTE: cannot currently specify what type of host
2180 required params:
2181 hostname = the string hostname
2182 optional key-value params
2183 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002184 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002185 """
2186 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002187 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002188 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002189 response = self.execute(
2190 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002191 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08002192 timeout=10 )
2193 if re.search( "already exists!", response ):
2194 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002195 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002196 elif re.search( "doesnt exists!", response ):
2197 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002198 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002199 elif re.search( "Error", response ):
2200 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002201 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002202 elif re.search( "usage:", response ):
2203 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002204 return main.FALSE
2205 else:
2206 return main.TRUE
2207 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002208 main.log.error( self.name + ": EOF exception found" )
2209 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002210 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002211 except Exception:
2212 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002213 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002214
kelvin-onlabd3b64892015-01-20 13:26:24 -08002215 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002216 """
2217 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002218 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002219 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002220 NOTE: this uses a custom mn function
2221 required params:
2222 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002223 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002224 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002225 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002226 response = self.execute(
2227 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002228 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08002229 timeout=10 )
2230 if re.search( "no host named", response ):
2231 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002232 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002233 elif re.search( "Error", response ):
2234 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002235 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002236 elif re.search( "usage:", response ):
2237 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002238 return main.FALSE
2239 else:
2240 return main.TRUE
2241 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002242 main.log.error( self.name + ": EOF exception found" )
2243 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002244 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002245 except Exception:
2246 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002247 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002248
Jon Hall7eb38402015-01-08 17:19:54 -08002249 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002250 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002251 Called at the end of the test to stop the mininet and
2252 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002253 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002254 try:
2255 self.handle.sendline( '' )
Jon Hall3c0114c2020-08-11 15:07:42 -07002256 i = self.handle.expect( [ self.mnPrompt, self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002257 timeout=2 )
2258 response = main.TRUE
2259 if i == 0:
2260 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002261 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002262 return main.TRUE
2263 # print "Disconnecting Mininet"
2264 if self.handle:
2265 self.handle.sendline( "exit" )
2266 self.handle.expect( "exit" )
2267 self.handle.expect( "(.*)" )
2268 else:
2269 main.log.error( "Connection failed to the host" )
2270 return response
2271 except pexpect.EOF:
2272 main.log.error( self.name + ": EOF exception found" )
2273 main.log.error( self.name + ": " + self.handle.before )
You Wangd4fae5c2018-08-22 13:56:49 -07002274 # Do not exit the entire test when pexpect.EOF is caught
2275 # FIXME: We might need to do something else here
2276 return main.ERROR
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002277 except Exception:
2278 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002279 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002280
Devin Lima7cfdbd2017-09-29 15:02:22 -07002281 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002282 """
Jon Hall21270ac2015-02-16 17:59:55 -08002283 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002284 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002285 main.FALSE if the pexpect handle does not exist.
2286
Jon Halld61331b2015-02-17 16:35:47 -08002287 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002288 """
Jon Halld61331b2015-02-17 16:35:47 -08002289 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002290 response = ''
2291 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002292 try:
Jon Halld80cc142015-07-06 13:36:05 -07002293 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07002294 i = self.handle.expect( [ self.mnPrompt,
Jon Hall3c0114c2020-08-11 15:07:42 -07002295 self.Prompt(),
kelvin-onlab56a3f462015-02-06 14:04:43 -08002296 pexpect.EOF,
2297 pexpect.TIMEOUT ],
2298 timeout )
2299 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002300 main.log.info( "Exiting mininet.." )
2301 startTime = time.time()
Jon Hallf6aeda22020-07-28 09:12:56 -07002302 self.handle.sendline( "exit" )
2303 exitRet = 1
Jon Hall3c0114c2020-08-11 15:07:42 -07002304 while exitRet:
2305 exitRet = self.handle.expect( [ self.Prompt(),
Jon Hallf6aeda22020-07-28 09:12:56 -07002306 "Traceback",
2307 "AssertionError",
2308 self.mnPrompt ],
2309 timeout=exitTimeout )
2310 response += self.handle.before + self.handle.after
2311 main.log.debug( response )
Devin Lima7cfdbd2017-09-29 15:02:22 -07002312 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jon Halldac3eae2020-06-05 12:04:06 -07002313 cmd = "mn -c"
2314 if self.sudoRequired:
2315 cmd = "sudo " + cmd
2316 self.handle.sendline( cmd )
Jeremyd9e4eb12016-04-13 12:09:06 -07002317 response = main.TRUE
Jon Hall3c0114c2020-08-11 15:07:42 -07002318 self.handle.expect( self.Prompt() )
Jon Hallafa8a472015-06-12 14:02:42 -07002319
Jeremyd9e4eb12016-04-13 12:09:06 -07002320 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002321 main.log.info( " Mininet trying to exit while not " +
2322 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002323 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002324 elif i == 2:
2325 main.log.error( "Something went wrong exiting mininet" )
2326 elif i == 3: # timeout
2327 main.log.error( "Something went wrong exiting mininet " +
2328 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002329
You Wang18db8592018-04-02 13:52:03 -07002330 self.handle.sendline( "" )
Jon Hall3c0114c2020-08-11 15:07:42 -07002331 self.handle.expect( self.Prompt() )
Jon Halldac3eae2020-06-05 12:04:06 -07002332 cmd = "killall -9 dhclient dhcpd zebra bgpd"
2333 if self.sudoRequired:
2334 cmd = "sudo " + cmd
2335 self.handle.sendline( cmd )
Jon Hall3c0114c2020-08-11 15:07:42 -07002336 self.handle.expect( self.Prompt() )
You Wang18db8592018-04-02 13:52:03 -07002337
Hari Krishnab35c6d02015-03-18 11:13:51 -07002338 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002339 self.handle.sendline( "" )
Jon Hall3c0114c2020-08-11 15:07:42 -07002340 self.handle.expect( self.Prompt() )
Jon Halldac3eae2020-06-05 12:04:06 -07002341 cmd = "kill -9 \`ps -ef | grep \"" + fileName + "\" | grep -v grep | awk '{print $2}'\`"
2342 if self.sudoRequired:
2343 cmd = "sudo " + cmd
2344 self.handle.sendline( cmd )
Jon Hall3c0114c2020-08-11 15:07:42 -07002345 self.handle.expect( self.Prompt() )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002346 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002347 main.log.error( self.name + ": TIMEOUT exception found" )
2348 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002349 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002350 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002351 main.log.error( self.name + ": EOF exception found" )
2352 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002353 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002354 except Exception:
2355 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002356 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002357 else:
2358 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002359 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002360 return response
2361
YPZhang26a139e2016-04-25 14:01:55 -07002362 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002363 """
2364 Description:
2365 Sends arp message from mininet host for hosts discovery
2366 Required:
2367 host - hosts name
2368 Optional:
2369 ip - ip address that does not exist in the network so there would
2370 be no reply.
2371 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002372 if ethDevice:
2373 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002374 cmd = srcHost + " arping -c1 "
2375 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002376 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 -07002377 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002378 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002379 if output:
2380 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002381 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07002382 i = self.handle.expect( [ self.mnPrompt, "arping: " ] )
Jon Halla5cb3412015-08-18 14:08:22 -07002383 if i == 0:
2384 return main.TRUE
2385 elif i == 1:
2386 response = self.handle.before + self.handle.after
Jon Hallf6aeda22020-07-28 09:12:56 -07002387 self.handle.expect( self.mnPrompt )
Jon Halla5cb3412015-08-18 14:08:22 -07002388 response += self.handle.before + self.handle.after
2389 main.log.warn( "Error sending arping, output was: " +
2390 response )
2391 return main.FALSE
2392 except pexpect.TIMEOUT:
2393 main.log.error( self.name + ": TIMEOUT exception found" )
2394 main.log.warn( self.handle.before )
2395 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002396 except pexpect.EOF:
2397 main.log.error( self.name + ": EOF exception found" )
2398 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002399 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002400 except Exception:
2401 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002402 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002403
Jon Hall7eb38402015-01-08 17:19:54 -08002404 def decToHex( self, num ):
2405 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002406
Jon Hall7eb38402015-01-08 17:19:54 -08002407 def getSwitchFlowCount( self, switch ):
2408 """
2409 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002410 if self.handle:
2411 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2412 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002413 response = self.execute(
2414 cmd=cmd,
Jon Hallf6aeda22020-07-28 09:12:56 -07002415 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08002416 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002417 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002418 main.log.error( self.name + ": EOF exception found" )
2419 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002420 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002421 except Exception:
2422 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002423 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002424 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002425 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002426 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002427 main.log.info(
2428 "Couldn't find flows on switch %s, found: %s" %
2429 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002430 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002431 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002432 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002433 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002434
Jon Hall9ed8f372016-02-24 17:34:07 -08002435 def checkFlows( self, sw, dumpFormat=None ):
2436 if dumpFormat:
2437 command = "sh ovs-ofctl -F " + \
2438 dumpFormat + " dump-flows " + str( sw )
2439 else:
2440 command = "sh ovs-ofctl dump-flows " + str( sw )
2441 try:
2442 response = self.execute(
2443 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002444 prompt=self.mnPrompt,
Jon Hall9ed8f372016-02-24 17:34:07 -08002445 timeout=10 )
2446 return response
2447 except pexpect.EOF:
2448 main.log.error( self.name + ": EOF exception found" )
2449 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002450 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002451 except Exception:
2452 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002453 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002454
GlennRC68467eb2015-11-16 18:01:01 -08002455 def flowTableComp( self, flowTable1, flowTable2 ):
2456 # This function compares the selctors and treatments of each flow
2457 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002458 assert flowTable1, "flowTable1 is empty or None"
2459 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002460 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002461 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002462 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002463 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002464 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2465 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002466 for field in dFields:
2467 try:
2468 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002469 except KeyError:
2470 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002471 try:
2472 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002473 except KeyError:
2474 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002475 for i in range( len( flowTable1 ) ):
2476 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002477 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002478 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002479 returnValue = main.FALSE
2480 break
2481 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002482 except AssertionError:
2483 main.log.exception( "Nothing to compare" )
2484 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002485 except Exception:
2486 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002487 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002488
GlennRC528ad292015-11-12 10:38:18 -08002489 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002490 '''
GlennRC956ea742015-11-05 16:14:15 -08002491 Discription: Parses flows into json format.
2492 NOTE: this can parse any string thats separated with commas
2493 Arguments:
2494 Required:
2495 flows: a list of strings that represnt flows
2496 Optional:
2497 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2498 debug: prints out the final result
2499 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002500 '''
GlennRC528ad292015-11-12 10:38:18 -08002501 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002502 try:
2503 for flow in flowTable:
2504 jsonFlow = {}
2505 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002506 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002507 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002508 for i in range( len( parsedFlow ) ):
2509 item = parsedFlow[ i ]
2510 if item[ 0 ] == " ":
2511 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002512 # grab the selector and treatment from the parsed flow
2513 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002514 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002515 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002516 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002517 index = 0
2518 # parse the flags
2519 # NOTE: This only parses one flag
2520 flag = {}
2521 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002522 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002523 index += 1
2524 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002525 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002526 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002527 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002528 # the priority is stuck in the selecter so put it back
2529 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002530 if 'priority' in sel[0]:
2531 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002532 # parse selector
2533 criteria = []
2534 for item in sel:
2535 # this is the type of the packet e.g. "arp"
2536 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002537 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002538 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002539 field = item.split( "=" )
2540 criteria.append( { field[ 0 ]: field[ 1 ] } )
2541 selector = { "selector": { "criteria": sorted( criteria ) } }
2542 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002543 # get rid of the action part e.g. "action=output:2"
2544 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002545 treat = treat.split( "=" )
2546 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002547 # parse treatment
2548 action = []
2549 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002550 if ":" in item:
2551 field = item.split( ":" )
2552 action.append( { field[ 0 ]: field[ 1 ] } )
2553 else:
2554 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2555 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002556 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002557 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002558 # parse the rest of the flow
2559 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002560 field = item.split( "=" )
2561 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002562 # add the treatment and the selector to the json flow
2563 jsonFlow.update( selector )
2564 jsonFlow.update( treatment )
2565 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002566
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002567 if debug:
2568 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002569
You Wang91c37cf2016-05-23 09:39:42 -07002570 # add the json flow to the json flow table
2571 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002572
You Wang91c37cf2016-05-23 09:39:42 -07002573 return jsonFlowTable
2574
2575 except IndexError:
2576 main.log.exception( self.name + ": IndexError found" )
2577 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002578 except pexpect.EOF:
2579 main.log.error( self.name + ": EOF exception found" )
2580 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002581 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002582 except Exception:
2583 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002584 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002585
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002586 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002587 '''
2588 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002589 Each element is a flow.
2590 Arguments:
2591 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002592 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002593 a list of switches.
2594 Optional:
2595 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2596 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002597 '''
GlennRC956ea742015-11-05 16:14:15 -08002598 try:
2599 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002600 if isinstance( sw, list ):
2601 switches.extend( sw )
2602 else:
2603 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002604
2605 flows = []
2606 for s in switches:
2607 cmd = "sh ovs-ofctl dump-flows " + s
2608
GlennRC528ad292015-11-12 10:38:18 -08002609 if "1.0" == version:
2610 cmd += " -F OpenFlow10-table_id"
2611 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002612 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002613
2614 main.log.info( "Sending: " + cmd )
2615 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07002616 self.handle.expect( self.mnPrompt )
GlennRC956ea742015-11-05 16:14:15 -08002617 response = self.handle.before
2618 response = response.split( "\r\n" )
2619 # dump the first two elements and the last
2620 # the first element is the command that was sent
2621 # the second is the table header
2622 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002623 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002624 flows.extend( response )
2625
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002626 if debug:
2627 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002628
GlennRC528ad292015-11-12 10:38:18 -08002629 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002630
GlennRC956ea742015-11-05 16:14:15 -08002631 except pexpect.EOF:
2632 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002633 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002634 except Exception:
2635 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002636 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002637
2638 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002639 '''
GlennRC956ea742015-11-05 16:14:15 -08002640 Discription: Checks whether the ID provided matches a flow ID in Mininet
2641 Arguments:
2642 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002643 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002644 a list of switches.
2645 flowId: the flow ID in hex format. Can also be a list of IDs
2646 Optional:
2647 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2648 debug: prints out the final result
2649 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2650 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002651 '''
GlennRC956ea742015-11-05 16:14:15 -08002652 try:
2653 main.log.info( "Getting flows from Mininet" )
2654 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002655 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002656 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002657
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002658 if debug:
2659 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002660
2661 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002662 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002663 result = False
2664 for f in flows:
2665 if flowId in f.get( 'cookie' ):
2666 result = True
2667 break
2668 # flowId is a list
2669 else:
2670 result = True
2671 # Get flow IDs from Mininet
2672 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2673 # Save the IDs that are not in Mininet
2674 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2675
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002676 if debug:
2677 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002678
2679 # Print out the IDs that are not in Mininet
2680 if absentIds:
2681 main.log.warn( "Absent ids: {}".format( absentIds ) )
2682 result = False
2683
2684 return main.TRUE if result else main.FALSE
2685
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002686 except pexpect.EOF:
2687 main.log.error( self.name + ": EOF exception found" )
2688 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002689 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002690 except Exception:
2691 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002692 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002693
Charles Chan029be652015-08-24 01:46:10 +08002694 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002695 """
Jon Hallefbd9792015-03-05 16:11:36 -08002696 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002697 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002698 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002699 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07002700 self.handle.expect( self.mnPrompt )
Jon Halldac3eae2020-06-05 12:04:06 -07002701 if self.sudoRequired:
2702 sudoStr = "sudo "
2703 else:
2704 sudoStr = ""
Jon Hall7eb38402015-01-08 17:19:54 -08002705 self.handle.sendline(
Jon Halldac3eae2020-06-05 12:04:06 -07002706 "sh " + sudoStr + "tcpdump -n -i " +
2707 intf + " " + port + " -w " +
2708 filename.strip() + " &" )
Jon Hall7eb38402015-01-08 17:19:54 -08002709 self.handle.sendline( "" )
2710 i = self.handle.expect( [ 'No\ssuch\device',
2711 'listening\son',
2712 pexpect.TIMEOUT,
Jon Hallf6aeda22020-07-28 09:12:56 -07002713 self.mnPrompt ],
Jon Hall7eb38402015-01-08 17:19:54 -08002714 timeout=10 )
2715 main.log.warn( self.handle.before + self.handle.after )
2716 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07002717 self.handle.expect( self.mnPrompt )
admin2a9548d2014-06-17 14:08:07 -07002718 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002719 main.log.error(
2720 self.name +
2721 ": tcpdump - No such device exists. " +
2722 "tcpdump attempted on: " +
2723 intf )
admin2a9548d2014-06-17 14:08:07 -07002724 return main.FALSE
2725 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002726 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002727 return main.TRUE
2728 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002729 main.log.error(
2730 self.name +
2731 ": tcpdump command timed out! Check interface name," +
2732 " given interface was: " +
2733 intf )
admin2a9548d2014-06-17 14:08:07 -07002734 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002735 elif i == 3:
2736 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002737 return main.TRUE
2738 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002739 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002740 return main.FALSE
2741 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002742 main.log.error( self.name + ": EOF exception found" )
2743 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002744 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002745 except Exception:
2746 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002747 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002748
kelvin-onlabd3b64892015-01-20 13:26:24 -08002749 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002750 """
2751 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002752 try:
Jon Halldac3eae2020-06-05 12:04:06 -07002753 if self.sudoRequired:
2754 sudoStr = "sudo "
2755 else:
2756 sudoStr = ""
2757 self.handle.sendline( "sh " + sudoStr + " pkill tcpdump" )
Jon Hallf6aeda22020-07-28 09:12:56 -07002758 self.handle.expect( self.mnPrompt )
Jon Hall7eb38402015-01-08 17:19:54 -08002759 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07002760 self.handle.expect( self.mnPrompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002761 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002762 main.log.error( self.name + ": TIMEOUT exception found" )
2763 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002764 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002765 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002766 main.log.error( self.name + ": EOF exception found" )
2767 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002768 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002769 except Exception:
2770 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002771 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002772
Jon Halld80cc142015-07-06 13:36:05 -07002773 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002774 """
2775 Read ports from a Mininet switch.
2776
2777 Returns a json structure containing information about the
2778 ports of the given switch.
2779 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002780 try:
2781 response = self.getInterfaces( nodeName )
2782 # TODO: Sanity check on response. log if no such switch exists
2783 ports = []
2784 for line in response.split( "\n" ):
2785 if not line.startswith( "name=" ):
2786 continue
2787 portVars = {}
2788 for var in line.split( "," ):
2789 key, value = var.split( "=" )
2790 portVars[ key ] = value
2791 isUp = portVars.pop( 'enabled', "True" )
2792 isUp = "True" in isUp
2793 if verbose:
2794 main.log.info( "Reading switch port %s(%s)" %
2795 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2796 mac = portVars[ 'mac' ]
2797 if mac == 'None':
2798 mac = None
2799 ips = []
2800 ip = portVars[ 'ip' ]
2801 if ip == 'None':
2802 ip = None
2803 ips.append( ip )
2804 name = portVars[ 'name' ]
2805 if name == 'None':
2806 name = None
2807 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2808 if name == 'lo':
2809 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2810 else:
2811 portNo = re.search( portRe, name ).group( 'port' )
2812 ports.append( { 'of_port': portNo,
2813 'mac': str( mac ).replace( '\'', '' ),
2814 'name': name,
2815 'ips': ips,
2816 'enabled': isUp } )
2817 return ports
2818 except pexpect.EOF:
2819 main.log.error( self.name + ": EOF exception found" )
2820 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002821 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002822 except Exception:
2823 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002824 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002825
You Wangdb8cd0a2016-05-26 15:19:45 -07002826 def getOVSPorts( self, nodeName ):
2827 """
2828 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2829
2830 Returns a list of dictionaries containing information about each
2831 port of the given switch.
2832 """
2833 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2834 try:
2835 response = self.execute(
2836 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002837 prompt=self.mnPrompt,
You Wang7d14d642019-01-23 15:10:08 -08002838 timeout=10,
2839 logCmd=False )
You Wangdb8cd0a2016-05-26 15:19:45 -07002840 ports = []
2841 if response:
2842 for line in response.split( "\n" ):
2843 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2844 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002845 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002846 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2847 result = re.search( pattern, line )
2848 if result:
2849 index = result.group( 'index' )
2850 name = result.group( 'name' )
2851 # This port number is extracted from port name
2852 port = result.group( 'port' )
2853 mac = result.group( 'mac' )
2854 ports.append( { 'index': index,
2855 'name': name,
2856 'port': port,
2857 'mac': mac } )
2858 return ports
2859 except pexpect.EOF:
2860 main.log.error( self.name + ": EOF exception found" )
2861 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002862 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002863 except Exception:
2864 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002865 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002866
Jon Halldac3eae2020-06-05 12:04:06 -07002867 def getSwitches( self, verbose=False, updateTimeout=1000, excludeNodes=[], switchRegex=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002868 """
2869 Read switches from Mininet.
2870
2871 Returns a dictionary whose keys are the switch names and the value is
2872 a dictionary containing information about the switch.
You Wangb1665b52019-02-01 15:49:48 -08002873 If excludeNodes is specified, switches with names included in excludeNodes
2874 will be ingored.
Jon Hallafa8a472015-06-12 14:02:42 -07002875 """
Jon Halla22481b2015-07-28 17:46:01 -07002876 # NOTE: To support new Mininet switch classes, just append the new
2877 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002878
Jon Halla22481b2015-07-28 17:46:01 -07002879 # Regex patterns to parse 'dump' output
2880 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002881 # <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 -07002882 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002883 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2884 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2885 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Jon Halldac3eae2020-06-05 12:04:06 -07002886 if not switchRegex:
2887 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2888 else:
2889 switchClasses = switchRegex
You Wang7d14d642019-01-23 15:10:08 -08002890 try:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002891 swRE = r"<(?P<class>" + switchClasses + r")" +\
2892 r"(?P<options>\{.*\})?\s" +\
2893 r"(?P<name>[^:]+)\:\s" +\
2894 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2895 r"\spid=(?P<pid>(\d)+)"
2896 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002897 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002898 output = {}
2899 dump = self.dump().split( "\n" )
2900 for line in dump:
2901 result = re.search( swRE, line, re.I )
2902 if result:
2903 name = result.group( 'name' )
You Wangb1665b52019-02-01 15:49:48 -08002904 if name in excludeNodes:
2905 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002906 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2907 pid = result.group( 'pid' )
2908 swClass = result.group( 'class' )
2909 options = result.group( 'options' )
2910 if verbose:
2911 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2912 ports = self.getPorts( name )
2913 output[ name ] = { "dpid": dpid,
2914 "ports": ports,
2915 "swClass": swClass,
2916 "pid": pid,
2917 "options": options }
2918 return output
2919 except pexpect.EOF:
2920 main.log.error( self.name + ": EOF exception found" )
2921 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002922 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002923 except Exception:
2924 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002925 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002926
You Wangd66de192018-04-30 17:30:12 -07002927 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002928 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2929 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002930 """
2931 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002932 Optional:
2933 hostClass: it is used to match the class of the mininet host. It
2934 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002935 Returns a dictionary whose keys are the host names and the value is
2936 a dictionary containing information about the host.
2937 """
2938 # Regex patterns to parse dump output
2939 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002940 # <Host h1: pid=12725>
2941 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2942 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2943 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002944 # NOTE: Does not correctly match hosts with multi-links
2945 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2946 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002947 try:
You Wang53dba1e2018-02-02 17:45:44 -08002948 if not isinstance( hostClass, types.ListType ):
2949 hostClass = [ str( hostClass ) ]
2950 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002951 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2952 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2953 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002954 if update:
2955 # update mn port info
2956 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002957 # Get mininet dump
2958 dump = self.dump().split( "\n" )
2959 hosts = {}
2960 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002961 result = re.search( hostRE, line )
2962 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002963 name = result.group( 'name' )
2964 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002965 if getInterfaces:
2966 response = self.getInterfaces( name )
2967 # Populate interface info
2968 for line in response.split( "\n" ):
2969 if line.startswith( "name=" ):
2970 portVars = {}
2971 for var in line.split( "," ):
2972 key, value = var.split( "=" )
2973 portVars[ key ] = value
2974 isUp = portVars.pop( 'enabled', "True" )
2975 isUp = "True" in isUp
2976 if verbose:
2977 main.log.info( "Reading host port %s(%s)" %
2978 ( portVars[ 'name' ],
2979 portVars[ 'mac' ] ) )
2980 mac = portVars[ 'mac' ]
2981 if mac == 'None':
2982 mac = None
2983 ips = []
2984 ip = portVars[ 'ip' ]
2985 if ip == 'None':
2986 ip = None
2987 ips.append( ip )
2988 intfName = portVars[ 'name' ]
2989 if name == 'None':
2990 name = None
2991 interfaces.append( {
2992 "name": intfName,
2993 "ips": ips,
2994 "mac": str( mac ),
2995 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002996 hosts[ name ] = { "interfaces": interfaces }
2997 return hosts
2998 except pexpect.EOF:
2999 main.log.error( self.name + ": EOF exception found" )
3000 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003001 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003002 except Exception:
3003 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003004 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003005
You Wang7d14d642019-01-23 15:10:08 -08003006 def getLinks( self, timeout=20, updateTimeout=1000, excludeNodes=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07003007 """
3008 Gathers information about current Mininet links. These links may not
3009 be up if one of the ports is down.
3010
3011 Returns a list of dictionaries with link endpoints.
3012
3013 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07003014 { 'node1': str( node1 name )
3015 'node2': str( node2 name )
3016 'port1': str( port1 of_port )
3017 'port2': str( port2 of_port ) }
You Wang7d14d642019-01-23 15:10:08 -08003018
You Wangb1665b52019-02-01 15:49:48 -08003019 If either node1 or node2 name matches any of the names sepcified in
3020 excludeNodes, the link will be excluded from the returned value
You Wang7d14d642019-01-23 15:10:08 -08003021
Jon Hallafa8a472015-06-12 14:02:42 -07003022 Note: The port number returned is the eth#, not necessarily the of_port
3023 number. In Mininet, for OVS switch, these should be the same. For
3024 hosts, this is just the eth#.
3025 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003026 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003027 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003028 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07003029
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003030 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003031 # s1-eth3<->s2-eth1 (OK OK)
3032 # s13-eth3<->h27-eth0 (OK OK)
You Wang7d14d642019-01-23 15:10:08 -08003033 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d\.]+)\<\-\>" +\
3034 "(?P<node2>[\w]+)\-eth(?P<port2>[\d\.]+)"
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003035 links = []
3036 for line in response:
3037 match = re.search( linkRE, line )
3038 if match:
3039 node1 = match.group( 'node1' )
3040 node2 = match.group( 'node2' )
You Wangb1665b52019-02-01 15:49:48 -08003041 if any( node1 == node or node2 == node for node in excludeNodes ):
You Wang7d14d642019-01-23 15:10:08 -08003042 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003043 port1 = match.group( 'port1' )
3044 port2 = match.group( 'port2' )
3045 links.append( { 'node1': node1,
3046 'node2': node2,
3047 'port1': port1,
3048 'port2': port2 } )
3049 return links
3050
3051 except pexpect.EOF:
3052 main.log.error( self.name + ": EOF exception found" )
3053 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003054 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003055 except Exception:
3056 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003057 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003058
3059 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003060 """
3061 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003062 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003063
Jon Hallafa8a472015-06-12 14:02:42 -07003064 Dependencies:
3065 1. numpy - "sudo pip install numpy"
3066 """
3067 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003068 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003069 try:
3070 mnDPIDs = []
3071 for swName, switch in switches.iteritems():
3072 mnDPIDs.append( switch[ 'dpid' ].lower() )
3073 mnDPIDs.sort()
3074 if switchesJson == "": # if rest call fails
3075 main.log.error(
3076 self.name +
3077 ".compareSwitches(): Empty JSON object given from ONOS" )
3078 return main.FALSE
3079 onos = switchesJson
3080 onosDPIDs = []
3081 for switch in onos:
3082 if switch[ 'available' ]:
3083 onosDPIDs.append(
3084 switch[ 'id' ].replace(
3085 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003086 '' ).replace(
3087 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003088 '' ).lower() )
3089 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003090
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003091 if mnDPIDs != onosDPIDs:
3092 switchResults = main.FALSE
3093 main.log.error( "Switches in MN but not in ONOS:" )
3094 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3095 main.log.error( str( list1 ) )
3096 main.log.error( "Switches in ONOS but not in MN:" )
3097 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3098 main.log.error( str( list2 ) )
3099 else: # list of dpid's match in onos and mn
3100 switchResults = main.TRUE
3101 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003102
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003103 # FIXME: this does not look for extra ports in ONOS, only checks that
3104 # ONOS has what is in MN
3105 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003106
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003107 # PORTS
3108 for name, mnSwitch in switches.iteritems():
3109 mnPorts = []
3110 onosPorts = []
3111 switchResult = main.TRUE
3112 for port in mnSwitch[ 'ports' ]:
3113 if port[ 'enabled' ]:
3114 mnPorts.append( int( port[ 'of_port' ] ) )
3115 for onosSwitch in portsJson:
3116 if onosSwitch[ 'device' ][ 'available' ]:
3117 if onosSwitch[ 'device' ][ 'id' ].replace(
3118 ':',
3119 '' ).replace(
3120 "of",
3121 '' ) == mnSwitch[ 'dpid' ]:
3122 for port in onosSwitch[ 'ports' ]:
3123 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003124 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003125 # onosPorts.append( 'local' )
3126 onosPorts.append( long( uint64( -2 ) ) )
3127 else:
3128 onosPorts.append( int( port[ 'port' ] ) )
3129 break
3130 mnPorts.sort( key=float )
3131 onosPorts.sort( key=float )
3132
3133 mnPortsLog = mnPorts
3134 onosPortsLog = onosPorts
3135 mnPorts = [ x for x in mnPorts ]
3136 onosPorts = [ x for x in onosPorts ]
3137
3138 # TODO: handle other reserved port numbers besides LOCAL
3139 # NOTE: Reserved ports
3140 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3141 # long( uint64( -2 ) )
3142 for mnPort in mnPortsLog:
3143 if mnPort in onosPorts:
3144 # don't set results to true here as this is just one of
3145 # many checks and it might override a failure
3146 mnPorts.remove( mnPort )
3147 onosPorts.remove( mnPort )
3148
3149 # NOTE: OVS reports this as down since there is no link
3150 # So ignoring these for now
3151 # TODO: Come up with a better way of handling these
3152 if 65534 in mnPorts:
3153 mnPorts.remove( 65534 )
3154 if long( uint64( -2 ) ) in onosPorts:
3155 onosPorts.remove( long( uint64( -2 ) ) )
3156 if len( mnPorts ): # the ports of this switch don't match
3157 switchResult = main.FALSE
3158 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3159 if len( onosPorts ): # the ports of this switch don't match
3160 switchResult = main.FALSE
3161 main.log.warn(
3162 "Ports in ONOS but not MN: " +
3163 str( onosPorts ) )
3164 if switchResult == main.FALSE:
3165 main.log.error(
3166 "The list of ports for switch %s(%s) does not match:" %
3167 ( name, mnSwitch[ 'dpid' ] ) )
3168 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3169 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3170 portsResults = portsResults and switchResult
3171 finalResults = finalResults and portsResults
3172 return finalResults
3173 except pexpect.EOF:
3174 main.log.error( self.name + ": EOF exception found" )
3175 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003176 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003177 except Exception:
3178 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003179 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003180
Jon Hallafa8a472015-06-12 14:02:42 -07003181 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003182 """
3183 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003184 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003185
Jon Hallafa8a472015-06-12 14:02:42 -07003186 """
Jon Hall7eb38402015-01-08 17:19:54 -08003187 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003188 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003189 try:
3190 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003191
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003192 mnLinks = []
3193 for l in links:
3194 try:
3195 node1 = switches[ l[ 'node1' ] ]
3196 node2 = switches[ l[ 'node2' ] ]
3197 enabled = True
3198 for port in node1[ 'ports' ]:
3199 if port[ 'of_port' ] == l[ 'port1' ]:
3200 enabled = enabled and port[ 'enabled' ]
3201 for port in node2[ 'ports' ]:
3202 if port[ 'of_port' ] == l[ 'port2' ]:
3203 enabled = enabled and port[ 'enabled' ]
3204 if enabled:
3205 mnLinks.append( l )
3206 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003207 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003208 if 2 * len( mnLinks ) == len( onos ):
3209 linkResults = main.TRUE
3210 else:
3211 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003212 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003213 "Mininet has " + str( len( mnLinks ) ) +
3214 " bidirectional links and ONOS has " +
3215 str( len( onos ) ) + " unidirectional links" )
3216
3217 # iterate through MN links and check if an ONOS link exists in
3218 # both directions
3219 for link in mnLinks:
3220 # TODO: Find a more efficient search method
3221 node1 = None
3222 port1 = None
3223 node2 = None
3224 port2 = None
3225 firstDir = main.FALSE
3226 secondDir = main.FALSE
3227 for swName, switch in switches.iteritems():
3228 if swName == link[ 'node1' ]:
3229 node1 = switch[ 'dpid' ]
3230 for port in switch[ 'ports' ]:
3231 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3232 port1 = port[ 'of_port' ]
3233 if node1 is not None and node2 is not None:
3234 break
3235 if swName == link[ 'node2' ]:
3236 node2 = switch[ 'dpid' ]
3237 for port in switch[ 'ports' ]:
3238 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3239 port2 = port[ 'of_port' ]
3240 if node1 is not None and node2 is not None:
3241 break
3242
3243 for onosLink in onos:
3244 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3245 ":", '' ).replace( "of", '' )
3246 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3247 ":", '' ).replace( "of", '' )
3248 onosPort1 = onosLink[ 'src' ][ 'port' ]
3249 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3250
3251 # check onos link from node1 to node2
3252 if str( onosNode1 ) == str( node1 ) and str(
3253 onosNode2 ) == str( node2 ):
3254 if int( onosPort1 ) == int( port1 ) and int(
3255 onosPort2 ) == int( port2 ):
3256 firstDir = main.TRUE
3257 else:
Jon Hallab611372018-02-21 15:26:05 -08003258 # The right switches, but wrong ports, could be
3259 # another link between these devices, or onos
3260 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003261 main.log.warn(
3262 'The port numbers do not match for ' +
3263 str( link ) +
3264 ' between ONOS and MN. When checking ONOS for ' +
3265 'link %s/%s -> %s/%s' %
3266 ( node1, port1, node2, port2 ) +
3267 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003268 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3269 '. This could be another link between these devices' +
3270 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003271
3272 # check onos link from node2 to node1
3273 elif ( str( onosNode1 ) == str( node2 ) and
3274 str( onosNode2 ) == str( node1 ) ):
3275 if ( int( onosPort1 ) == int( port2 )
3276 and int( onosPort2 ) == int( port1 ) ):
3277 secondDir = main.TRUE
3278 else:
Jon Hallab611372018-02-21 15:26:05 -08003279 # The right switches, but wrong ports, could be
3280 # another link between these devices, or onos
3281 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003282 main.log.warn(
3283 'The port numbers do not match for ' +
3284 str( link ) +
3285 ' between ONOS and MN. When checking ONOS for ' +
3286 'link %s/%s -> %s/%s' %
3287 ( node1, port1, node2, port2 ) +
3288 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003289 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3290 '. This could be another link between these devices' +
3291 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003292 else: # this is not the link you're looking for
3293 pass
3294 if not firstDir:
3295 main.log.error(
3296 'ONOS does not have the link %s/%s -> %s/%s' %
3297 ( node1, port1, node2, port2 ) )
3298 if not secondDir:
3299 main.log.error(
3300 'ONOS does not have the link %s/%s -> %s/%s' %
3301 ( node2, port2, node1, port1 ) )
3302 linkResults = linkResults and firstDir and secondDir
3303 return linkResults
3304 except pexpect.EOF:
3305 main.log.error( self.name + ": EOF exception found" )
3306 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003307 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003308 except Exception:
3309 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003310 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003311
Jon Hallafa8a472015-06-12 14:02:42 -07003312 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003313 """
Jon Hallafa8a472015-06-12 14:02:42 -07003314 Compare mn and onos Hosts.
3315 Since Mininet hosts are quiet, ONOS will only know of them when they
3316 speak. For this reason, we will only check that the hosts in ONOS
3317 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003318
Jon Hallafa8a472015-06-12 14:02:42 -07003319 Arguments:
3320 hostsJson: parsed json object from the onos hosts api
3321 Returns:
3322 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003323 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003324 try:
3325 hostResults = main.TRUE
3326 for onosHost in hostsJson:
3327 onosMAC = onosHost[ 'mac' ].lower()
3328 match = False
3329 for mnHost, info in hosts.iteritems():
3330 for mnIntf in info[ 'interfaces' ]:
3331 if onosMAC == mnIntf[ 'mac' ].lower():
3332 match = True
3333 for ip in mnIntf[ 'ips' ]:
3334 if ip in onosHost[ 'ipAddresses' ]:
3335 pass # all is well
3336 else:
3337 # misssing ip
3338 main.log.error( "ONOS host " +
3339 onosHost[ 'id' ] +
3340 " has a different IP(" +
3341 str( onosHost[ 'ipAddresses' ] ) +
3342 ") than the Mininet host(" +
3343 str( ip ) +
3344 ")." )
3345 output = json.dumps(
3346 onosHost,
3347 sort_keys=True,
3348 indent=4,
3349 separators=( ',', ': ' ) )
3350 main.log.info( output )
3351 hostResults = main.FALSE
3352 if not match:
3353 hostResults = main.FALSE
3354 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3355 "corresponding Mininet host." )
3356 output = json.dumps( onosHost,
3357 sort_keys=True,
3358 indent=4,
3359 separators=( ',', ': ' ) )
3360 main.log.info( output )
3361 return hostResults
3362 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003363 main.log.error( self.name + ": EOF exception found" )
3364 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003365 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003366 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003367 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003368 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003369
You Wangd66de192018-04-30 17:30:12 -07003370 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003371 """
3372 Description:
3373 Verify that all hosts have IP address assigned to them
3374 Optional:
3375 hostList: If specified, verifications only happen to the hosts
3376 in hostList
3377 prefix: at least one of the ip address assigned to the host
3378 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003379 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003380 Returns:
3381 main.TRUE if all hosts have specific IP address assigned;
3382 main.FALSE otherwise
3383 """
3384 try:
You Wangd66de192018-04-30 17:30:12 -07003385 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003386 if not hostList:
3387 hostList = hosts.keys()
3388 for hostName in hosts.keys():
3389 if hostName not in hostList:
3390 continue
3391 ipList = []
3392 self.handle.sendline( str( hostName ) + " ip a" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003393 self.handle.expect( self.mnPrompt )
You Wang53dba1e2018-02-02 17:45:44 -08003394 ipa = self.handle.before
3395 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3396 ipList += re.findall( ipv4Pattern, ipa )
3397 # It's tricky to make regex for IPv6 addresses and this one is simplified
3398 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})/'
3399 ipList += re.findall( ipv6Pattern, ipa )
3400 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3401 if not ipList:
3402 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3403 else:
3404 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3405 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3406 else:
3407 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3408 hostList.remove( hostName )
3409 return main.FALSE if hostList else main.TRUE
3410 except KeyError:
3411 main.log.exception( self.name + ": host data not as expected: " + hosts )
3412 return None
3413 except pexpect.EOF:
3414 main.log.error( self.name + ": EOF exception found" )
3415 main.log.error( self.name + ": " + self.handle.before )
3416 main.cleanAndExit()
3417 except Exception:
3418 main.log.exception( self.name + ": Uncaught exception" )
3419 return None
3420
Jon Hallafa8a472015-06-12 14:02:42 -07003421 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003422 """
3423 Returns a list of all hosts
3424 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003425 try:
3426 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003427 self.handle.expect( self.mnPrompt )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003428
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003429 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003430 self.handle.expect( self.mnPrompt )
admin2a9548d2014-06-17 14:08:07 -07003431
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003432 handlePy = self.handle.before
3433 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3434 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003435
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003436 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003437 self.handle.expect( self.mnPrompt )
admin2a9548d2014-06-17 14:08:07 -07003438
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003439 hostStr = handlePy.replace( "]", "" )
3440 hostStr = hostStr.replace( "'", "" )
3441 hostStr = hostStr.replace( "[", "" )
3442 hostStr = hostStr.replace( " ", "" )
3443 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003444
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003445 return hostList
3446 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003447 main.log.error( self.name + ": TIMEOUT exception found" )
3448 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003449 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003450 except pexpect.EOF:
3451 main.log.error( self.name + ": EOF exception found" )
3452 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003453 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003454 except Exception:
3455 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003456 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003457
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003458 def getSwitch( self ):
3459 """
3460 Returns a list of all switches
3461 Again, don't ask question just use it...
3462 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003463 try:
3464 # get host list...
3465 hostList = self.getHosts()
3466 # Make host set
3467 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003468
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003469 # Getting all the nodes in mininet
3470 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003471 self.handle.expect( self.mnPrompt )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003472
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003473 self.handle.sendline( "py [ node.name for node in net.values() ]" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003474 self.handle.expect( self.mnPrompt )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003475
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003476 handlePy = self.handle.before
3477 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3478 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003479
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003480 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003481 self.handle.expect( self.mnPrompt )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003482
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003483 nodesStr = handlePy.replace( "]", "" )
3484 nodesStr = nodesStr.replace( "'", "" )
3485 nodesStr = nodesStr.replace( "[", "" )
3486 nodesStr = nodesStr.replace( " ", "" )
3487 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003488
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003489 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003490 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003491 nodesSet.discard( 'c0' )
3492 nodesSet.discard( 'c1' )
3493 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003494
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003495 switchSet = nodesSet - hostSet
3496 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003497
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003498 return switchList
3499 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003500 main.log.error( self.name + ": TIMEOUT exception found" )
3501 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003502 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003503 except pexpect.EOF:
3504 main.log.error( self.name + ": EOF exception found" )
3505 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003506 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003507 except Exception:
3508 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003509 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003510
You Wang7d14d642019-01-23 15:10:08 -08003511 def getGraphDict( self, timeout=60, useId=True, includeHost=False,
You Wangb1665b52019-02-01 15:49:48 -08003512 excludeNodes=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07003513 """
3514 Return a dictionary which describes the latest Mininet topology data as a
3515 graph.
3516 An example of the dictionary:
3517 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3518 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3519 Each vertex should at least have an 'edges' attribute which describes the
3520 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003521 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003522 list of attributes.
3523 An example of the edges dictionary:
3524 'edges': { vertex2: { 'port': ..., 'weight': ... },
3525 vertex3: { 'port': ..., 'weight': ... } }
3526 If useId == True, dpid/mac will be used instead of names to identify
3527 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3528 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003529 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003530 in topology data.
You Wangb1665b52019-02-01 15:49:48 -08003531 excludeNodes will be passed to getSwitches and getLinks methods to exclude
3532 unexpected switches and links.
You Wangdb8cd0a2016-05-26 15:19:45 -07003533 Note that link or switch that are brought down by 'link x x down' or 'switch
3534 x down' commands still show in the output of Mininet CLI commands such as
3535 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3536 recommended to use delLink() or delSwitch functions to simulate link/switch
3537 down, and addLink() or addSwitch to add them back.
3538 """
3539 graphDict = {}
3540 try:
You Wang7d14d642019-01-23 15:10:08 -08003541 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003542 portDict = {}
You Wangb1665b52019-02-01 15:49:48 -08003543 switches = self.getSwitches( excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003544 if includeHost:
3545 hosts = self.getHosts()
3546 for link in links:
You Wangb1665b52019-02-01 15:49:48 -08003547 # TODO: support 'includeHost' argument
You Wangdb8cd0a2016-05-26 15:19:45 -07003548 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3549 continue
3550 nodeName1 = link[ 'node1' ]
3551 nodeName2 = link[ 'node2' ]
You Wang7d14d642019-01-23 15:10:08 -08003552 if not self.getOVSPorts( nodeName1 ) or not self.getOVSPorts( nodeName2 ):
3553 # The device is probably offline
3554 continue
You Wangdb8cd0a2016-05-26 15:19:45 -07003555 port1 = link[ 'port1' ]
3556 port2 = link[ 'port2' ]
3557 # Loop for two nodes
3558 for i in range( 2 ):
3559 # Get port index from OVS
3560 # The index extracted from port name may be inconsistent with ONOS
3561 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003562 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003563 portList = self.getOVSPorts( nodeName1 )
3564 if len( portList ) == 0:
3565 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3566 return None
3567 portDict[ nodeName1 ] = portList
3568 for port in portDict[ nodeName1 ]:
3569 if port[ 'port' ] == port1:
3570 portIndex = port[ 'index' ]
3571 break
3572 if portIndex == -1:
3573 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3574 return None
3575 if useId:
3576 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3577 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3578 else:
3579 node1 = nodeName1
3580 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003581 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003582 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003583 graphDict[ node1 ] = { 'edges': {},
3584 'dpid': switches[ nodeName1 ][ 'dpid' ],
3585 'name': nodeName1,
3586 'ports': switches[ nodeName1 ][ 'ports' ],
3587 'swClass': switches[ nodeName1 ][ 'swClass' ],
3588 'pid': switches[ nodeName1 ][ 'pid' ],
3589 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003590 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003591 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003592 else:
3593 # Assert node2 is not connected to any current links of node1
You Wang7d14d642019-01-23 15:10:08 -08003594 # assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
3595 pass
3596 for port in switches[ nodeName1 ][ 'ports' ]:
3597 if port[ 'of_port' ] == str( portIndex ):
3598 # Use -1 as index for disabled port
You Wangb1665b52019-02-01 15:49:48 -08003599 if port[ 'enabled' ]:
You Wang7d14d642019-01-23 15:10:08 -08003600 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
3601 else:
3602 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': -1 }
You Wangdb8cd0a2016-05-26 15:19:45 -07003603 # Swap two nodes/ports
3604 nodeName1, nodeName2 = nodeName2, nodeName1
3605 port1, port2 = port2, port1
You Wang7d14d642019-01-23 15:10:08 -08003606 # Remove links with disabled ports
3607 linksToRemove = []
3608 for node, edges in graphDict.items():
3609 for neighbor, port in edges[ 'edges' ].items():
3610 if port[ 'port' ] == -1:
3611 linksToRemove.append( ( node, neighbor ) )
3612 for node1, node2 in linksToRemove:
3613 for i in range( 2 ):
3614 if graphDict.get( node1 )[ 'edges' ].get( node2 ):
3615 graphDict[ node1 ][ 'edges' ].pop( node2 )
3616 node1, node2 = node2, node1
You Wangdb8cd0a2016-05-26 15:19:45 -07003617 return graphDict
3618 except KeyError:
3619 main.log.exception( self.name + ": KeyError exception found" )
3620 return None
3621 except AssertionError:
3622 main.log.exception( self.name + ": AssertionError exception found" )
3623 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003624 except pexpect.EOF:
3625 main.log.error( self.name + ": EOF exception found" )
3626 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003627 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003628 except Exception:
3629 main.log.exception( self.name + ": Uncaught exception" )
3630 return None
3631
Devin Lima7cfdbd2017-09-29 15:02:22 -07003632 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003633 """
3634 updates the port address and status information for
3635 each port in mn"""
Jon Hallefbd9792015-03-05 16:11:36 -08003636 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003637 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003638 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003639 self.handle.expect( self.mnPrompt )
Jon Hall38481722014-11-04 16:50:05 -05003640
Jon Hall43060f62020-06-23 13:13:33 -07003641 # If update command isn't available, do it manually
Jon Hall7eb38402015-01-08 17:19:54 -08003642 self.handle.sendline( "update" )
Jon Hall43060f62020-06-23 13:13:33 -07003643 self.handle.expect( "update" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003644 i = self.handle.expect( [ "Unknown command: update", self.mnPrompt ], timeout )
Jon Hall43060f62020-06-23 13:13:33 -07003645 if i == 0:
3646 main.log.debug( self.handle.before + self.handle.after )
3647 main.log.warn( "Mininet cli does not have update command, attempting to update interfaces without it" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003648 self.handle.expect( self.mnPrompt )
Jon Hall43060f62020-06-23 13:13:33 -07003649 self.handle.sendline( "px [i.updateAddr() for h in net.hosts for i in h.intfs.values() ] " )
Jon Hallf6aeda22020-07-28 09:12:56 -07003650 self.handle.expect( self.mnPrompt, timeout )
Jon Hall43060f62020-06-23 13:13:33 -07003651 self.handle.sendline( "px [i.updateAddr() for s in net.switches for i in h.intfs.values() ] " )
Jon Hallf6aeda22020-07-28 09:12:56 -07003652 self.handle.expect( self.mnPrompt, timeout )
Jon Hall38481722014-11-04 16:50:05 -05003653
Jon Hall7eb38402015-01-08 17:19:54 -08003654 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003655 self.handle.expect( self.mnPrompt )
Jon Hall38481722014-11-04 16:50:05 -05003656
Jon Hallb1290e82014-11-18 16:17:48 -05003657 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003658 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()
Jon Hallb1290e82014-11-18 16:17:48 -05003662 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003663 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()
Jon Hallb1290e82014-11-18 16:17:48 -05003669
Jon Halld80cc142015-07-06 13:36:05 -07003670 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003671 """
3672 Add vlan tag to a host.
3673 Dependencies:
3674 This class depends on the "vlan" package
3675 $ sudo apt-get install vlan
3676 Configuration:
3677 Load the 8021q module into the kernel
3678 $sudo modprobe 8021q
3679
3680 To make this setup permanent:
3681 $ sudo su -c 'echo "8021q" >> /etc/modules'
3682 """
3683 if self.handle:
3684 try:
Jon Halld80cc142015-07-06 13:36:05 -07003685 # get the ip address of the host
3686 main.log.info( "Get the ip address of the host" )
3687 ipaddr = self.getIPAddress( host )
3688 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003689
Jon Halld80cc142015-07-06 13:36:05 -07003690 # remove IP from interface intf
3691 # Ex: h1 ifconfig h1-eth0 inet 0
3692 main.log.info( "Remove IP from interface " )
3693 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3694 self.handle.sendline( cmd2 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003695 self.handle.expect( self.mnPrompt )
Jon Halld80cc142015-07-06 13:36:05 -07003696 response = self.handle.before
3697 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003698
Jon Halld80cc142015-07-06 13:36:05 -07003699 # create VLAN interface
3700 # Ex: h1 vconfig add h1-eth0 100
3701 main.log.info( "Create Vlan" )
3702 cmd3 = host + " vconfig add " + intf + " " + vlan
3703 self.handle.sendline( cmd3 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003704 self.handle.expect( self.mnPrompt )
Jon Halld80cc142015-07-06 13:36:05 -07003705 response = self.handle.before
3706 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003707
Jon Halld80cc142015-07-06 13:36:05 -07003708 # assign the host's IP to the VLAN interface
3709 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3710 main.log.info( "Assign the host IP to the vlan interface" )
3711 vintf = intf + "." + vlan
3712 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3713 self.handle.sendline( cmd4 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003714 self.handle.expect( self.mnPrompt )
Jon Halld80cc142015-07-06 13:36:05 -07003715 response = self.handle.before
3716 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003717
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003718 # update Mininet node variables
3719 main.log.info( "Update Mininet node variables" )
3720 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3721 self.handle.sendline( cmd5 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003722 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003723 response = self.handle.before
3724 main.log.info( "====> %s ", response )
3725
3726 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3727 self.handle.sendline( cmd6 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003728 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003729 response = self.handle.before
3730 main.log.info( "====> %s ", response )
3731
3732 return main.TRUE
3733 except pexpect.TIMEOUT:
3734 main.log.error( self.name + ": TIMEOUT exception found" )
3735 main.log.error( self.name + ": " + self.handle.before )
3736 main.cleanAndExit()
3737 except pexpect.EOF:
3738 main.log.error( self.name + ": EOF exception found" )
3739 main.log.error( self.name + ": " + self.handle.before )
3740 return main.FALSE
3741 except Exception:
3742 main.log.exception( self.name + ": Uncaught exception!" )
3743 return main.FALSE
3744
3745 def removeVLAN( self, host, intf ):
3746 """
3747 Remove vlan tag from a host.
3748 Dependencies:
3749 This class depends on the "vlan" package
3750 $ sudo apt-get install vlan
3751 Configuration:
3752 Load the 8021q module into the kernel
3753 $sudo modprobe 8021q
3754
3755 To make this setup permanent:
3756 $ sudo su -c 'echo "8021q" >> /etc/modules'
3757 """
3758 if self.handle:
3759 try:
3760 # get the ip address of the host
3761 main.log.info( "Get the ip address of the host" )
3762 ipaddr = self.getIPAddress( host )
3763
3764 # remove VLAN interface
3765 # Ex: h1 vconfig rem h1-eth0.100
3766 main.log.info( "Remove Vlan interface" )
3767 cmd2 = host + " vconfig rem " + intf
3768 self.handle.sendline( cmd2 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003769 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003770 response = self.handle.before
3771 main.log.info( "====> %s ", response )
3772
3773 # assign the host's IP to the original interface
3774 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3775 main.log.info( "Assign the host IP to the original interface" )
3776 original_intf = intf.split(".")[0]
3777 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3778 self.handle.sendline( cmd3 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003779 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003780 response = self.handle.before
3781 main.log.info( "====> %s ", response )
3782
3783 # update Mininet node variables
3784 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3785 self.handle.sendline( cmd4 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003786 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003787 response = self.handle.before
3788 main.log.info( "====> %s ", response )
3789
3790 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3791 self.handle.sendline( cmd5 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003792 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003793 response = self.handle.before
3794 main.log.info( "====> %s ", response )
3795
kaouthera3f13ca22015-05-05 15:01:41 -07003796 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003797 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003798 main.log.error( self.name + ": TIMEOUT exception found" )
3799 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003800 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003801 except pexpect.EOF:
3802 main.log.error( self.name + ": EOF exception found" )
3803 main.log.error( self.name + ": " + self.handle.before )
3804 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003805 except Exception:
3806 main.log.exception( self.name + ": Uncaught exception!" )
3807 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003808
Jon Hall43060f62020-06-23 13:13:33 -07003809 def createHostComponent( self, name, execDir=None, hostHome=None ):
Jon Hall892818c2015-10-20 17:58:34 -07003810 """
3811 Creates a new mininet cli component with the same parameters as self.
3812 This new component is intended to be used to login to the hosts created
3813 by mininet.
3814
3815 Arguments:
3816 name - The string of the name of this component. The new component
3817 will be assigned to main.<name> .
3818 In addition, main.<name>.name = str( name )
3819 """
3820 try:
3821 # look to see if this component already exists
3822 getattr( main, name )
3823 except AttributeError:
3824 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003825 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3826 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall43060f62020-06-23 13:13:33 -07003827 component = main.componentInit( name )
3828 if execDir is not None:
3829 component.mExecDir = execDir
3830 else:
3831 component.mExecDir = self.mExecDir
3832
3833 if hostHome is not None:
3834 component.hostHome = hostHome
3835 else:
3836 component.hostHome = self.hostHome
3837 component.hostPrompt = self.hostPrompt
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003838 except pexpect.EOF:
3839 main.log.error( self.name + ": EOF exception found" )
3840 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003841 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003842 except Exception:
3843 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003844 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003845 else:
3846 # namespace is not clear!
3847 main.log.error( name + " component already exists!" )
3848 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003849 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003850
3851 def removeHostComponent( self, name ):
3852 """
3853 Remove host component
3854 Arguments:
3855 name - The string of the name of the component to delete.
3856 """
3857 try:
3858 # Get host component
3859 component = getattr( main, name )
3860 except AttributeError:
3861 main.log.error( "Component " + name + " does not exist." )
3862 return
3863 try:
3864 # Disconnect from component
3865 component.disconnect()
You Wangf32c6ed2018-08-23 17:10:22 -07003866 component.close_log_handles()
Jon Hall892818c2015-10-20 17:58:34 -07003867 # Delete component
3868 delattr( main, name )
3869 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003870 del( main.componentDictionary[ name ] )
You Wangf32c6ed2018-08-23 17:10:22 -07003871 except StandardError:
3872 self.log.exception( "Exception while closing log files for " + name )
3873 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003874 except pexpect.EOF:
3875 main.log.error( self.name + ": EOF exception found" )
3876 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003877 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003878 except Exception:
3879 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003880 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003881
Jon Hall43060f62020-06-23 13:13:33 -07003882 def startHostCli( self, host=None, execDir=None, hostHome=None ):
Jon Hall892818c2015-10-20 17:58:34 -07003883 """
3884 Use the mininet m utility to connect to the host's cli
Jon Hall43060f62020-06-23 13:13:33 -07003885 mnexec tries to cd to cwd after it connects to the host. If execDir
3886 is set, this will change cwd to execDir before executing m.
3887 If hostHome is set, the function will export the value to the HOME
3888 environment variable.
Jon Hall892818c2015-10-20 17:58:34 -07003889 """
3890 # These are fields that can be used by scapy packets. Initialized to None
3891 self.hostIp = None
3892 self.hostMac = None
Jon Hall43060f62020-06-23 13:13:33 -07003893 if execDir is not None:
3894 self.mExecDir = execDir
3895 if hostHome is not None:
3896 self.hostHome = hostHome
Jon Hall892818c2015-10-20 17:58:34 -07003897 try:
3898 if not host:
3899 host = self.name
Jon Hall43060f62020-06-23 13:13:33 -07003900 if self.mExecDir:
3901 self.handle.sendline( "cd %s" % self.mExecDir )
Jon Hall3c0114c2020-08-11 15:07:42 -07003902 self.handle.expect( self.Prompt() )
Jon Hall43060f62020-06-23 13:13:33 -07003903
Jon Hall892818c2015-10-20 17:58:34 -07003904 self.handle.sendline( self.home + "/util/m " + host )
Jon Hall43060f62020-06-23 13:13:33 -07003905 if self.hostHome:
3906 self.handle.sendline( "export HOME=%s" % self.hostHome )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003907 self.handle.sendline( "cd" )
3908 self.handle.expect( self.hostPrompt )
3909 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003910 self.handle.expect( self.hostPrompt )
3911 return main.TRUE
3912 except pexpect.TIMEOUT:
3913 main.log.exception( self.name + ": Command timed out" )
Jon Hall43060f62020-06-23 13:13:33 -07003914 main.log.debug( self.handle.before )
Jon Hall892818c2015-10-20 17:58:34 -07003915 return main.FALSE
3916 except pexpect.EOF:
3917 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003918 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003919 except Exception:
3920 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003921 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003922
YPZhang801d46d2016-08-08 13:26:28 -07003923 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003924 '''
3925
YPZhang801d46d2016-08-08 13:26:28 -07003926 Args:
3927 devicename: switch name
3928 intf: port name on switch
3929 status: up or down
3930
3931 Returns: boolean to show success change status
3932
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003933 '''
YPZhang801d46d2016-08-08 13:26:28 -07003934 if status == "down" or status == "up":
3935 try:
3936 cmd = devicename + " ifconfig " + intf + " " + status
3937 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07003938 self.handle.expect( self.mnPrompt )
YPZhang801d46d2016-08-08 13:26:28 -07003939 return main.TRUE
3940 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003941 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003942 return main.FALSE
3943 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003944 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003945 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003946 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003947 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003948 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003949 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003950 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003951 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003952 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003953 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003954 return main.FALSE
3955
You Wang6e5b48e2018-07-23 16:17:38 -07003956 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003957 """
You Wang6e5b48e2018-07-23 16:17:38 -07003958 Moves a host from one switch to another on the fly
3959 Optional:
3960 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3961 prefixLen: length of the host IP prefix
3962 ipv6: move an IPv6 host if True
3963 intfSuffix: suffix of the new interface after host movement
3964 vlan: vlan ID of the host. Use None for non-vlan host
3965 Note: The intf between host and oldSw when detached
3966 using detach(), will still show up in the 'net'
3967 cmd, because switch.detach() doesn't affect switch.intfs[]
3968 ( which is correct behavior since the interfaces
3969 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003970 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003971 if self.handle:
3972 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003973 newIntf = "%s-%s" % ( host, intfSuffix )
3974 commands = [
3975 # Bring link between oldSw-host down
3976 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3977 # Determine hostintf and Oldswitchintf
3978 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
3979 ]
3980 # Determine ip address of the host-oldSw interface
3981 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3982 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3983 commands += [
3984 # Determine mac address of the host-oldSw interface
3985 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3986 # Detach interface between oldSw-host
3987 "px " + oldSw + ".detach( sintf )",
3988 # Add link between host-newSw
3989 "py net.addLink(" + host + "," + newSw + ")",
3990 # Determine hostintf and Newswitchintf
3991 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3992 # Attach interface between newSw-host
3993 "px " + newSw + ".attach( sintf )",
3994 ]
3995 if vlan:
3996 vlanIntf = "%s.%s" % ( newIntf, vlan )
3997 commands += [
3998 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
3999 host + " ip link set up %s" % vlanIntf,
4000 "px hintf.name = '" + vlanIntf + "'",
4001 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
4002 ]
4003 newIntf = vlanIntf
4004 commands += [
4005 # Set mac address of the host-newSw interface
4006 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
4007 # Set IP address of the host-newSw interface
4008 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
4009 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
4010 ]
4011 if ipv6:
4012 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
4013 commands += [
4014 "net",
4015 host + " ifconfig"
4016 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004017 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004018 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004019 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07004020 self.handle.expect( self.mnPrompt )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004021 main.log.info( "====> %s ", self.handle.before )
4022 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004023 except pexpect.TIMEOUT:
4024 main.log.error( self.name + ": TIMEOUT exception found" )
4025 main.log.error( self.name + ": " + self.handle.before )
4026 main.cleanAndExit()
4027 except pexpect.EOF:
4028 main.log.error( self.name + ": EOF exception found" )
4029 main.log.error( self.name + ": " + self.handle.before )
4030 return main.FALSE
4031 except Exception:
4032 main.log.exception( self.name + ": Uncaught exception!" )
4033 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07004034
You Wang6e5b48e2018-07-23 16:17:38 -07004035 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
4036 macAddr=None, prefixLen=None, ipv6=False,
4037 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07004038 """
You Wang6e5b48e2018-07-23 16:17:38 -07004039 Moves a dual-homed host from one switch-pair to another pair on the fly
4040 Optional:
4041 macAddr: when specified, change MAC address of the host interface to specified MAC address.
4042 prefixLen: length of the host IP prefix
4043 ipv6: move an IPv6 host if True
4044 intfSuffix1: suffix of the first new interface
4045 intfSuffix2: suffix of the second new interface
4046 bondSuffix: suffix of the new bond interface
4047 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07004048 """
You Wang7ea90582018-07-19 15:27:58 -07004049 if self.handle:
4050 try:
You Wang6e5b48e2018-07-23 16:17:38 -07004051 bondIntf = "%s-%s" % ( host, bondSuffix )
4052 newIntf = "%s-%s" % ( host, intfSuffix1 )
4053 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07004054 commands = [
4055 # Bring link between oldSw-host down
4056 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
4057 # Bring link between oldPairSw-host down
4058 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
4059 # Determine hostintf and Oldswitchintf
4060 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07004061 ]
4062 # Determine ip address of the host-oldSw interface
4063 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
4064 commands.append( 'px ipaddr = "{}"'.format( IP ) )
4065 commands += [
4066 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07004067 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
4068 # Detach interface between oldSw-host
4069 "px " + oldSw + ".detach( sintf )",
4070 # Determine hostintf and Oldpairswitchintf
4071 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
4072 # Detach interface between oldPairSw-host
4073 "px " + oldPairSw + ".detach( sintfpair )",
4074 # Add link between host-newSw
4075 "py net.addLink(" + host + "," + newSw + ", 2)",
4076 # Add link between host-newPairSw
4077 "py net.addLink(" + host + "," + newPairSw + ")",
4078 # Determine hostintf and Newswitchintf
4079 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
4080 # Determine hostintf and NewPairswitchintf
4081 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
4082 # Attach interface between newSw-host
4083 "px " + newSw + ".attach( sintf )",
4084 # Attach interface between newPairSw-host
4085 "px " + newPairSw + ".attach( sintfpair )",
4086 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07004087 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004088 host + ' ip link set %s down' % newIntf,
4089 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004090 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
4091 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07004092 host + ' ip addr flush dev %s' % newIntf,
4093 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004094 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004095 "px lowestIntf = min( [ hintf, hintfpair ] )",
4096 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07004097 "px lowestIntf.name = '" + bondIntf + "'",
4098 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07004099 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
4100 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07004101 ]
4102 if vlan:
4103 vlanIntf = "%s.%s" % ( bondIntf, vlan )
4104 commands += [
4105 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
4106 host + " ip link set up %s" % vlanIntf,
4107 "px lowestIntf.name = '" + vlanIntf + "'",
4108 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
4109 ]
4110 bondIntf = vlanIntf
4111 commands += [
4112 # Set macaddress of the host-newSw interface
4113 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07004114 # Set ipaddress of the host-newSw interface
4115 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
4116 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07004117 ]
You Wang6e5b48e2018-07-23 16:17:38 -07004118 if ipv6:
4119 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
4120 commands += [
4121 "net",
4122 host + " ifconfig"
4123 ]
You Wang7ea90582018-07-19 15:27:58 -07004124 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004125 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07004126 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07004127 self.handle.expect( self.mnPrompt )
You Wang7ea90582018-07-19 15:27:58 -07004128 main.log.info( "====> %s ", self.handle.before )
4129 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07004130 except pexpect.TIMEOUT:
4131 main.log.error( self.name + ": TIMEOUT exception found" )
4132 main.log.error( self.name + ": " + self.handle.before )
4133 main.cleanAndExit()
4134 except pexpect.EOF:
4135 main.log.error( self.name + ": EOF exception found" )
4136 main.log.error( self.name + ": " + self.handle.before )
4137 return main.FALSE
4138 except Exception:
4139 main.log.exception( self.name + ": Uncaught exception!" )
4140 return main.FALSE
4141
adminbae64d82013-08-01 10:50:15 -07004142if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004143 sys.modules[ __name__ ] = MininetCliDriver()