blob: 682760a55f4e5883355e9de7c24510cbb0cd6cc2 [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,
Devin Limdc78e202017-06-09 18:30:07 -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( "" )
Devin Limdc78e202017-06-09 18:30:07 -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:
218 i = self.handle.expect( [ 'mininet>',
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 )
Devin Limdc78e202017-06-09 18:30:07 -0700231 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700232 response += str( self.handle.before +
233 self.handle.after )
234 main.log.error(
235 self.name +
236 ": Launching Mininet failed: " + response )
237 return main.FALSE
238 elif i == 2:
239 self.handle.expect( [ "\n",
240 pexpect.EOF,
241 pexpect.TIMEOUT ],
242 timeout )
243 main.log.info( self.handle.before )
244 elif i == 3:
245 main.log.error( self.name + ": Connection timeout" )
246 return main.FALSE
247 elif i == 4: # timeout
248 main.log.error(
249 self.name +
250 ": Something took too long... " )
Jon Hallbc743112018-04-18 11:09:01 -0700251 main.log.debug( self.handle.before + self.handle.after )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700252 return main.FALSE
Jon Hallab611372018-02-21 15:26:05 -0800253 elif i == 5:
254 main.log.error( self.name + ": " + self.handle.before + self.handle.after )
255 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700256 # Why did we hit this part?
257 main.log.error( "startNet did not return correctly" )
258 return main.FASLE
259 else: # if no handle
260 main.log.error( self.name + ": Connection failed to the host " +
261 self.user_name + "@" + self.ip_address )
262 main.log.error( self.name + ": Failed to connect to the Mininet" )
263 return main.FALSE
264 except pexpect.TIMEOUT:
265 main.log.exception( self.name + ": TIMEOUT exception found while starting Mininet" )
266 main.log.error( self.name + ": " + self.handle.before )
adminbae64d82013-08-01 10:50:15 -0700267 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700268 except pexpect.EOF:
269 main.log.error( self.name + ": EOF exception found" )
270 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700271 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700272 except Exception:
273 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700274 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800275
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800276 def numSwitchesNlinks( self, topoType, depth, fanout ):
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700277 try:
278 if topoType == 'tree':
279 # In tree topology, if fanout arg is not given, by default it is 2
280 if fanout is None:
281 fanout = 2
282 k = 0
283 count = 0
284 while( k <= depth - 1 ):
285 count = count + pow( fanout, k )
286 k = k + 1
287 numSwitches = count
288 while( k <= depth - 2 ):
289 # depth-2 gives you only core links and not considering
290 # edge links as seen by ONOS. If all the links including
291 # edge links are required, do depth-1
292 count = count + pow( fanout, k )
293 k = k + 1
294 numLinks = count * fanout
295 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
296 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800297
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700298 elif topoType == 'linear':
299 # In linear topology, if fanout or numHostsPerSw is not given,
300 # by default it is 1
301 if fanout is None:
302 fanout = 1
303 numSwitches = depth
304 numHostsPerSw = fanout
305 totalNumHosts = numSwitches * numHostsPerSw
306 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hallab611372018-02-21 15:26:05 -0800307 main.log.debug( "num_switches for %s(%d,%d) = %d and links=%d" %
308 ( topoType, depth, fanout, numSwitches, numLinks ) )
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700309 topoDict = { "num_switches": int( numSwitches ),
310 "num_corelinks": int( numLinks ) }
311 return topoDict
312 except Exception:
313 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700314 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400315
kelvin-onlabd3b64892015-01-20 13:26:24 -0800316 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700317 """
318 Calculate the number of switches and links in a topo."""
319 # TODO: combine this function and numSwitchesNlinks
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700320 try:
321 argList = self.options[ 'arg1' ].split( "," )
322 topoArgList = argList[ 0 ].split( " " )
323 argList = map( int, argList[ 1: ] )
324 topoArgList = topoArgList[ 1: ] + argList
Jon Hall689d8e42015-04-03 13:59:24 -0700325
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700326 topoDict = self.numSwitchesNlinks( *topoArgList )
327 return topoDict
328 except Exception:
329 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700330 main.cleanAndExit()
Jon Hall1ccf82c2014-10-15 14:55:16 -0400331
GlennRCf07c44a2015-09-18 13:33:46 -0700332 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800333 """
334 Verifies the reachability of the hosts using pingall command.
335 Optional parameter timeout allows you to specify how long to
336 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700337 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700338 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700339 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700340 ping
341 acceptableFailed - Set the number of acceptable failed pings for the
342 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800343 Returns:
344 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700345 otherwise main.FALSE
346 """
347 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700348 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700349 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700350 if self.handle:
351 main.log.info(
352 self.name +
353 ": Checking reachabilty to the hosts using pingall" )
354 response = ""
355 failedPings = 0
356 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700357 cmd = "pingall"
358 if protocol == "IPv6":
359 cmd = "py net.pingAll6()"
360 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700361 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700362 while True:
Jon Hallf6aeda22020-07-28 09:12:56 -0700363 i = self.handle.expect( [ self.mnPrompt, "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700364 pexpect.EOF,
365 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700366 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700367 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700368 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700369 response += self.handle.before
370 break
371 elif i == 1:
372 response += self.handle.before + self.handle.after
373 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700374 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700375 returnValue = main.FALSE
376 if shortCircuit:
377 main.log.error( self.name +
378 ": Aborting pingall - "
379 + str( failedPings ) +
380 " pings failed" )
381 break
Jon Hall390696c2015-05-05 17:13:41 -0700382 if ( time.time() - startTime ) > timeout:
383 returnValue = main.FALSE
384 main.log.error( self.name +
385 ": Aborting pingall - " +
386 "Function took too long " )
387 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700388 elif i == 2:
389 main.log.error( self.name +
390 ": EOF exception found" )
391 main.log.error( self.name + ": " +
392 self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700393 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700394 elif i == 3:
395 response += self.handle.before
396 main.log.error( self.name +
397 ": TIMEOUT exception found" )
398 main.log.error( self.name +
399 ": " +
400 str( response ) )
401 # NOTE: Send ctrl-c to make sure pingall is done
Jon Hallf6aeda22020-07-28 09:12:56 -0700402 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
You Wang7ce29462019-03-04 13:37:14 -0800403 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -0700404 self.handle.expect( self.mnPrompt )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700405 break
406 pattern = "Results\:"
407 main.log.info( "Pingall output: " + str( response ) )
408 if re.search( pattern, response ):
409 main.log.info( self.name + ": Pingall finished with "
410 + str( failedPings ) + " failed pings" )
411 return returnValue
412 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700413 # NOTE: Send ctrl-c to make sure pingall is done
Jon Hallf6aeda22020-07-28 09:12:56 -0700414 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
You Wang7ce29462019-03-04 13:37:14 -0800415 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -0700416 self.handle.expect( self.mnPrompt )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700417 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700418 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700419 main.log.error( self.name + ": Connection failed to the host" )
Devin Lim44075962017-08-11 10:56:37 -0700420 main.cleanAndExit()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700421 except pexpect.TIMEOUT:
422 if response:
423 main.log.info( "Pingall output: " + str( response ) )
424 main.log.error( self.name + ": pexpect.TIMEOUT found" )
425 return main.FALSE
426 except pexpect.EOF:
427 main.log.error( self.name + ": EOF exception found" )
428 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700429 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -0700430
Jon Hall7eb38402015-01-08 17:19:54 -0800431 def fpingHost( self, **pingParams ):
432 """
433 Uses the fping package for faster pinging...
434 *requires fping to be installed on machine running mininet"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700435 try:
436 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
437 command = args[ "SRC" ] + \
438 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
439 self.handle.sendline( command )
440 self.handle.expect(
441 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
442 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
443 response = self.handle.before
444 if re.search( ":\s-", response ):
445 main.log.info( self.name + ": Ping fail" )
446 return main.FALSE
447 elif re.search( ":\s\d{1,2}\.\d\d", response ):
448 main.log.info( self.name + ": Ping good!" )
449 return main.TRUE
450 main.log.info( self.name + ": Install fping on mininet machine... " )
451 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700452 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700453 except Exception:
454 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700455 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700456
Jon Hall3b489db2015-10-05 14:38:37 -0700457 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400458 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700459 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700460
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400461 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700462 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700463
464 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400465 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700466
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400467 Returns main.FALSE if one or more of hosts specified
468 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700469 wait = int( wait )
470 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400471
472 try:
473 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700474
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400475 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700476 pingResponse = "IPv4 ping across specified hosts\n"
477 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400478 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700479 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400480 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700481 pingList = hostList[ :listIndex ] + \
482 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700483
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700484 pingResponse += str( str( host ) + " -> " )
GlennRCd10d3cc2015-09-24 12:47:16 -0700485
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400486 for temp in pingList:
487 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700488 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700489 self.handle.sendline( pingCmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700490 self.handle.expect( self.mnPrompt, timeout=wait + 5 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400491 response = self.handle.before
492 if re.search( ',\s0\%\spacket\sloss', response ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700493 pingResponse += str( " h" + str( temp[ 1: ] ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400494 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700495 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400496 # One of the host to host pair is unreachable
497 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700498 failedPings += 1
You Wang11f9ead2018-03-21 14:34:59 -0700499 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
GlennRCd10d3cc2015-09-24 12:47:16 -0700500 pingResponse += "\n"
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700501 main.log.info( pingResponse + "Failed pings: " + str( failedPings ) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700502 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700503 except pexpect.TIMEOUT:
504 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800505 response = self.handle.before
506 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hallf6aeda22020-07-28 09:12:56 -0700507 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
Jon Hall3c910162018-03-07 14:42:16 -0800508 response += self.handle.before + self.handle.after
You Wang7ce29462019-03-04 13:37:14 -0800509 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -0700510 self.handle.expect( self.mnPrompt )
Jon Hall3c910162018-03-07 14:42:16 -0800511 response += self.handle.before + self.handle.after
512 main.log.debug( response )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700513 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400514 except pexpect.EOF:
515 main.log.error( self.name + ": EOF exception found" )
516 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700517 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700518 except Exception:
519 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700520 main.cleanAndExit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400521
You Wangf19d9f42018-02-23 16:34:19 -0800522 def pingIpv6Hosts( self, hostList, wait=1, acceptableFailed=0 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700523 """
You Wangf19d9f42018-02-23 16:34:19 -0800524 IPv6 ping all hosts in hostList.
525
526 acceptableFailed: max number of acceptable failed pings
Hari Krishna9592fc82015-07-31 15:11:15 -0700527
Jon Hall3b489db2015-10-05 14:38:37 -0700528 Returns main.TRUE if all hosts specified can reach each other
Jon Hall3b489db2015-10-05 14:38:37 -0700529 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700530 """
531 try:
532 main.log.info( "Testing reachability between specified IPv6 hosts" )
533 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700534 wait = int( wait )
535 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700536 pingResponse = "IPv6 Pingall output:\n"
You Wangf19d9f42018-02-23 16:34:19 -0800537 failedPingsTotal = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700538 for host in hostList:
539 listIndex = hostList.index( host )
540 # List of hosts to ping other than itself
541 pingList = hostList[ :listIndex ] + \
542 hostList[ ( listIndex + 1 ): ]
543
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700544 pingResponse += str( str( host ) + " -> " )
GlennRC2cf7d952015-09-11 16:32:13 -0700545
Hari Krishna9592fc82015-07-31 15:11:15 -0700546 for temp in pingList:
547 # Current host pings all other hosts specified
You Wangf19d9f42018-02-23 16:34:19 -0800548 failedPings = 0
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700549 pingCmd = str( host ) + cmd + str( self.getIPAddress( temp, proto='IPv6' ) )
You Wangf19d9f42018-02-23 16:34:19 -0800550 while failedPings <= acceptableFailed:
551 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
552 self.handle.sendline( pingCmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700553 self.handle.expect( self.mnPrompt, timeout=wait + 5 )
You Wangf19d9f42018-02-23 16:34:19 -0800554 response = self.handle.before
555 if re.search( ',\s0\%\spacket\sloss', response ):
You Wangba231e72018-03-01 13:18:21 -0800556 pingResponse += " " + str( temp )
557 break
558 else:
559 failedPings += 1
560 time.sleep(1)
561 if failedPings > acceptableFailed:
562 # One of the host to host pair is unreachable
563 pingResponse += " X"
564 isReachable = main.FALSE
565 failedPingsTotal += 1
You Wang11f9ead2018-03-21 14:34:59 -0700566 main.log.warn( "Cannot ping between {} and {}".format( host, temp ) )
You Wangba231e72018-03-01 13:18:21 -0800567 pingResponse += "\n"
568 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
569 return isReachable
570
571 except pexpect.TIMEOUT:
572 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800573 response = self.handle.before
574 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hallf6aeda22020-07-28 09:12:56 -0700575 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
Jon Hall3c910162018-03-07 14:42:16 -0800576 response += self.handle.before + self.handle.after
You Wang7ce29462019-03-04 13:37:14 -0800577 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -0700578 self.handle.expect( self.mnPrompt )
Jon Hall3c910162018-03-07 14:42:16 -0800579 response += self.handle.before + self.handle.after
580 main.log.debug( response )
You Wangba231e72018-03-01 13:18:21 -0800581 return main.FALSE
582 except pexpect.EOF:
583 main.log.error( self.name + ": EOF exception found" )
584 main.log.error( self.name + ": " + self.handle.before )
585 main.cleanAndExit()
586 except Exception:
587 main.log.exception( self.name + ": Uncaught exception!" )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700588
589 main.cleanAndExit()
590
You Wang32833172018-10-23 15:19:31 -0700591 def discoverHosts( self, hostList=[], wait=1000, dstIp="6.6.6.6", dstIp6="1020::3fe" ):
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700592 '''
You Wang32833172018-10-23 15:19:31 -0700593 Hosts in hostList will do a single ARP/ND to a non-existent address for ONOS to
594 discover them. A host will use arping/ndisc6 to send ARP/ND depending on if it
595 has IPv4/IPv6 addresses configured.
You Wang48381752018-05-07 13:50:57 -0700596 Optional:
597 hostList: a list of names of the hosts that need to be discovered. If not
598 specified mininet will send ping from all the hosts
You Wang32833172018-10-23 15:19:31 -0700599 wait: timeout for ARP/ND in milliseconds
You Wang48381752018-05-07 13:50:57 -0700600 dstIp: destination address used by IPv4 hosts
601 dstIp6: destination address used by IPv6 hosts
602 Returns:
You Wang32833172018-10-23 15:19:31 -0700603 main.TRUE if all packets were successfully sent. Otherwise main.FALSE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700604 '''
605 try:
You Wang32833172018-10-23 15:19:31 -0700606 hosts = self.getHosts()
You Wang48381752018-05-07 13:50:57 -0700607 if not hostList:
You Wang48381752018-05-07 13:50:57 -0700608 hostList = hosts.keys()
609 discoveryResult = main.TRUE
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700610 for host in hostList:
You Wang0b82aa52018-06-06 14:33:58 -0700611 flushCmd = ""
You Wang036ec2c2019-02-27 15:44:15 -0800612 cmds = []
You Wang48381752018-05-07 13:50:57 -0700613 if self.getIPAddress( host ):
You Wang0b82aa52018-06-06 14:33:58 -0700614 flushCmd = "{} ip neigh flush all".format( host )
Jon Hall43060f62020-06-23 13:13:33 -0700615 intf = hosts[ host ][ 'interfaces' ][ 0 ].get( 'name' )
616 intfStr = "-i {}".format( intf ) if intf else ""
617 cmds.append( "{} arping -c 1 -w {} {} {}".format(
618 host, wait, intfStr, dstIp ) )
You Wang32833172018-10-23 15:19:31 -0700619 main.log.debug( "Sending IPv4 arping from host {}".format( host ) )
You Wang48381752018-05-07 13:50:57 -0700620 elif self.getIPAddress( host, proto='IPV6' ):
You Wang0b82aa52018-06-06 14:33:58 -0700621 flushCmd = "{} ip -6 neigh flush all".format( host )
You Wang036ec2c2019-02-27 15:44:15 -0800622 # FIXME: we are using the same ipv6Addr for all interfaces
623 ipv6Addr = self.getIPAddress( host, proto='IPV6' )
You Wangad347c92019-02-20 16:13:47 -0800624 for intf in hosts[ host ][ 'interfaces' ]:
625 intfName = intf[ 'name' ]
You Wang036ec2c2019-02-27 15:44:15 -0800626 cmds.append( "{} ndsend {} {}".format( host, ipv6Addr, intfName ) )
You Wangad347c92019-02-20 16:13:47 -0800627 main.log.debug( "Sending IPv6 ND from interface {} on host {}".format( intfName, host ) )
You Wang48381752018-05-07 13:50:57 -0700628 else:
629 main.log.warn( "No IP addresses configured on host {}, skipping discovery".format( host ) )
630 discoveryResult = main.FALSE
You Wang036ec2c2019-02-27 15:44:15 -0800631 if flushCmd:
You Wang0b82aa52018-06-06 14:33:58 -0700632 self.handle.sendline( flushCmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700633 self.handle.expect( self.mnPrompt )
You Wang036ec2c2019-02-27 15:44:15 -0800634 for cmd in cmds:
You Wang48381752018-05-07 13:50:57 -0700635 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700636 self.handle.expect( self.mnPrompt, timeout=wait + 5 )
You Wang48381752018-05-07 13:50:57 -0700637 return discoveryResult
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700638 except pexpect.TIMEOUT:
639 main.log.exception( self.name + ": TIMEOUT exception" )
640 response = self.handle.before
641 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hallf6aeda22020-07-28 09:12:56 -0700642 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700643 response += self.handle.before + self.handle.after
You Wang7ce29462019-03-04 13:37:14 -0800644 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -0700645 self.handle.expect( self.mnPrompt )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700646 response += self.handle.before + self.handle.after
647 main.log.debug( response )
648 return main.FALSE
649 except pexpect.EOF:
650 main.log.error( self.name + ": EOF exception found" )
651 main.log.error( self.name + ": " + self.handle.before )
652 main.cleanAndExit()
653 except Exception:
654 main.log.exception( self.name + ": Uncaught exception!" )
You Wangba231e72018-03-01 13:18:21 -0800655 main.cleanAndExit()
656
657 def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0 ):
658 """
659 Verify ping from each host in srcList to each host in dstList
660
661 acceptableFailed: max number of acceptable failed pings
662
663 Returns main.TRUE if all src hosts can reach all dst hosts
664 Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
665 """
666 try:
667 main.log.info( "Verifying ping from each src host to each dst host" )
668 isReachable = main.TRUE
669 wait = int( wait )
670 cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
671 pingResponse = "Ping output:\n"
672 failedPingsTotal = 0
673 for host in srcList:
674 pingResponse += str( str( host ) + " -> " )
675 for temp in dstList:
676 failedPings = 0
You Wang5da39c82018-04-26 22:55:08 -0700677 dstIP = self.getIPAddress( temp, proto='IPV6' if ipv6 else 'IPV4' )
678 assert dstIP, "Not able to get IP address of host {}".format( temp )
679 pingCmd = str( host ) + cmd + str( dstIP )
You Wangba231e72018-03-01 13:18:21 -0800680 while failedPings <= acceptableFailed:
681 main.log.debug( "Pinging from " + str( host ) + " to " + str( temp ) )
682 self.handle.sendline( pingCmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700683 self.handle.expect( self.mnPrompt, timeout=wait + 5 )
You Wangba231e72018-03-01 13:18:21 -0800684 response = self.handle.before
685 if re.search( ',\s0\%\spacket\sloss', response ):
686 pingResponse += " " + str( temp )
You Wangf19d9f42018-02-23 16:34:19 -0800687 break
688 else:
689 failedPings += 1
690 time.sleep(1)
691 if failedPings > acceptableFailed:
Hari Krishna9592fc82015-07-31 15:11:15 -0700692 # One of the host to host pair is unreachable
You Wangf19d9f42018-02-23 16:34:19 -0800693 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700694 isReachable = main.FALSE
You Wangf19d9f42018-02-23 16:34:19 -0800695 failedPingsTotal += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700696 pingResponse += "\n"
You Wangf19d9f42018-02-23 16:34:19 -0800697 main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700698 return isReachable
You Wang5da39c82018-04-26 22:55:08 -0700699 except AssertionError:
700 main.log.exception( "" )
701 return main.FALSE
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700702 except pexpect.TIMEOUT:
703 main.log.exception( self.name + ": TIMEOUT exception" )
Jon Hall3c910162018-03-07 14:42:16 -0800704 response = self.handle.before
705 # NOTE: Send ctrl-c to make sure command is stopped
Jon Hallf6aeda22020-07-28 09:12:56 -0700706 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
Jon Hall3c910162018-03-07 14:42:16 -0800707 response += self.handle.before + self.handle.after
You Wang7ce29462019-03-04 13:37:14 -0800708 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -0700709 self.handle.expect( self.mnPrompt )
Jon Hall3c910162018-03-07 14:42:16 -0800710 response += self.handle.before + self.handle.after
711 main.log.debug( response )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700712 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700713 except pexpect.EOF:
714 main.log.error( self.name + ": EOF exception found" )
715 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700716 main.cleanAndExit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700717 except Exception:
718 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700719 main.cleanAndExit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700720
Jon Hall7eb38402015-01-08 17:19:54 -0800721 def pingHost( self, **pingParams ):
722 """
Jon Hall3b489db2015-10-05 14:38:37 -0700723 Ping from one mininet host to another
724 Currently the only supported Params: SRC, TARGET, and WAIT
725 """
726 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700727 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700728 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800729 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700730 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700731 try:
Jon Hall61282e32015-03-19 11:34:11 -0700732 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800733 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700734 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700735 timeout=wait + 5 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700736 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800737 main.log.error(
738 self.name +
739 ": timeout when waiting for response from mininet" )
740 main.log.error( "response: " + str( self.handle.before ) )
Jon Hallf6aeda22020-07-28 09:12:56 -0700741 i = self.handle.expect( [ self.mnPrompt, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700742 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800743 main.log.error(
744 self.name +
745 ": timeout when waiting for response from mininet" )
746 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700747 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700748 if re.search( ',\s0\%\spacket\sloss', response ):
749 main.log.info( self.name + ": no packets lost, host is reachable" )
750 return main.TRUE
751 else:
Jon Hall2c8959e2016-12-16 12:17:34 -0800752 main.log.warn(
Hari Krishna012a1c12015-08-25 14:23:58 -0700753 self.name +
754 ": PACKET LOST, HOST IS NOT REACHABLE" )
755 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800756 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800757 main.log.error( self.name + ": EOF exception found" )
758 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700759 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700760 except Exception:
761 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700762 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700763
764 def ping6pair( self, **pingParams ):
765 """
GlennRC2cf7d952015-09-11 16:32:13 -0700766 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700767 Currently the only supported Params are: SRC, TARGET, and WAIT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000768 FLOWLABEL and -I (src interface) will be added later after running some tests.
Hari Krishna012a1c12015-08-25 14:23:58 -0700769 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
770 """
Jon Hall3b489db2015-10-05 14:38:37 -0700771 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700772 wait = args[ 'WAIT' ]
Jon Hall3b489db2015-10-05 14:38:37 -0700773 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530774 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700775 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700776 try:
777 main.log.info( "Sending: " + command )
778 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700779 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700780 timeout=wait + 5 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700781 if i == 1:
782 main.log.error(
783 self.name +
784 ": timeout when waiting for response from mininet" )
785 main.log.error( "response: " + str( self.handle.before ) )
Jon Hallf6aeda22020-07-28 09:12:56 -0700786 i = self.handle.expect( [ self.mnPrompt, pexpect.TIMEOUT ] )
Hari Krishna012a1c12015-08-25 14:23:58 -0700787 if i == 1:
788 main.log.error(
789 self.name +
790 ": timeout when waiting for response from mininet" )
791 main.log.error( "response: " + str( self.handle.before ) )
792 response = self.handle.before
793 main.log.info( self.name + ": Ping Response: " + response )
794 if re.search( ',\s0\%\spacket\sloss', response ):
795 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700796 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700797 else:
alisone4121a92016-11-22 16:31:36 -0800798 main.log.info(
Hari Krishna012a1c12015-08-25 14:23:58 -0700799 self.name +
800 ": PACKET LOST, HOST IS NOT REACHABLE" )
801 return main.FALSE
Hari Krishna012a1c12015-08-25 14:23:58 -0700802 except pexpect.EOF:
803 main.log.error( self.name + ": EOF exception found" )
804 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700805 main.cleanAndExit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700806 except Exception:
807 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700808 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800809
You Wangdb927a52016-02-26 11:03:28 -0800810 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
811 """
812 Description:
813 Ping a set of destination host from host CLI.
814 Logging into a Mininet host CLI is required before calling this funtion.
815 Params:
816 dstIPList is a list of destination ip addresses
817 Returns:
818 main.TRUE if the destination host is reachable
819 main.FALSE otherwise
820 """
821 isReachable = main.TRUE
822 wait = int( wait )
823 cmd = "ping"
824 if IPv6:
825 cmd = cmd + "6"
826 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
827 try:
828 for dstIP in dstIPList:
829 pingCmd = cmd + " " + dstIP
830 self.handle.sendline( pingCmd )
831 i = self.handle.expect( [ self.hostPrompt,
832 '\*\*\* Unknown command: ' + pingCmd,
833 pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700834 timeout=wait + 5 )
You Wang5da39c82018-04-26 22:55:08 -0700835 # For some reason we need to send something
836 # Otherwise ping results won't be read by handle
Jon Hall43060f62020-06-23 13:13:33 -0700837 response = self.handle.before
You Wang5da39c82018-04-26 22:55:08 -0700838 self.handle.sendline( "" )
839 self.handle.expect( self.hostPrompt )
You Wangdb927a52016-02-26 11:03:28 -0800840 if i == 0:
Jon Hall43060f62020-06-23 13:13:33 -0700841 response += self.handle.before
You Wangdb927a52016-02-26 11:03:28 -0800842 if not re.search( ',\s0\%\spacket\sloss', response ):
843 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
844 isReachable = main.FALSE
845 elif i == 1:
846 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
Devin Lim44075962017-08-11 10:56:37 -0700847 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800848 elif i == 2:
849 main.log.error( self.name + ": timeout when waiting for response" )
850 isReachable = main.FALSE
851 else:
852 main.log.error( self.name + ": unknown response: " + self.handle.before )
853 isReachable = main.FALSE
854 except pexpect.TIMEOUT:
855 main.log.exception( self.name + ": TIMEOUT exception" )
You Wangd4fae5c2018-08-22 13:56:49 -0700856 self.exitFromCmd( [ self.hostPrompt, self.bashPrompt ] )
You Wangdb927a52016-02-26 11:03:28 -0800857 isReachable = main.FALSE
858 except pexpect.EOF:
859 main.log.error( self.name + ": EOF exception found" )
860 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700861 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800862 except Exception:
863 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700864 main.cleanAndExit()
You Wangdb927a52016-02-26 11:03:28 -0800865 return isReachable
866
Jon Hall7eb38402015-01-08 17:19:54 -0800867 def checkIP( self, host ):
868 """
869 Verifies the host's ip configured or not."""
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700870 try:
871 if self.handle:
872 try:
873 response = self.execute(
874 cmd=host +
875 " ifconfig",
Jon Hallf6aeda22020-07-28 09:12:56 -0700876 prompt=self.mnPrompt,
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700877 timeout=10 )
878 except pexpect.EOF:
879 main.log.error( self.name + ": EOF exception found" )
880 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700881 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700882
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700883 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
884 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
885 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
886 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
887 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
888 "[0-9]|25[0-5]|[0-9]{1,2})"
889 # pattern = "inet addr:10.0.0.6"
890 if re.search( pattern, response ):
891 main.log.info( self.name + ": Host Ip configured properly" )
892 return main.TRUE
893 else:
894 main.log.error( self.name + ": Host IP not found" )
895 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700896 else:
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700897 main.log.error( self.name + ": Connection failed to the host" )
898 except Exception:
899 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700900 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800901
Jon Hall7eb38402015-01-08 17:19:54 -0800902 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800903 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700904 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800905 response = self.execute(
906 cmd="h1 /usr/sbin/sshd -D&",
Jon Hallf6aeda22020-07-28 09:12:56 -0700907 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -0800908 timeout=10 )
909 response = self.execute(
910 cmd="h4 /usr/sbin/sshd -D&",
Jon Hallf6aeda22020-07-28 09:12:56 -0700911 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -0800912 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700913 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800914 vars( self )[ key ] = connectargs[ key ]
915 response = self.execute(
916 cmd="xterm h1 h4 ",
Jon Hallf6aeda22020-07-28 09:12:56 -0700917 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -0800918 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800919 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800920 main.log.error( self.name + ": EOF exception found" )
921 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700922 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -0700923 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800924 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700925 if self.flag == 0:
926 self.flag = 1
927 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800928 else:
adminbae64d82013-08-01 10:50:15 -0700929 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800930
Jon Hall7eb38402015-01-08 17:19:54 -0800931 def changeIP( self, host, intf, newIP, newNetmask ):
932 """
933 Changes the ip address of a host on the fly
934 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800935 if self.handle:
936 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800937 cmd = host + " ifconfig " + intf + " " + \
938 newIP + " " + 'netmask' + " " + newNetmask
939 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700940 self.handle.expect( self.mnPrompt )
shahshreyae6c7cf42014-11-26 16:39:01 -0800941 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800942 main.log.info( "response = " + response )
943 main.log.info(
944 "Ip of host " +
945 host +
946 " changed to new IP " +
947 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800948 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700949 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700950 main.log.error( self.name + ": TIMEOUT exception found" )
951 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700952 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800953 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800954 main.log.error( self.name + ": EOF exception found" )
955 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800956 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700957 except Exception:
958 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700959 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800960
Jon Hall7eb38402015-01-08 17:19:54 -0800961 def changeDefaultGateway( self, host, newGW ):
962 """
963 Changes the default gateway of a host
964 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800965 if self.handle:
966 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800967 cmd = host + " route add default gw " + newGW
968 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -0700969 self.handle.expect( self.mnPrompt )
shahshreyae6c7cf42014-11-26 16:39:01 -0800970 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800971 main.log.info( "response = " + response )
972 main.log.info(
973 "Default gateway of host " +
974 host +
975 " changed to " +
976 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800977 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700978 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700979 main.log.error( self.name + ": TIMEOUT exception found" )
980 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700981 main.cleanAndExit()
shahshreyae6c7cf42014-11-26 16:39:01 -0800982 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800983 main.log.error( self.name + ": EOF exception found" )
984 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800985 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -0700986 except Exception:
987 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700988 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800989
You Wange24d6272018-03-27 21:18:50 -0700990 def addRoute( self, host, dstIP, interface, ipv6=False ):
991 """
992 Add a route to host
993 Ex: h1 route add -host 224.2.0.1 h1-eth0
994 """
995 if self.handle:
996 try:
997 cmd = str( host )
998 if ipv6:
999 cmd += " route -A inet6 add "
1000 else:
1001 cmd += " route add -host "
1002 cmd += str( dstIP ) + " " + str( interface )
1003 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07001004 self.handle.expect( self.mnPrompt )
You Wange24d6272018-03-27 21:18:50 -07001005 response = self.handle.before
1006 main.log.debug( "response = " + response )
1007 return main.TRUE
1008 except pexpect.TIMEOUT:
1009 main.log.error( self.name + ": TIMEOUT exception found" )
1010 main.log.error( self.name + ": " + self.handle.before )
1011 main.cleanAndExit()
1012 except pexpect.EOF:
1013 main.log.error( self.name + ": EOF exception found" )
1014 main.log.error( self.name + ": " + self.handle.before )
1015 return main.FALSE
1016 except Exception:
1017 main.log.exception( self.name + ": Uncaught exception!" )
1018 main.cleanAndExit()
1019
Jon Hall7eb38402015-01-08 17:19:54 -08001020 def addStaticMACAddress( self, host, GW, macaddr ):
1021 """
Jon Hallefbd9792015-03-05 16:11:36 -08001022 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -08001023 if self.handle:
1024 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001025 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
1026 cmd = host + " arp -s " + GW + " " + macaddr
1027 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07001028 self.handle.expect( self.mnPrompt )
shahshreyad0c80432014-12-04 16:56:05 -08001029 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001030 main.log.info( "response = " + response )
1031 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -08001032 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -08001033 GW +
1034 " changed to " +
1035 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -08001036 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001037 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001038 main.log.error( self.name + ": TIMEOUT exception found" )
1039 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001040 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001041 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001042 main.log.error( self.name + ": EOF exception found" )
1043 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001044 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001045 except Exception:
1046 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001047 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001048
Jon Hall7eb38402015-01-08 17:19:54 -08001049 def verifyStaticGWandMAC( self, host ):
1050 """
1051 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001052 if self.handle:
1053 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001054 # h1 arp -an
1055 cmd = host + " arp -an "
1056 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07001057 self.handle.expect( self.mnPrompt )
shahshreyad0c80432014-12-04 16:56:05 -08001058 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001059 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001060 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001061 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001062 main.log.error( self.name + ": TIMEOUT exception found" )
1063 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001064 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001065 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001066 main.log.error( self.name + ": EOF exception found" )
1067 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001068 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001069 except Exception:
1070 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001071 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001072
Jon Hall7eb38402015-01-08 17:19:54 -08001073 def getMacAddress( self, host ):
1074 """
1075 Verifies the host's ip configured or not."""
1076 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001077 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001078 response = self.execute(
1079 cmd=host +
1080 " ifconfig",
Jon Hallf6aeda22020-07-28 09:12:56 -07001081 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001082 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001083 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001084 main.log.error( self.name + ": EOF exception found" )
1085 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001086 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001087 except Exception:
1088 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001089 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001090
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001091 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001092 macAddressSearch = re.search( pattern, response, re.I )
1093 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001094 main.log.info(
1095 self.name +
1096 ": Mac-Address of Host " +
1097 host +
1098 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001099 macAddress )
1100 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001101 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001102 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001103
Jon Hall7eb38402015-01-08 17:19:54 -08001104 def getInterfaceMACAddress( self, host, interface ):
1105 """
1106 Return the IP address of the interface on the given host"""
1107 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001108 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001109 response = self.execute( cmd=host + " ifconfig " + interface,
Jon Hallf6aeda22020-07-28 09:12:56 -07001110 prompt=self.mnPrompt, timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001111 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001112 main.log.error( self.name + ": EOF exception found" )
1113 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001114 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001115 except Exception:
1116 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001117 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001118
1119 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001120 macAddressSearch = re.search( pattern, response, re.I )
1121 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001122 main.log.info( "No mac address found in %s" % response )
1123 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001124 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001125 main.log.info(
1126 "Mac-Address of " +
1127 host +
1128 ":" +
1129 interface +
1130 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001131 macAddress )
1132 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001133 else:
1134 main.log.error( "Connection failed to the host" )
1135
You Wang5da39c82018-04-26 22:55:08 -07001136 def getIPAddress( self, host, proto='IPV4' ):
Jon Hall7eb38402015-01-08 17:19:54 -08001137 """
1138 Verifies the host's ip configured or not."""
1139 if self.handle:
1140 try:
1141 response = self.execute(
1142 cmd=host +
1143 " ifconfig",
Jon Hallf6aeda22020-07-28 09:12:56 -07001144 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001145 timeout=10 )
1146 except pexpect.EOF:
1147 main.log.error( self.name + ": EOF exception found" )
1148 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001149 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001150 except Exception:
1151 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001152 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001153
sathishmad953462015-12-03 17:42:07 +05301154 pattern = ''
1155 if proto == 'IPV4':
Jon Hall43060f62020-06-23 13:13:33 -07001156 ip4Pat = r"(\d+\.\d+\.\d+\.\d+)"
1157 pattern = r"inet\s(addr:)?(?P<ip>" + ip4Pat + ")\s\s((Bcast:" + ip4Pat + "\s\s|netmask\s" + ip4Pat + "\s\sbroadcast\s" + ip4Pat + "))"
sathishmad953462015-12-03 17:42:07 +05301158 else:
Jon Hall43060f62020-06-23 13:13:33 -07001159 inet6Pat = r'(?P<ip>((?:[0-9a-fA-F]{1,4})?(?:[:0-9a-fA-F]{1,4}){1,7}(?:::)?(?:[:0-9a-fA-F]{1,4}){1,7}))'
1160 pattern = r"inet6\s(addr:\s)?" + inet6Pat + r"(/\d+)?\s(Scope:(Global|Link)|\sprefixlen\s(\d)+\s\sscopeid 0x(\d+)\<(link|global>))"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001161 ipAddressSearch = re.search( pattern, response )
Jon Hall3c910162018-03-07 14:42:16 -08001162 if not ipAddressSearch:
Jon Hall43060f62020-06-23 13:13:33 -07001163 main.log.debug( response )
1164 main.log.warn( "Could not find %s address" % proto )
Jon Hall3c910162018-03-07 14:42:16 -08001165 return None
Jon Hall7eb38402015-01-08 17:19:54 -08001166 main.log.info(
1167 self.name +
1168 ": IP-Address of Host " +
1169 host +
1170 " is " +
Jon Hall43060f62020-06-23 13:13:33 -07001171 ipAddressSearch.group( 'ip' ) )
1172 return ipAddressSearch.group( 'ip' )
Jon Hall7eb38402015-01-08 17:19:54 -08001173 else:
1174 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001175
Jon Hall7eb38402015-01-08 17:19:54 -08001176 def getSwitchDPID( self, switch ):
1177 """
1178 return the datapath ID of the switch"""
1179 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001180 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001181 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001182 response = self.execute(
1183 cmd=cmd,
Jon Hallf6aeda22020-07-28 09:12:56 -07001184 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001185 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001186 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001187 main.log.error( self.name + ": EOF exception found" )
1188 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001189 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001190 except Exception:
1191 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001192 main.cleanAndExit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001193 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001194 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001195 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001196 main.log.info(
1197 "Couldn't find DPID for switch %s, found: %s" %
1198 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001199 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001200 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001201 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001202 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001203
Jon Hall7eb38402015-01-08 17:19:54 -08001204 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001205 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001206 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07001207 self.expect( self.mnPrompt )
Jon Hall7eb38402015-01-08 17:19:54 -08001208 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001209 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001210 response = self.execute(
1211 cmd=cmd,
Jon Hallf6aeda22020-07-28 09:12:56 -07001212 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001213 timeout=10 )
Jon Hallf6aeda22020-07-28 09:12:56 -07001214 self.handle.expect( self.mnPrompt )
admin2580a0e2014-07-29 11:24:34 -07001215 response = self.handle.before
1216 return response
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001217 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001218 main.log.error( self.name + ": TIMEOUT exception found" )
1219 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001220 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001221 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001222 main.log.error( self.name + ": EOF exception found" )
1223 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001224 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001225 except Exception:
1226 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001227 main.cleanAndExit()
admin2580a0e2014-07-29 11:24:34 -07001228
Jon Hall7eb38402015-01-08 17:19:54 -08001229 def getInterfaces( self, node ):
1230 """
1231 return information dict about interfaces connected to the node"""
1232 if self.handle:
1233 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001234 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001235 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001236 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001237 response = self.execute(
1238 cmd=cmd,
Jon Hallf6aeda22020-07-28 09:12:56 -07001239 prompt=self.mnPrompt,
You Wang7d14d642019-01-23 15:10:08 -08001240 timeout=10,
1241 logCmd=False )
Jon Hallfbc828e2015-01-06 17:30:19 -08001242 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001243 main.log.error( self.name + ": EOF exception found" )
1244 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001245 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001246 except Exception:
1247 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001248 main.cleanAndExit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001249 return response
1250 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001251 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001252
Jon Hall7eb38402015-01-08 17:19:54 -08001253 def dump( self ):
1254 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001255 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001256 response = self.execute(
1257 cmd='dump',
1258 prompt='mininet>',
1259 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001260 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001261 main.log.error( self.name + ": EOF exception found" )
1262 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001263 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001264 except Exception:
1265 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001266 main.cleanAndExit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001267 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001268
Jon Hall7eb38402015-01-08 17:19:54 -08001269 def intfs( self ):
1270 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001271 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001272 response = self.execute(
1273 cmd='intfs',
1274 prompt='mininet>',
1275 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001276 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001277 main.log.error( self.name + ": EOF exception found" )
1278 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001279 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001280 except Exception:
1281 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001282 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001283 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001284
Jon Hall7eb38402015-01-08 17:19:54 -08001285 def net( self ):
1286 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001287 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001288 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001289 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001290 main.log.error( self.name + ": EOF exception found" )
1291 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001292 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001293 except Exception:
1294 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001295 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001296 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001297
Devin Lima7cfdbd2017-09-29 15:02:22 -07001298 def links( self, timeout=1000 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001299 main.log.info( self.name + ": List network links" )
1300 try:
1301 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001302 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001303 except pexpect.EOF:
1304 main.log.error( self.name + ": EOF exception found" )
1305 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001306 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001307 except Exception:
1308 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001309 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07001310 return response
1311
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001312 def iperftcpAll( self, hosts, timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001313 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001314 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001315
kelvin-onlab7cce9382015-07-17 10:21:03 -07001316 @parm:
1317 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1318 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001319 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001320 try:
1321 for host1 in hosts:
1322 for host2 in hosts:
1323 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001324 if self.iperftcp( host1, host2, timeout ) == main.FALSE:
1325 main.log.error( self.name + ": iperftcp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001326 except Exception:
1327 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001328 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001329
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001330 def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001331 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001332 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1333 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001334
kelvin-onlab7cce9382015-07-17 10:21:03 -07001335 @parm:
1336 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1337 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001338 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001339 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1340 try:
1341 # Setup the mininet command
1342 cmd1 = 'iperf ' + host1 + " " + host2
1343 self.handle.sendline( cmd1 )
Jon Hallf6aeda22020-07-28 09:12:56 -07001344 outcome = self.handle.expect( self.mnPrompt, timeout )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001345 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001346
kelvin-onlab7cce9382015-07-17 10:21:03 -07001347 # checks if there are results in the mininet response
1348 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001349 main.log.report( self.name + ": iperf test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001350 # parse the mn results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001351 response = response.split( "\r\n" )
1352 response = response[ len( response )-2 ]
1353 response = response.split( ": " )
1354 response = response[ len( response )-1 ]
1355 response = response.replace( "[", "" )
1356 response = response.replace( "]", "" )
1357 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001358
kelvin-onlab7cce9382015-07-17 10:21:03 -07001359 # this is the bandwith two and from the two hosts
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001360 bandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001361
kelvin-onlab7cce9382015-07-17 10:21:03 -07001362 # there should be two elements in the bandwidth list
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001363 # ['host1 to host2', 'host2 to host1"]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001364 if len( bandwidth ) == 2:
1365 main.log.report( self.name + ": iperf test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001366 return main.TRUE
1367 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001368 main.log.error( self.name + ": invalid iperf results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001369 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001370 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001371 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001372 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001373 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001374 main.log.error( self.name + ": TIMEOUT exception found" )
1375 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001376 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001377 # NOTE: Send ctrl-c to make sure iperf is done
Jon Hallf6aeda22020-07-28 09:12:56 -07001378 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
You Wang7ce29462019-03-04 13:37:14 -08001379 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07001380 self.handle.expect( self.mnPrompt )
GlennRC61321f22015-07-16 13:36:54 -07001381 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001382 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001383 main.log.error( self.name + ": EOF exception found" )
1384 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001385 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001386 except Exception:
1387 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001388 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001389
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001390 def iperftcpipv6( self, host1="h1", host2="h2", timeout=50 ):
Jon Hall439c8912016-04-15 02:22:03 -07001391 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1392 try:
1393 IP1 = self.getIPAddress( host1, proto='IPV6' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001394 cmd1 = host1 + ' iperf -V -sD -B ' + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001395 self.handle.sendline( cmd1 )
Jon Hallf6aeda22020-07-28 09:12:56 -07001396 outcome1 = self.handle.expect( self.mnPrompt )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001397 cmd2 = host2 + ' iperf -V -c ' + str( IP1 ) + ' -t 5'
Jon Hall439c8912016-04-15 02:22:03 -07001398 self.handle.sendline( cmd2 )
Jon Hallf6aeda22020-07-28 09:12:56 -07001399 outcome2 = self.handle.expect( self.mnPrompt )
Jon Hall439c8912016-04-15 02:22:03 -07001400 response1 = self.handle.before
1401 response2 = self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001402 print response1, response2
1403 pattern = "connected with " + str( IP1 )
Jon Hall439c8912016-04-15 02:22:03 -07001404 if pattern in response1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001405 main.log.report( self.name + ": iperf test completed" )
Jon Hall439c8912016-04-15 02:22:03 -07001406 return main.TRUE
1407 else:
1408 main.log.error( self.name + ": iperf test failed" )
1409 return main.FALSE
1410 except pexpect.TIMEOUT:
1411 main.log.error( self.name + ": TIMEOUT exception found" )
1412 main.log.error( self.name + " response: " + repr( self.handle.before ) )
Jon Hallf6aeda22020-07-28 09:12:56 -07001413 self.exitFromCmd( [ "Interrupt", self.mnPrompt ] )
You Wang7ce29462019-03-04 13:37:14 -08001414 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07001415 self.handle.expect( self.mnPrompt )
Jon Hall439c8912016-04-15 02:22:03 -07001416 return main.FALSE
1417 except pexpect.EOF:
1418 main.log.error( self.name + ": EOF exception found" )
1419 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001420 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001421 except Exception:
1422 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001423 main.cleanAndExit()
Jon Hall439c8912016-04-15 02:22:03 -07001424
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001425 def iperfudpAll( self, hosts, bandwidth="10M" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001426 '''
GlennRC61321f22015-07-16 13:36:54 -07001427 Runs the iperfudp function with a given set of hosts and specified
1428 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001429
GlennRC61321f22015-07-16 13:36:54 -07001430 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001431 bandwidth: the targeted bandwidth, in megabits ('M')
1432 '''
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001433 try:
1434 for host1 in hosts:
1435 for host2 in hosts:
1436 if host1 != host2:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001437 if self.iperfudp( host1, host2, bandwidth ) == main.FALSE:
1438 main.log.error( self.name + ": iperfudp test failed for " + host1 + " and " + host2 )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001439 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001440 main.log.exception( self.name + ": Object not as expected" )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001441 return main.FALSE
1442 except Exception:
1443 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001444 main.cleanAndExit()
GlennRC61321f22015-07-16 13:36:54 -07001445
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001446 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001447 '''
kelvin-onlab7cce9382015-07-17 10:21:03 -07001448 Creates an iperf UDP test with a specific bandwidth.
1449 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001450
kelvin-onlab7cce9382015-07-17 10:21:03 -07001451 @param:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001452 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1453 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001454 main.log.info( self.name + ": Simple iperf UDP test between two hosts" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001455 try:
1456 # setup the mininet command
1457 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001458 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07001459 self.handle.expect( self.mnPrompt )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001460 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001461
kelvin-onlab7cce9382015-07-17 10:21:03 -07001462 # check if there are in results in the mininet response
1463 if "Results:" in response:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001464 main.log.report( self.name + ": iperfudp test completed" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001465 # parse the results
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001466 response = response.split( "\r\n" )
1467 response = response[ len( response )-2 ]
1468 response = response.split( ": " )
1469 response = response[ len( response )-1 ]
1470 response = response.replace( "[", "" )
1471 response = response.replace( "]", "" )
1472 response = response.replace( "\'", "" )
GlennRC61321f22015-07-16 13:36:54 -07001473
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001474 mnBandwidth = response.split( ", " )
GlennRC61321f22015-07-16 13:36:54 -07001475
kelvin-onlab7cce9382015-07-17 10:21:03 -07001476 # check to see if there are at least three entries
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001477 # ['bandwidth', 'host1 to host2', 'host2 to host1']
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001478 if len( mnBandwidth ) == 3:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001479 # if one entry is blank then something is wrong
1480 for item in mnBandwidth:
1481 if item == "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001482 main.log.error( self.name + ": Could not parse iperf output" )
1483 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001484 return main.FALSE
1485 # otherwise results are vaild
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001486 main.log.report( self.name + ": iperfudp test successful" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001487 return main.TRUE
1488 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001489 main.log.error( self.name + ": invalid iperfudp results" )
kelvin-onlab7cce9382015-07-17 10:21:03 -07001490 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001491
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001492 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001493 main.log.error( self.name + ": TIMEOUT exception found" )
1494 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001495 main.cleanAndExit()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001496 except pexpect.EOF:
1497 main.log.error( self.name + ": EOF exception found" )
1498 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001499 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001500 except Exception:
1501 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001502 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001503
Jon Hall7eb38402015-01-08 17:19:54 -08001504 def nodes( self ):
1505 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001506 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001507 response = self.execute(
1508 cmd='nodes',
1509 prompt='mininet>',
1510 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001511 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001512 main.log.error( self.name + ": EOF exception found" )
1513 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001514 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001515 except Exception:
1516 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001517 main.cleanAndExit()
Jon Hall668ed802014-04-08 17:17:59 -07001518 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001519
Jon Hall7eb38402015-01-08 17:19:54 -08001520 def pingpair( self ):
1521 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001522 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001523 response = self.execute(
1524 cmd='pingpair',
1525 prompt='mininet>',
1526 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001527 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001528 main.log.error( self.name + ": EOF exception found" )
1529 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001530 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001531 except Exception:
1532 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001533 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001534
Jon Hall7eb38402015-01-08 17:19:54 -08001535 if re.search( ',\s0\%\spacket\sloss', response ):
1536 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001537 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001538 else:
alisone4121a92016-11-22 16:31:36 -08001539 main.log.info( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001540 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001541
Jon Hall7eb38402015-01-08 17:19:54 -08001542 def link( self, **linkargs ):
1543 """
GlennRCed771242016-01-13 17:02:47 -08001544 Bring link( s ) between two nodes up or down
1545 """
Jon Hall6094a362014-04-11 14:46:56 -07001546 try:
GlennRCed771242016-01-13 17:02:47 -08001547 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1548 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1549 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1550 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1551
1552 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1553 cmd = "link {} {} {}".format( end1, end2, option )
1554 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07001555 self.handle.expect( self.mnPrompt )
GlennRCed771242016-01-13 17:02:47 -08001556 response = self.handle.before
1557 main.log.info( response )
Jon Hallab611372018-02-21 15:26:05 -08001558 if "not in network" in response:
1559 main.log.error( self.name + ": Could not find one of the endpoints of the link" )
1560 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08001561 return main.TRUE
1562 except pexpect.TIMEOUT:
1563 main.log.exception( self.name + ": Command timed out" )
1564 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001565 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001566 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07001567 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08001568 except Exception:
1569 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001570 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001571
pingping-lin8244a3b2015-09-16 13:36:56 -07001572 def switch( self, **switchargs ):
1573 """
1574 start/stop a switch
1575 """
1576 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1577 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1578 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1579 command = "switch " + str( sw ) + " " + str( option )
1580 main.log.info( command )
1581 try:
1582 self.handle.sendline( command )
Jon Hallf6aeda22020-07-28 09:12:56 -07001583 self.handle.expect( self.mnPrompt )
pingping-lin8244a3b2015-09-16 13:36:56 -07001584 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001585 main.log.error( self.name + ": TIMEOUT exception found" )
1586 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001587 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001588 except pexpect.EOF:
1589 main.log.error( self.name + ": EOF exception found" )
1590 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001591 main.cleanAndExit()
pingping-lin8244a3b2015-09-16 13:36:56 -07001592 return main.TRUE
1593
pingping-lin5bb663b2015-09-24 11:47:50 -07001594 def node( self, nodeName, commandStr ):
1595 """
1596 Carry out a command line on a given node
1597 @parm:
1598 nodeName: the node name in Mininet testbed
1599 commandStr: the command line will be carried out on the node
1600 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1601 """
1602 command = str( nodeName ) + " " + str( commandStr )
1603 main.log.info( command )
1604
1605 try:
Jon Hallf6aeda22020-07-28 09:12:56 -07001606 response = self.execute( cmd = command, prompt = self.mnPrompt )
pingping-lin5bb663b2015-09-24 11:47:50 -07001607 if re.search( "Unknown command", response ):
1608 main.log.warn( response )
1609 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001610 if re.search( "Permission denied", response ):
1611 main.log.warn( response )
1612 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001613 except pexpect.EOF:
1614 main.log.error( self.name + ": EOF exception found" )
1615 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001616 main.cleanAndExit()
pingping-lin5bb663b2015-09-24 11:47:50 -07001617 main.log.info( " response is :" )
1618 main.log.info( response )
1619 return response
1620
Jon Hall7eb38402015-01-08 17:19:54 -08001621 def yank( self, **yankargs ):
1622 """
1623 yank a mininet switch interface to a host"""
1624 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001625 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001626 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1627 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001628 command = "py " + str( sw ) + '.detach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001629 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001630 response = self.execute(
1631 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001632 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001633 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001634 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001635 main.log.error( self.name + ": EOF exception found" )
1636 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001637 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001638 except Exception:
1639 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001640 main.cleanAndExit()
adminaeedddd2013-08-02 15:14:15 -07001641 return main.TRUE
1642
Jon Hall7eb38402015-01-08 17:19:54 -08001643 def plug( self, **plugargs ):
1644 """
1645 plug the yanked mininet switch interface to a switch"""
1646 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001647 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001648 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1649 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001650 command = "py " + str( sw ) + '.attach("' + str( intf ) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001651 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001652 response = self.execute(
1653 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001654 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001655 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001656 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001657 main.log.error( self.name + ": EOF exception found" )
1658 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001659 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001660 except Exception:
1661 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001662 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001663 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001664
Jon Hall7eb38402015-01-08 17:19:54 -08001665 def dpctl( self, **dpctlargs ):
1666 """
1667 Run dpctl command on all switches."""
1668 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001669 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001670 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1671 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1672 command = "dpctl " + cmd + " " + str( cmdargs )
1673 try:
1674 response = self.execute(
1675 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001676 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001677 timeout=10 )
1678 except pexpect.EOF:
1679 main.log.error( self.name + ": EOF exception found" )
1680 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001681 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001682 except Exception:
1683 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001684 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08001685 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001686
kelvin-onlabd3b64892015-01-20 13:26:24 -08001687 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001688 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001689 # version from MN and not some other file
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001690 try:
1691 fileInput = path + '/lib/Mininet/INSTALL'
1692 version = super( Mininet, self ).getVersion()
1693 pattern = 'Mininet\s\w\.\w\.\w\w*'
1694 for line in open( fileInput, 'r' ).readlines():
1695 result = re.match( pattern, line )
1696 if result:
1697 version = result.group( 0 )
1698 return version
1699 except Exception:
1700 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001701 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001702
kelvin-onlabd3b64892015-01-20 13:26:24 -08001703 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001704 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001705 Parameters:
1706 sw: The name of an OVS switch. Example "s1"
1707 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001708 The output of the command from the mininet cli
1709 or main.FALSE on timeout"""
1710 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001711 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001712 response = self.execute(
1713 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001714 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001715 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001716 if response:
Jon Hallab611372018-02-21 15:26:05 -08001717 if "no bridge named" in response:
1718 main.log.error( self.name + ": Error in getSwController: " +
1719 self.handle.before )
1720 return main.FALSE
1721 else:
1722 return response
admin2a9548d2014-06-17 14:08:07 -07001723 else:
1724 return main.FALSE
1725 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001726 main.log.error( self.name + ": EOF exception found" )
1727 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001728 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001729 except Exception:
1730 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001731 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001732
Charles Chan029be652015-08-24 01:46:10 +08001733 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001734 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001735 Description:
1736 Assign switches to the controllers ( for ovs use only )
1737 Required:
1738 sw - Name of the switch. This can be a list or a string.
1739 ip - Ip addresses of controllers. This can be a list or a string.
1740 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001741 port - ONOS use port 6653, if no list of ports is passed, then
1742 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001743 ptcp - ptcp number, This can be a string or a list that has
1744 the same length as switch. This is optional and not required
1745 when using ovs switches.
1746 NOTE: If switches and ptcp are given in a list type they should have the
1747 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1748 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001749
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001750 Return:
1751 Returns main.TRUE if mininet correctly assigned switches to
1752 controllers, otherwise it will return main.FALSE or an appropriate
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001753 exception(s)
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001754 """
1755 assignResult = main.TRUE
1756 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001757 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001758 command = "sh ovs-vsctl set-controller "
1759 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001760 try:
1761 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001762 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001763 if isinstance( port, types.StringType ) or \
1764 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001765 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001766 elif isinstance( port, types.ListType ):
1767 main.log.error( self.name + ": Only one controller " +
1768 "assigned and a list of ports has" +
1769 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001770 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001771 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001772 main.log.error( self.name + ": Invalid controller port " +
1773 "number. Please specify correct " +
1774 "controller port" )
1775 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001776
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001777 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001778 if isinstance( port, types.StringType ) or \
1779 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001780 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001781 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1782 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001783 elif isinstance( port, types.ListType ):
1784 if ( len( ip ) != len( port ) ):
1785 main.log.error( self.name + ": Port list = " +
1786 str( len( port ) ) +
1787 "should be the same as controller" +
1788 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001789 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001790 else:
1791 onosIp = ""
1792 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001793 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1794 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001795 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001796 main.log.error( self.name + ": Invalid controller port " +
1797 "number. Please specify correct " +
1798 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001799 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001800 else:
1801 main.log.error( self.name + ": Invalid ip address" )
1802 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001803
1804 if isinstance( sw, types.StringType ):
1805 command += sw + " "
1806 if ptcp:
1807 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001808 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001809 elif isinstance( ptcp, types.ListType ):
1810 main.log.error( self.name + ": Only one switch is " +
1811 "being set and multiple PTCP is " +
1812 "being passed " )
1813 else:
1814 main.log.error( self.name + ": Invalid PTCP" )
1815 ptcp = ""
1816 command += onosIp
1817 commandList.append( command )
1818
1819 elif isinstance( sw, types.ListType ):
1820 if ptcp:
1821 if isinstance( ptcp, types.ListType ):
1822 if len( ptcp ) != len( sw ):
1823 main.log.error( self.name + ": PTCP length = " +
1824 str( len( ptcp ) ) +
1825 " is not the same as switch" +
1826 " length = " +
1827 str( len( sw ) ) )
1828 return main.FALSE
1829 else:
1830 for switch, ptcpNum in zip( sw, ptcp ):
1831 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001832 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001833 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001834 tempCmd += onosIp
1835 commandList.append( tempCmd )
1836 else:
1837 main.log.error( self.name + ": Invalid PTCP" )
1838 return main.FALSE
1839 else:
1840 for switch in sw:
1841 tempCmd = "sh ovs-vsctl set-controller "
1842 tempCmd += switch + " " + onosIp
1843 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001844 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001845 main.log.error( self.name + ": Invalid switch type " )
1846 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001847
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001848 for cmd in commandList:
1849 try:
Jon Hallf6aeda22020-07-28 09:12:56 -07001850 self.execute( cmd=cmd, prompt=self.mnPrompt, timeout=5 )
Jon Hallab611372018-02-21 15:26:05 -08001851 if "no bridge named" in self.handle.before:
1852 main.log.error( self.name + ": Error in assignSwController: " +
1853 self.handle.before )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001854 except pexpect.TIMEOUT:
1855 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1856 return main.FALSE
1857 except pexpect.EOF:
1858 main.log.error( self.name + ": EOF exception found" )
1859 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001860 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001861 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001862 except pexpect.EOF:
1863 main.log.error( self.name + ": EOF exception found" )
1864 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001865 main.cleanAndExit()
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001866 except Exception:
1867 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001868 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07001869
kelvin-onlabd3b64892015-01-20 13:26:24 -08001870 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001871 """
1872 Removes the controller target from sw"""
1873 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001874 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001875 response = self.execute(
1876 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001877 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001878 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001879 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001880 main.log.error( self.name + ": EOF exception found" )
1881 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001882 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001883 except Exception:
1884 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001885 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07001886 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001887 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001888
kelvin-onlabd3b64892015-01-20 13:26:24 -08001889 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001890 """
Jon Hallb1290e82014-11-18 16:17:48 -05001891 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001892 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001893 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001894 NOTE: cannot currently specify what type of switch
1895 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001896 sw = name of the new switch as a string
1897 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001898 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001899 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001900 """
1901 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001902 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001903 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001904 response = self.execute(
1905 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001906 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001907 timeout=10 )
1908 if re.search( "already exists!", response ):
1909 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001910 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001911 elif re.search( "Error", response ):
1912 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001913 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001914 elif re.search( "usage:", response ):
1915 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001916 return main.FALSE
1917 else:
1918 return main.TRUE
1919 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001920 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001921 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001922 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001923 except Exception:
1924 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001925 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001926
kelvin-onlabd3b64892015-01-20 13:26:24 -08001927 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001928 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001929 delete a switch from the mininet topology
1930 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001931 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001932 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001933 sw = name of the switch as a string
1934 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001935 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001936 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001937 response = self.execute(
1938 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07001939 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08001940 timeout=10 )
1941 if re.search( "no switch named", response ):
1942 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001943 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001944 elif re.search( "Error", response ):
1945 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001946 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001947 elif re.search( "usage:", response ):
1948 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001949 return main.FALSE
1950 else:
1951 return main.TRUE
1952 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001953 main.log.error( self.name + ": EOF exception found" )
1954 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001955 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07001956 except Exception:
1957 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001958 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05001959
You Wangb1665b52019-02-01 15:49:48 -08001960 def getSwitchRandom( self, timeout=60, nonCut=True, excludeNodes=[], skipSwitches=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07001961 """
1962 Randomly get a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001963 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07001964 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001965 components of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07001966 it just randomly returns one switch from all current switches in
1967 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08001968 excludeNodes will be pased to getGraphDict method
You Wangb1665b52019-02-01 15:49:48 -08001969 Switches specified in skipSwitches will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07001970 Returns the name of the chosen switch.
1971 """
1972 import random
1973 candidateSwitches = []
1974 try:
1975 if not nonCut:
You Wangb1665b52019-02-01 15:49:48 -08001976 switches = self.getSwitches( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07001977 assert len( switches ) != 0
1978 for switchName in switches.keys():
1979 candidateSwitches.append( switchName )
1980 else:
You Wang7d14d642019-01-23 15:10:08 -08001981 graphDict = self.getGraphDict( timeout=timeout, useId=False,
You Wang7d14d642019-01-23 15:10:08 -08001982 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001983 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001984 return None
1985 self.graph.update( graphDict )
1986 candidateSwitches = self.graph.getNonCutVertices()
You Wangb1665b52019-02-01 15:49:48 -08001987 candidateSwitches = [ switch for switch in candidateSwitches if switch not in skipSwitches ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001988 if candidateSwitches is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07001989 return None
1990 elif len( candidateSwitches ) == 0:
1991 main.log.info( self.name + ": No candidate switch for deletion" )
1992 return None
1993 else:
1994 switch = random.sample( candidateSwitches, 1 )
1995 return switch[ 0 ]
1996 except KeyError:
1997 main.log.exception( self.name + ": KeyError exception found" )
1998 return None
1999 except AssertionError:
2000 main.log.exception( self.name + ": AssertionError exception found" )
2001 return None
2002 except Exception:
2003 main.log.exception( self.name + ": Uncaught exception" )
2004 return None
2005
2006 def delSwitchRandom( self, timeout=60, nonCut=True ):
2007 """
2008 Randomly delete a switch from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002009 If nonCut is True, it gets a list of non-cut switches (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002010 of a non-cut switch will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002011 components of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002012 otherwise it just randomly delete one switch from all current
2013 switches in Mininet.
2014 Returns the name of the deleted switch
2015 """
2016 try:
2017 switch = self.getSwitchRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002018 if switch is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002019 return None
2020 else:
2021 deletionResult = self.delSwitch( switch )
2022 if deletionResult:
2023 return switch
2024 else:
2025 return None
2026 except Exception:
2027 main.log.exception( self.name + ": Uncaught exception" )
2028 return None
2029
kelvin-onlabd3b64892015-01-20 13:26:24 -08002030 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002031 """
2032 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002033 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002034 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002035 NOTE: cannot currently specify what type of link
2036 required params:
2037 node1 = the string node name of the first endpoint of the link
2038 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08002039 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002040 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002041 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002042 response = self.execute(
2043 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002044 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08002045 timeout=10 )
2046 if re.search( "doesnt exist!", response ):
2047 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002048 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002049 elif re.search( "Error", response ):
2050 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002051 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002052 elif re.search( "usage:", response ):
2053 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002054 return main.FALSE
2055 else:
2056 return main.TRUE
2057 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002058 main.log.error( self.name + ": EOF exception found" )
2059 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002060 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002061 except Exception:
2062 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002063 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002064
kelvin-onlabd3b64892015-01-20 13:26:24 -08002065 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08002066 """
2067 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002068 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002069 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002070 required params:
2071 node1 = the string node name of the first endpoint of the link
2072 node2 = the string node name of the second endpoint of the link
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002073 returns: main.FALSE on an error, else main.TRUE
2074 """
Jon Hallffb386d2014-11-21 13:43:38 -08002075 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05002076 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002077 response = self.execute(
2078 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002079 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08002080 timeout=10 )
2081 if re.search( "no node named", response ):
2082 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002083 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002084 elif re.search( "Error", response ):
2085 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002086 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002087 elif re.search( "usage:", response ):
2088 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002089 return main.FALSE
2090 else:
2091 return main.TRUE
2092 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002093 main.log.error( self.name + ": EOF exception found" )
2094 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002095 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002096 except Exception:
2097 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002098 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002099
You Wangb1665b52019-02-01 15:49:48 -08002100 def getLinkRandom( self, timeout=60, nonCut=True, excludeNodes=[], skipLinks=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07002101 """
2102 Randomly get a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002103 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002104 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002105 component of a graph) and randomly returns one of them, otherwise
You Wangdb8cd0a2016-05-26 15:19:45 -07002106 it just randomly returns one link from all current links in
2107 Mininet.
You Wang7d14d642019-01-23 15:10:08 -08002108 excludeNodes will be passed to getLinks method to exclude unexpected links.
You Wangb1665b52019-02-01 15:49:48 -08002109 Any link that has either end included in skipLinks will be excluded
You Wangdb8cd0a2016-05-26 15:19:45 -07002110 Returns the link as a list, e.g. [ 's1', 's2' ]
2111 """
2112 import random
2113 candidateLinks = []
2114 try:
2115 if not nonCut:
You Wang7d14d642019-01-23 15:10:08 -08002116 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07002117 assert len( links ) != 0
2118 for link in links:
2119 # Exclude host-switch link
2120 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
2121 continue
2122 candidateLinks.append( [ link[ 'node1' ], link[ 'node2' ] ] )
2123 else:
You Wang7d14d642019-01-23 15:10:08 -08002124 graphDict = self.getGraphDict( timeout=timeout, useId=False,
You Wang7d14d642019-01-23 15:10:08 -08002125 excludeNodes=excludeNodes )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002126 if graphDict is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002127 return None
2128 self.graph.update( graphDict )
2129 candidateLinks = self.graph.getNonCutEdges()
You Wangb1665b52019-02-01 15:49:48 -08002130 candidateLinks = [ link for link in candidateLinks
2131 if link[0] not in skipLinks and link[1] not in skipLinks ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002132 if candidateLinks is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002133 return None
2134 elif len( candidateLinks ) == 0:
2135 main.log.info( self.name + ": No candidate link for deletion" )
2136 return None
2137 else:
2138 link = random.sample( candidateLinks, 1 )
2139 return link[ 0 ]
2140 except KeyError:
2141 main.log.exception( self.name + ": KeyError exception found" )
2142 return None
2143 except AssertionError:
2144 main.log.exception( self.name + ": AssertionError exception found" )
2145 return None
2146 except Exception:
2147 main.log.exception( self.name + ": Uncaught exception" )
2148 return None
2149
2150 def delLinkRandom( self, timeout=60, nonCut=True ):
2151 """
2152 Randomly delete a link from Mininet topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002153 If nonCut is True, it gets a list of non-cut links (the deletion
You Wangdb8cd0a2016-05-26 15:19:45 -07002154 of a non-cut link will not increase the number of connected
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002155 component of a graph) and randomly chooses one for deletion,
You Wangdb8cd0a2016-05-26 15:19:45 -07002156 otherwise it just randomly delete one link from all current links
2157 in Mininet.
2158 Returns the deleted link as a list, e.g. [ 's1', 's2' ]
2159 """
2160 try:
2161 link = self.getLinkRandom( timeout, nonCut )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002162 if link is None:
You Wangdb8cd0a2016-05-26 15:19:45 -07002163 return None
2164 else:
2165 deletionResult = self.delLink( link[ 0 ], link[ 1 ] )
2166 if deletionResult:
2167 return link
2168 else:
2169 return None
2170 except Exception:
2171 main.log.exception( self.name + ": Uncaught exception" )
2172 return None
2173
kelvin-onlabd3b64892015-01-20 13:26:24 -08002174 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08002175 """
Jon Hallb1290e82014-11-18 16:17:48 -05002176 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002177 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002178 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05002179 NOTE: cannot currently specify what type of host
2180 required params:
2181 hostname = the string hostname
2182 optional key-value params
2183 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08002184 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08002185 """
2186 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08002187 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05002188 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002189 response = self.execute(
2190 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002191 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08002192 timeout=10 )
2193 if re.search( "already exists!", response ):
2194 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002195 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002196 elif re.search( "doesnt exists!", response ):
2197 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002198 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002199 elif re.search( "Error", response ):
2200 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002201 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002202 elif re.search( "usage:", response ):
2203 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002204 return main.FALSE
2205 else:
2206 return main.TRUE
2207 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002208 main.log.error( self.name + ": EOF exception found" )
2209 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002210 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002211 except Exception:
2212 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002213 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05002214
kelvin-onlabd3b64892015-01-20 13:26:24 -08002215 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08002216 """
2217 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08002218 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08002219 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08002220 NOTE: this uses a custom mn function
2221 required params:
2222 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08002223 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08002224 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05002225 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002226 response = self.execute(
2227 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002228 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08002229 timeout=10 )
2230 if re.search( "no host named", response ):
2231 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002232 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002233 elif re.search( "Error", response ):
2234 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002235 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002236 elif re.search( "usage:", response ):
2237 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05002238 return main.FALSE
2239 else:
2240 return main.TRUE
2241 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002242 main.log.error( self.name + ": EOF exception found" )
2243 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002244 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002245 except Exception:
2246 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002247 main.cleanAndExit()
Jon Hall0819fd92014-05-23 12:08:13 -07002248
Jon Hall7eb38402015-01-08 17:19:54 -08002249 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08002250 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002251 Called at the end of the test to stop the mininet and
2252 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08002253 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002254 try:
2255 self.handle.sendline( '' )
You Wangd66de192018-04-30 17:30:12 -07002256 i = self.handle.expect( [ 'mininet>', self.hostPrompt, pexpect.EOF, pexpect.TIMEOUT ],
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002257 timeout=2 )
2258 response = main.TRUE
2259 if i == 0:
2260 response = self.stopNet()
You Wangd66de192018-04-30 17:30:12 -07002261 elif i == 2:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002262 return main.TRUE
2263 # print "Disconnecting Mininet"
2264 if self.handle:
2265 self.handle.sendline( "exit" )
2266 self.handle.expect( "exit" )
2267 self.handle.expect( "(.*)" )
2268 else:
2269 main.log.error( "Connection failed to the host" )
2270 return response
2271 except pexpect.EOF:
2272 main.log.error( self.name + ": EOF exception found" )
2273 main.log.error( self.name + ": " + self.handle.before )
You Wangd4fae5c2018-08-22 13:56:49 -07002274 # Do not exit the entire test when pexpect.EOF is caught
2275 # FIXME: We might need to do something else here
2276 return main.ERROR
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002277 except Exception:
2278 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002279 main.cleanAndExit()
kelvin-onlaba1484582015-02-02 15:46:20 -08002280
Devin Lima7cfdbd2017-09-29 15:02:22 -07002281 def stopNet( self, fileName="", timeout=5, exitTimeout=1000 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002282 """
Jon Hall21270ac2015-02-16 17:59:55 -08002283 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08002284 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08002285 main.FALSE if the pexpect handle does not exist.
2286
Jon Halld61331b2015-02-17 16:35:47 -08002287 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08002288 """
Jon Halld61331b2015-02-17 16:35:47 -08002289 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07002290 response = ''
2291 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07002292 try:
Jon Halld80cc142015-07-06 13:36:05 -07002293 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07002294 i = self.handle.expect( [ self.mnPrompt,
2295 self.bashPrompt,
kelvin-onlab56a3f462015-02-06 14:04:43 -08002296 pexpect.EOF,
2297 pexpect.TIMEOUT ],
2298 timeout )
2299 if i == 0:
Devin Lima7cfdbd2017-09-29 15:02:22 -07002300 main.log.info( "Exiting mininet.." )
2301 startTime = time.time()
Jon Hallf6aeda22020-07-28 09:12:56 -07002302 self.handle.sendline( "exit" )
2303 exitRet = 1
2304 while not exitRet:
2305 exitRet = self.handle.expect( [ self.bashprompt,
2306 "Traceback",
2307 "AssertionError",
2308 self.mnPrompt ],
2309 timeout=exitTimeout )
2310 response += self.handle.before + self.handle.after
2311 main.log.debug( response )
Devin Lima7cfdbd2017-09-29 15:02:22 -07002312 main.log.info( self.name + ": Stopped\nTime Took : " + str( time.time() - startTime ) )
Jon Halldac3eae2020-06-05 12:04:06 -07002313 cmd = "mn -c"
2314 if self.sudoRequired:
2315 cmd = "sudo " + cmd
2316 self.handle.sendline( cmd )
Jeremyd9e4eb12016-04-13 12:09:06 -07002317 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002318
Jeremyd9e4eb12016-04-13 12:09:06 -07002319 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002320 main.log.info( " Mininet trying to exit while not " +
2321 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002322 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002323 elif i == 2:
2324 main.log.error( "Something went wrong exiting mininet" )
2325 elif i == 3: # timeout
2326 main.log.error( "Something went wrong exiting mininet " +
2327 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002328
You Wang18db8592018-04-02 13:52:03 -07002329 self.handle.sendline( "" )
2330 self.handle.expect( self.prompt )
Jon Halldac3eae2020-06-05 12:04:06 -07002331 cmd = "killall -9 dhclient dhcpd zebra bgpd"
2332 if self.sudoRequired:
2333 cmd = "sudo " + cmd
2334 self.handle.sendline( cmd )
2335 self.handle.expect( self.prompt )
You Wang18db8592018-04-02 13:52:03 -07002336
Hari Krishnab35c6d02015-03-18 11:13:51 -07002337 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002338 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -07002339 self.handle.expect( self.prompt )
Jon Halldac3eae2020-06-05 12:04:06 -07002340 cmd = "kill -9 \`ps -ef | grep \"" + fileName + "\" | grep -v grep | awk '{print $2}'\`"
2341 if self.sudoRequired:
2342 cmd = "sudo " + cmd
2343 self.handle.sendline( cmd )
2344 self.handle.expect( self.prompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002345 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002346 main.log.error( self.name + ": TIMEOUT exception found" )
2347 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002348 main.cleanAndExit()
Jon Hallfbc828e2015-01-06 17:30:19 -08002349 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002350 main.log.error( self.name + ": EOF exception found" )
2351 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002352 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002353 except Exception:
2354 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002355 main.cleanAndExit()
Jon Hall7eb38402015-01-08 17:19:54 -08002356 else:
2357 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002358 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002359 return response
2360
YPZhang26a139e2016-04-25 14:01:55 -07002361 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002362 """
2363 Description:
2364 Sends arp message from mininet host for hosts discovery
2365 Required:
2366 host - hosts name
2367 Optional:
2368 ip - ip address that does not exist in the network so there would
2369 be no reply.
2370 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002371 if ethDevice:
2372 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002373 cmd = srcHost + " arping -c1 "
2374 if noResult:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002375 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 -07002376 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002377 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002378 if output:
2379 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002380 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07002381 i = self.handle.expect( [ self.mnPrompt, "arping: " ] )
Jon Halla5cb3412015-08-18 14:08:22 -07002382 if i == 0:
2383 return main.TRUE
2384 elif i == 1:
2385 response = self.handle.before + self.handle.after
Jon Hallf6aeda22020-07-28 09:12:56 -07002386 self.handle.expect( self.mnPrompt )
Jon Halla5cb3412015-08-18 14:08:22 -07002387 response += self.handle.before + self.handle.after
2388 main.log.warn( "Error sending arping, output was: " +
2389 response )
2390 return main.FALSE
2391 except pexpect.TIMEOUT:
2392 main.log.error( self.name + ": TIMEOUT exception found" )
2393 main.log.warn( self.handle.before )
2394 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002395 except pexpect.EOF:
2396 main.log.error( self.name + ": EOF exception found" )
2397 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002398 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002399 except Exception:
2400 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002401 main.cleanAndExit()
admin07529932013-11-22 14:58:28 -08002402
Jon Hall7eb38402015-01-08 17:19:54 -08002403 def decToHex( self, num ):
2404 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002405
Jon Hall7eb38402015-01-08 17:19:54 -08002406 def getSwitchFlowCount( self, switch ):
2407 """
2408 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002409 if self.handle:
2410 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2411 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002412 response = self.execute(
2413 cmd=cmd,
Jon Hallf6aeda22020-07-28 09:12:56 -07002414 prompt=self.mnPrompt,
Jon Hall7eb38402015-01-08 17:19:54 -08002415 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002416 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002417 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()
admin2a9548d2014-06-17 14:08:07 -07002423 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002424 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002425 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002426 main.log.info(
2427 "Couldn't find flows on switch %s, found: %s" %
2428 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002429 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002430 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002431 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002432 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002433
Jon Hall9ed8f372016-02-24 17:34:07 -08002434 def checkFlows( self, sw, dumpFormat=None ):
2435 if dumpFormat:
2436 command = "sh ovs-ofctl -F " + \
2437 dumpFormat + " dump-flows " + str( sw )
2438 else:
2439 command = "sh ovs-ofctl dump-flows " + str( sw )
2440 try:
2441 response = self.execute(
2442 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002443 prompt=self.mnPrompt,
Jon Hall9ed8f372016-02-24 17:34:07 -08002444 timeout=10 )
2445 return response
2446 except pexpect.EOF:
2447 main.log.error( self.name + ": EOF exception found" )
2448 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002449 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002450 except Exception:
2451 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002452 main.cleanAndExit()
Jon Hall9ed8f372016-02-24 17:34:07 -08002453
GlennRC68467eb2015-11-16 18:01:01 -08002454 def flowTableComp( self, flowTable1, flowTable2 ):
2455 # This function compares the selctors and treatments of each flow
2456 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002457 assert flowTable1, "flowTable1 is empty or None"
2458 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002459 returnValue = main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002460 if len( flowTable1 ) != len( flowTable2 ):
GlennRC68467eb2015-11-16 18:01:01 -08002461 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002462 returnValue = main.FALSE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002463 dFields = [ "n_bytes", "cookie", "n_packets", "duration" ]
2464 for flow1, flow2 in zip( flowTable1, flowTable2 ):
Jon Hallacd1b182015-12-17 11:43:20 -08002465 for field in dFields:
2466 try:
2467 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002468 except KeyError:
2469 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002470 try:
2471 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002472 except KeyError:
2473 pass
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002474 for i in range( len( flowTable1 ) ):
2475 if flowTable1[ i ] not in flowTable2:
GlennRC17bbcf52015-12-14 17:31:50 -08002476 main.log.warn( "Flow tables do not match:" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002477 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[ i ] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002478 returnValue = main.FALSE
2479 break
2480 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002481 except AssertionError:
2482 main.log.exception( "Nothing to compare" )
2483 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002484 except Exception:
2485 main.log.exception( "Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002486 main.cleanAndExit()
Jon Hall9043c902015-07-30 14:23:44 -07002487
GlennRC528ad292015-11-12 10:38:18 -08002488 def parseFlowTable( self, flowTable, version="", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002489 '''
GlennRC956ea742015-11-05 16:14:15 -08002490 Discription: Parses flows into json format.
2491 NOTE: this can parse any string thats separated with commas
2492 Arguments:
2493 Required:
2494 flows: a list of strings that represnt flows
2495 Optional:
2496 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2497 debug: prints out the final result
2498 returns: A list of flows in json format
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002499 '''
GlennRC528ad292015-11-12 10:38:18 -08002500 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002501 try:
2502 for flow in flowTable:
2503 jsonFlow = {}
2504 # split up the fields of the flow
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002505 parsedFlow = flow.split( ", " )
You Wang91c37cf2016-05-23 09:39:42 -07002506 # get rid of any spaces in front of the field
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002507 for i in range( len( parsedFlow ) ):
2508 item = parsedFlow[ i ]
2509 if item[ 0 ] == " ":
2510 parsedFlow[ i ] = item[ 1: ]
You Wang91c37cf2016-05-23 09:39:42 -07002511 # grab the selector and treatment from the parsed flow
2512 # the last element is the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002513 temp = parsedFlow.pop( -1 )
You Wang91c37cf2016-05-23 09:39:42 -07002514 # split up the selector and the treatment
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002515 temp = temp.split( " " )
You Wang91c37cf2016-05-23 09:39:42 -07002516 index = 0
2517 # parse the flags
2518 # NOTE: This only parses one flag
2519 flag = {}
2520 if version == "1.3":
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002521 flag = { "flag": [ temp[ index ] ] }
You Wang91c37cf2016-05-23 09:39:42 -07002522 index += 1
2523 # the first element is the selector and split it up
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002524 sel = temp[ index ]
GlennRC528ad292015-11-12 10:38:18 -08002525 index += 1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002526 sel = sel.split( "," )
You Wang91c37cf2016-05-23 09:39:42 -07002527 # the priority is stuck in the selecter so put it back
2528 # in the flow
Jon Hallab611372018-02-21 15:26:05 -08002529 if 'priority' in sel[0]:
2530 parsedFlow.append( sel.pop( 0 ) )
You Wang91c37cf2016-05-23 09:39:42 -07002531 # parse selector
2532 criteria = []
2533 for item in sel:
2534 # this is the type of the packet e.g. "arp"
2535 if "=" not in item:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002536 criteria.append( { "type": item } )
You Wang91c37cf2016-05-23 09:39:42 -07002537 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002538 field = item.split( "=" )
2539 criteria.append( { field[ 0 ]: field[ 1 ] } )
2540 selector = { "selector": { "criteria": sorted( criteria ) } }
2541 treat = temp[ index ]
You Wang91c37cf2016-05-23 09:39:42 -07002542 # get rid of the action part e.g. "action=output:2"
2543 # we will add it back later
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002544 treat = treat.split( "=" )
2545 treat.pop( 0 )
You Wang91c37cf2016-05-23 09:39:42 -07002546 # parse treatment
2547 action = []
2548 for item in treat:
Jon Hallab611372018-02-21 15:26:05 -08002549 if ":" in item:
2550 field = item.split( ":" )
2551 action.append( { field[ 0 ]: field[ 1 ] } )
2552 else:
2553 main.log.warn( "Do not know how to process this treatment:{}, ignoring.".format(
2554 item ) )
You Wang91c37cf2016-05-23 09:39:42 -07002555 # create the treatment field and add the actions
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002556 treatment = { "treatment": { "action": sorted( action ) } }
You Wang91c37cf2016-05-23 09:39:42 -07002557 # parse the rest of the flow
2558 for item in parsedFlow:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002559 field = item.split( "=" )
2560 jsonFlow.update( { field[ 0 ]: field[ 1 ] } )
You Wang91c37cf2016-05-23 09:39:42 -07002561 # add the treatment and the selector to the json flow
2562 jsonFlow.update( selector )
2563 jsonFlow.update( treatment )
2564 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002565
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002566 if debug:
2567 main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format( jsonFlow ) )
GlennRC956ea742015-11-05 16:14:15 -08002568
You Wang91c37cf2016-05-23 09:39:42 -07002569 # add the json flow to the json flow table
2570 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002571
You Wang91c37cf2016-05-23 09:39:42 -07002572 return jsonFlowTable
2573
2574 except IndexError:
2575 main.log.exception( self.name + ": IndexError found" )
2576 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002577 except pexpect.EOF:
2578 main.log.error( self.name + ": EOF exception found" )
2579 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002580 main.cleanAndExit()
You Wang91c37cf2016-05-23 09:39:42 -07002581 except Exception:
2582 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002583 main.cleanAndExit()
GlennRC528ad292015-11-12 10:38:18 -08002584
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002585 def getFlowTable( self, sw, version="", debug=False ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002586 '''
2587 Discription: Returns the flow table(s) on a switch or switches in a list.
GlennRC956ea742015-11-05 16:14:15 -08002588 Each element is a flow.
2589 Arguments:
2590 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002591 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002592 a list of switches.
2593 Optional:
2594 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2595 debug: prints out the final result
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002596 '''
GlennRC956ea742015-11-05 16:14:15 -08002597 try:
2598 switches = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002599 if isinstance( sw, list ):
2600 switches.extend( sw )
2601 else:
2602 switches.append( sw )
GlennRC956ea742015-11-05 16:14:15 -08002603
2604 flows = []
2605 for s in switches:
2606 cmd = "sh ovs-ofctl dump-flows " + s
2607
GlennRC528ad292015-11-12 10:38:18 -08002608 if "1.0" == version:
2609 cmd += " -F OpenFlow10-table_id"
2610 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002611 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002612
2613 main.log.info( "Sending: " + cmd )
2614 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07002615 self.handle.expect( self.mnPrompt )
GlennRC956ea742015-11-05 16:14:15 -08002616 response = self.handle.before
2617 response = response.split( "\r\n" )
2618 # dump the first two elements and the last
2619 # the first element is the command that was sent
2620 # the second is the table header
2621 # the last element is empty
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002622 response = response[ 2:-1 ]
GlennRC956ea742015-11-05 16:14:15 -08002623 flows.extend( response )
2624
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002625 if debug:
2626 print "Flows:\n{}\n\n".format( flows )
GlennRC956ea742015-11-05 16:14:15 -08002627
GlennRC528ad292015-11-12 10:38:18 -08002628 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002629
GlennRC956ea742015-11-05 16:14:15 -08002630 except pexpect.EOF:
2631 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07002632 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002633 except Exception:
2634 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002635 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002636
2637 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002638 '''
GlennRC956ea742015-11-05 16:14:15 -08002639 Discription: Checks whether the ID provided matches a flow ID in Mininet
2640 Arguments:
2641 Required:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002642 sw: The switch name ("s1") to retrive the flow table. Can also be
GlennRC956ea742015-11-05 16:14:15 -08002643 a list of switches.
2644 flowId: the flow ID in hex format. Can also be a list of IDs
2645 Optional:
2646 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2647 debug: prints out the final result
2648 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2649 NOTE: prints out IDs that are not present
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002650 '''
GlennRC956ea742015-11-05 16:14:15 -08002651 try:
2652 main.log.info( "Getting flows from Mininet" )
2653 flows = self.getFlowTable( sw, version, debug )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002654 if flows is None:
You Wang083ae982016-05-25 09:31:09 -07002655 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002656
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002657 if debug:
2658 print "flow ids:\n{}\n\n".format( flowId )
GlennRC956ea742015-11-05 16:14:15 -08002659
2660 # Check flowId is a list or a string
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002661 if isinstance( flowId, str ):
GlennRC956ea742015-11-05 16:14:15 -08002662 result = False
2663 for f in flows:
2664 if flowId in f.get( 'cookie' ):
2665 result = True
2666 break
2667 # flowId is a list
2668 else:
2669 result = True
2670 # Get flow IDs from Mininet
2671 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2672 # Save the IDs that are not in Mininet
2673 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2674
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002675 if debug:
2676 print "mn flow ids:\n{}\n\n".format( mnFlowIds )
GlennRC956ea742015-11-05 16:14:15 -08002677
2678 # Print out the IDs that are not in Mininet
2679 if absentIds:
2680 main.log.warn( "Absent ids: {}".format( absentIds ) )
2681 result = False
2682
2683 return main.TRUE if result else main.FALSE
2684
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002685 except pexpect.EOF:
2686 main.log.error( self.name + ": EOF exception found" )
2687 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002688 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002689 except Exception:
2690 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002691 main.cleanAndExit()
GlennRC956ea742015-11-05 16:14:15 -08002692
Charles Chan029be652015-08-24 01:46:10 +08002693 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002694 """
Jon Hallefbd9792015-03-05 16:11:36 -08002695 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002696 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002697 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002698 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07002699 self.handle.expect( self.mnPrompt )
Jon Halldac3eae2020-06-05 12:04:06 -07002700 if self.sudoRequired:
2701 sudoStr = "sudo "
2702 else:
2703 sudoStr = ""
Jon Hall7eb38402015-01-08 17:19:54 -08002704 self.handle.sendline(
Jon Halldac3eae2020-06-05 12:04:06 -07002705 "sh " + sudoStr + "tcpdump -n -i " +
2706 intf + " " + port + " -w " +
2707 filename.strip() + " &" )
Jon Hall7eb38402015-01-08 17:19:54 -08002708 self.handle.sendline( "" )
2709 i = self.handle.expect( [ 'No\ssuch\device',
2710 'listening\son',
2711 pexpect.TIMEOUT,
Jon Hallf6aeda22020-07-28 09:12:56 -07002712 self.mnPrompt ],
Jon Hall7eb38402015-01-08 17:19:54 -08002713 timeout=10 )
2714 main.log.warn( self.handle.before + self.handle.after )
2715 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07002716 self.handle.expect( self.mnPrompt )
admin2a9548d2014-06-17 14:08:07 -07002717 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002718 main.log.error(
2719 self.name +
2720 ": tcpdump - No such device exists. " +
2721 "tcpdump attempted on: " +
2722 intf )
admin2a9548d2014-06-17 14:08:07 -07002723 return main.FALSE
2724 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002725 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002726 return main.TRUE
2727 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002728 main.log.error(
2729 self.name +
2730 ": tcpdump command timed out! Check interface name," +
2731 " given interface was: " +
2732 intf )
admin2a9548d2014-06-17 14:08:07 -07002733 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002734 elif i == 3:
2735 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002736 return main.TRUE
2737 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002738 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002739 return main.FALSE
2740 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002741 main.log.error( self.name + ": EOF exception found" )
2742 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002743 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002744 except Exception:
2745 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002746 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002747
kelvin-onlabd3b64892015-01-20 13:26:24 -08002748 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002749 """
2750 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002751 try:
Jon Halldac3eae2020-06-05 12:04:06 -07002752 if self.sudoRequired:
2753 sudoStr = "sudo "
2754 else:
2755 sudoStr = ""
2756 self.handle.sendline( "sh " + sudoStr + " pkill tcpdump" )
Jon Hallf6aeda22020-07-28 09:12:56 -07002757 self.handle.expect( self.mnPrompt )
Jon Hall7eb38402015-01-08 17:19:54 -08002758 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07002759 self.handle.expect( self.mnPrompt )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002760 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002761 main.log.error( self.name + ": TIMEOUT exception found" )
2762 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002763 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002764 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002765 main.log.error( self.name + ": EOF exception found" )
2766 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002767 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002768 except Exception:
2769 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002770 main.cleanAndExit()
admin2a9548d2014-06-17 14:08:07 -07002771
Jon Halld80cc142015-07-06 13:36:05 -07002772 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002773 """
2774 Read ports from a Mininet switch.
2775
2776 Returns a json structure containing information about the
2777 ports of the given switch.
2778 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002779 try:
2780 response = self.getInterfaces( nodeName )
2781 # TODO: Sanity check on response. log if no such switch exists
2782 ports = []
2783 for line in response.split( "\n" ):
2784 if not line.startswith( "name=" ):
2785 continue
2786 portVars = {}
2787 for var in line.split( "," ):
2788 key, value = var.split( "=" )
2789 portVars[ key ] = value
2790 isUp = portVars.pop( 'enabled', "True" )
2791 isUp = "True" in isUp
2792 if verbose:
2793 main.log.info( "Reading switch port %s(%s)" %
2794 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2795 mac = portVars[ 'mac' ]
2796 if mac == 'None':
2797 mac = None
2798 ips = []
2799 ip = portVars[ 'ip' ]
2800 if ip == 'None':
2801 ip = None
2802 ips.append( ip )
2803 name = portVars[ 'name' ]
2804 if name == 'None':
2805 name = None
2806 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2807 if name == 'lo':
2808 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2809 else:
2810 portNo = re.search( portRe, name ).group( 'port' )
2811 ports.append( { 'of_port': portNo,
2812 'mac': str( mac ).replace( '\'', '' ),
2813 'name': name,
2814 'ips': ips,
2815 'enabled': isUp } )
2816 return ports
2817 except pexpect.EOF:
2818 main.log.error( self.name + ": EOF exception found" )
2819 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002820 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002821 except Exception:
2822 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002823 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002824
You Wangdb8cd0a2016-05-26 15:19:45 -07002825 def getOVSPorts( self, nodeName ):
2826 """
2827 Read ports from OVS by executing 'ovs-ofctl dump-ports-desc' command.
2828
2829 Returns a list of dictionaries containing information about each
2830 port of the given switch.
2831 """
2832 command = "sh ovs-ofctl dump-ports-desc " + str( nodeName )
2833 try:
2834 response = self.execute(
2835 cmd=command,
Jon Hallf6aeda22020-07-28 09:12:56 -07002836 prompt=self.mnPrompt,
You Wang7d14d642019-01-23 15:10:08 -08002837 timeout=10,
2838 logCmd=False )
You Wangdb8cd0a2016-05-26 15:19:45 -07002839 ports = []
2840 if response:
2841 for line in response.split( "\n" ):
2842 # Regex patterns to parse 'ovs-ofctl dump-ports-desc' output
2843 # Example port:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002844 # 1(s1-eth1): addr:ae:60:72:77:55:51
You Wangdb8cd0a2016-05-26 15:19:45 -07002845 pattern = "(?P<index>\d+)\((?P<name>[^-]+-eth(?P<port>\d+))\):\saddr:(?P<mac>([a-f0-9]{2}:){5}[a-f0-9]{2})"
2846 result = re.search( pattern, line )
2847 if result:
2848 index = result.group( 'index' )
2849 name = result.group( 'name' )
2850 # This port number is extracted from port name
2851 port = result.group( 'port' )
2852 mac = result.group( 'mac' )
2853 ports.append( { 'index': index,
2854 'name': name,
2855 'port': port,
2856 'mac': mac } )
2857 return ports
2858 except pexpect.EOF:
2859 main.log.error( self.name + ": EOF exception found" )
2860 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002861 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002862 except Exception:
2863 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002864 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07002865
Jon Halldac3eae2020-06-05 12:04:06 -07002866 def getSwitches( self, verbose=False, updateTimeout=1000, excludeNodes=[], switchRegex=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07002867 """
2868 Read switches from Mininet.
2869
2870 Returns a dictionary whose keys are the switch names and the value is
2871 a dictionary containing information about the switch.
You Wangb1665b52019-02-01 15:49:48 -08002872 If excludeNodes is specified, switches with names included in excludeNodes
2873 will be ingored.
Jon Hallafa8a472015-06-12 14:02:42 -07002874 """
Jon Halla22481b2015-07-28 17:46:01 -07002875 # NOTE: To support new Mininet switch classes, just append the new
2876 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002877
Jon Halla22481b2015-07-28 17:46:01 -07002878 # Regex patterns to parse 'dump' output
2879 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002880 # <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 -07002881 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002882 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2883 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2884 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
Jon Halldac3eae2020-06-05 12:04:06 -07002885 if not switchRegex:
2886 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2887 else:
2888 switchClasses = switchRegex
You Wang7d14d642019-01-23 15:10:08 -08002889 try:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002890 swRE = r"<(?P<class>" + switchClasses + r")" +\
2891 r"(?P<options>\{.*\})?\s" +\
2892 r"(?P<name>[^:]+)\:\s" +\
2893 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2894 r"\spid=(?P<pid>(\d)+)"
2895 # Update mn port info
Devin Lima7cfdbd2017-09-29 15:02:22 -07002896 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002897 output = {}
2898 dump = self.dump().split( "\n" )
2899 for line in dump:
2900 result = re.search( swRE, line, re.I )
2901 if result:
2902 name = result.group( 'name' )
You Wangb1665b52019-02-01 15:49:48 -08002903 if name in excludeNodes:
2904 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002905 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
2906 pid = result.group( 'pid' )
2907 swClass = result.group( 'class' )
2908 options = result.group( 'options' )
2909 if verbose:
2910 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2911 ports = self.getPorts( name )
2912 output[ name ] = { "dpid": dpid,
2913 "ports": ports,
2914 "swClass": swClass,
2915 "pid": pid,
2916 "options": options }
2917 return output
2918 except pexpect.EOF:
2919 main.log.error( self.name + ": EOF exception found" )
2920 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002921 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002922 except Exception:
2923 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002924 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07002925
You Wangd66de192018-04-30 17:30:12 -07002926 def getHosts( self, verbose=False, update=True, updateTimeout=1000,
Jon Hallab611372018-02-21 15:26:05 -08002927 hostClass=[ "Host", "DhcpClient", "Dhcp6Client", "DhcpServer", "Dhcp6Server", "DhcpRelay" ],
2928 getInterfaces=True ):
Jon Hallafa8a472015-06-12 14:02:42 -07002929 """
2930 Read hosts from Mininet.
You Wang53dba1e2018-02-02 17:45:44 -08002931 Optional:
2932 hostClass: it is used to match the class of the mininet host. It
2933 can be a string or a list of strings.
Jon Hallafa8a472015-06-12 14:02:42 -07002934 Returns a dictionary whose keys are the host names and the value is
2935 a dictionary containing information about the host.
2936 """
2937 # Regex patterns to parse dump output
2938 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002939 # <Host h1: pid=12725>
2940 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2941 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2942 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002943 # NOTE: Does not correctly match hosts with multi-links
2944 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2945 # FIXME: Fix that
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002946 try:
You Wang53dba1e2018-02-02 17:45:44 -08002947 if not isinstance( hostClass, types.ListType ):
2948 hostClass = [ str( hostClass ) ]
2949 classRE = "(" + "|".join([c for c in hostClass]) + ")"
Jon Hallab611372018-02-21 15:26:05 -08002950 ifaceRE = r"(?P<ifname>[^:]+)\:(?P<ip>[^\s,]+),?"
2951 ifacesRE = r"(?P<ifaces>[^:]+\:[^\s]+)"
2952 hostRE = r"" + classRE + "\s(?P<name>[^:]+)\:(" + ifacesRE + "*\spid=(?P<pid>[^>]+))"
You Wangd66de192018-04-30 17:30:12 -07002953 if update:
2954 # update mn port info
2955 self.update( updateTimeout )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002956 # Get mininet dump
2957 dump = self.dump().split( "\n" )
2958 hosts = {}
2959 for line in dump:
You Wang53dba1e2018-02-02 17:45:44 -08002960 result = re.search( hostRE, line )
2961 if result:
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002962 name = result.group( 'name' )
2963 interfaces = []
You Wang79f5c5b2018-03-14 11:10:44 -07002964 if getInterfaces:
2965 response = self.getInterfaces( name )
2966 # Populate interface info
2967 for line in response.split( "\n" ):
2968 if line.startswith( "name=" ):
2969 portVars = {}
2970 for var in line.split( "," ):
2971 key, value = var.split( "=" )
2972 portVars[ key ] = value
2973 isUp = portVars.pop( 'enabled', "True" )
2974 isUp = "True" in isUp
2975 if verbose:
2976 main.log.info( "Reading host port %s(%s)" %
2977 ( portVars[ 'name' ],
2978 portVars[ 'mac' ] ) )
2979 mac = portVars[ 'mac' ]
2980 if mac == 'None':
2981 mac = None
2982 ips = []
2983 ip = portVars[ 'ip' ]
2984 if ip == 'None':
2985 ip = None
2986 ips.append( ip )
2987 intfName = portVars[ 'name' ]
2988 if name == 'None':
2989 name = None
2990 interfaces.append( {
2991 "name": intfName,
2992 "ips": ips,
2993 "mac": str( mac ),
2994 "isUp": isUp } )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07002995 hosts[ name ] = { "interfaces": interfaces }
2996 return hosts
2997 except pexpect.EOF:
2998 main.log.error( self.name + ": EOF exception found" )
2999 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003000 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003001 except Exception:
3002 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003003 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003004
You Wang7d14d642019-01-23 15:10:08 -08003005 def getLinks( self, timeout=20, updateTimeout=1000, excludeNodes=[] ):
Jon Hallafa8a472015-06-12 14:02:42 -07003006 """
3007 Gathers information about current Mininet links. These links may not
3008 be up if one of the ports is down.
3009
3010 Returns a list of dictionaries with link endpoints.
3011
3012 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07003013 { 'node1': str( node1 name )
3014 'node2': str( node2 name )
3015 'port1': str( port1 of_port )
3016 'port2': str( port2 of_port ) }
You Wang7d14d642019-01-23 15:10:08 -08003017
You Wangb1665b52019-02-01 15:49:48 -08003018 If either node1 or node2 name matches any of the names sepcified in
3019 excludeNodes, the link will be excluded from the returned value
You Wang7d14d642019-01-23 15:10:08 -08003020
Jon Hallafa8a472015-06-12 14:02:42 -07003021 Note: The port number returned is the eth#, not necessarily the of_port
3022 number. In Mininet, for OVS switch, these should be the same. For
3023 hosts, this is just the eth#.
3024 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003025 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003026 self.update()
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003027 response = self.links( timeout=timeout ).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07003028
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003029 # Examples:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003030 # s1-eth3<->s2-eth1 (OK OK)
3031 # s13-eth3<->h27-eth0 (OK OK)
You Wang7d14d642019-01-23 15:10:08 -08003032 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d\.]+)\<\-\>" +\
3033 "(?P<node2>[\w]+)\-eth(?P<port2>[\d\.]+)"
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003034 links = []
3035 for line in response:
3036 match = re.search( linkRE, line )
3037 if match:
3038 node1 = match.group( 'node1' )
3039 node2 = match.group( 'node2' )
You Wangb1665b52019-02-01 15:49:48 -08003040 if any( node1 == node or node2 == node for node in excludeNodes ):
You Wang7d14d642019-01-23 15:10:08 -08003041 continue
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003042 port1 = match.group( 'port1' )
3043 port2 = match.group( 'port2' )
3044 links.append( { 'node1': node1,
3045 'node2': node2,
3046 'port1': port1,
3047 'port2': port2 } )
3048 return links
3049
3050 except pexpect.EOF:
3051 main.log.error( self.name + ": EOF exception found" )
3052 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003053 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003054 except Exception:
3055 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003056 main.cleanAndExit()
Jon Hallafa8a472015-06-12 14:02:42 -07003057
3058 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003059 """
3060 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07003061 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04003062
Jon Hallafa8a472015-06-12 14:02:42 -07003063 Dependencies:
3064 1. numpy - "sudo pip install numpy"
3065 """
3066 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04003067 # created sorted list of dpid's in MN and ONOS for comparison
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003068 try:
3069 mnDPIDs = []
3070 for swName, switch in switches.iteritems():
3071 mnDPIDs.append( switch[ 'dpid' ].lower() )
3072 mnDPIDs.sort()
3073 if switchesJson == "": # if rest call fails
3074 main.log.error(
3075 self.name +
3076 ".compareSwitches(): Empty JSON object given from ONOS" )
3077 return main.FALSE
3078 onos = switchesJson
3079 onosDPIDs = []
3080 for switch in onos:
3081 if switch[ 'available' ]:
3082 onosDPIDs.append(
3083 switch[ 'id' ].replace(
3084 ":",
Jon Halld80cc142015-07-06 13:36:05 -07003085 '' ).replace(
3086 "of",
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003087 '' ).lower() )
3088 onosDPIDs.sort()
Jon Hallafa8a472015-06-12 14:02:42 -07003089
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003090 if mnDPIDs != onosDPIDs:
3091 switchResults = main.FALSE
3092 main.log.error( "Switches in MN but not in ONOS:" )
3093 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
3094 main.log.error( str( list1 ) )
3095 main.log.error( "Switches in ONOS but not in MN:" )
3096 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
3097 main.log.error( str( list2 ) )
3098 else: # list of dpid's match in onos and mn
3099 switchResults = main.TRUE
3100 finalResults = switchResults
Jon Hall38481722014-11-04 16:50:05 -05003101
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003102 # FIXME: this does not look for extra ports in ONOS, only checks that
3103 # ONOS has what is in MN
3104 portsResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07003105
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003106 # PORTS
3107 for name, mnSwitch in switches.iteritems():
3108 mnPorts = []
3109 onosPorts = []
3110 switchResult = main.TRUE
3111 for port in mnSwitch[ 'ports' ]:
3112 if port[ 'enabled' ]:
3113 mnPorts.append( int( port[ 'of_port' ] ) )
3114 for onosSwitch in portsJson:
3115 if onosSwitch[ 'device' ][ 'available' ]:
3116 if onosSwitch[ 'device' ][ 'id' ].replace(
3117 ':',
3118 '' ).replace(
3119 "of",
3120 '' ) == mnSwitch[ 'dpid' ]:
3121 for port in onosSwitch[ 'ports' ]:
3122 if port[ 'isEnabled' ]:
Jeremy Ronquillob2ca25e2017-06-15 08:51:23 -07003123 if port[ 'port' ].lower() == 'local':
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003124 # onosPorts.append( 'local' )
3125 onosPorts.append( long( uint64( -2 ) ) )
3126 else:
3127 onosPorts.append( int( port[ 'port' ] ) )
3128 break
3129 mnPorts.sort( key=float )
3130 onosPorts.sort( key=float )
3131
3132 mnPortsLog = mnPorts
3133 onosPortsLog = onosPorts
3134 mnPorts = [ x for x in mnPorts ]
3135 onosPorts = [ x for x in onosPorts ]
3136
3137 # TODO: handle other reserved port numbers besides LOCAL
3138 # NOTE: Reserved ports
3139 # Local port: -2 in Openflow, ONOS shows 'local', we store as
3140 # long( uint64( -2 ) )
3141 for mnPort in mnPortsLog:
3142 if mnPort in onosPorts:
3143 # don't set results to true here as this is just one of
3144 # many checks and it might override a failure
3145 mnPorts.remove( mnPort )
3146 onosPorts.remove( mnPort )
3147
3148 # NOTE: OVS reports this as down since there is no link
3149 # So ignoring these for now
3150 # TODO: Come up with a better way of handling these
3151 if 65534 in mnPorts:
3152 mnPorts.remove( 65534 )
3153 if long( uint64( -2 ) ) in onosPorts:
3154 onosPorts.remove( long( uint64( -2 ) ) )
3155 if len( mnPorts ): # the ports of this switch don't match
3156 switchResult = main.FALSE
3157 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
3158 if len( onosPorts ): # the ports of this switch don't match
3159 switchResult = main.FALSE
3160 main.log.warn(
3161 "Ports in ONOS but not MN: " +
3162 str( onosPorts ) )
3163 if switchResult == main.FALSE:
3164 main.log.error(
3165 "The list of ports for switch %s(%s) does not match:" %
3166 ( name, mnSwitch[ 'dpid' ] ) )
3167 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
3168 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
3169 portsResults = portsResults and switchResult
3170 finalResults = finalResults and portsResults
3171 return finalResults
3172 except pexpect.EOF:
3173 main.log.error( self.name + ": EOF exception found" )
3174 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003175 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003176 except Exception:
3177 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003178 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003179
Jon Hallafa8a472015-06-12 14:02:42 -07003180 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08003181 """
3182 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08003183 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04003184
Jon Hallafa8a472015-06-12 14:02:42 -07003185 """
Jon Hall7eb38402015-01-08 17:19:54 -08003186 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08003187 # ONOS has what is in MN
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003188 try:
3189 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04003190
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003191 mnLinks = []
3192 for l in links:
3193 try:
3194 node1 = switches[ l[ 'node1' ] ]
3195 node2 = switches[ l[ 'node2' ] ]
3196 enabled = True
3197 for port in node1[ 'ports' ]:
3198 if port[ 'of_port' ] == l[ 'port1' ]:
3199 enabled = enabled and port[ 'enabled' ]
3200 for port in node2[ 'ports' ]:
3201 if port[ 'of_port' ] == l[ 'port2' ]:
3202 enabled = enabled and port[ 'enabled' ]
3203 if enabled:
3204 mnLinks.append( l )
3205 except KeyError:
Jon Hall72cf1dc2014-10-20 21:04:50 -04003206 pass
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003207 if 2 * len( mnLinks ) == len( onos ):
3208 linkResults = main.TRUE
3209 else:
3210 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07003211 main.log.error(
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003212 "Mininet has " + str( len( mnLinks ) ) +
3213 " bidirectional links and ONOS has " +
3214 str( len( onos ) ) + " unidirectional links" )
3215
3216 # iterate through MN links and check if an ONOS link exists in
3217 # both directions
3218 for link in mnLinks:
3219 # TODO: Find a more efficient search method
3220 node1 = None
3221 port1 = None
3222 node2 = None
3223 port2 = None
3224 firstDir = main.FALSE
3225 secondDir = main.FALSE
3226 for swName, switch in switches.iteritems():
3227 if swName == link[ 'node1' ]:
3228 node1 = switch[ 'dpid' ]
3229 for port in switch[ 'ports' ]:
3230 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
3231 port1 = port[ 'of_port' ]
3232 if node1 is not None and node2 is not None:
3233 break
3234 if swName == link[ 'node2' ]:
3235 node2 = switch[ 'dpid' ]
3236 for port in switch[ 'ports' ]:
3237 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
3238 port2 = port[ 'of_port' ]
3239 if node1 is not None and node2 is not None:
3240 break
3241
3242 for onosLink in onos:
3243 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
3244 ":", '' ).replace( "of", '' )
3245 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
3246 ":", '' ).replace( "of", '' )
3247 onosPort1 = onosLink[ 'src' ][ 'port' ]
3248 onosPort2 = onosLink[ 'dst' ][ 'port' ]
3249
3250 # check onos link from node1 to node2
3251 if str( onosNode1 ) == str( node1 ) and str(
3252 onosNode2 ) == str( node2 ):
3253 if int( onosPort1 ) == int( port1 ) and int(
3254 onosPort2 ) == int( port2 ):
3255 firstDir = main.TRUE
3256 else:
Jon Hallab611372018-02-21 15:26:05 -08003257 # The right switches, but wrong ports, could be
3258 # another link between these devices, or onos
3259 # discovered the links incorrectly
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003260 main.log.warn(
3261 'The port numbers do not match for ' +
3262 str( link ) +
3263 ' between ONOS and MN. When checking ONOS for ' +
3264 'link %s/%s -> %s/%s' %
3265 ( node1, port1, node2, port2 ) +
3266 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallab611372018-02-21 15:26:05 -08003267 ( onosNode1, onosPort1, onosNode2, onosPort2 ) +
3268 '. This could be another link between these devices' +
3269 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003270
3271 # check onos link from node2 to node1
3272 elif ( str( onosNode1 ) == str( node2 ) and
3273 str( onosNode2 ) == str( node1 ) ):
3274 if ( int( onosPort1 ) == int( port2 )
3275 and int( onosPort2 ) == int( port1 ) ):
3276 secondDir = 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 ( onosNode2, onosPort2, onosNode1, onosPort1 ) +
3289 '. This could be another link between these devices' +
3290 ' or a incorrectly discoved link' )
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003291 else: # this is not the link you're looking for
3292 pass
3293 if not firstDir:
3294 main.log.error(
3295 'ONOS does not have the link %s/%s -> %s/%s' %
3296 ( node1, port1, node2, port2 ) )
3297 if not secondDir:
3298 main.log.error(
3299 'ONOS does not have the link %s/%s -> %s/%s' %
3300 ( node2, port2, node1, port1 ) )
3301 linkResults = linkResults and firstDir and secondDir
3302 return linkResults
3303 except pexpect.EOF:
3304 main.log.error( self.name + ": EOF exception found" )
3305 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003306 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003307 except Exception:
3308 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003309 main.cleanAndExit()
Jon Hall72cf1dc2014-10-20 21:04:50 -04003310
Jon Hallafa8a472015-06-12 14:02:42 -07003311 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08003312 """
Jon Hallafa8a472015-06-12 14:02:42 -07003313 Compare mn and onos Hosts.
3314 Since Mininet hosts are quiet, ONOS will only know of them when they
3315 speak. For this reason, we will only check that the hosts in ONOS
3316 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08003317
Jon Hallafa8a472015-06-12 14:02:42 -07003318 Arguments:
3319 hostsJson: parsed json object from the onos hosts api
3320 Returns:
3321 """
Jon Hallff6b4b22015-02-23 09:25:15 -08003322 import json
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003323 try:
3324 hostResults = main.TRUE
3325 for onosHost in hostsJson:
3326 onosMAC = onosHost[ 'mac' ].lower()
3327 match = False
3328 for mnHost, info in hosts.iteritems():
3329 for mnIntf in info[ 'interfaces' ]:
3330 if onosMAC == mnIntf[ 'mac' ].lower():
3331 match = True
3332 for ip in mnIntf[ 'ips' ]:
3333 if ip in onosHost[ 'ipAddresses' ]:
3334 pass # all is well
3335 else:
3336 # misssing ip
3337 main.log.error( "ONOS host " +
3338 onosHost[ 'id' ] +
3339 " has a different IP(" +
3340 str( onosHost[ 'ipAddresses' ] ) +
3341 ") than the Mininet host(" +
3342 str( ip ) +
3343 ")." )
3344 output = json.dumps(
3345 onosHost,
3346 sort_keys=True,
3347 indent=4,
3348 separators=( ',', ': ' ) )
3349 main.log.info( output )
3350 hostResults = main.FALSE
3351 if not match:
3352 hostResults = main.FALSE
3353 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
3354 "corresponding Mininet host." )
3355 output = json.dumps( onosHost,
3356 sort_keys=True,
3357 indent=4,
3358 separators=( ',', ': ' ) )
3359 main.log.info( output )
3360 return hostResults
3361 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003362 main.log.error( self.name + ": EOF exception found" )
3363 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003364 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003365 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003366 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003367 main.cleanAndExit()
Jon Hallff6b4b22015-02-23 09:25:15 -08003368
You Wangd66de192018-04-30 17:30:12 -07003369 def verifyHostIp( self, hostList=[], prefix="", update=True ):
You Wang53dba1e2018-02-02 17:45:44 -08003370 """
3371 Description:
3372 Verify that all hosts have IP address assigned to them
3373 Optional:
3374 hostList: If specified, verifications only happen to the hosts
3375 in hostList
3376 prefix: at least one of the ip address assigned to the host
3377 needs to have the specified prefix
You Wangd66de192018-04-30 17:30:12 -07003378 update: Update Mininet information if True
You Wang53dba1e2018-02-02 17:45:44 -08003379 Returns:
3380 main.TRUE if all hosts have specific IP address assigned;
3381 main.FALSE otherwise
3382 """
3383 try:
You Wangd66de192018-04-30 17:30:12 -07003384 hosts = self.getHosts( update=update, getInterfaces=False )
You Wang53dba1e2018-02-02 17:45:44 -08003385 if not hostList:
3386 hostList = hosts.keys()
3387 for hostName in hosts.keys():
3388 if hostName not in hostList:
3389 continue
3390 ipList = []
3391 self.handle.sendline( str( hostName ) + " ip a" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003392 self.handle.expect( self.mnPrompt )
You Wang53dba1e2018-02-02 17:45:44 -08003393 ipa = self.handle.before
3394 ipv4Pattern = r'inet ((?:[0-9]{1,3}\.){3}[0-9]{1,3})/'
3395 ipList += re.findall( ipv4Pattern, ipa )
3396 # It's tricky to make regex for IPv6 addresses and this one is simplified
3397 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})/'
3398 ipList += re.findall( ipv6Pattern, ipa )
3399 main.log.debug( self.name + ": IP list on host " + str( hostName ) + ": " + str( ipList ) )
3400 if not ipList:
3401 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostName ) )
3402 else:
3403 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
3404 main.log.warn( self.name + ": None of the IPs on host " + str( hostName ) + " has prefix " + str( prefix ) )
3405 else:
3406 main.log.debug( self.name + ": Found matching IP on host " + str( hostName ) )
3407 hostList.remove( hostName )
3408 return main.FALSE if hostList else main.TRUE
3409 except KeyError:
3410 main.log.exception( self.name + ": host data not as expected: " + hosts )
3411 return None
3412 except pexpect.EOF:
3413 main.log.error( self.name + ": EOF exception found" )
3414 main.log.error( self.name + ": " + self.handle.before )
3415 main.cleanAndExit()
3416 except Exception:
3417 main.log.exception( self.name + ": Uncaught exception" )
3418 return None
3419
Jon Hallafa8a472015-06-12 14:02:42 -07003420 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08003421 """
3422 Returns a list of all hosts
3423 Don't ask questions just use it"""
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003424 try:
3425 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003426 self.handle.expect( self.mnPrompt )
Jon Hall72cf1dc2014-10-20 21:04:50 -04003427
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003428 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003429 self.handle.expect( self.mnPrompt )
admin2a9548d2014-06-17 14:08:07 -07003430
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003431 handlePy = self.handle.before
3432 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3433 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07003434
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003435 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003436 self.handle.expect( self.mnPrompt )
admin2a9548d2014-06-17 14:08:07 -07003437
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003438 hostStr = handlePy.replace( "]", "" )
3439 hostStr = hostStr.replace( "'", "" )
3440 hostStr = hostStr.replace( "[", "" )
3441 hostStr = hostStr.replace( " ", "" )
3442 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04003443
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003444 return hostList
3445 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003446 main.log.error( self.name + ": TIMEOUT exception found" )
3447 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003448 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003449 except pexpect.EOF:
3450 main.log.error( self.name + ": EOF exception found" )
3451 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003452 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003453 except Exception:
3454 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003455 main.cleanAndExit()
adminbae64d82013-08-01 10:50:15 -07003456
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003457 def getSwitch( self ):
3458 """
3459 Returns a list of all switches
3460 Again, don't ask question just use it...
3461 """
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003462 try:
3463 # get host list...
3464 hostList = self.getHosts()
3465 # Make host set
3466 hostSet = set( hostList )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003467
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003468 # Getting all the nodes in mininet
3469 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003470 self.handle.expect( self.mnPrompt )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003471
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003472 self.handle.sendline( "py [ node.name for node in net.values() ]" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003473 self.handle.expect( self.mnPrompt )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003474
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003475 handlePy = self.handle.before
3476 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
3477 handlePy = handlePy.rstrip()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003478
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003479 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003480 self.handle.expect( self.mnPrompt )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003481
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003482 nodesStr = handlePy.replace( "]", "" )
3483 nodesStr = nodesStr.replace( "'", "" )
3484 nodesStr = nodesStr.replace( "[", "" )
3485 nodesStr = nodesStr.replace( " ", "" )
3486 nodesList = nodesStr.split( "," )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003487
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003488 nodesSet = set( nodesList )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003489 # discarding default controller(s) node
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003490 nodesSet.discard( 'c0' )
3491 nodesSet.discard( 'c1' )
3492 nodesSet.discard( 'c2' )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003493
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003494 switchSet = nodesSet - hostSet
3495 switchList = list( switchSet )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003496
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003497 return switchList
3498 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003499 main.log.error( self.name + ": TIMEOUT exception found" )
3500 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003501 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003502 except pexpect.EOF:
3503 main.log.error( self.name + ": EOF exception found" )
3504 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003505 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003506 except Exception:
3507 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003508 main.cleanAndExit()
kelvin-onlabfa6ada82015-06-11 13:06:24 -07003509
You Wang7d14d642019-01-23 15:10:08 -08003510 def getGraphDict( self, timeout=60, useId=True, includeHost=False,
You Wangb1665b52019-02-01 15:49:48 -08003511 excludeNodes=[] ):
You Wangdb8cd0a2016-05-26 15:19:45 -07003512 """
3513 Return a dictionary which describes the latest Mininet topology data as a
3514 graph.
3515 An example of the dictionary:
3516 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
3517 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
3518 Each vertex should at least have an 'edges' attribute which describes the
3519 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003520 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07003521 list of attributes.
3522 An example of the edges dictionary:
3523 'edges': { vertex2: { 'port': ..., 'weight': ... },
3524 vertex3: { 'port': ..., 'weight': ... } }
3525 If useId == True, dpid/mac will be used instead of names to identify
3526 vertices, which is helpful when e.g. comparing Mininet topology with ONOS
3527 topology.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003528 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07003529 in topology data.
You Wangb1665b52019-02-01 15:49:48 -08003530 excludeNodes will be passed to getSwitches and getLinks methods to exclude
3531 unexpected switches and links.
You Wangdb8cd0a2016-05-26 15:19:45 -07003532 Note that link or switch that are brought down by 'link x x down' or 'switch
3533 x down' commands still show in the output of Mininet CLI commands such as
3534 'links', 'dump', etc. Thus, to ensure the correctness of this function, it is
3535 recommended to use delLink() or delSwitch functions to simulate link/switch
3536 down, and addLink() or addSwitch to add them back.
3537 """
3538 graphDict = {}
3539 try:
You Wang7d14d642019-01-23 15:10:08 -08003540 links = self.getLinks( timeout=timeout, excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003541 portDict = {}
You Wangb1665b52019-02-01 15:49:48 -08003542 switches = self.getSwitches( excludeNodes=excludeNodes )
You Wangdb8cd0a2016-05-26 15:19:45 -07003543 if includeHost:
3544 hosts = self.getHosts()
3545 for link in links:
You Wangb1665b52019-02-01 15:49:48 -08003546 # TODO: support 'includeHost' argument
You Wangdb8cd0a2016-05-26 15:19:45 -07003547 if link[ 'node1' ].startswith( 'h' ) or link[ 'node2' ].startswith( 'h' ):
3548 continue
3549 nodeName1 = link[ 'node1' ]
3550 nodeName2 = link[ 'node2' ]
You Wang7d14d642019-01-23 15:10:08 -08003551 if not self.getOVSPorts( nodeName1 ) or not self.getOVSPorts( nodeName2 ):
3552 # The device is probably offline
3553 continue
You Wangdb8cd0a2016-05-26 15:19:45 -07003554 port1 = link[ 'port1' ]
3555 port2 = link[ 'port2' ]
3556 # Loop for two nodes
3557 for i in range( 2 ):
3558 # Get port index from OVS
3559 # The index extracted from port name may be inconsistent with ONOS
3560 portIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003561 if nodeName1 not in portDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003562 portList = self.getOVSPorts( nodeName1 )
3563 if len( portList ) == 0:
3564 main.log.warn( self.name + ": No port found on switch " + nodeName1 )
3565 return None
3566 portDict[ nodeName1 ] = portList
3567 for port in portDict[ nodeName1 ]:
3568 if port[ 'port' ] == port1:
3569 portIndex = port[ 'index' ]
3570 break
3571 if portIndex == -1:
3572 main.log.warn( self.name + ": Cannot find port index for interface {}-eth{}".format( nodeName1, port1 ) )
3573 return None
3574 if useId:
3575 node1 = 'of:' + str( switches[ nodeName1 ][ 'dpid' ] )
3576 node2 = 'of:' + str( switches[ nodeName2 ][ 'dpid' ] )
3577 else:
3578 node1 = nodeName1
3579 node2 = nodeName2
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003580 if node1 not in graphDict.keys():
You Wangdb8cd0a2016-05-26 15:19:45 -07003581 if useId:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003582 graphDict[ node1 ] = { 'edges': {},
3583 'dpid': switches[ nodeName1 ][ 'dpid' ],
3584 'name': nodeName1,
3585 'ports': switches[ nodeName1 ][ 'ports' ],
3586 'swClass': switches[ nodeName1 ][ 'swClass' ],
3587 'pid': switches[ nodeName1 ][ 'pid' ],
3588 'options': switches[ nodeName1 ][ 'options' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07003589 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003590 graphDict[ node1 ] = { 'edges': {} }
You Wangdb8cd0a2016-05-26 15:19:45 -07003591 else:
3592 # Assert node2 is not connected to any current links of node1
You Wang7d14d642019-01-23 15:10:08 -08003593 # assert node2 not in graphDict[ node1 ][ 'edges' ].keys()
3594 pass
3595 for port in switches[ nodeName1 ][ 'ports' ]:
3596 if port[ 'of_port' ] == str( portIndex ):
3597 # Use -1 as index for disabled port
You Wangb1665b52019-02-01 15:49:48 -08003598 if port[ 'enabled' ]:
You Wang7d14d642019-01-23 15:10:08 -08003599 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': portIndex }
3600 else:
3601 graphDict[ node1 ][ 'edges' ][ node2 ] = { 'port': -1 }
You Wangdb8cd0a2016-05-26 15:19:45 -07003602 # Swap two nodes/ports
3603 nodeName1, nodeName2 = nodeName2, nodeName1
3604 port1, port2 = port2, port1
You Wang7d14d642019-01-23 15:10:08 -08003605 # Remove links with disabled ports
3606 linksToRemove = []
3607 for node, edges in graphDict.items():
3608 for neighbor, port in edges[ 'edges' ].items():
3609 if port[ 'port' ] == -1:
3610 linksToRemove.append( ( node, neighbor ) )
3611 for node1, node2 in linksToRemove:
3612 for i in range( 2 ):
3613 if graphDict.get( node1 )[ 'edges' ].get( node2 ):
3614 graphDict[ node1 ][ 'edges' ].pop( node2 )
3615 node1, node2 = node2, node1
You Wangdb8cd0a2016-05-26 15:19:45 -07003616 return graphDict
3617 except KeyError:
3618 main.log.exception( self.name + ": KeyError exception found" )
3619 return None
3620 except AssertionError:
3621 main.log.exception( self.name + ": AssertionError exception found" )
3622 return None
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003623 except pexpect.EOF:
3624 main.log.error( self.name + ": EOF exception found" )
3625 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003626 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07003627 except Exception:
3628 main.log.exception( self.name + ": Uncaught exception" )
3629 return None
3630
Devin Lima7cfdbd2017-09-29 15:02:22 -07003631 def update( self, timeout=1000 ):
Jon Hall7eb38402015-01-08 17:19:54 -08003632 """
3633 updates the port address and status information for
3634 each port in mn"""
Jon Hallefbd9792015-03-05 16:11:36 -08003635 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05003636 try:
Jon Hall7eb38402015-01-08 17:19:54 -08003637 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003638 self.handle.expect( self.mnPrompt )
Jon Hall38481722014-11-04 16:50:05 -05003639
Jon Hall43060f62020-06-23 13:13:33 -07003640 # If update command isn't available, do it manually
Jon Hall7eb38402015-01-08 17:19:54 -08003641 self.handle.sendline( "update" )
Jon Hall43060f62020-06-23 13:13:33 -07003642 self.handle.expect( "update" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003643 i = self.handle.expect( [ "Unknown command: update", self.mnPrompt ], timeout )
Jon Hall43060f62020-06-23 13:13:33 -07003644 if i == 0:
3645 main.log.debug( self.handle.before + self.handle.after )
3646 main.log.warn( "Mininet cli does not have update command, attempting to update interfaces without it" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003647 self.handle.expect( self.mnPrompt )
Jon Hall43060f62020-06-23 13:13:33 -07003648 self.handle.sendline( "px [i.updateAddr() for h in net.hosts for i in h.intfs.values() ] " )
Jon Hallf6aeda22020-07-28 09:12:56 -07003649 self.handle.expect( self.mnPrompt, timeout )
Jon Hall43060f62020-06-23 13:13:33 -07003650 self.handle.sendline( "px [i.updateAddr() for s in net.switches for i in h.intfs.values() ] " )
Jon Hallf6aeda22020-07-28 09:12:56 -07003651 self.handle.expect( self.mnPrompt, timeout )
Jon Hall38481722014-11-04 16:50:05 -05003652
Jon Hall7eb38402015-01-08 17:19:54 -08003653 self.handle.sendline( "" )
Jon Hallf6aeda22020-07-28 09:12:56 -07003654 self.handle.expect( self.mnPrompt )
Jon Hall38481722014-11-04 16:50:05 -05003655
Jon Hallb1290e82014-11-18 16:17:48 -05003656 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003657 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003658 main.log.error( self.name + ": TIMEOUT exception found" )
3659 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003660 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003661 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08003662 main.log.error( self.name + ": EOF exception found" )
3663 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003664 main.cleanAndExit()
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003665 except Exception:
3666 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003667 main.cleanAndExit()
Jon Hallb1290e82014-11-18 16:17:48 -05003668
Jon Halld80cc142015-07-06 13:36:05 -07003669 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07003670 """
3671 Add vlan tag to a host.
3672 Dependencies:
3673 This class depends on the "vlan" package
3674 $ sudo apt-get install vlan
3675 Configuration:
3676 Load the 8021q module into the kernel
3677 $sudo modprobe 8021q
3678
3679 To make this setup permanent:
3680 $ sudo su -c 'echo "8021q" >> /etc/modules'
3681 """
3682 if self.handle:
3683 try:
Jon Halld80cc142015-07-06 13:36:05 -07003684 # get the ip address of the host
3685 main.log.info( "Get the ip address of the host" )
3686 ipaddr = self.getIPAddress( host )
3687 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003688
Jon Halld80cc142015-07-06 13:36:05 -07003689 # remove IP from interface intf
3690 # Ex: h1 ifconfig h1-eth0 inet 0
3691 main.log.info( "Remove IP from interface " )
3692 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3693 self.handle.sendline( cmd2 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003694 self.handle.expect( self.mnPrompt )
Jon Halld80cc142015-07-06 13:36:05 -07003695 response = self.handle.before
3696 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003697
Jon Halld80cc142015-07-06 13:36:05 -07003698 # create VLAN interface
3699 # Ex: h1 vconfig add h1-eth0 100
3700 main.log.info( "Create Vlan" )
3701 cmd3 = host + " vconfig add " + intf + " " + vlan
3702 self.handle.sendline( cmd3 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003703 self.handle.expect( self.mnPrompt )
Jon Halld80cc142015-07-06 13:36:05 -07003704 response = self.handle.before
3705 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003706
Jon Halld80cc142015-07-06 13:36:05 -07003707 # assign the host's IP to the VLAN interface
3708 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3709 main.log.info( "Assign the host IP to the vlan interface" )
3710 vintf = intf + "." + vlan
3711 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3712 self.handle.sendline( cmd4 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003713 self.handle.expect( self.mnPrompt )
Jon Halld80cc142015-07-06 13:36:05 -07003714 response = self.handle.before
3715 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003716
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003717 # update Mininet node variables
3718 main.log.info( "Update Mininet node variables" )
3719 cmd5 = "px %s.defaultIntf().name='%s'" % ( host, vintf )
3720 self.handle.sendline( cmd5 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003721 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003722 response = self.handle.before
3723 main.log.info( "====> %s ", response )
3724
3725 cmd6 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, vintf, host )
3726 self.handle.sendline( cmd6 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003727 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003728 response = self.handle.before
3729 main.log.info( "====> %s ", response )
3730
3731 return main.TRUE
3732 except pexpect.TIMEOUT:
3733 main.log.error( self.name + ": TIMEOUT exception found" )
3734 main.log.error( self.name + ": " + self.handle.before )
3735 main.cleanAndExit()
3736 except pexpect.EOF:
3737 main.log.error( self.name + ": EOF exception found" )
3738 main.log.error( self.name + ": " + self.handle.before )
3739 return main.FALSE
3740 except Exception:
3741 main.log.exception( self.name + ": Uncaught exception!" )
3742 return main.FALSE
3743
3744 def removeVLAN( self, host, intf ):
3745 """
3746 Remove vlan tag from a host.
3747 Dependencies:
3748 This class depends on the "vlan" package
3749 $ sudo apt-get install vlan
3750 Configuration:
3751 Load the 8021q module into the kernel
3752 $sudo modprobe 8021q
3753
3754 To make this setup permanent:
3755 $ sudo su -c 'echo "8021q" >> /etc/modules'
3756 """
3757 if self.handle:
3758 try:
3759 # get the ip address of the host
3760 main.log.info( "Get the ip address of the host" )
3761 ipaddr = self.getIPAddress( host )
3762
3763 # remove VLAN interface
3764 # Ex: h1 vconfig rem h1-eth0.100
3765 main.log.info( "Remove Vlan interface" )
3766 cmd2 = host + " vconfig rem " + intf
3767 self.handle.sendline( cmd2 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003768 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003769 response = self.handle.before
3770 main.log.info( "====> %s ", response )
3771
3772 # assign the host's IP to the original interface
3773 # Ex: h1 ifconfig h1-eth0 inet 10.0.0.1
3774 main.log.info( "Assign the host IP to the original interface" )
3775 original_intf = intf.split(".")[0]
3776 cmd3 = host + " ifconfig " + original_intf + " " + " inet " + ipaddr
3777 self.handle.sendline( cmd3 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003778 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003779 response = self.handle.before
3780 main.log.info( "====> %s ", response )
3781
3782 # update Mininet node variables
3783 cmd4 = "px %s.defaultIntf().name='%s'" % ( host, original_intf )
3784 self.handle.sendline( cmd4 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003785 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003786 response = self.handle.before
3787 main.log.info( "====> %s ", response )
3788
3789 cmd5 = "px %s.nameToIntf['%s']=%s.defaultIntf()" % ( host, original_intf, host )
3790 self.handle.sendline( cmd5 )
Jon Hallf6aeda22020-07-28 09:12:56 -07003791 self.handle.expect( self.mnPrompt )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08003792 response = self.handle.before
3793 main.log.info( "====> %s ", response )
3794
kaouthera3f13ca22015-05-05 15:01:41 -07003795 return main.TRUE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003796 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003797 main.log.error( self.name + ": TIMEOUT exception found" )
3798 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003799 main.cleanAndExit()
kaouthera3f13ca22015-05-05 15:01:41 -07003800 except pexpect.EOF:
3801 main.log.error( self.name + ": EOF exception found" )
3802 main.log.error( self.name + ": " + self.handle.before )
3803 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003804 except Exception:
3805 main.log.exception( self.name + ": Uncaught exception!" )
3806 return main.FALSE
kaouthera3f13ca22015-05-05 15:01:41 -07003807
Jon Hall43060f62020-06-23 13:13:33 -07003808 def createHostComponent( self, name, execDir=None, hostHome=None ):
Jon Hall892818c2015-10-20 17:58:34 -07003809 """
3810 Creates a new mininet cli component with the same parameters as self.
3811 This new component is intended to be used to login to the hosts created
3812 by mininet.
3813
3814 Arguments:
3815 name - The string of the name of this component. The new component
3816 will be assigned to main.<name> .
3817 In addition, main.<name>.name = str( name )
3818 """
3819 try:
3820 # look to see if this component already exists
3821 getattr( main, name )
3822 except AttributeError:
3823 # namespace is clear, creating component
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003824 main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
3825 main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
Jon Hall43060f62020-06-23 13:13:33 -07003826 component = main.componentInit( name )
3827 if execDir is not None:
3828 component.mExecDir = execDir
3829 else:
3830 component.mExecDir = self.mExecDir
3831
3832 if hostHome is not None:
3833 component.hostHome = hostHome
3834 else:
3835 component.hostHome = self.hostHome
3836 component.hostPrompt = self.hostPrompt
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003837 except pexpect.EOF:
3838 main.log.error( self.name + ": EOF exception found" )
3839 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003840 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003841 except Exception:
3842 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003843 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003844 else:
3845 # namespace is not clear!
3846 main.log.error( name + " component already exists!" )
3847 # FIXME: Should we exit here?
Devin Lim44075962017-08-11 10:56:37 -07003848 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003849
3850 def removeHostComponent( self, name ):
3851 """
3852 Remove host component
3853 Arguments:
3854 name - The string of the name of the component to delete.
3855 """
3856 try:
3857 # Get host component
3858 component = getattr( main, name )
3859 except AttributeError:
3860 main.log.error( "Component " + name + " does not exist." )
3861 return
3862 try:
3863 # Disconnect from component
3864 component.disconnect()
You Wangf32c6ed2018-08-23 17:10:22 -07003865 component.close_log_handles()
Jon Hall892818c2015-10-20 17:58:34 -07003866 # Delete component
3867 delattr( main, name )
3868 # Delete component from ComponentDictionary
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003869 del( main.componentDictionary[ name ] )
You Wangf32c6ed2018-08-23 17:10:22 -07003870 except StandardError:
3871 self.log.exception( "Exception while closing log files for " + name )
3872 return main.FALSE
Ming Yan Shu404f7e72016-07-22 14:37:03 -07003873 except pexpect.EOF:
3874 main.log.error( self.name + ": EOF exception found" )
3875 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003876 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003877 except Exception:
3878 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003879 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003880
Jon Hall43060f62020-06-23 13:13:33 -07003881 def startHostCli( self, host=None, execDir=None, hostHome=None ):
Jon Hall892818c2015-10-20 17:58:34 -07003882 """
3883 Use the mininet m utility to connect to the host's cli
Jon Hall43060f62020-06-23 13:13:33 -07003884 mnexec tries to cd to cwd after it connects to the host. If execDir
3885 is set, this will change cwd to execDir before executing m.
3886 If hostHome is set, the function will export the value to the HOME
3887 environment variable.
Jon Hall892818c2015-10-20 17:58:34 -07003888 """
3889 # These are fields that can be used by scapy packets. Initialized to None
3890 self.hostIp = None
3891 self.hostMac = None
Jon Hall43060f62020-06-23 13:13:33 -07003892 if execDir is not None:
3893 self.mExecDir = execDir
3894 if hostHome is not None:
3895 self.hostHome = hostHome
Jon Hall892818c2015-10-20 17:58:34 -07003896 try:
3897 if not host:
3898 host = self.name
Jon Hall43060f62020-06-23 13:13:33 -07003899 if self.mExecDir:
3900 self.handle.sendline( "cd %s" % self.mExecDir )
3901 self.handle.expect( self.prompt )
3902
Jon Hall892818c2015-10-20 17:58:34 -07003903 self.handle.sendline( self.home + "/util/m " + host )
Jon Hall43060f62020-06-23 13:13:33 -07003904 if self.hostHome:
3905 self.handle.sendline( "export HOME=%s" % self.hostHome )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -07003906 self.handle.sendline( "cd" )
3907 self.handle.expect( self.hostPrompt )
3908 self.handle.sendline( "" )
Jon Hall892818c2015-10-20 17:58:34 -07003909 self.handle.expect( self.hostPrompt )
3910 return main.TRUE
3911 except pexpect.TIMEOUT:
3912 main.log.exception( self.name + ": Command timed out" )
Jon Hall43060f62020-06-23 13:13:33 -07003913 main.log.debug( self.handle.before )
Jon Hall892818c2015-10-20 17:58:34 -07003914 return main.FALSE
3915 except pexpect.EOF:
3916 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003917 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003918 except Exception:
3919 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003920 main.cleanAndExit()
Jon Hall892818c2015-10-20 17:58:34 -07003921
YPZhang801d46d2016-08-08 13:26:28 -07003922 def changeInterfaceStatus( self, devicename, intf, status ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003923 '''
3924
YPZhang801d46d2016-08-08 13:26:28 -07003925 Args:
3926 devicename: switch name
3927 intf: port name on switch
3928 status: up or down
3929
3930 Returns: boolean to show success change status
3931
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003932 '''
YPZhang801d46d2016-08-08 13:26:28 -07003933 if status == "down" or status == "up":
3934 try:
3935 cmd = devicename + " ifconfig " + intf + " " + status
3936 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07003937 self.handle.expect( self.mnPrompt )
YPZhang801d46d2016-08-08 13:26:28 -07003938 return main.TRUE
3939 except pexpect.TIMEOUT:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003940 main.log.exception( self.name + ": Command timed out" )
YPZhang801d46d2016-08-08 13:26:28 -07003941 return main.FALSE
3942 except pexpect.EOF:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003943 main.log.exception( self.name + ": connection closed." )
Devin Lim44075962017-08-11 10:56:37 -07003944 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003945 except TypeError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003946 main.log.exception( self.name + ": TypeError" )
Devin Lim44075962017-08-11 10:56:37 -07003947 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003948 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003949 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003950 main.cleanAndExit()
YPZhang801d46d2016-08-08 13:26:28 -07003951 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003952 main.log.warn( "Interface status should be up or down!" )
YPZhang801d46d2016-08-08 13:26:28 -07003953 return main.FALSE
3954
You Wang6e5b48e2018-07-23 16:17:38 -07003955 def moveHost( self, host, oldSw, newSw, macAddr=None, prefixLen=64, ipv6=False, intfSuffix="eth1", vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003956 """
You Wang6e5b48e2018-07-23 16:17:38 -07003957 Moves a host from one switch to another on the fly
3958 Optional:
3959 macAddr: when specified, change MAC address of the host interface to specified MAC address.
3960 prefixLen: length of the host IP prefix
3961 ipv6: move an IPv6 host if True
3962 intfSuffix: suffix of the new interface after host movement
3963 vlan: vlan ID of the host. Use None for non-vlan host
3964 Note: The intf between host and oldSw when detached
3965 using detach(), will still show up in the 'net'
3966 cmd, because switch.detach() doesn't affect switch.intfs[]
3967 ( which is correct behavior since the interfaces
3968 haven't moved ).
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003969 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07003970 if self.handle:
3971 try:
You Wang6e5b48e2018-07-23 16:17:38 -07003972 newIntf = "%s-%s" % ( host, intfSuffix )
3973 commands = [
3974 # Bring link between oldSw-host down
3975 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
3976 # Determine hostintf and Oldswitchintf
3977 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
3978 ]
3979 # Determine ip address of the host-oldSw interface
3980 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
3981 commands.append( 'px ipaddr = "{}"'.format( IP ) )
3982 commands += [
3983 # Determine mac address of the host-oldSw interface
3984 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
3985 # Detach interface between oldSw-host
3986 "px " + oldSw + ".detach( sintf )",
3987 # Add link between host-newSw
3988 "py net.addLink(" + host + "," + newSw + ")",
3989 # Determine hostintf and Newswitchintf
3990 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
3991 # Attach interface between newSw-host
3992 "px " + newSw + ".attach( sintf )",
3993 ]
3994 if vlan:
3995 vlanIntf = "%s.%s" % ( newIntf, vlan )
3996 commands += [
3997 host + " ip link add link %s name %s type vlan id %s" % ( newIntf, vlanIntf, vlan ),
3998 host + " ip link set up %s" % vlanIntf,
3999 "px hintf.name = '" + vlanIntf + "'",
4000 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = hintf"
4001 ]
4002 newIntf = vlanIntf
4003 commands += [
4004 # Set mac address of the host-newSw interface
4005 "px " + host + ".setMAC( mac = macaddr, intf = hintf )",
4006 # Set IP address of the host-newSw interface
4007 "px " + host + ".setIP( ip = ipaddr, intf = hintf " +
4008 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" )
4009 ]
4010 if ipv6:
4011 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, newIntf ) )
4012 commands += [
4013 "net",
4014 host + " ifconfig"
4015 ]
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004016 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004017 main.log.info( "cmd={}".format( cmd ) )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004018 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07004019 self.handle.expect( self.mnPrompt )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004020 main.log.info( "====> %s ", self.handle.before )
4021 return main.TRUE
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07004022 except pexpect.TIMEOUT:
4023 main.log.error( self.name + ": TIMEOUT exception found" )
4024 main.log.error( self.name + ": " + self.handle.before )
4025 main.cleanAndExit()
4026 except pexpect.EOF:
4027 main.log.error( self.name + ": EOF exception found" )
4028 main.log.error( self.name + ": " + self.handle.before )
4029 return main.FALSE
4030 except Exception:
4031 main.log.exception( self.name + ": Uncaught exception!" )
4032 return main.FALSE
YPZhang801d46d2016-08-08 13:26:28 -07004033
You Wang6e5b48e2018-07-23 16:17:38 -07004034 def moveDualHomedHost( self, host, oldSw, oldPairSw, newSw, newPairSw,
4035 macAddr=None, prefixLen=None, ipv6=False,
4036 intfSuffix1='eth2', intfSuffix2='eth3', bondSuffix='bond1', vlan=None ):
You Wang7ea90582018-07-19 15:27:58 -07004037 """
You Wang6e5b48e2018-07-23 16:17:38 -07004038 Moves a dual-homed host from one switch-pair to another pair on the fly
4039 Optional:
4040 macAddr: when specified, change MAC address of the host interface to specified MAC address.
4041 prefixLen: length of the host IP prefix
4042 ipv6: move an IPv6 host if True
4043 intfSuffix1: suffix of the first new interface
4044 intfSuffix2: suffix of the second new interface
4045 bondSuffix: suffix of the new bond interface
4046 vlan: vlan ID of the host. Use None for non-vlan host
You Wang7ea90582018-07-19 15:27:58 -07004047 """
You Wang7ea90582018-07-19 15:27:58 -07004048 if self.handle:
4049 try:
You Wang6e5b48e2018-07-23 16:17:38 -07004050 bondIntf = "%s-%s" % ( host, bondSuffix )
4051 newIntf = "%s-%s" % ( host, intfSuffix1 )
4052 newIntfPair = "%s-%s" % ( host, intfSuffix2 )
You Wang7ea90582018-07-19 15:27:58 -07004053 commands = [
4054 # Bring link between oldSw-host down
4055 "py net.configLinkStatus('" + oldSw + "'," + "'" + host + "'," + "'down')",
4056 # Bring link between oldPairSw-host down
4057 "py net.configLinkStatus('" + oldPairSw + "'," + "'" + host + "'," + "'down')",
4058 # Determine hostintf and Oldswitchintf
4059 "px hintf,sintf = " + host + ".connectionsTo(" + oldSw + ")[0]",
You Wang6e5b48e2018-07-23 16:17:38 -07004060 ]
4061 # Determine ip address of the host-oldSw interface
4062 IP = str( self.getIPAddress( host, proto='IPV6' if ipv6 else 'IPV4' ) ) + "/" + str( prefixLen )
4063 commands.append( 'px ipaddr = "{}"'.format( IP ) )
4064 commands += [
4065 # Determine mac address of the host-oldSw interface
You Wang7ea90582018-07-19 15:27:58 -07004066 "px macaddr = hintf.MAC()" if macAddr is None else 'px macaddr = "%s"' % macAddr,
4067 # Detach interface between oldSw-host
4068 "px " + oldSw + ".detach( sintf )",
4069 # Determine hostintf and Oldpairswitchintf
4070 "px sintfpair,hintfpair = " + oldPairSw + ".connectionsTo(" + host + ")[0]",
4071 # Detach interface between oldPairSw-host
4072 "px " + oldPairSw + ".detach( sintfpair )",
4073 # Add link between host-newSw
4074 "py net.addLink(" + host + "," + newSw + ", 2)",
4075 # Add link between host-newPairSw
4076 "py net.addLink(" + host + "," + newPairSw + ")",
4077 # Determine hostintf and Newswitchintf
4078 "px hintf,sintf = " + host + ".connectionsTo(" + newSw + ")[-1]",
4079 # Determine hostintf and NewPairswitchintf
4080 "px hintfpair,sintfpair = " + host + ".connectionsTo(" + newPairSw + ")[-1]",
4081 # Attach interface between newSw-host
4082 "px " + newSw + ".attach( sintf )",
4083 # Attach interface between newPairSw-host
4084 "px " + newPairSw + ".attach( sintfpair )",
4085 # Bond two interfaces
You Wang6e5b48e2018-07-23 16:17:38 -07004086 host + ' ip link add %s type bond' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004087 host + ' ip link set %s down' % newIntf,
4088 host + ' ip link set %s down' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004089 host + ' ip link set %s master %s' % ( newIntf, bondIntf ),
4090 host + ' ip link set %s master %s' % ( newIntfPair, bondIntf ),
You Wang7ea90582018-07-19 15:27:58 -07004091 host + ' ip addr flush dev %s' % newIntf,
4092 host + ' ip addr flush dev %s' % newIntfPair,
You Wang6e5b48e2018-07-23 16:17:38 -07004093 host + ' ip link set %s up' % bondIntf,
You Wang7ea90582018-07-19 15:27:58 -07004094 "px lowestIntf = min( [ hintf, hintfpair ] )",
4095 "px highestIntf = max( [ hintf, hintfpair ] )",
You Wang6e5b48e2018-07-23 16:17:38 -07004096 "px lowestIntf.name = '" + bondIntf + "'",
4097 "px " + host + ".nameToIntf['" + bondIntf + "'] = lowestIntf",
You Wang7ea90582018-07-19 15:27:58 -07004098 "px del " + host + ".intfs[ " + host + ".ports[ highestIntf ] ]",
4099 "px del " + host + ".ports[ highestIntf ]",
You Wang6e5b48e2018-07-23 16:17:38 -07004100 ]
4101 if vlan:
4102 vlanIntf = "%s.%s" % ( bondIntf, vlan )
4103 commands += [
4104 host + " ip link add link %s name %s type vlan id %s" % ( bondIntf, vlanIntf, vlan ),
4105 host + " ip link set up %s" % vlanIntf,
4106 "px lowestIntf.name = '" + vlanIntf + "'",
4107 "px " + host + ".nameToIntf[ '" + vlanIntf + "' ] = lowestIntf",
4108 ]
4109 bondIntf = vlanIntf
4110 commands += [
4111 # Set macaddress of the host-newSw interface
4112 "px " + host + ".setMAC( mac = macaddr, intf = lowestIntf)",
You Wang7ea90582018-07-19 15:27:58 -07004113 # Set ipaddress of the host-newSw interface
4114 "px " + host + ".setIP( ip = ipaddr, intf = lowestIntf " +
4115 ( ", prefixLen = %s )" % str( prefixLen ) if prefixLen is not None else " )" ),
You Wang7ea90582018-07-19 15:27:58 -07004116 ]
You Wang6e5b48e2018-07-23 16:17:38 -07004117 if ipv6:
4118 commands.append( host + " ip -6 addr add %s dev %s" % ( IP, bondIntf ) )
4119 commands += [
4120 "net",
4121 host + " ifconfig"
4122 ]
You Wang7ea90582018-07-19 15:27:58 -07004123 for cmd in commands:
You Wang0f745de2018-07-27 15:49:22 -07004124 main.log.info( "cmd={}".format( cmd ) )
You Wang7ea90582018-07-19 15:27:58 -07004125 self.handle.sendline( cmd )
Jon Hallf6aeda22020-07-28 09:12:56 -07004126 self.handle.expect( self.mnPrompt )
You Wang7ea90582018-07-19 15:27:58 -07004127 main.log.info( "====> %s ", self.handle.before )
4128 return main.TRUE
You Wang7ea90582018-07-19 15:27:58 -07004129 except pexpect.TIMEOUT:
4130 main.log.error( self.name + ": TIMEOUT exception found" )
4131 main.log.error( self.name + ": " + self.handle.before )
4132 main.cleanAndExit()
4133 except pexpect.EOF:
4134 main.log.error( self.name + ": EOF exception found" )
4135 main.log.error( self.name + ": " + self.handle.before )
4136 return main.FALSE
4137 except Exception:
4138 main.log.exception( self.name + ": Uncaught exception!" )
4139 return main.FALSE
4140
adminbae64d82013-08-01 10:50:15 -07004141if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07004142 sys.modules[ __name__ ] = MininetCliDriver()