blob: 439b4fbda45ad2e5b45a1e40ce57135f597aefd5 [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:
Jon Hallb369cba2020-08-14 14:55:39 -0700606 failAsserts = [ "command not found", "Unable to get" ]
You Wang32833172018-10-23 15:19:31 -0700607 hosts = self.getHosts()
You Wang48381752018-05-07 13:50:57 -0700608 if not hostList:
You Wang48381752018-05-07 13:50:57 -0700609 hostList = hosts.keys()
610 discoveryResult = main.TRUE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700611 for host in hostList:
Jon Hallb369cba2020-08-14 14:55:39 -0700612 flushV6 = False
613 flushV4 = False
You Wang036ec2c2019-02-27 15:44:15 -0800614 cmds = []
Jon Hallb369cba2020-08-14 14:55:39 -0700615 for intf in hosts[ host ][ 'interfaces' ]:
616 intfName = intf.get( 'name' )
617 if self.getIPAddress( host, iface=intfName ):
618 flushV4 = True
619 intfStr = "-i {}".format( intfName ) if intfName else ""
620 cmds.append( "{} arping -c 1 -w {} {} {}".format(
621 host, wait, intfStr, dstIp ) )
622 main.log.debug( "Sending IPv4 arping from host {}:{}".format( host, intfName ) )
623 elif self.getIPAddress( host, proto='IPV6', iface=intfName ):
624 flushV6 = True
625 ipv6Addr = self.getIPAddress( host, proto='IPV6', iface=intfName )
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 ) )
Jon Hallb369cba2020-08-14 14:55:39 -0700628 else:
629 main.log.warn( "No IP addresses configured on host {}, trying ping".format( host ) )
630 cmds.append( "{} ping -c 1 -i 1 -w {} -I {} {}".format(
631 host, str( int( wait / 1000 ) ), intfName, dstIp ) )
632 if flushV6:
633 flushCmd = "{} ip -6 neigh flush all".format( host )
You Wang0b82aa52018-06-06 14:33:58 -0700634 self.handle.sendline( flushCmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700635 self.handle.expect( self.mnPrompt )
Jon Hallb369cba2020-08-14 14:55:39 -0700636 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
637 response = self.handle.before
638 for failure in failAsserts:
639 assert failure not in response, response
640 if flushV4:
641 flushCmd = "{} ip neigh flush all".format( host )
642 self.handle.sendline( flushCmd )
643 self.handle.expect( self.mnPrompt )
644 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
645 response = self.handle.before
646 for failure in failAsserts:
647 assert failure not in response, response
You Wang036ec2c2019-02-27 15:44:15 -0800648 for cmd in cmds:
You Wang48381752018-05-07 13:50:57 -0700649 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700650 self.handle.expect( self.mnPrompt, timeout=wait + 5 )
Jon Hallb369cba2020-08-14 14:55:39 -0700651 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
652 response = self.handle.before
653 for failure in failAsserts:
654 assert failure not in response, response
655 # FIXME we are always returning TRUE now
You Wang48381752018-05-07 13:50:57 -0700656 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700657 except pexpect.TIMEOUT:
658 main.log.exception( self.name + ": TIMEOUT exception" )
659 response = self.handle.before
660 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hallf6aeda22020-07-28 09:12:56 -0700661 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700662 response += self.handle.before + self.handle.after
You Wang7ce29462019-03-04 13:37:14 -0800663 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -0700664 self.handle.expect( self.mnPrompt )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700665 response += self.handle.before + self.handle.after
666 main.log.debug( response )
667 return main.FALSE
668 except pexpect.EOF:
669 main.log.error( self.name + ": EOF exception found" )
670 main.log.error( self.name + ": " + self.handle.before )
671 main.cleanAndExit()
672 except Exception:
673 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800674 main.cleanAndExit()
675
676 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
677 """
678 Verify ping from each host in srcList to each host in dstList
679
680 acceptableFailed: max number of acceptable failed pings
681
682 Returns main.TRUE if all src hosts can reach all dst hosts
683 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
684 """
685 try:
686 main.log.info( "Verifying ping from each src host to each dst host" )
687 isReachable = main.TRUE
688 wait = int( wait )
689 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
690 pingResponse = "Ping output:\n"
691 failedPingsTotal = 0
692 for host in srcList:
693 pingResponse += str( str( host ) + " -> " )
694 for temp in dstList:
695 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700696 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
697 assert dstIP, "Not able to get IP address of host {}".format( temp )
698 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800699 while failedPings <= acceptableFailed:
700 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
701 self.handle.sendline( pingCmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700702 self.handle.expect( self.mnPrompt, timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800703 response = self.handle.before
704 if re.search( ',\s0\%\spacket\sloss', response ):
705 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800706 break
707 else:
708 failedPings += 1
709 time.sleep(1)
710 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700711 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800712 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700713 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800714 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700715 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800716 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700717 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700718 except AssertionError:
719 main.log.exception( "" )
720 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700721 except pexpect.TIMEOUT:
722 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800723 response = self.handle.before
724 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hallf6aeda22020-07-28 09:12:56 -0700725 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
Jon Hall3c910162018-03-07 14:42:16 -0800726 response += self.handle.before + self.handle.after
You Wang7ce29462019-03-04 13:37:14 -0800727 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -0700728 self.handle.expect( self.mnPrompt )
Jon Hall3c910162018-03-07 14:42:16 -0800729 response += self.handle.before + self.handle.after
730 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700731 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700732 except pexpect.EOF:
733 main.log.error( self.name + ": EOF exception found" )
734 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700735 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700736 except Exception:
737 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700738 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700739
Jon Hall7eb38402015-01-08 17:19:54 -0800740 def pingHost( self, **pingParams ):
741 """
Jon Hall3b489db2015-10-05 14:38:37 -0700742 Ping from one mininet host to another
743 Currently the only supported Params: SRC, TARGET, and WAIT
744 """
745 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700746 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700747 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800748 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700749 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700750 try:
Jon Hall61282e32015-03-19 11:34:11 -0700751 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800752 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700753 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700754 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700755 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800756 main.log.error(
757 self.name +
758 ": timeout when waiting for response from mininet" )
759 main.log.error( "response: " + str( self.handle.before ) )
Jon Hallf6aeda22020-07-28 09:12:56 -0700760 i = self.handle.expect( [ self.mnPrompt, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700761 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800762 main.log.error(
763 self.name +
764 ": timeout when waiting for response from mininet" )
765 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700766 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700767 if re.search( ',\s0\%\spacket\sloss', response ):
768 main.log.info( self.name + ": no packets lost, host is reachable" )
769 return main.TRUE
770 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800771 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700772 self.name +
773 ": PACKET LOST, HOST IS NOT REACHABLE" )
774 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800775 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800776 main.log.error( self.name + ": EOF exception found" )
777 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700778 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700779 except Exception:
780 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700781 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700782
783 def ping6pair( self, **pingParams ):
784 """
GlennRC2cf7d952015-09-11 16:32:13 -0700785 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700786 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000787 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700788 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
789 """
Jon Hall3b489db2015-10-05 14:38:37 -0700790 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700791 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700792 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530793 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700794 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700795 try:
796 main.log.info( "Sending: " + command )
797 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700798 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700799 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700800 if i == 1:
801 main.log.error(
802 self.name +
803 ": timeout when waiting for response from mininet" )
804 main.log.error( "response: " + str( self.handle.before ) )
Jon Hallf6aeda22020-07-28 09:12:56 -0700805 i = self.handle.expect( [ self.mnPrompt, pexpect.TIMEOUT ] )
Hari Krishna012a1c12015-08-25 14:23:58 -0700806 if i == 1:
807 main.log.error(
808 self.name +
809 ": timeout when waiting for response from mininet" )
810 main.log.error( "response: " + str( self.handle.before ) )
811 response = self.handle.before
812 main.log.info( self.name + ": Ping Response: " + response )
813 if re.search( ',\s0\%\spacket\sloss', response ):
814 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700815 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700816 else:
alisone4121a92016-11-22 16:31:36 -0800817 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700818 self.name +
819 ": PACKET LOST, HOST IS NOT REACHABLE" )
820 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700821 except pexpect.EOF:
822 main.log.error( self.name + ": EOF exception found" )
823 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700824 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700825 except Exception:
826 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700827 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800828
You Wangdb927a52016-02-26 11:03:28 -0800829 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
830 """
831 Description:
832 Ping a set of destination host from host CLI.
833 Logging into a Mininet host CLI is required before calling this funtion.
834 Params:
835 dstIPList is a list of destination ip addresses
836 Returns:
837 main.TRUE if the destination host is reachable
838 main.FALSE otherwise
839 """
840 isReachable = main.TRUE
841 wait = int( wait )
842 cmd = "ping"
843 if IPv6:
844 cmd = cmd + "6"
845 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
846 try:
847 for dstIP in dstIPList:
848 pingCmd = cmd + " " + dstIP
849 self.handle.sendline( pingCmd )
850 i = self.handle.expect( [ self.hostPrompt,
851 '\*\*\* Unknown command: ' + pingCmd,
852 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700853 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700854 # For some reason we need to send something
855 # Otherwise ping results won't be read by handle
Jon Hall43060f62020-06-23 13:13:33 -0700856 response = self.handle.before
You Wang5da39c82018-04-26 22:55:08 -0700857 self.handle.sendline( "" )
858 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800859 if i == 0:
Jon Hall43060f62020-06-23 13:13:33 -0700860 response += self.handle.before
You Wangdb927a52016-02-26 11:03:28 -0800861 if not re.search( ',\s0\%\spacket\sloss', response ):
862 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
863 isReachable = main.FALSE
864 elif i == 1:
865 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700866 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800867 elif i == 2:
868 main.log.error( self.name + ": timeout when waiting for response" )
869 isReachable = main.FALSE
870 else:
871 main.log.error( self.name + ": unknown response: " + self.handle.before )
872 isReachable = main.FALSE
873 except pexpect.TIMEOUT:
874 main.log.exception( self.name + ": TIMEOUT exception" )
You Wangd4fae5c2018-08-22 13:56:49 -0700875 self.exitFromCmd( [ self.hostPrompt, self.bashPrompt ] )
You Wangdb927a52016-02-26 11:03:28 -0800876 isReachable = main.FALSE
877 except pexpect.EOF:
878 main.log.error( self.name + ": EOF exception found" )
879 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700880 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800881 except Exception:
882 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700883 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800884 return isReachable
885
Jon Hall7eb38402015-01-08 17:19:54 -0800886 def checkIP( self, host ):
887 """
888 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700889 try:
890 if self.handle:
891 try:
892 response = self.execute(
893 cmd=host +
894 " ifconfig",
Jon Hallf6aeda22020-07-28 09:12:56 -0700895 prompt=self.mnPrompt,
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700896 timeout=10 )
897 except pexpect.EOF:
898 main.log.error( self.name + ": EOF exception found" )
899 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700900 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700901
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700902 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
903 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
904 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
905 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
906 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
907 "[0-9]|25[0-5]|[0-9]{1,2})"
908 # pattern = "inet addr:10.0.0.6"
909 if re.search( pattern, response ):
910 main.log.info( self.name + ": Host Ip configured properly" )
911 return main.TRUE
912 else:
913 main.log.error( self.name + ": Host IP not found" )
914 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700915 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700916 main.log.error( self.name + ": Connection failed to the host" )
917 except Exception:
918 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700919 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800920
Jon Hall7eb38402015-01-08 17:19:54 -0800921 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800922 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700923 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800924 response = self.execute(
925 cmd="h1 /usr/sbin/sshd -D&",
Jon Hallf6aeda22020-07-28 09:12:56 -0700926 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -0800927 timeout=10 )
928 response = self.execute(
929 cmd="h4 /usr/sbin/sshd -D&",
Jon Hallf6aeda22020-07-28 09:12:56 -0700930 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -0800931 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700932 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800933 vars( self )[ key ] = connectargs[ key ]
934 response = self.execute(
935 cmd="xterm h1 h4 ",
Jon Hallf6aeda22020-07-28 09:12:56 -0700936 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -0800937 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800938 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800939 main.log.error( self.name + ": EOF exception found" )
940 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700941 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700942 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800943 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700944 if self.flag == 0:
945 self.flag = 1
946 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800947 else:
adminbae64d82013-08-01 10:50:15 -0700948 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800949
Jon Hall7eb38402015-01-08 17:19:54 -0800950 def changeIP( self, host, intf, newIP, newNetmask ):
951 """
952 Changes the ip address of a host on the fly
953 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800954 if self.handle:
955 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800956 cmd = host + " ifconfig " + intf + " " + \
957 newIP + " " + 'netmask' + " " + newNetmask
958 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700959 self.handle.expect( self.mnPrompt )
shahshreyae6c7cf42014-11-26 16:39:01 -0800960 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800961 main.log.info( "response = " + response )
962 main.log.info(
963 "Ip of host " +
964 host +
965 " changed to new IP " +
966 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800967 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700968 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700969 main.log.error( self.name + ": TIMEOUT exception found" )
970 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700971 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800972 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800973 main.log.error( self.name + ": EOF exception found" )
974 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800975 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700976 except Exception:
977 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700978 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800979
Jon Hall7eb38402015-01-08 17:19:54 -0800980 def changeDefaultGateway( self, host, newGW ):
981 """
982 Changes the default gateway of a host
983 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800984 if self.handle:
985 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800986 cmd = host + " route add default gw " + newGW
987 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700988 self.handle.expect( self.mnPrompt )
shahshreyae6c7cf42014-11-26 16:39:01 -0800989 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800990 main.log.info( "response = " + response )
991 main.log.info(
992 "Default gateway of host " +
993 host +
994 " changed to " +
995 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800996 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700997 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700998 main.log.error( self.name + ": TIMEOUT exception found" )
999 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001000 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -08001001 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001002 main.log.error( self.name + ": EOF exception found" )
1003 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -08001004 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001005 except Exception:
1006 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001007 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001008
You Wange24d6272018-03-27 21:18:50 -07001009 def addRoute( self, host, dstIP, interface, ipv6=False ):
1010 """
1011 Add a route to host
1012 Ex: h1 route add -host 224.2.0.1 h1-eth0
1013 """
1014 if self.handle:
1015 try:
1016 cmd = str( host )
1017 if ipv6:
1018 cmd += " route -A inet6 add "
1019 else:
1020 cmd += " route add -host "
1021 cmd += str( dstIP ) + " " + str( interface )
1022 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07001023 self.handle.expect( self.mnPrompt )
You Wange24d6272018-03-27 21:18:50 -07001024 response = self.handle.before
1025 main.log.debug( "response = " + response )
1026 return main.TRUE
1027 except pexpect.TIMEOUT:
1028 main.log.error( self.name + ": TIMEOUT exception found" )
1029 main.log.error( self.name + ": " + self.handle.before )
1030 main.cleanAndExit()
1031 except pexpect.EOF:
1032 main.log.error( self.name + ": EOF exception found" )
1033 main.log.error( self.name + ": " + self.handle.before )
1034 return main.FALSE
1035 except Exception:
1036 main.log.exception( self.name + ": Uncaught exception!" )
1037 main.cleanAndExit()
1038
Jon Hall7eb38402015-01-08 17:19:54 -08001039 def addStaticMACAddress( self, host, GW, macaddr ):
1040 """
Jon Hallefbd9792015-03-05 16:11:36 -08001041 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001042 if self.handle:
1043 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001044 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1045 cmd = host + " arp -s " + GW + " " + macaddr
1046 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07001047 self.handle.expect( self.mnPrompt )
shahshreyad0c80432014-12-04 16:56:05 -08001048 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001049 main.log.info( "response = " + response )
1050 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001051 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001052 GW +
1053 " changed to " +
1054 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001055 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001056 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001057 main.log.error( self.name + ": TIMEOUT exception found" )
1058 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001059 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001060 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001061 main.log.error( self.name + ": EOF exception found" )
1062 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001063 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001064 except Exception:
1065 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001066 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001067
Jon Hall7eb38402015-01-08 17:19:54 -08001068 def verifyStaticGWandMAC( self, host ):
1069 """
1070 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001071 if self.handle:
1072 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001073 # h1 arp -an
1074 cmd = host + " arp -an "
1075 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07001076 self.handle.expect( self.mnPrompt )
shahshreyad0c80432014-12-04 16:56:05 -08001077 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001078 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001079 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001080 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001081 main.log.error( self.name + ": TIMEOUT exception found" )
1082 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001083 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001084 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001085 main.log.error( self.name + ": EOF exception found" )
1086 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001087 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001088 except Exception:
1089 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001090 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001091
Jon Hall7eb38402015-01-08 17:19:54 -08001092 def getMacAddress( self, host ):
1093 """
1094 Verifies the host's ip configured or not."""
1095 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001096 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001097 response = self.execute(
1098 cmd=host +
1099 " ifconfig",
Jon Hallf6aeda22020-07-28 09:12:56 -07001100 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001101 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001102 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001103 main.log.error( self.name + ": EOF exception found" )
1104 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001105 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001106 except Exception:
1107 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001108 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001109
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001110 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001111 macAddressSearch = re.search( pattern, response, re.I )
1112 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001113 main.log.info(
1114 self.name +
1115 ": Mac-Address of Host " +
1116 host +
1117 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001118 macAddress )
1119 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001120 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001121 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001122
Jon Hall7eb38402015-01-08 17:19:54 -08001123 def getInterfaceMACAddress( self, host, interface ):
1124 """
1125 Return the IP address of the interface on the given host"""
1126 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001127 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001128 response = self.execute( cmd=host + " ifconfig " + interface,
Jon Hallf6aeda22020-07-28 09:12:56 -07001129 prompt=self.mnPrompt, timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001130 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001131 main.log.error( self.name + ": EOF exception found" )
1132 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001133 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001134 except Exception:
1135 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001136 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001137
1138 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001139 macAddressSearch = re.search( pattern, response, re.I )
1140 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001141 main.log.info( "No mac address found in %s" % response )
1142 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001143 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001144 main.log.info(
1145 "Mac-Address of " +
1146 host +
1147 ":" +
1148 interface +
1149 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001150 macAddress )
1151 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001152 else:
1153 main.log.error( "Connection failed to the host" )
1154
Jon Hallb369cba2020-08-14 14:55:39 -07001155 def getIPAddress( self, host, proto='IPV4', iface="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001156 """
1157 Verifies the host's ip configured or not."""
1158 if self.handle:
1159 try:
1160 response = self.execute(
1161 cmd=host +
Jon Hallb369cba2020-08-14 14:55:39 -07001162 " ifconfig %s" % iface,
Jon Hallf6aeda22020-07-28 09:12:56 -07001163 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001164 timeout=10 )
Jon Hallb369cba2020-08-14 14:55:39 -07001165 assert "Device not found" not in response, response
Jon Hall7eb38402015-01-08 17:19:54 -08001166 except pexpect.EOF:
1167 main.log.error( self.name + ": EOF exception found" )
1168 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001169 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001170 except Exception:
1171 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001172 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001173
sathishmad953462015-12-03 17:42:07 +05301174 pattern = ''
1175 if proto == 'IPV4':
Jon Hall43060f62020-06-23 13:13:33 -07001176 ip4Pat = r"(\d+\.\d+\.\d+\.\d+)"
1177 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 +05301178 else:
Jon Hall43060f62020-06-23 13:13:33 -07001179 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}))'
Jon Hallb369cba2020-08-14 14:55:39 -07001180 pattern = r"inet6\s(addr:\s)?" + inet6Pat + r"(/\d+)?\s(Scope:(Global)|\sprefixlen\s(\d)+\s\sscopeid 0x(\d+)\<(global)>)"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001181 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001182 if not ipAddressSearch:
Jon Hall43060f62020-06-23 13:13:33 -07001183 main.log.debug( response )
1184 main.log.warn( "Could not find %s address" % proto )
Jon Hall3c910162018-03-07 14:42:16 -08001185 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001186 main.log.info(
1187 self.name +
1188 ": IP-Address of Host " +
1189 host +
1190 " is " +
Jon Hall43060f62020-06-23 13:13:33 -07001191 ipAddressSearch.group( 'ip' ) )
1192 return ipAddressSearch.group( 'ip' )
Jon Hall7eb38402015-01-08 17:19:54 -08001193 else:
1194 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001195
Jon Hall7eb38402015-01-08 17:19:54 -08001196 def getSwitchDPID( self, switch ):
1197 """
1198 return the datapath ID of the switch"""
1199 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001200 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001201 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001202 response = self.execute(
1203 cmd=cmd,
Jon Hallf6aeda22020-07-28 09:12:56 -07001204 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001205 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001206 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001207 main.log.error( self.name + ": EOF exception found" )
1208 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001209 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001210 except Exception:
1211 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001212 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001213 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001214 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001215 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001216 main.log.info(
1217 "Couldn't find DPID for switch %s, found: %s" %
1218 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001219 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001220 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001221 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001222 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001223
Jon Hall7eb38402015-01-08 17:19:54 -08001224 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001225 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001226 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07001227 self.expect( self.mnPrompt )
Jon Hall7eb38402015-01-08 17:19:54 -08001228 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001229 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001230 response = self.execute(
1231 cmd=cmd,
Jon Hallf6aeda22020-07-28 09:12:56 -07001232 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001233 timeout=10 )
Jon Hallf6aeda22020-07-28 09:12:56 -07001234 self.handle.expect( self.mnPrompt )
admin2580a0e2014-07-29 11:24:34 -07001235 response = self.handle.before
1236 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001237 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001238 main.log.error( self.name + ": TIMEOUT exception found" )
1239 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001240 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001241 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001242 main.log.error( self.name + ": EOF exception found" )
1243 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001244 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001245 except Exception:
1246 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001247 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001248
Jon Hall7eb38402015-01-08 17:19:54 -08001249 def getInterfaces( self, node ):
1250 """
1251 return information dict about interfaces connected to the node"""
1252 if self.handle:
1253 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001254 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001255 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001256 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001257 response = self.execute(
1258 cmd=cmd,
Jon Hallf6aeda22020-07-28 09:12:56 -07001259 prompt=self.mnPrompt,
You Wang7d14d642019-01-23 15:10:08 -08001260 timeout=10,
1261 logCmd=False )
Jon Hallfbc828e2015-01-06 17:30:19 -08001262 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001263 main.log.error( self.name + ": EOF exception found" )
1264 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001265 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001266 except Exception:
1267 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001268 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001269 return response
1270 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001271 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001272
Jon Hall7eb38402015-01-08 17:19:54 -08001273 def dump( self ):
1274 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001275 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001276 response = self.execute(
1277 cmd='dump',
Jon Hall3c0114c2020-08-11 15:07:42 -07001278 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001279 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001280 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001281 main.log.error( self.name + ": EOF exception found" )
1282 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001283 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001284 except Exception:
1285 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001286 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001287 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001288
Jon Hall7eb38402015-01-08 17:19:54 -08001289 def intfs( self ):
1290 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001291 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001292 response = self.execute(
1293 cmd='intfs',
Jon Hall3c0114c2020-08-11 15:07:42 -07001294 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001295 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001296 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001297 main.log.error( self.name + ": EOF exception found" )
1298 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001299 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001300 except Exception:
1301 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001302 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001303 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001304
Jon Hall7eb38402015-01-08 17:19:54 -08001305 def net( self ):
1306 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001307 try:
Jon Hall3c0114c2020-08-11 15:07:42 -07001308 response = self.execute( cmd='net', prompt=self.mnPrompt, timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001309 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001310 main.log.error( self.name + ": EOF exception found" )
1311 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001312 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001313 except Exception:
1314 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001315 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001316 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001317
Devin Lima7cfdbd2017-09-29 15:02:22 -07001318 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001319 main.log.info( self.name + ": List network links" )
1320 try:
Jon Hall3c0114c2020-08-11 15:07:42 -07001321 response = self.execute( cmd='links', prompt=self.mnPrompt,
YPZhang81a7d4e2016-04-18 13:10:17 -07001322 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001323 except pexpect.EOF:
1324 main.log.error( self.name + ": EOF exception found" )
1325 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001326 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001327 except Exception:
1328 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001329 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001330 return response
1331
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001332 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001333 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001334 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001335
kelvin-onlab7cce9382015-07-17 10:21:03 -07001336 @parm:
1337 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1338 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001339 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001340 try:
1341 for host1 in hosts:
1342 for host2 in hosts:
1343 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001344 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1345 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001346 except Exception:
1347 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001348 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001349
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001350 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001351 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001352 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1353 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001354
kelvin-onlab7cce9382015-07-17 10:21:03 -07001355 @parm:
1356 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1357 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001358 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001359 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1360 try:
1361 # Setup the mininet command
1362 cmd1 = 'iperf ' + host1 + " " + host2
1363 self.handle.sendline( cmd1 )
Jon Hallf6aeda22020-07-28 09:12:56 -07001364 outcome = self.handle.expect( self.mnPrompt, timeout )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001365 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001366
kelvin-onlab7cce9382015-07-17 10:21:03 -07001367 # checks if there are results in the mininet response
1368 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001369 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001370 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001371 response = response.split( "\r\n" )
1372 response = response[ len( response )-2 ]
1373 response = response.split( ": " )
1374 response = response[ len( response )-1 ]
1375 response = response.replace( "[", "" )
1376 response = response.replace( "]", "" )
1377 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001378
kelvin-onlab7cce9382015-07-17 10:21:03 -07001379 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001380 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001381
kelvin-onlab7cce9382015-07-17 10:21:03 -07001382 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001383 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001384 if len( bandwidth ) == 2:
1385 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001386 return main.TRUE
1387 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001388 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001389 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001390 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001391 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001392 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001393 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001394 main.log.error( self.name + ": TIMEOUT exception found" )
1395 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001396 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001397 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hallf6aeda22020-07-28 09:12:56 -07001398 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
You Wang7ce29462019-03-04 13:37:14 -08001399 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07001400 self.handle.expect( self.mnPrompt )
GlennRC61321f22015-07-16 13:36:54 -07001401 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001402 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001403 main.log.error( self.name + ": EOF exception found" )
1404 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001405 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001406 except Exception:
1407 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001408 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001409
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001410 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001411 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1412 try:
1413 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001414 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001415 self.handle.sendline( cmd1 )
Jon Hallf6aeda22020-07-28 09:12:56 -07001416 outcome1 = self.handle.expect( self.mnPrompt )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001417 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001418 self.handle.sendline( cmd2 )
Jon Hallf6aeda22020-07-28 09:12:56 -07001419 outcome2 = self.handle.expect( self.mnPrompt )
Jon Hall439c8912016-04-15 02:22:03 -07001420 response1 = self.handle.before
1421 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001422 print response1, response2
1423 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001424 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001425 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001426 return main.TRUE
1427 else:
1428 main.log.error( self.name + ": iperf test failed" )
1429 return main.FALSE
1430 except pexpect.TIMEOUT:
1431 main.log.error( self.name + ": TIMEOUT exception found" )
1432 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hallf6aeda22020-07-28 09:12:56 -07001433 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
You Wang7ce29462019-03-04 13:37:14 -08001434 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07001435 self.handle.expect( self.mnPrompt )
Jon Hall439c8912016-04-15 02:22:03 -07001436 return main.FALSE
1437 except pexpect.EOF:
1438 main.log.error( self.name + ": EOF exception found" )
1439 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001440 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001441 except Exception:
1442 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001443 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001444
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001445 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001446 '''
GlennRC61321f22015-07-16 13:36:54 -07001447 Runs the iperfudp function with a given set of hosts and specified
1448 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001449
GlennRC61321f22015-07-16 13:36:54 -07001450 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001451 bandwidth: the targeted bandwidth, in megabits ('M')
1452 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001453 try:
1454 for host1 in hosts:
1455 for host2 in hosts:
1456 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001457 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1458 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001459 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001460 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001461 return main.FALSE
1462 except Exception:
1463 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001464 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001465
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001466 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001467 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001468 Creates an iperf UDP test with a specific bandwidth.
1469 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001470
kelvin-onlab7cce9382015-07-17 10:21:03 -07001471 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001472 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1473 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001474 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001475 try:
1476 # setup the mininet command
1477 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001478 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07001479 self.handle.expect( self.mnPrompt )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001480 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001481
kelvin-onlab7cce9382015-07-17 10:21:03 -07001482 # check if there are in results in the mininet response
1483 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001484 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001485 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001486 response = response.split( "\r\n" )
1487 response = response[ len( response )-2 ]
1488 response = response.split( ": " )
1489 response = response[ len( response )-1 ]
1490 response = response.replace( "[", "" )
1491 response = response.replace( "]", "" )
1492 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001493
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001494 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001495
kelvin-onlab7cce9382015-07-17 10:21:03 -07001496 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001497 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001498 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001499 # if one entry is blank then something is wrong
1500 for item in mnBandwidth:
1501 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001502 main.log.error( self.name + ": Could not parse iperf output" )
1503 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001504 return main.FALSE
1505 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001506 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001507 return main.TRUE
1508 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001509 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001510 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001511
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001512 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001513 main.log.error( self.name + ": TIMEOUT exception found" )
1514 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001515 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001516 except pexpect.EOF:
1517 main.log.error( self.name + ": EOF exception found" )
1518 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001519 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001520 except Exception:
1521 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001522 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001523
Jon Hall7eb38402015-01-08 17:19:54 -08001524 def nodes( self ):
1525 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001526 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001527 response = self.execute(
1528 cmd='nodes',
Jon Hall3c0114c2020-08-11 15:07:42 -07001529 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001530 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001531 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001532 main.log.error( self.name + ": EOF exception found" )
1533 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001534 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001535 except Exception:
1536 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001537 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001538 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001539
Jon Hall7eb38402015-01-08 17:19:54 -08001540 def pingpair( self ):
1541 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001542 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001543 response = self.execute(
1544 cmd='pingpair',
Jon Hall3c0114c2020-08-11 15:07:42 -07001545 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001546 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001547 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001548 main.log.error( self.name + ": EOF exception found" )
1549 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001550 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001551 except Exception:
1552 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001553 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001554
Jon Hall7eb38402015-01-08 17:19:54 -08001555 if re.search( ',\s0\%\spacket\sloss', response ):
1556 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001557 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001558 else:
alisone4121a92016-11-22 16:31:36 -08001559 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001560 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001561
Jon Hall7eb38402015-01-08 17:19:54 -08001562 def link( self, **linkargs ):
1563 """
GlennRCed771242016-01-13 17:02:47 -08001564 Bring link( s ) between two nodes up or down
1565 """
Jon Hall6094a362014-04-11 14:46:56 -07001566 try:
GlennRCed771242016-01-13 17:02:47 -08001567 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1568 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1569 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1570 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1571
1572 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1573 cmd = "link {} {} {}".format( end1, end2, option )
1574 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07001575 self.handle.expect( self.mnPrompt )
GlennRCed771242016-01-13 17:02:47 -08001576 response = self.handle.before
1577 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001578 if "not in network" in response:
1579 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1580 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001581 return main.TRUE
1582 except pexpect.TIMEOUT:
1583 main.log.exception( self.name + ": Command timed out" )
1584 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001585 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001586 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001587 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001588 except Exception:
1589 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001590 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001591
pingping-lin8244a3b2015-09-16 13:36:56 -07001592 def switch( self, **switchargs ):
1593 """
1594 start/stop a switch
1595 """
1596 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1597 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1598 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1599 command = "switch " + str( sw ) + " " + str( option )
1600 main.log.info( command )
1601 try:
1602 self.handle.sendline( command )
Jon Hallf6aeda22020-07-28 09:12:56 -07001603 self.handle.expect( self.mnPrompt )
pingping-lin8244a3b2015-09-16 13:36:56 -07001604 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001605 main.log.error( self.name + ": TIMEOUT exception found" )
1606 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001607 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001608 except pexpect.EOF:
1609 main.log.error( self.name + ": EOF exception found" )
1610 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001611 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001612 return main.TRUE
1613
pingping-lin5bb663b2015-09-24 11:47:50 -07001614 def node( self, nodeName, commandStr ):
1615 """
1616 Carry out a command line on a given node
1617 @parm:
1618 nodeName: the node name in Mininet testbed
1619 commandStr: the command line will be carried out on the node
1620 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1621 """
1622 command = str( nodeName ) + " " + str( commandStr )
1623 main.log.info( command )
1624
1625 try:
Jon Hallf6aeda22020-07-28 09:12:56 -07001626 response = self.execute( cmd = command, prompt = self.mnPrompt )
pingping-lin5bb663b2015-09-24 11:47:50 -07001627 if re.search( "Unknown command", response ):
1628 main.log.warn( response )
1629 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001630 if re.search( "Permission denied", response ):
1631 main.log.warn( response )
1632 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001633 except pexpect.EOF:
1634 main.log.error( self.name + ": EOF exception found" )
1635 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001636 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001637 main.log.info( " response is :" )
1638 main.log.info( response )
1639 return response
1640
Jon Hall7eb38402015-01-08 17:19:54 -08001641 def yank( self, **yankargs ):
1642 """
1643 yank a mininet switch interface to a host"""
1644 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001645 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001646 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1647 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001648 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001649 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001650 response = self.execute(
1651 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001652 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001653 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001654 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001655 main.log.error( self.name + ": EOF exception found" )
1656 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001657 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001658 except Exception:
1659 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001660 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001661 return main.TRUE
1662
Jon Hall7eb38402015-01-08 17:19:54 -08001663 def plug( self, **plugargs ):
1664 """
1665 plug the yanked mininet switch interface to a switch"""
1666 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001667 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001668 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1669 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001670 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001671 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001672 response = self.execute(
1673 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001674 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001675 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001676 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001677 main.log.error( self.name + ": EOF exception found" )
1678 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001679 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001680 except Exception:
1681 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001682 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001683 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001684
Jon Hall7eb38402015-01-08 17:19:54 -08001685 def dpctl( self, **dpctlargs ):
1686 """
1687 Run dpctl command on all switches."""
1688 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001689 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001690 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1691 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1692 command = "dpctl " + cmd + " " + str( cmdargs )
1693 try:
1694 response = self.execute(
1695 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001696 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001697 timeout=10 )
1698 except pexpect.EOF:
1699 main.log.error( self.name + ": EOF exception found" )
1700 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001701 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001702 except Exception:
1703 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001704 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001705 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001706
kelvin-onlabd3b64892015-01-20 13:26:24 -08001707 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001708 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001709 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001710 try:
1711 fileInput = path + '/lib/Mininet/INSTALL'
1712 version = super( Mininet, self ).getVersion()
1713 pattern = 'Mininet\s\w\.\w\.\w\w*'
1714 for line in open( fileInput, 'r' ).readlines():
1715 result = re.match( pattern, line )
1716 if result:
1717 version = result.group( 0 )
1718 return version
1719 except Exception:
1720 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001721 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001722
kelvin-onlabd3b64892015-01-20 13:26:24 -08001723 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001724 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001725 Parameters:
1726 sw: The name of an OVS switch. Example "s1"
1727 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001728 The output of the command from the mininet cli
1729 or main.FALSE on timeout"""
1730 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001731 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001732 response = self.execute(
1733 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001734 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001735 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001736 if response:
Jon Hallab611372018-02-21 15:26:05 -08001737 if "no bridge named" in response:
1738 main.log.error( self.name + ": Error in getSwController: " +
1739 self.handle.before )
1740 return main.FALSE
1741 else:
1742 return response
admin2a9548d2014-06-17 14:08:07 -07001743 else:
1744 return main.FALSE
1745 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001746 main.log.error( self.name + ": EOF exception found" )
1747 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001748 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001749 except Exception:
1750 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001751 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001752
Charles Chan029be652015-08-24 01:46:10 +08001753 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001754 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001755 Description:
1756 Assign switches to the controllers ( for ovs use only )
1757 Required:
1758 sw - Name of the switch. This can be a list or a string.
1759 ip - Ip addresses of controllers. This can be a list or a string.
1760 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001761 port - ONOS use port 6653, if no list of ports is passed, then
1762 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001763 ptcp - ptcp number, This can be a string or a list that has
1764 the same length as switch. This is optional and not required
1765 when using ovs switches.
1766 NOTE: If switches and ptcp are given in a list type they should have the
1767 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1768 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001769
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001770 Return:
1771 Returns main.TRUE if mininet correctly assigned switches to
1772 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001773 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001774 """
1775 assignResult = main.TRUE
1776 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001777 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001778 command = "sh ovs-vsctl set-controller "
1779 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001780 try:
1781 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001782 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001783 if isinstance( port, types.StringType ) or \
1784 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001785 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001786 elif isinstance( port, types.ListType ):
1787 main.log.error( self.name + ": Only one controller " +
1788 "assigned and a list of ports has" +
1789 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001790 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001791 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001792 main.log.error( self.name + ": Invalid controller port " +
1793 "number. Please specify correct " +
1794 "controller port" )
1795 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001796
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001797 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001798 if isinstance( port, types.StringType ) or \
1799 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001800 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001801 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1802 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001803 elif isinstance( port, types.ListType ):
1804 if ( len( ip ) != len( port ) ):
1805 main.log.error( self.name + ": Port list = " +
1806 str( len( port ) ) +
1807 "should be the same as controller" +
1808 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001809 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001810 else:
1811 onosIp = ""
1812 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001813 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1814 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001815 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001816 main.log.error( self.name + ": Invalid controller port " +
1817 "number. Please specify correct " +
1818 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001819 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001820 else:
1821 main.log.error( self.name + ": Invalid ip address" )
1822 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001823
1824 if isinstance( sw, types.StringType ):
1825 command += sw + " "
1826 if ptcp:
1827 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001828 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001829 elif isinstance( ptcp, types.ListType ):
1830 main.log.error( self.name + ": Only one switch is " +
1831 "being set and multiple PTCP is " +
1832 "being passed " )
1833 else:
1834 main.log.error( self.name + ": Invalid PTCP" )
1835 ptcp = ""
1836 command += onosIp
1837 commandList.append( command )
1838
1839 elif isinstance( sw, types.ListType ):
1840 if ptcp:
1841 if isinstance( ptcp, types.ListType ):
1842 if len( ptcp ) != len( sw ):
1843 main.log.error( self.name + ": PTCP length = " +
1844 str( len( ptcp ) ) +
1845 " is not the same as switch" +
1846 " length = " +
1847 str( len( sw ) ) )
1848 return main.FALSE
1849 else:
1850 for switch, ptcpNum in zip( sw, ptcp ):
1851 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001852 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001853 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001854 tempCmd += onosIp
1855 commandList.append( tempCmd )
1856 else:
1857 main.log.error( self.name + ": Invalid PTCP" )
1858 return main.FALSE
1859 else:
1860 for switch in sw:
1861 tempCmd = "sh ovs-vsctl set-controller "
1862 tempCmd += switch + " " + onosIp
1863 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001864 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001865 main.log.error( self.name + ": Invalid switch type " )
1866 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001867
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001868 for cmd in commandList:
1869 try:
Jon Hallf6aeda22020-07-28 09:12:56 -07001870 self.execute( cmd=cmd, prompt=self.mnPrompt, timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08001871 if "no bridge named" in self.handle.before:
1872 main.log.error( self.name + ": Error in assignSwController: " +
1873 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001874 except pexpect.TIMEOUT:
1875 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1876 return main.FALSE
1877 except pexpect.EOF:
1878 main.log.error( self.name + ": EOF exception found" )
1879 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001880 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001881 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001882 except pexpect.EOF:
1883 main.log.error( self.name + ": EOF exception found" )
1884 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001885 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001886 except Exception:
1887 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001888 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001889
kelvin-onlabd3b64892015-01-20 13:26:24 -08001890 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001891 """
1892 Removes the controller target from sw"""
1893 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001894 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001895 response = self.execute(
1896 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001897 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001898 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001899 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001900 main.log.error( self.name + ": EOF exception found" )
1901 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001902 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001903 except Exception:
1904 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001905 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001906 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001907 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001908
kelvin-onlabd3b64892015-01-20 13:26:24 -08001909 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001910 """
Jon Hallb1290e82014-11-18 16:17:48 -05001911 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001912 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001913 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001914 NOTE: cannot currently specify what type of switch
1915 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001916 sw = name of the new switch as a string
1917 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001918 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001919 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001920 """
1921 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001922 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001923 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001924 response = self.execute(
1925 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001926 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001927 timeout=10 )
1928 if re.search( "already exists!", response ):
1929 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001930 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001931 elif re.search( "Error", response ):
1932 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001933 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001934 elif re.search( "usage:", response ):
1935 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001936 return main.FALSE
1937 else:
1938 return main.TRUE
1939 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001940 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001941 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001942 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001943 except Exception:
1944 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001945 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001946
kelvin-onlabd3b64892015-01-20 13:26:24 -08001947 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001948 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001949 delete a switch from the mininet topology
1950 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001951 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001952 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001953 sw = name of the switch as a string
1954 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001955 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001956 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001957 response = self.execute(
1958 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001959 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001960 timeout=10 )
1961 if re.search( "no switch named", response ):
1962 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001963 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001964 elif re.search( "Error", response ):
1965 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001966 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001967 elif re.search( "usage:", response ):
1968 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001969 return main.FALSE
1970 else:
1971 return main.TRUE
1972 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001973 main.log.error( self.name + ": EOF exception found" )
1974 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001975 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001976 except Exception:
1977 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001978 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001979
You Wangb1665b52019-02-01 15:49:48 -08001980 def getSwitchRandom( self, timeout=60, nonCut=True, excludeNodes=[], skipSwitches=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07001981 """
1982 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001983 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001984 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001985 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07001986 it just randomly returns one switch from all current switches in
1987 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08001988 excludeNodes will be pased to getGraphDict method
You Wangb1665b52019-02-01 15:49:48 -08001989 Switches specified in skipSwitches will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07001990 Returns the name of the chosen switch.
1991 """
1992 import random
1993 candidateSwitches = []
1994 try:
1995 if not nonCut:
You Wangb1665b52019-02-01 15:49:48 -08001996 switches = self.getSwitches( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07001997 assert len( switches ) != 0
1998 for switchName in switches.keys():
1999 candidateSwitches.append( switchName )
2000 else:
You Wang7d14d642019-01-23 15:10:08 -08002001 graphDict = self.getGraphDict( timeout=timeout, useId=False,
You Wang7d14d642019-01-23 15:10:08 -08002002 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002003 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002004 return None
2005 self.graph.update( graphDict )
2006 candidateSwitches = self.graph.getNonCutVertices()
You Wangb1665b52019-02-01 15:49:48 -08002007 candidateSwitches = [ switch for switch in candidateSwitches if switch not in skipSwitches ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002008 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002009 return None
2010 elif len( candidateSwitches ) == 0:
2011 main.log.info( self.name + ": No candidate switch for deletion" )
2012 return None
2013 else:
2014 switch = random.sample( candidateSwitches, 1 )
2015 return switch[ 0 ]
2016 except KeyError:
2017 main.log.exception( self.name + ": KeyError exception found" )
2018 return None
2019 except AssertionError:
2020 main.log.exception( self.name + ": AssertionError exception found" )
2021 return None
2022 except Exception:
2023 main.log.exception( self.name + ": Uncaught exception" )
2024 return None
2025
2026 def delSwitchRandom( self, timeout=60, nonCut=True ):
2027 """
2028 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002029 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002030 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002031 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002032 otherwise it just randomly delete one switch from all current
2033 switches in Mininet.
2034 Returns the name of the deleted switch
2035 """
2036 try:
2037 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002038 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002039 return None
2040 else:
2041 deletionResult = self.delSwitch( switch )
2042 if deletionResult:
2043 return switch
2044 else:
2045 return None
2046 except Exception:
2047 main.log.exception( self.name + ": Uncaught exception" )
2048 return None
2049
kelvin-onlabd3b64892015-01-20 13:26:24 -08002050 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002051 """
2052 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002053 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002054 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002055 NOTE: cannot currently specify what type of link
2056 required params:
2057 node1 = the string node name of the first endpoint of the link
2058 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002059 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002060 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002061 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002062 response = self.execute(
2063 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002064 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08002065 timeout=10 )
2066 if re.search( "doesnt exist!", response ):
2067 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002068 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002069 elif re.search( "Error", response ):
2070 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002071 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002072 elif re.search( "usage:", response ):
2073 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002074 return main.FALSE
2075 else:
2076 return main.TRUE
2077 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002078 main.log.error( self.name + ": EOF exception found" )
2079 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002080 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002081 except Exception:
2082 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002083 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002084
kelvin-onlabd3b64892015-01-20 13:26:24 -08002085 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002086 """
2087 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002088 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002089 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002090 required params:
2091 node1 = the string node name of the first endpoint of the link
2092 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002093 returns: main.FALSE on an error, else main.TRUE
2094 """
Jon Hallffb386d2014-11-21 13:43:38 -08002095 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002096 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002097 response = self.execute(
2098 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002099 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08002100 timeout=10 )
2101 if re.search( "no node named", response ):
2102 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002103 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002104 elif re.search( "Error", response ):
2105 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002106 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002107 elif re.search( "usage:", response ):
2108 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002109 return main.FALSE
2110 else:
2111 return main.TRUE
2112 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002113 main.log.error( self.name + ": EOF exception found" )
2114 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002115 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002116 except Exception:
2117 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002118 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002119
You Wangb1665b52019-02-01 15:49:48 -08002120 def getLinkRandom( self, timeout=60, nonCut=True, excludeNodes=[], skipLinks=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07002121 """
2122 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002123 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002124 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002125 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002126 it just randomly returns one link from all current links in
2127 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08002128 excludeNodes will be passed to getLinks method to exclude unexpected links.
You Wangb1665b52019-02-01 15:49:48 -08002129 Any link that has either end included in skipLinks will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07002130 Returns the link as a list, e.g. [ 's1', 's2' ]
2131 """
2132 import random
2133 candidateLinks = []
2134 try:
2135 if not nonCut:
You Wang7d14d642019-01-23 15:10:08 -08002136 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07002137 assert len( links ) != 0
2138 for link in links:
2139 # Exclude host-switch link
2140 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2141 continue
2142 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2143 else:
You Wang7d14d642019-01-23 15:10:08 -08002144 graphDict = self.getGraphDict( timeout=timeout, useId=False,
You Wang7d14d642019-01-23 15:10:08 -08002145 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002146 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002147 return None
2148 self.graph.update( graphDict )
2149 candidateLinks = self.graph.getNonCutEdges()
You Wangb1665b52019-02-01 15:49:48 -08002150 candidateLinks = [ link for link in candidateLinks
2151 if link[0] not in skipLinks and link[1] not in skipLinks ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002152 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002153 return None
2154 elif len( candidateLinks ) == 0:
2155 main.log.info( self.name + ": No candidate link for deletion" )
2156 return None
2157 else:
2158 link = random.sample( candidateLinks, 1 )
2159 return link[ 0 ]
2160 except KeyError:
2161 main.log.exception( self.name + ": KeyError exception found" )
2162 return None
2163 except AssertionError:
2164 main.log.exception( self.name + ": AssertionError exception found" )
2165 return None
2166 except Exception:
2167 main.log.exception( self.name + ": Uncaught exception" )
2168 return None
2169
2170 def delLinkRandom( self, timeout=60, nonCut=True ):
2171 """
2172 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002173 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002174 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002175 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002176 otherwise it just randomly delete one link from all current links
2177 in Mininet.
2178 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2179 """
2180 try:
2181 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002182 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002183 return None
2184 else:
2185 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2186 if deletionResult:
2187 return link
2188 else:
2189 return None
2190 except Exception:
2191 main.log.exception( self.name + ": Uncaught exception" )
2192 return None
2193
kelvin-onlabd3b64892015-01-20 13:26:24 -08002194 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002195 """
Jon Hallb1290e82014-11-18 16:17:48 -05002196 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002197 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002198 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002199 NOTE: cannot currently specify what type of host
2200 required params:
2201 hostname = the string hostname
2202 optional key-value params
2203 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002204 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002205 """
2206 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002207 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002208 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002209 response = self.execute(
2210 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002211 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08002212 timeout=10 )
2213 if re.search( "already exists!", response ):
2214 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002215 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002216 elif re.search( "doesnt exists!", response ):
2217 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002218 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002219 elif re.search( "Error", response ):
2220 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002221 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002222 elif re.search( "usage:", response ):
2223 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002224 return main.FALSE
2225 else:
2226 return main.TRUE
2227 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002228 main.log.error( self.name + ": EOF exception found" )
2229 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002230 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002231 except Exception:
2232 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002233 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002234
kelvin-onlabd3b64892015-01-20 13:26:24 -08002235 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002236 """
2237 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002238 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002239 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002240 NOTE: this uses a custom mn function
2241 required params:
2242 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002243 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002244 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002245 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002246 response = self.execute(
2247 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002248 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08002249 timeout=10 )
2250 if re.search( "no host named", response ):
2251 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002252 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002253 elif re.search( "Error", response ):
2254 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002255 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002256 elif re.search( "usage:", response ):
2257 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002258 return main.FALSE
2259 else:
2260 return main.TRUE
2261 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002262 main.log.error( self.name + ": EOF exception found" )
2263 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002264 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002265 except Exception:
2266 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002267 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002268
Jon Hall7eb38402015-01-08 17:19:54 -08002269 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002270 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002271 Called at the end of the test to stop the mininet and
2272 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002273 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002274 try:
2275 self.handle.sendline( '' )
Jon Hall3c0114c2020-08-11 15:07:42 -07002276 i = self.handle.expect( [ self.mnPrompt, self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002277 timeout=2 )
2278 response = main.TRUE
2279 if i == 0:
2280 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002281 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002282 return main.TRUE
2283 # print "Disconnecting Mininet"
2284 if self.handle:
2285 self.handle.sendline( "exit" )
2286 self.handle.expect( "exit" )
2287 self.handle.expect( "(.*)" )
2288 else:
2289 main.log.error( "Connection failed to the host" )
2290 return response
2291 except pexpect.EOF:
2292 main.log.error( self.name + ": EOF exception found" )
2293 main.log.error( self.name + ": " + self.handle.before )
You Wangd4fae5c2018-08-22 13:56:49 -07002294 # Do not exit the entire test when pexpect.EOF is caught
2295 # FIXME: We might need to do something else here
2296 return main.ERROR
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002297 except Exception:
2298 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002299 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002300
Devin Lima7cfdbd2017-09-29 15:02:22 -07002301 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002302 """
Jon Hall21270ac2015-02-16 17:59:55 -08002303 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002304 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002305 main.FALSE if the pexpect handle does not exist.
2306
Jon Halld61331b2015-02-17 16:35:47 -08002307 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002308 """
Jon Halld61331b2015-02-17 16:35:47 -08002309 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002310 response = ''
2311 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002312 try:
Jon Halld80cc142015-07-06 13:36:05 -07002313 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07002314 i = self.handle.expect( [ self.mnPrompt,
Jon Hall3c0114c2020-08-11 15:07:42 -07002315 self.Prompt(),
kelvin-onlab56a3f462015-02-06 14:04:43 -08002316 pexpect.EOF,
2317 pexpect.TIMEOUT ],
2318 timeout )
2319 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002320 main.log.info( "Exiting mininet.." )
2321 startTime = time.time()
Jon Hallf6aeda22020-07-28 09:12:56 -07002322 self.handle.sendline( "exit" )
2323 exitRet = 1
Jon Hall3c0114c2020-08-11 15:07:42 -07002324 while exitRet:
2325 exitRet = self.handle.expect( [ self.Prompt(),
Jon Hallf6aeda22020-07-28 09:12:56 -07002326 "Traceback",
2327 "AssertionError",
2328 self.mnPrompt ],
2329 timeout=exitTimeout )
2330 response += self.handle.before + self.handle.after
2331 main.log.debug( response )
Devin Lima7cfdbd2017-09-29 15:02:22 -07002332 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jon Halldac3eae2020-06-05 12:04:06 -07002333 cmd = "mn -c"
2334 if self.sudoRequired:
2335 cmd = "sudo " + cmd
2336 self.handle.sendline( cmd )
Jeremyd9e4eb12016-04-13 12:09:06 -07002337 response = main.TRUE
Jon Hall3c0114c2020-08-11 15:07:42 -07002338 self.handle.expect( self.Prompt() )
Jon Hallafa8a472015-06-12 14:02:42 -07002339
Jeremyd9e4eb12016-04-13 12:09:06 -07002340 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002341 main.log.info( " Mininet trying to exit while not " +
2342 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002343 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002344 elif i == 2:
2345 main.log.error( "Something went wrong exiting mininet" )
2346 elif i == 3: # timeout
2347 main.log.error( "Something went wrong exiting mininet " +
2348 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002349
You Wang18db8592018-04-02 13:52:03 -07002350 self.handle.sendline( "" )
Jon Hall3c0114c2020-08-11 15:07:42 -07002351 self.handle.expect( self.Prompt() )
Jon Halldac3eae2020-06-05 12:04:06 -07002352 cmd = "killall -9 dhclient dhcpd zebra bgpd"
2353 if self.sudoRequired:
2354 cmd = "sudo " + cmd
2355 self.handle.sendline( cmd )
Jon Hall3c0114c2020-08-11 15:07:42 -07002356 self.handle.expect( self.Prompt() )
You Wang18db8592018-04-02 13:52:03 -07002357
Hari Krishnab35c6d02015-03-18 11:13:51 -07002358 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002359 self.handle.sendline( "" )
Jon Hall3c0114c2020-08-11 15:07:42 -07002360 self.handle.expect( self.Prompt() )
Jon Halldac3eae2020-06-05 12:04:06 -07002361 cmd = "kill -9 \`ps -ef | grep \"" + fileName + "\" | grep -v grep | awk '{print $2}'\`"
2362 if self.sudoRequired:
2363 cmd = "sudo " + cmd
2364 self.handle.sendline( cmd )
Jon Hall3c0114c2020-08-11 15:07:42 -07002365 self.handle.expect( self.Prompt() )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002366 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002367 main.log.error( self.name + ": TIMEOUT exception found" )
2368 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002369 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002370 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002371 main.log.error( self.name + ": EOF exception found" )
2372 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002373 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002374 except Exception:
2375 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002376 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002377 else:
2378 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002379 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002380 return response
2381
YPZhang26a139e2016-04-25 14:01:55 -07002382 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002383 """
2384 Description:
2385 Sends arp message from mininet host for hosts discovery
2386 Required:
2387 host - hosts name
2388 Optional:
2389 ip - ip address that does not exist in the network so there would
2390 be no reply.
2391 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002392 if ethDevice:
2393 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002394 cmd = srcHost + " arping -c1 "
2395 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002396 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 -07002397 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002398 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002399 if output:
2400 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002401 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07002402 i = self.handle.expect( [ self.mnPrompt, "arping: " ] )
Jon Halla5cb3412015-08-18 14:08:22 -07002403 if i == 0:
2404 return main.TRUE
2405 elif i == 1:
2406 response = self.handle.before + self.handle.after
Jon Hallf6aeda22020-07-28 09:12:56 -07002407 self.handle.expect( self.mnPrompt )
Jon Halla5cb3412015-08-18 14:08:22 -07002408 response += self.handle.before + self.handle.after
2409 main.log.warn( "Error sending arping, output was: " +
2410 response )
2411 return main.FALSE
2412 except pexpect.TIMEOUT:
2413 main.log.error( self.name + ": TIMEOUT exception found" )
2414 main.log.warn( self.handle.before )
2415 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002416 except pexpect.EOF:
2417 main.log.error( self.name + ": EOF exception found" )
2418 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002419 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002420 except Exception:
2421 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002422 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002423
Jon Hall7eb38402015-01-08 17:19:54 -08002424 def decToHex( self, num ):
2425 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002426
Jon Hall7eb38402015-01-08 17:19:54 -08002427 def getSwitchFlowCount( self, switch ):
2428 """
2429 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002430 if self.handle:
2431 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2432 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002433 response = self.execute(
2434 cmd=cmd,
Jon Hallf6aeda22020-07-28 09:12:56 -07002435 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08002436 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002437 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002438 main.log.error( self.name + ": EOF exception found" )
2439 main.log.error( self.name + " " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002440 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002441 except Exception:
2442 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002443 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002444 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002445 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002446 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002447 main.log.info(
2448 "Couldn't find flows on switch %s, found: %s" %
2449 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002450 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002451 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002452 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002453 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002454
Jon Hall9ed8f372016-02-24 17:34:07 -08002455 def checkFlows( self, sw, dumpFormat=None ):
2456 if dumpFormat:
2457 command = "sh ovs-ofctl -F " + \
2458 dumpFormat + " dump-flows " + str( sw )
2459 else:
2460 command = "sh ovs-ofctl dump-flows " + str( sw )
2461 try:
2462 response = self.execute(
2463 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002464 prompt=self.mnPrompt,
Jon Hall9ed8f372016-02-24 17:34:07 -08002465 timeout=10 )
2466 return response
2467 except pexpect.EOF:
2468 main.log.error( self.name + ": EOF exception found" )
2469 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002470 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002471 except Exception:
2472 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002473 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002474
GlennRC68467eb2015-11-16 18:01:01 -08002475 def flowTableComp( self, flowTable1, flowTable2 ):
2476 # This function compares the selctors and treatments of each flow
2477 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002478 assert flowTable1, "flowTable1 is empty or None"
2479 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002480 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002481 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002482 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002483 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002484 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2485 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002486 for field in dFields:
2487 try:
2488 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002489 except KeyError:
2490 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002491 try:
2492 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002493 except KeyError:
2494 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002495 for i in range( len( flowTable1 ) ):
2496 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002497 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002498 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002499 returnValue = main.FALSE
2500 break
2501 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002502 except AssertionError:
2503 main.log.exception( "Nothing to compare" )
2504 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002505 except Exception:
2506 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002507 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002508
GlennRC528ad292015-11-12 10:38:18 -08002509 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002510 '''
GlennRC956ea742015-11-05 16:14:15 -08002511 Discription: Parses flows into json format.
2512 NOTE: this can parse any string thats separated with commas
2513 Arguments:
2514 Required:
2515 flows: a list of strings that represnt flows
2516 Optional:
2517 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2518 debug: prints out the final result
2519 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002520 '''
GlennRC528ad292015-11-12 10:38:18 -08002521 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002522 try:
2523 for flow in flowTable:
2524 jsonFlow = {}
2525 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002526 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002527 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002528 for i in range( len( parsedFlow ) ):
2529 item = parsedFlow[ i ]
2530 if item[ 0 ] == " ":
2531 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002532 # grab the selector and treatment from the parsed flow
2533 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002534 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002535 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002536 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002537 index = 0
2538 # parse the flags
2539 # NOTE: This only parses one flag
2540 flag = {}
2541 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002542 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002543 index += 1
2544 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002545 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002546 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002547 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002548 # the priority is stuck in the selecter so put it back
2549 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002550 if 'priority' in sel[0]:
2551 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002552 # parse selector
2553 criteria = []
2554 for item in sel:
2555 # this is the type of the packet e.g. "arp"
2556 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002557 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002558 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002559 field = item.split( "=" )
2560 criteria.append( { field[ 0 ]: field[ 1 ] } )
2561 selector = { "selector": { "criteria": sorted( criteria ) } }
2562 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002563 # get rid of the action part e.g. "action=output:2"
2564 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002565 treat = treat.split( "=" )
2566 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002567 # parse treatment
2568 action = []
2569 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002570 if ":" in item:
2571 field = item.split( ":" )
2572 action.append( { field[ 0 ]: field[ 1 ] } )
2573 else:
2574 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2575 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002576 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002577 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002578 # parse the rest of the flow
2579 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002580 field = item.split( "=" )
2581 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002582 # add the treatment and the selector to the json flow
2583 jsonFlow.update( selector )
2584 jsonFlow.update( treatment )
2585 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002586
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002587 if debug:
2588 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002589
You Wang91c37cf2016-05-23 09:39:42 -07002590 # add the json flow to the json flow table
2591 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002592
You Wang91c37cf2016-05-23 09:39:42 -07002593 return jsonFlowTable
2594
2595 except IndexError:
2596 main.log.exception( self.name + ": IndexError found" )
2597 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002598 except pexpect.EOF:
2599 main.log.error( self.name + ": EOF exception found" )
2600 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002601 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002602 except Exception:
2603 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002604 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002605
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002606 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002607 '''
2608 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002609 Each element is a flow.
2610 Arguments:
2611 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002612 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002613 a list of switches.
2614 Optional:
2615 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2616 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002617 '''
GlennRC956ea742015-11-05 16:14:15 -08002618 try:
2619 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002620 if isinstance( sw, list ):
2621 switches.extend( sw )
2622 else:
2623 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002624
2625 flows = []
2626 for s in switches:
2627 cmd = "sh ovs-ofctl dump-flows " + s
2628
GlennRC528ad292015-11-12 10:38:18 -08002629 if "1.0" == version:
2630 cmd += " -F OpenFlow10-table_id"
2631 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002632 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002633
2634 main.log.info( "Sending: " + cmd )
2635 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07002636 self.handle.expect( self.mnPrompt )
GlennRC956ea742015-11-05 16:14:15 -08002637 response = self.handle.before
2638 response = response.split( "\r\n" )
2639 # dump the first two elements and the last
2640 # the first element is the command that was sent
2641 # the second is the table header
2642 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002643 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002644 flows.extend( response )
2645
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002646 if debug:
2647 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002648
GlennRC528ad292015-11-12 10:38:18 -08002649 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002650
GlennRC956ea742015-11-05 16:14:15 -08002651 except pexpect.EOF:
2652 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002653 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002654 except Exception:
2655 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002656 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002657
2658 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002659 '''
GlennRC956ea742015-11-05 16:14:15 -08002660 Discription: Checks whether the ID provided matches a flow ID in Mininet
2661 Arguments:
2662 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002663 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002664 a list of switches.
2665 flowId: the flow ID in hex format. Can also be a list of IDs
2666 Optional:
2667 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2668 debug: prints out the final result
2669 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2670 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002671 '''
GlennRC956ea742015-11-05 16:14:15 -08002672 try:
2673 main.log.info( "Getting flows from Mininet" )
2674 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002675 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002676 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002677
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002678 if debug:
2679 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002680
2681 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002682 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002683 result = False
2684 for f in flows:
2685 if flowId in f.get( 'cookie' ):
2686 result = True
2687 break
2688 # flowId is a list
2689 else:
2690 result = True
2691 # Get flow IDs from Mininet
2692 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2693 # Save the IDs that are not in Mininet
2694 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2695
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002696 if debug:
2697 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002698
2699 # Print out the IDs that are not in Mininet
2700 if absentIds:
2701 main.log.warn( "Absent ids: {}".format( absentIds ) )
2702 result = False
2703
2704 return main.TRUE if result else main.FALSE
2705
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002706 except pexpect.EOF:
2707 main.log.error( self.name + ": EOF exception found" )
2708 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002709 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002710 except Exception:
2711 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002712 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002713
Charles Chan029be652015-08-24 01:46:10 +08002714 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002715 """
Jon Hallefbd9792015-03-05 16:11:36 -08002716 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002717 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002718 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002719 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07002720 self.handle.expect( self.mnPrompt )
Jon Halldac3eae2020-06-05 12:04:06 -07002721 if self.sudoRequired:
2722 sudoStr = "sudo "
2723 else:
2724 sudoStr = ""
Jon Hall7eb38402015-01-08 17:19:54 -08002725 self.handle.sendline(
Jon Halldac3eae2020-06-05 12:04:06 -07002726 "sh " + sudoStr + "tcpdump -n -i " +
2727 intf + " " + port + " -w " +
2728 filename.strip() + " &" )
Jon Hall7eb38402015-01-08 17:19:54 -08002729 self.handle.sendline( "" )
2730 i = self.handle.expect( [ 'No\ssuch\device',
2731 'listening\son',
2732 pexpect.TIMEOUT,
Jon Hallf6aeda22020-07-28 09:12:56 -07002733 self.mnPrompt ],
Jon Hall7eb38402015-01-08 17:19:54 -08002734 timeout=10 )
2735 main.log.warn( self.handle.before + self.handle.after )
2736 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07002737 self.handle.expect( self.mnPrompt )
admin2a9548d2014-06-17 14:08:07 -07002738 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002739 main.log.error(
2740 self.name +
2741 ": tcpdump - No such device exists. " +
2742 "tcpdump attempted on: " +
2743 intf )
admin2a9548d2014-06-17 14:08:07 -07002744 return main.FALSE
2745 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002746 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002747 return main.TRUE
2748 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002749 main.log.error(
2750 self.name +
2751 ": tcpdump command timed out! Check interface name," +
2752 " given interface was: " +
2753 intf )
admin2a9548d2014-06-17 14:08:07 -07002754 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002755 elif i == 3:
2756 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002757 return main.TRUE
2758 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002759 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002760 return main.FALSE
2761 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002762 main.log.error( self.name + ": EOF exception found" )
2763 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002764 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002765 except Exception:
2766 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002767 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002768
kelvin-onlabd3b64892015-01-20 13:26:24 -08002769 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002770 """
2771 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002772 try:
Jon Halldac3eae2020-06-05 12:04:06 -07002773 if self.sudoRequired:
2774 sudoStr = "sudo "
2775 else:
2776 sudoStr = ""
2777 self.handle.sendline( "sh " + sudoStr + " pkill tcpdump" )
Jon Hallf6aeda22020-07-28 09:12:56 -07002778 self.handle.expect( self.mnPrompt )
Jon Hall7eb38402015-01-08 17:19:54 -08002779 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07002780 self.handle.expect( self.mnPrompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002781 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002782 main.log.error( self.name + ": TIMEOUT exception found" )
2783 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002784 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002785 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002786 main.log.error( self.name + ": EOF exception found" )
2787 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002788 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002789 except Exception:
2790 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002791 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002792
Jon Halld80cc142015-07-06 13:36:05 -07002793 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002794 """
2795 Read ports from a Mininet switch.
2796
2797 Returns a json structure containing information about the
2798 ports of the given switch.
2799 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002800 try:
2801 response = self.getInterfaces( nodeName )
2802 # TODO: Sanity check on response. log if no such switch exists
2803 ports = []
2804 for line in response.split( "\n" ):
2805 if not line.startswith( "name=" ):
2806 continue
2807 portVars = {}
2808 for var in line.split( "," ):
2809 key, value = var.split( "=" )
2810 portVars[ key ] = value
2811 isUp = portVars.pop( 'enabled', "True" )
2812 isUp = "True" in isUp
2813 if verbose:
2814 main.log.info( "Reading switch port %s(%s)" %
2815 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2816 mac = portVars[ 'mac' ]
2817 if mac == 'None':
2818 mac = None
2819 ips = []
2820 ip = portVars[ 'ip' ]
2821 if ip == 'None':
2822 ip = None
2823 ips.append( ip )
2824 name = portVars[ 'name' ]
2825 if name == 'None':
2826 name = None
2827 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2828 if name == 'lo':
2829 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2830 else:
2831 portNo = re.search( portRe, name ).group( 'port' )
2832 ports.append( { 'of_port': portNo,
2833 'mac': str( mac ).replace( '\'', '' ),
2834 'name': name,
2835 'ips': ips,
2836 'enabled': isUp } )
2837 return ports
2838 except pexpect.EOF:
2839 main.log.error( self.name + ": EOF exception found" )
2840 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002841 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002842 except Exception:
2843 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002844 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002845
You Wangdb8cd0a2016-05-26 15:19:45 -07002846 def getOVSPorts( self, nodeName ):
2847 """
2848 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2849
2850 Returns a list of dictionaries containing information about each
2851 port of the given switch.
2852 """
2853 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2854 try:
2855 response = self.execute(
2856 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002857 prompt=self.mnPrompt,
You Wang7d14d642019-01-23 15:10:08 -08002858 timeout=10,
2859 logCmd=False )
You Wangdb8cd0a2016-05-26 15:19:45 -07002860 ports = []
2861 if response:
2862 for line in response.split( "\n" ):
2863 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2864 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002865 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002866 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2867 result = re.search( pattern, line )
2868 if result:
2869 index = result.group( 'index' )
2870 name = result.group( 'name' )
2871 # This port number is extracted from port name
2872 port = result.group( 'port' )
2873 mac = result.group( 'mac' )
2874 ports.append( { 'index': index,
2875 'name': name,
2876 'port': port,
2877 'mac': mac } )
2878 return ports
2879 except pexpect.EOF:
2880 main.log.error( self.name + ": EOF exception found" )
2881 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002882 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002883 except Exception:
2884 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002885 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002886
Jon Halldac3eae2020-06-05 12:04:06 -07002887 def getSwitches( self, verbose=False, updateTimeout=1000, excludeNodes=[], switchRegex=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002888 """
2889 Read switches from Mininet.
2890
2891 Returns a dictionary whose keys are the switch names and the value is
2892 a dictionary containing information about the switch.
You Wangb1665b52019-02-01 15:49:48 -08002893 If excludeNodes is specified, switches with names included in excludeNodes
2894 will be ingored.
Jon Hallafa8a472015-06-12 14:02:42 -07002895 """
Jon Halla22481b2015-07-28 17:46:01 -07002896 # NOTE: To support new Mininet switch classes, just append the new
2897 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002898
Jon Halla22481b2015-07-28 17:46:01 -07002899 # Regex patterns to parse 'dump' output
2900 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002901 # <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 -07002902 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002903 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2904 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2905 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Jon Halldac3eae2020-06-05 12:04:06 -07002906 if not switchRegex:
2907 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2908 else:
2909 switchClasses = switchRegex
You Wang7d14d642019-01-23 15:10:08 -08002910 try:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002911 swRE = r"<(?P<class>" + switchClasses + r")" +\
2912 r"(?P<options>\{.*\})?\s" +\
2913 r"(?P<name>[^:]+)\:\s" +\
2914 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2915 r"\spid=(?P<pid>(\d)+)"
2916 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002917 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002918 output = {}
2919 dump = self.dump().split( "\n" )
2920 for line in dump:
2921 result = re.search( swRE, line, re.I )
2922 if result:
2923 name = result.group( 'name' )
You Wangb1665b52019-02-01 15:49:48 -08002924 if name in excludeNodes:
2925 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002926 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2927 pid = result.group( 'pid' )
2928 swClass = result.group( 'class' )
2929 options = result.group( 'options' )
2930 if verbose:
2931 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2932 ports = self.getPorts( name )
2933 output[ name ] = { "dpid": dpid,
2934 "ports": ports,
2935 "swClass": swClass,
2936 "pid": pid,
2937 "options": options }
2938 return output
2939 except pexpect.EOF:
2940 main.log.error( self.name + ": EOF exception found" )
2941 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002942 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002943 except Exception:
2944 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002945 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002946
You Wangd66de192018-04-30 17:30:12 -07002947 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002948 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2949 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002950 """
2951 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002952 Optional:
2953 hostClass: it is used to match the class of the mininet host. It
2954 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002955 Returns a dictionary whose keys are the host names and the value is
2956 a dictionary containing information about the host.
2957 """
2958 # Regex patterns to parse dump output
2959 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002960 # <Host h1: pid=12725>
2961 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2962 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2963 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002964 # NOTE: Does not correctly match hosts with multi-links
2965 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2966 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002967 try:
You Wang53dba1e2018-02-02 17:45:44 -08002968 if not isinstance( hostClass, types.ListType ):
2969 hostClass = [ str( hostClass ) ]
2970 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002971 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2972 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2973 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002974 if update:
2975 # update mn port info
2976 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002977 # Get mininet dump
2978 dump = self.dump().split( "\n" )
2979 hosts = {}
2980 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002981 result = re.search( hostRE, line )
2982 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002983 name = result.group( 'name' )
2984 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002985 if getInterfaces:
2986 response = self.getInterfaces( name )
2987 # Populate interface info
2988 for line in response.split( "\n" ):
2989 if line.startswith( "name=" ):
2990 portVars = {}
2991 for var in line.split( "," ):
2992 key, value = var.split( "=" )
2993 portVars[ key ] = value
2994 isUp = portVars.pop( 'enabled', "True" )
2995 isUp = "True" in isUp
2996 if verbose:
2997 main.log.info( "Reading host port %s(%s)" %
2998 ( portVars[ 'name' ],
2999 portVars[ 'mac' ] ) )
3000 mac = portVars[ 'mac' ]
3001 if mac == 'None':
3002 mac = None
3003 ips = []
3004 ip = portVars[ 'ip' ]
3005 if ip == 'None':
3006 ip = None
3007 ips.append( ip )
3008 intfName = portVars[ 'name' ]
3009 if name == 'None':
3010 name = None
3011 interfaces.append( {
3012 "name": intfName,
3013 "ips": ips,
3014 "mac": str( mac ),
3015 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003016 hosts[ name ] = { "interfaces": interfaces }
3017 return hosts
3018 except pexpect.EOF:
3019 main.log.error( self.name + ": EOF exception found" )
3020 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003021 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003022 except Exception:
3023 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003024 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003025
You Wang7d14d642019-01-23 15:10:08 -08003026 def getLinks( self, timeout=20, updateTimeout=1000, excludeNodes=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07003027 """
3028 Gathers information about current Mininet links. These links may not
3029 be up if one of the ports is down.
3030
3031 Returns a list of dictionaries with link endpoints.
3032
3033 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07003034 { 'node1': str( node1 name )
3035 'node2': str( node2 name )
3036 'port1': str( port1 of_port )
3037 'port2': str( port2 of_port ) }
You Wang7d14d642019-01-23 15:10:08 -08003038
You Wangb1665b52019-02-01 15:49:48 -08003039 If either node1 or node2 name matches any of the names sepcified in
3040 excludeNodes, the link will be excluded from the returned value
You Wang7d14d642019-01-23 15:10:08 -08003041
Jon Hallafa8a472015-06-12 14:02:42 -07003042 Note: The port number returned is the eth#, not necessarily the of_port
3043 number. In Mininet, for OVS switch, these should be the same. For
3044 hosts, this is just the eth#.
3045 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003046 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003047 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003048 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07003049
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003050 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003051 # s1-eth3<->s2-eth1 (OK OK)
3052 # s13-eth3<->h27-eth0 (OK OK)
You Wang7d14d642019-01-23 15:10:08 -08003053 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d\.]+)\<\-\>" +\
3054 "(?P<node2>[\w]+)\-eth(?P<port2>[\d\.]+)"
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003055 links = []
3056 for line in response:
3057 match = re.search( linkRE, line )
3058 if match:
3059 node1 = match.group( 'node1' )
3060 node2 = match.group( 'node2' )
You Wangb1665b52019-02-01 15:49:48 -08003061 if any( node1 == node or node2 == node for node in excludeNodes ):
You Wang7d14d642019-01-23 15:10:08 -08003062 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003063 port1 = match.group( 'port1' )
3064 port2 = match.group( 'port2' )
3065 links.append( { 'node1': node1,
3066 'node2': node2,
3067 'port1': port1,
3068 'port2': port2 } )
3069 return links
3070
3071 except pexpect.EOF:
3072 main.log.error( self.name + ": EOF exception found" )
3073 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003074 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003075 except Exception:
3076 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003077 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003078
3079 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003080 """
3081 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003082 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003083
Jon Hallafa8a472015-06-12 14:02:42 -07003084 Dependencies:
3085 1. numpy - "sudo pip install numpy"
3086 """
3087 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003088 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003089 try:
3090 mnDPIDs = []
3091 for swName, switch in switches.iteritems():
3092 mnDPIDs.append( switch[ 'dpid' ].lower() )
3093 mnDPIDs.sort()
3094 if switchesJson == "": # if rest call fails
3095 main.log.error(
3096 self.name +
3097 ".compareSwitches(): Empty JSON object given from ONOS" )
3098 return main.FALSE
3099 onos = switchesJson
3100 onosDPIDs = []
3101 for switch in onos:
3102 if switch[ 'available' ]:
3103 onosDPIDs.append(
3104 switch[ 'id' ].replace(
3105 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003106 '' ).replace(
3107 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003108 '' ).lower() )
3109 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003110
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003111 if mnDPIDs != onosDPIDs:
3112 switchResults = main.FALSE
3113 main.log.error( "Switches in MN but not in ONOS:" )
3114 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3115 main.log.error( str( list1 ) )
3116 main.log.error( "Switches in ONOS but not in MN:" )
3117 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3118 main.log.error( str( list2 ) )
3119 else: # list of dpid's match in onos and mn
3120 switchResults = main.TRUE
3121 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003122
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003123 # FIXME: this does not look for extra ports in ONOS, only checks that
3124 # ONOS has what is in MN
3125 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003126
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003127 # PORTS
3128 for name, mnSwitch in switches.iteritems():
3129 mnPorts = []
3130 onosPorts = []
3131 switchResult = main.TRUE
3132 for port in mnSwitch[ 'ports' ]:
3133 if port[ 'enabled' ]:
3134 mnPorts.append( int( port[ 'of_port' ] ) )
3135 for onosSwitch in portsJson:
3136 if onosSwitch[ 'device' ][ 'available' ]:
3137 if onosSwitch[ 'device' ][ 'id' ].replace(
3138 ':',
3139 '' ).replace(
3140 "of",
3141 '' ) == mnSwitch[ 'dpid' ]:
3142 for port in onosSwitch[ 'ports' ]:
3143 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003144 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003145 # onosPorts.append( 'local' )
3146 onosPorts.append( long( uint64( -2 ) ) )
3147 else:
3148 onosPorts.append( int( port[ 'port' ] ) )
3149 break
3150 mnPorts.sort( key=float )
3151 onosPorts.sort( key=float )
3152
3153 mnPortsLog = mnPorts
3154 onosPortsLog = onosPorts
3155 mnPorts = [ x for x in mnPorts ]
3156 onosPorts = [ x for x in onosPorts ]
3157
3158 # TODO: handle other reserved port numbers besides LOCAL
3159 # NOTE: Reserved ports
3160 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3161 # long( uint64( -2 ) )
3162 for mnPort in mnPortsLog:
3163 if mnPort in onosPorts:
3164 # don't set results to true here as this is just one of
3165 # many checks and it might override a failure
3166 mnPorts.remove( mnPort )
3167 onosPorts.remove( mnPort )
3168
3169 # NOTE: OVS reports this as down since there is no link
3170 # So ignoring these for now
3171 # TODO: Come up with a better way of handling these
3172 if 65534 in mnPorts:
3173 mnPorts.remove( 65534 )
3174 if long( uint64( -2 ) ) in onosPorts:
3175 onosPorts.remove( long( uint64( -2 ) ) )
3176 if len( mnPorts ): # the ports of this switch don't match
3177 switchResult = main.FALSE
3178 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3179 if len( onosPorts ): # the ports of this switch don't match
3180 switchResult = main.FALSE
3181 main.log.warn(
3182 "Ports in ONOS but not MN: " +
3183 str( onosPorts ) )
3184 if switchResult == main.FALSE:
3185 main.log.error(
3186 "The list of ports for switch %s(%s) does not match:" %
3187 ( name, mnSwitch[ 'dpid' ] ) )
3188 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3189 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3190 portsResults = portsResults and switchResult
3191 finalResults = finalResults and portsResults
3192 return finalResults
3193 except pexpect.EOF:
3194 main.log.error( self.name + ": EOF exception found" )
3195 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003196 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003197 except Exception:
3198 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003199 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003200
Jon Hallafa8a472015-06-12 14:02:42 -07003201 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003202 """
3203 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003204 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003205
Jon Hallafa8a472015-06-12 14:02:42 -07003206 """
Jon Hall7eb38402015-01-08 17:19:54 -08003207 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003208 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003209 try:
3210 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003211
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003212 mnLinks = []
3213 for l in links:
3214 try:
3215 node1 = switches[ l[ 'node1' ] ]
3216 node2 = switches[ l[ 'node2' ] ]
3217 enabled = True
3218 for port in node1[ 'ports' ]:
3219 if port[ 'of_port' ] == l[ 'port1' ]:
3220 enabled = enabled and port[ 'enabled' ]
3221 for port in node2[ 'ports' ]:
3222 if port[ 'of_port' ] == l[ 'port2' ]:
3223 enabled = enabled and port[ 'enabled' ]
3224 if enabled:
3225 mnLinks.append( l )
3226 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003227 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003228 if 2 * len( mnLinks ) == len( onos ):
3229 linkResults = main.TRUE
3230 else:
3231 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003232 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003233 "Mininet has " + str( len( mnLinks ) ) +
3234 " bidirectional links and ONOS has " +
3235 str( len( onos ) ) + " unidirectional links" )
3236
3237 # iterate through MN links and check if an ONOS link exists in
3238 # both directions
3239 for link in mnLinks:
3240 # TODO: Find a more efficient search method
3241 node1 = None
3242 port1 = None
3243 node2 = None
3244 port2 = None
3245 firstDir = main.FALSE
3246 secondDir = main.FALSE
3247 for swName, switch in switches.iteritems():
3248 if swName == link[ 'node1' ]:
3249 node1 = switch[ 'dpid' ]
3250 for port in switch[ 'ports' ]:
3251 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3252 port1 = port[ 'of_port' ]
3253 if node1 is not None and node2 is not None:
3254 break
3255 if swName == link[ 'node2' ]:
3256 node2 = switch[ 'dpid' ]
3257 for port in switch[ 'ports' ]:
3258 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3259 port2 = port[ 'of_port' ]
3260 if node1 is not None and node2 is not None:
3261 break
3262
3263 for onosLink in onos:
3264 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3265 ":", '' ).replace( "of", '' )
3266 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3267 ":", '' ).replace( "of", '' )
3268 onosPort1 = onosLink[ 'src' ][ 'port' ]
3269 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3270
3271 # check onos link from node1 to node2
3272 if str( onosNode1 ) == str( node1 ) and str(
3273 onosNode2 ) == str( node2 ):
3274 if int( onosPort1 ) == int( port1 ) and int(
3275 onosPort2 ) == int( port2 ):
3276 firstDir = main.TRUE
3277 else:
Jon Hallab611372018-02-21 15:26:05 -08003278 # The right switches, but wrong ports, could be
3279 # another link between these devices, or onos
3280 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003281 main.log.warn(
3282 'The port numbers do not match for ' +
3283 str( link ) +
3284 ' between ONOS and MN. When checking ONOS for ' +
3285 'link %s/%s -> %s/%s' %
3286 ( node1, port1, node2, port2 ) +
3287 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003288 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3289 '. This could be another link between these devices' +
3290 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003291
3292 # check onos link from node2 to node1
3293 elif ( str( onosNode1 ) == str( node2 ) and
3294 str( onosNode2 ) == str( node1 ) ):
3295 if ( int( onosPort1 ) == int( port2 )
3296 and int( onosPort2 ) == int( port1 ) ):
3297 secondDir = main.TRUE
3298 else:
Jon Hallab611372018-02-21 15:26:05 -08003299 # The right switches, but wrong ports, could be
3300 # another link between these devices, or onos
3301 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003302 main.log.warn(
3303 'The port numbers do not match for ' +
3304 str( link ) +
3305 ' between ONOS and MN. When checking ONOS for ' +
3306 'link %s/%s -> %s/%s' %
3307 ( node1, port1, node2, port2 ) +
3308 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003309 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3310 '. This could be another link between these devices' +
3311 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003312 else: # this is not the link you're looking for
3313 pass
3314 if not firstDir:
3315 main.log.error(
3316 'ONOS does not have the link %s/%s -> %s/%s' %
3317 ( node1, port1, node2, port2 ) )
3318 if not secondDir:
3319 main.log.error(
3320 'ONOS does not have the link %s/%s -> %s/%s' %
3321 ( node2, port2, node1, port1 ) )
3322 linkResults = linkResults and firstDir and secondDir
3323 return linkResults
3324 except pexpect.EOF:
3325 main.log.error( self.name + ": EOF exception found" )
3326 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003327 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003328 except Exception:
3329 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003330 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003331
Jon Hallafa8a472015-06-12 14:02:42 -07003332 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003333 """
Jon Hallafa8a472015-06-12 14:02:42 -07003334 Compare mn and onos Hosts.
3335 Since Mininet hosts are quiet, ONOS will only know of them when they
3336 speak. For this reason, we will only check that the hosts in ONOS
3337 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003338
Jon Hallafa8a472015-06-12 14:02:42 -07003339 Arguments:
3340 hostsJson: parsed json object from the onos hosts api
3341 Returns:
3342 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003343 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003344 try:
3345 hostResults = main.TRUE
3346 for onosHost in hostsJson:
3347 onosMAC = onosHost[ 'mac' ].lower()
3348 match = False
3349 for mnHost, info in hosts.iteritems():
3350 for mnIntf in info[ 'interfaces' ]:
3351 if onosMAC == mnIntf[ 'mac' ].lower():
3352 match = True
3353 for ip in mnIntf[ 'ips' ]:
3354 if ip in onosHost[ 'ipAddresses' ]:
3355 pass # all is well
3356 else:
3357 # misssing ip
3358 main.log.error( "ONOS host " +
3359 onosHost[ 'id' ] +
3360 " has a different IP(" +
3361 str( onosHost[ 'ipAddresses' ] ) +
3362 ") than the Mininet host(" +
3363 str( ip ) +
3364 ")." )
3365 output = json.dumps(
3366 onosHost,
3367 sort_keys=True,
3368 indent=4,
3369 separators=( ',', ': ' ) )
3370 main.log.info( output )
3371 hostResults = main.FALSE
3372 if not match:
3373 hostResults = main.FALSE
3374 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3375 "corresponding Mininet host." )
3376 output = json.dumps( onosHost,
3377 sort_keys=True,
3378 indent=4,
3379 separators=( ',', ': ' ) )
3380 main.log.info( output )
3381 return hostResults
3382 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003383 main.log.error( self.name + ": EOF exception found" )
3384 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003385 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003386 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003387 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003388 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003389
You Wangd66de192018-04-30 17:30:12 -07003390 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003391 """
3392 Description:
3393 Verify that all hosts have IP address assigned to them
3394 Optional:
3395 hostList: If specified, verifications only happen to the hosts
3396 in hostList
3397 prefix: at least one of the ip address assigned to the host
3398 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003399 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003400 Returns:
3401 main.TRUE if all hosts have specific IP address assigned;
3402 main.FALSE otherwise
3403 """
3404 try:
You Wangd66de192018-04-30 17:30:12 -07003405 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003406 if not hostList:
3407 hostList = hosts.keys()
3408 for hostName in hosts.keys():
3409 if hostName not in hostList:
3410 continue
3411 ipList = []
3412 self.handle.sendline( str( hostName ) + " ip a" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003413 self.handle.expect( self.mnPrompt )
You Wang53dba1e2018-02-02 17:45:44 -08003414 ipa = self.handle.before
3415 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3416 ipList += re.findall( ipv4Pattern, ipa )
3417 # It's tricky to make regex for IPv6 addresses and this one is simplified
3418 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})/'
3419 ipList += re.findall( ipv6Pattern, ipa )
3420 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3421 if not ipList:
3422 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3423 else:
3424 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3425 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3426 else:
3427 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3428 hostList.remove( hostName )
3429 return main.FALSE if hostList else main.TRUE
3430 except KeyError:
3431 main.log.exception( self.name + ": host data not as expected: " + hosts )
3432 return None
3433 except pexpect.EOF:
3434 main.log.error( self.name + ": EOF exception found" )
3435 main.log.error( self.name + ": " + self.handle.before )
3436 main.cleanAndExit()
3437 except Exception:
3438 main.log.exception( self.name + ": Uncaught exception" )
3439 return None
3440
Jon Hallafa8a472015-06-12 14:02:42 -07003441 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003442 """
3443 Returns a list of all hosts
3444 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003445 try:
3446 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003447 self.handle.expect( self.mnPrompt )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003448
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003449 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003450 self.handle.expect( self.mnPrompt )
admin2a9548d2014-06-17 14:08:07 -07003451
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003452 handlePy = self.handle.before
3453 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3454 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003455
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003456 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003457 self.handle.expect( self.mnPrompt )
admin2a9548d2014-06-17 14:08:07 -07003458
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003459 hostStr = handlePy.replace( "]", "" )
3460 hostStr = hostStr.replace( "'", "" )
3461 hostStr = hostStr.replace( "[", "" )
3462 hostStr = hostStr.replace( " ", "" )
3463 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003464
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003465 return hostList
3466 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003467 main.log.error( self.name + ": TIMEOUT exception found" )
3468 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003469 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003470 except pexpect.EOF:
3471 main.log.error( self.name + ": EOF exception found" )
3472 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003473 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003474 except Exception:
3475 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003476 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003477
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003478 def getSwitch( self ):
3479 """
3480 Returns a list of all switches
3481 Again, don't ask question just use it...
3482 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003483 try:
3484 # get host list...
3485 hostList = self.getHosts()
3486 # Make host set
3487 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003488
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003489 # Getting all the nodes in mininet
3490 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003491 self.handle.expect( self.mnPrompt )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003492
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003493 self.handle.sendline( "py [ node.name for node in net.values() ]" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003494 self.handle.expect( self.mnPrompt )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003495
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003496 handlePy = self.handle.before
3497 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3498 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003499
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003500 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003501 self.handle.expect( self.mnPrompt )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003502
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003503 nodesStr = handlePy.replace( "]", "" )
3504 nodesStr = nodesStr.replace( "'", "" )
3505 nodesStr = nodesStr.replace( "[", "" )
3506 nodesStr = nodesStr.replace( " ", "" )
3507 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003508
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003509 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003510 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003511 nodesSet.discard( 'c0' )
3512 nodesSet.discard( 'c1' )
3513 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003514
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003515 switchSet = nodesSet - hostSet
3516 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003517
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003518 return switchList
3519 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003520 main.log.error( self.name + ": TIMEOUT exception found" )
3521 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003522 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003523 except pexpect.EOF:
3524 main.log.error( self.name + ": EOF exception found" )
3525 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003526 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003527 except Exception:
3528 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003529 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003530
You Wang7d14d642019-01-23 15:10:08 -08003531 def getGraphDict( self, timeout=60, useId=True, includeHost=False,
You Wangb1665b52019-02-01 15:49:48 -08003532 excludeNodes=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07003533 """
3534 Return a dictionary which describes the latest Mininet topology data as a
3535 graph.
3536 An example of the dictionary:
3537 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3538 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3539 Each vertex should at least have an 'edges' attribute which describes the
3540 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003541 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003542 list of attributes.
3543 An example of the edges dictionary:
3544 'edges': { vertex2: { 'port': ..., 'weight': ... },
3545 vertex3: { 'port': ..., 'weight': ... } }
3546 If useId == True, dpid/mac will be used instead of names to identify
3547 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3548 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003549 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003550 in topology data.
You Wangb1665b52019-02-01 15:49:48 -08003551 excludeNodes will be passed to getSwitches and getLinks methods to exclude
3552 unexpected switches and links.
You Wangdb8cd0a2016-05-26 15:19:45 -07003553 Note that link or switch that are brought down by 'link x x down' or 'switch
3554 x down' commands still show in the output of Mininet CLI commands such as
3555 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3556 recommended to use delLink() or delSwitch functions to simulate link/switch
3557 down, and addLink() or addSwitch to add them back.
3558 """
3559 graphDict = {}
3560 try:
You Wang7d14d642019-01-23 15:10:08 -08003561 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003562 portDict = {}
You Wangb1665b52019-02-01 15:49:48 -08003563 switches = self.getSwitches( excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003564 if includeHost:
3565 hosts = self.getHosts()
3566 for link in links:
You Wangb1665b52019-02-01 15:49:48 -08003567 # TODO: support 'includeHost' argument
You Wangdb8cd0a2016-05-26 15:19:45 -07003568 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3569 continue
3570 nodeName1 = link[ 'node1' ]
3571 nodeName2 = link[ 'node2' ]
You Wang7d14d642019-01-23 15:10:08 -08003572 if not self.getOVSPorts( nodeName1 ) or not self.getOVSPorts( nodeName2 ):
3573 # The device is probably offline
3574 continue
You Wangdb8cd0a2016-05-26 15:19:45 -07003575 port1 = link[ 'port1' ]
3576 port2 = link[ 'port2' ]
3577 # Loop for two nodes
3578 for i in range( 2 ):
3579 # Get port index from OVS
3580 # The index extracted from port name may be inconsistent with ONOS
3581 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003582 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003583 portList = self.getOVSPorts( nodeName1 )
3584 if len( portList ) == 0:
3585 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3586 return None
3587 portDict[ nodeName1 ] = portList
3588 for port in portDict[ nodeName1 ]:
3589 if port[ 'port' ] == port1:
3590 portIndex = port[ 'index' ]
3591 break
3592 if portIndex == -1:
3593 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3594 return None
3595 if useId:
3596 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3597 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3598 else:
3599 node1 = nodeName1
3600 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003601 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003602 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003603 graphDict[ node1 ] = { 'edges': {},
3604 'dpid': switches[ nodeName1 ][ 'dpid' ],
3605 'name': nodeName1,
3606 'ports': switches[ nodeName1 ][ 'ports' ],
3607 'swClass': switches[ nodeName1 ][ 'swClass' ],
3608 'pid': switches[ nodeName1 ][ 'pid' ],
3609 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003610 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003611 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003612 else:
3613 # Assert node2 is not connected to any current links of node1
You Wang7d14d642019-01-23 15:10:08 -08003614 # assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
3615 pass
3616 for port in switches[ nodeName1 ][ 'ports' ]:
3617 if port[ 'of_port' ] == str( portIndex ):
3618 # Use -1 as index for disabled port
You Wangb1665b52019-02-01 15:49:48 -08003619 if port[ 'enabled' ]:
You Wang7d14d642019-01-23 15:10:08 -08003620 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
3621 else:
3622 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': -1 }
You Wangdb8cd0a2016-05-26 15:19:45 -07003623 # Swap two nodes/ports
3624 nodeName1, nodeName2 = nodeName2, nodeName1
3625 port1, port2 = port2, port1
You Wang7d14d642019-01-23 15:10:08 -08003626 # Remove links with disabled ports
3627 linksToRemove = []
3628 for node, edges in graphDict.items():
3629 for neighbor, port in edges[ 'edges' ].items():
3630 if port[ 'port' ] == -1:
3631 linksToRemove.append( ( node, neighbor ) )
3632 for node1, node2 in linksToRemove:
3633 for i in range( 2 ):
3634 if graphDict.get( node1 )[ 'edges' ].get( node2 ):
3635 graphDict[ node1 ][ 'edges' ].pop( node2 )
3636 node1, node2 = node2, node1
You Wangdb8cd0a2016-05-26 15:19:45 -07003637 return graphDict
3638 except KeyError:
3639 main.log.exception( self.name + ": KeyError exception found" )
3640 return None
3641 except AssertionError:
3642 main.log.exception( self.name + ": AssertionError exception found" )
3643 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003644 except pexpect.EOF:
3645 main.log.error( self.name + ": EOF exception found" )
3646 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003647 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003648 except Exception:
3649 main.log.exception( self.name + ": Uncaught exception" )
3650 return None
3651
Devin Lima7cfdbd2017-09-29 15:02:22 -07003652 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003653 """
3654 updates the port address and status information for
3655 each port in mn"""
Jon Hallefbd9792015-03-05 16:11:36 -08003656 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003657 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003658 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003659 self.handle.expect( self.mnPrompt )
Jon Hall38481722014-11-04 16:50:05 -05003660
Jon Hall43060f62020-06-23 13:13:33 -07003661 # If update command isn't available, do it manually
Jon Hall7eb38402015-01-08 17:19:54 -08003662 self.handle.sendline( "update" )
Jon Hall43060f62020-06-23 13:13:33 -07003663 self.handle.expect( "update" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003664 i = self.handle.expect( [ "Unknown command: update", self.mnPrompt ], timeout )
Jon Hall43060f62020-06-23 13:13:33 -07003665 if i == 0:
3666 main.log.debug( self.handle.before + self.handle.after )
3667 main.log.warn( "Mininet cli does not have update command, attempting to update interfaces without it" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003668 self.handle.expect( self.mnPrompt )
Jon Hall43060f62020-06-23 13:13:33 -07003669 self.handle.sendline( "px [i.updateAddr() for h in net.hosts for i in h.intfs.values() ] " )
Jon Hallf6aeda22020-07-28 09:12:56 -07003670 self.handle.expect( self.mnPrompt, timeout )
Jon Hall43060f62020-06-23 13:13:33 -07003671 self.handle.sendline( "px [i.updateAddr() for s in net.switches for i in h.intfs.values() ] " )
Jon Hallf6aeda22020-07-28 09:12:56 -07003672 self.handle.expect( self.mnPrompt, timeout )
Jon Hall38481722014-11-04 16:50:05 -05003673
Jon Hall7eb38402015-01-08 17:19:54 -08003674 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003675 self.handle.expect( self.mnPrompt )
Jon Hall38481722014-11-04 16:50:05 -05003676
Jon Hallb1290e82014-11-18 16:17:48 -05003677 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003678 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003679 main.log.error( self.name + ": TIMEOUT exception found" )
3680 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003681 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003682 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003683 main.log.error( self.name + ": EOF exception found" )
3684 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003685 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003686 except Exception:
3687 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003688 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003689
Jon Halld80cc142015-07-06 13:36:05 -07003690 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003691 """
3692 Add vlan tag to a host.
3693 Dependencies:
3694 This class depends on the "vlan" package
3695 $ sudo apt-get install vlan
3696 Configuration:
3697 Load the 8021q module into the kernel
3698 $sudo modprobe 8021q
3699
3700 To make this setup permanent:
3701 $ sudo su -c 'echo "8021q" >> /etc/modules'
3702 """
3703 if self.handle:
3704 try:
Jon Halld80cc142015-07-06 13:36:05 -07003705 # get the ip address of the host
3706 main.log.info( "Get the ip address of the host" )
3707 ipaddr = self.getIPAddress( host )
3708 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003709
Jon Halld80cc142015-07-06 13:36:05 -07003710 # remove IP from interface intf
3711 # Ex: h1 ifconfig h1-eth0 inet 0
3712 main.log.info( "Remove IP from interface " )
3713 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3714 self.handle.sendline( cmd2 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003715 self.handle.expect( self.mnPrompt )
Jon Halld80cc142015-07-06 13:36:05 -07003716 response = self.handle.before
3717 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003718
Jon Halld80cc142015-07-06 13:36:05 -07003719 # create VLAN interface
3720 # Ex: h1 vconfig add h1-eth0 100
3721 main.log.info( "Create Vlan" )
3722 cmd3 = host + " vconfig add " + intf + " " + vlan
3723 self.handle.sendline( cmd3 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003724 self.handle.expect( self.mnPrompt )
Jon Halld80cc142015-07-06 13:36:05 -07003725 response = self.handle.before
3726 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003727
Jon Halld80cc142015-07-06 13:36:05 -07003728 # assign the host's IP to the VLAN interface
3729 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3730 main.log.info( "Assign the host IP to the vlan interface" )
3731 vintf = intf + "." + vlan
3732 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3733 self.handle.sendline( cmd4 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003734 self.handle.expect( self.mnPrompt )
Jon Halld80cc142015-07-06 13:36:05 -07003735 response = self.handle.before
3736 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003737
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003738 # update Mininet node variables
3739 main.log.info( "Update Mininet node variables" )
3740 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3741 self.handle.sendline( cmd5 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003742 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003743 response = self.handle.before
3744 main.log.info( "====> %s ", response )
3745
3746 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3747 self.handle.sendline( cmd6 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003748 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003749 response = self.handle.before
3750 main.log.info( "====> %s ", response )
3751
3752 return main.TRUE
3753 except pexpect.TIMEOUT:
3754 main.log.error( self.name + ": TIMEOUT exception found" )
3755 main.log.error( self.name + ": " + self.handle.before )
3756 main.cleanAndExit()
3757 except pexpect.EOF:
3758 main.log.error( self.name + ": EOF exception found" )
3759 main.log.error( self.name + ": " + self.handle.before )
3760 return main.FALSE
3761 except Exception:
3762 main.log.exception( self.name + ": Uncaught exception!" )
3763 return main.FALSE
3764
3765 def removeVLAN( self, host, intf ):
3766 """
3767 Remove vlan tag from a host.
3768 Dependencies:
3769 This class depends on the "vlan" package
3770 $ sudo apt-get install vlan
3771 Configuration:
3772 Load the 8021q module into the kernel
3773 $sudo modprobe 8021q
3774
3775 To make this setup permanent:
3776 $ sudo su -c 'echo "8021q" >> /etc/modules'
3777 """
3778 if self.handle:
3779 try:
3780 # get the ip address of the host
3781 main.log.info( "Get the ip address of the host" )
3782 ipaddr = self.getIPAddress( host )
3783
3784 # remove VLAN interface
3785 # Ex: h1 vconfig rem h1-eth0.100
3786 main.log.info( "Remove Vlan interface" )
3787 cmd2 = host + " vconfig rem " + intf
3788 self.handle.sendline( cmd2 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003789 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003790 response = self.handle.before
3791 main.log.info( "====> %s ", response )
3792
3793 # assign the host's IP to the original interface
3794 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3795 main.log.info( "Assign the host IP to the original interface" )
3796 original_intf = intf.split(".")[0]
3797 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3798 self.handle.sendline( cmd3 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003799 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003800 response = self.handle.before
3801 main.log.info( "====> %s ", response )
3802
3803 # update Mininet node variables
3804 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3805 self.handle.sendline( cmd4 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003806 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003807 response = self.handle.before
3808 main.log.info( "====> %s ", response )
3809
3810 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3811 self.handle.sendline( cmd5 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003812 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003813 response = self.handle.before
3814 main.log.info( "====> %s ", response )
3815
kaouthera3f13ca22015-05-05 15:01:41 -07003816 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003817 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003818 main.log.error( self.name + ": TIMEOUT exception found" )
3819 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003820 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003821 except pexpect.EOF:
3822 main.log.error( self.name + ": EOF exception found" )
3823 main.log.error( self.name + ": " + self.handle.before )
3824 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003825 except Exception:
3826 main.log.exception( self.name + ": Uncaught exception!" )
3827 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003828
Jon Hall43060f62020-06-23 13:13:33 -07003829 def createHostComponent( self, name, execDir=None, hostHome=None ):
Jon Hall892818c2015-10-20 17:58:34 -07003830 """
3831 Creates a new mininet cli component with the same parameters as self.
3832 This new component is intended to be used to login to the hosts created
3833 by mininet.
3834
3835 Arguments:
3836 name - The string of the name of this component. The new component
3837 will be assigned to main.<name> .
3838 In addition, main.<name>.name = str( name )
3839 """
3840 try:
3841 # look to see if this component already exists
3842 getattr( main, name )
3843 except AttributeError:
3844 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003845 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3846 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall43060f62020-06-23 13:13:33 -07003847 component = main.componentInit( name )
3848 if execDir is not None:
3849 component.mExecDir = execDir
3850 else:
3851 component.mExecDir = self.mExecDir
3852
3853 if hostHome is not None:
3854 component.hostHome = hostHome
3855 else:
3856 component.hostHome = self.hostHome
3857 component.hostPrompt = self.hostPrompt
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003858 except pexpect.EOF:
3859 main.log.error( self.name + ": EOF exception found" )
3860 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003861 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003862 except Exception:
3863 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003864 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003865 else:
3866 # namespace is not clear!
3867 main.log.error( name + " component already exists!" )
3868 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003869 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003870
3871 def removeHostComponent( self, name ):
3872 """
3873 Remove host component
3874 Arguments:
3875 name - The string of the name of the component to delete.
3876 """
3877 try:
3878 # Get host component
3879 component = getattr( main, name )
3880 except AttributeError:
3881 main.log.error( "Component " + name + " does not exist." )
3882 return
3883 try:
3884 # Disconnect from component
3885 component.disconnect()
You Wangf32c6ed2018-08-23 17:10:22 -07003886 component.close_log_handles()
Jon Hall892818c2015-10-20 17:58:34 -07003887 # Delete component
3888 delattr( main, name )
3889 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003890 del( main.componentDictionary[ name ] )
You Wangf32c6ed2018-08-23 17:10:22 -07003891 except StandardError:
3892 self.log.exception( "Exception while closing log files for " + name )
3893 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003894 except pexpect.EOF:
3895 main.log.error( self.name + ": EOF exception found" )
3896 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003897 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003898 except Exception:
3899 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003900 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003901
Jon Hall43060f62020-06-23 13:13:33 -07003902 def startHostCli( self, host=None, execDir=None, hostHome=None ):
Jon Hall892818c2015-10-20 17:58:34 -07003903 """
3904 Use the mininet m utility to connect to the host's cli
Jon Hall43060f62020-06-23 13:13:33 -07003905 mnexec tries to cd to cwd after it connects to the host. If execDir
3906 is set, this will change cwd to execDir before executing m.
3907 If hostHome is set, the function will export the value to the HOME
3908 environment variable.
Jon Hall892818c2015-10-20 17:58:34 -07003909 """
3910 # These are fields that can be used by scapy packets. Initialized to None
3911 self.hostIp = None
3912 self.hostMac = None
Jon Hall43060f62020-06-23 13:13:33 -07003913 if execDir is not None:
3914 self.mExecDir = execDir
3915 if hostHome is not None:
3916 self.hostHome = hostHome
Jon Hall892818c2015-10-20 17:58:34 -07003917 try:
Jon Hall39570262020-11-17 12:18:19 -08003918 self.handle.sendline( "" )
3919 self.handle.expect( self.Prompt() )
Jon Hall892818c2015-10-20 17:58:34 -07003920 if not host:
3921 host = self.name
Jon Hall43060f62020-06-23 13:13:33 -07003922 if self.mExecDir:
3923 self.handle.sendline( "cd %s" % self.mExecDir )
Jon Hall3c0114c2020-08-11 15:07:42 -07003924 self.handle.expect( self.Prompt() )
Jon Hall43060f62020-06-23 13:13:33 -07003925
Jon Hall892818c2015-10-20 17:58:34 -07003926 self.handle.sendline( self.home + "/util/m " + host )
Jon Hall43060f62020-06-23 13:13:33 -07003927 if self.hostHome:
3928 self.handle.sendline( "export HOME=%s" % self.hostHome )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003929 self.handle.sendline( "cd" )
3930 self.handle.expect( self.hostPrompt )
3931 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003932 self.handle.expect( self.hostPrompt )
3933 return main.TRUE
3934 except pexpect.TIMEOUT:
3935 main.log.exception( self.name + ": Command timed out" )
Jon Hall43060f62020-06-23 13:13:33 -07003936 main.log.debug( self.handle.before )
Jon Hall892818c2015-10-20 17:58:34 -07003937 return main.FALSE
3938 except pexpect.EOF:
3939 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003940 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003941 except Exception:
3942 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003943 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003944
YPZhang801d46d2016-08-08 13:26:28 -07003945 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003946 '''
3947
YPZhang801d46d2016-08-08 13:26:28 -07003948 Args:
3949 devicename: switch name
3950 intf: port name on switch
3951 status: up or down
3952
3953 Returns: boolean to show success change status
3954
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003955 '''
YPZhang801d46d2016-08-08 13:26:28 -07003956 if status == "down" or status == "up":
3957 try:
3958 cmd = devicename + " ifconfig " + intf + " " + status
3959 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07003960 self.handle.expect( self.mnPrompt )
YPZhang801d46d2016-08-08 13:26:28 -07003961 return main.TRUE
3962 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003963 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003964 return main.FALSE
3965 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003966 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003967 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003968 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003969 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003970 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003971 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003972 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003973 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003974 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003975 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003976 return main.FALSE
3977
You Wang6e5b48e2018-07-23 16:17:38 -07003978 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003979 """
You Wang6e5b48e2018-07-23 16:17:38 -07003980 Moves a host from one switch to another on the fly
3981 Optional:
3982 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3983 prefixLen: length of the host IP prefix
3984 ipv6: move an IPv6 host if True
3985 intfSuffix: suffix of the new interface after host movement
3986 vlan: vlan ID of the host. Use None for non-vlan host
3987 Note: The intf between host and oldSw when detached
3988 using detach(), will still show up in the 'net'
3989 cmd, because switch.detach() doesn't affect switch.intfs[]
3990 ( which is correct behavior since the interfaces
3991 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003992 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003993 if self.handle:
3994 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003995 newIntf = "%s-%s" % ( host, intfSuffix )
3996 commands = [
3997 # Bring link between oldSw-host down
3998 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3999 # Determine hostintf and Oldswitchintf
4000 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
4001 ]
4002 # Determine ip address of the host-oldSw interface
4003 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
4004 commands.append( 'px ipaddr = "{}"'.format( IP ) )
4005 commands += [
4006 # Determine mac address of the host-oldSw interface
4007 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
4008 # Detach interface between oldSw-host
4009 "px " + oldSw + ".detach( sintf )",
4010 # Add link between host-newSw
4011 "py net.addLink(" + host + "," + newSw + ")",
4012 # Determine hostintf and Newswitchintf
4013 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
4014 # Attach interface between newSw-host
4015 "px " + newSw + ".attach( sintf )",
4016 ]
4017 if vlan:
4018 vlanIntf = "%s.%s" % ( newIntf, vlan )
4019 commands += [
4020 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
4021 host + " ip link set up %s" % vlanIntf,
4022 "px hintf.name = '" + vlanIntf + "'",
4023 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
4024 ]
4025 newIntf = vlanIntf
4026 commands += [
4027 # Set mac address of the host-newSw interface
4028 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
4029 # Set IP address of the host-newSw interface
4030 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
4031 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
4032 ]
4033 if ipv6:
4034 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
4035 commands += [
4036 "net",
4037 host + " ifconfig"
4038 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004039 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004040 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004041 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07004042 self.handle.expect( self.mnPrompt )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004043 main.log.info( "====> %s ", self.handle.before )
4044 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004045 except pexpect.TIMEOUT:
4046 main.log.error( self.name + ": TIMEOUT exception found" )
4047 main.log.error( self.name + ": " + self.handle.before )
4048 main.cleanAndExit()
4049 except pexpect.EOF:
4050 main.log.error( self.name + ": EOF exception found" )
4051 main.log.error( self.name + ": " + self.handle.before )
4052 return main.FALSE
4053 except Exception:
4054 main.log.exception( self.name + ": Uncaught exception!" )
4055 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07004056
You Wang6e5b48e2018-07-23 16:17:38 -07004057 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
4058 macAddr=None, prefixLen=None, ipv6=False,
4059 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07004060 """
You Wang6e5b48e2018-07-23 16:17:38 -07004061 Moves a dual-homed host from one switch-pair to another pair on the fly
4062 Optional:
4063 macAddr: when specified, change MAC address of the host interface to specified MAC address.
4064 prefixLen: length of the host IP prefix
4065 ipv6: move an IPv6 host if True
4066 intfSuffix1: suffix of the first new interface
4067 intfSuffix2: suffix of the second new interface
4068 bondSuffix: suffix of the new bond interface
4069 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07004070 """
You Wang7ea90582018-07-19 15:27:58 -07004071 if self.handle:
4072 try:
You Wang6e5b48e2018-07-23 16:17:38 -07004073 bondIntf = "%s-%s" % ( host, bondSuffix )
4074 newIntf = "%s-%s" % ( host, intfSuffix1 )
4075 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07004076 commands = [
4077 # Bring link between oldSw-host down
4078 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
4079 # Bring link between oldPairSw-host down
4080 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
4081 # Determine hostintf and Oldswitchintf
4082 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07004083 ]
4084 # Determine ip address of the host-oldSw interface
4085 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
4086 commands.append( 'px ipaddr = "{}"'.format( IP ) )
4087 commands += [
4088 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07004089 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
4090 # Detach interface between oldSw-host
4091 "px " + oldSw + ".detach( sintf )",
4092 # Determine hostintf and Oldpairswitchintf
4093 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
4094 # Detach interface between oldPairSw-host
4095 "px " + oldPairSw + ".detach( sintfpair )",
4096 # Add link between host-newSw
4097 "py net.addLink(" + host + "," + newSw + ", 2)",
4098 # Add link between host-newPairSw
4099 "py net.addLink(" + host + "," + newPairSw + ")",
4100 # Determine hostintf and Newswitchintf
4101 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
4102 # Determine hostintf and NewPairswitchintf
4103 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
4104 # Attach interface between newSw-host
4105 "px " + newSw + ".attach( sintf )",
4106 # Attach interface between newPairSw-host
4107 "px " + newPairSw + ".attach( sintfpair )",
4108 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07004109 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004110 host + ' ip link set %s down' % newIntf,
4111 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004112 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
4113 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07004114 host + ' ip addr flush dev %s' % newIntf,
4115 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004116 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004117 "px lowestIntf = min( [ hintf, hintfpair ] )",
4118 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07004119 "px lowestIntf.name = '" + bondIntf + "'",
4120 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07004121 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
4122 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07004123 ]
4124 if vlan:
4125 vlanIntf = "%s.%s" % ( bondIntf, vlan )
4126 commands += [
4127 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
4128 host + " ip link set up %s" % vlanIntf,
4129 "px lowestIntf.name = '" + vlanIntf + "'",
4130 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
4131 ]
4132 bondIntf = vlanIntf
4133 commands += [
4134 # Set macaddress of the host-newSw interface
4135 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07004136 # Set ipaddress of the host-newSw interface
4137 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
4138 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07004139 ]
You Wang6e5b48e2018-07-23 16:17:38 -07004140 if ipv6:
4141 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
4142 commands += [
4143 "net",
4144 host + " ifconfig"
4145 ]
You Wang7ea90582018-07-19 15:27:58 -07004146 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004147 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07004148 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07004149 self.handle.expect( self.mnPrompt )
You Wang7ea90582018-07-19 15:27:58 -07004150 main.log.info( "====> %s ", self.handle.before )
4151 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07004152 except pexpect.TIMEOUT:
4153 main.log.error( self.name + ": TIMEOUT exception found" )
4154 main.log.error( self.name + ": " + self.handle.before )
4155 main.cleanAndExit()
4156 except pexpect.EOF:
4157 main.log.error( self.name + ": EOF exception found" )
4158 main.log.error( self.name + ": " + self.handle.before )
4159 return main.FALSE
4160 except Exception:
4161 main.log.exception( self.name + ": Uncaught exception!" )
4162 return main.FALSE
4163
adminbae64d82013-08-01 10:50:15 -07004164if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004165 sys.modules[ __name__ ] = MininetCliDriver()